Ограничение области обнаружения в Google Vision, распознавание текста

11

Я весь день искал решение. Я проверил несколько тем относительно моей проблемы.

Но это мне не сильно помогло. По сути, я хочу, чтобы предварительный просмотр камеры был полноэкранным, но текст распознается только в центре экрана, где рисуется прямоугольник.

Технологии, которые я использую:

  • Google Mobile Vision API для оптического распознавания символов (OCR)
  • зависимые пакеты: play-services-vision

Мое текущее состояние: я создал класс BoxDetector:

public class BoxDetector extends Detector {
    private Detector mDelegate;
    private int mBoxWidth, mBoxHeight;

    public BoxDetector(Detector delegate, int boxWidth, int boxHeight) {
        mDelegate = delegate;
        mBoxWidth = boxWidth;
        mBoxHeight = boxHeight;
    }

    public SparseArray detect(Frame frame) {
        int width = frame.getMetadata().getWidth();
        int height = frame.getMetadata().getHeight();
        int right = (width / 2) + (mBoxHeight / 2);
        int left = (width / 2) - (mBoxHeight / 2);
        int bottom = (height / 2) + (mBoxWidth / 2);
        int top = (height / 2) - (mBoxWidth / 2);

        YuvImage yuvImage = new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, width, height, null);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(left, top, right, bottom), 100, byteArrayOutputStream);
        byte[] jpegArray = byteArrayOutputStream.toByteArray();
        Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);

        Frame croppedFrame =
                new Frame.Builder()
                        .setBitmap(bitmap)
                        .setRotation(frame.getMetadata().getRotation())
                        .build();

        return mDelegate.detect(croppedFrame);
    }

    public boolean isOperational() {
        return mDelegate.isOperational();
    }

    public boolean setFocus(int id) {
        return mDelegate.setFocus(id);
    }

    @Override
    public void receiveFrame(Frame frame) {
        mDelegate.receiveFrame(frame);
    }
}

И реализовал экземпляр этого класса здесь:

   final TextRecognizer textRecognizer = new TextRecognizer.Builder(App.getContext()).build();

    // Instantiate the created box detector in order to limit the Text Detector scan area
    BoxDetector boxDetector = new BoxDetector(textRecognizer, width, height);

    //Set the TextRecognizer's Processor but using the box collider

    boxDetector.setProcessor(new Detector.Processor<TextBlock>() {
        @Override
        public void release() {
        }

        /*
            Detect all the text from camera using TextBlock
            and the values into a stringBuilder which will then be set to the textView.
        */
        @Override
        public void receiveDetections(Detector.Detections<TextBlock> detections) {
            final SparseArray<TextBlock> items = detections.getDetectedItems();
            if (items.size() != 0) {

                mTextView.post(new Runnable() {
                    @Override
                    public void run() {
                        StringBuilder stringBuilder = new StringBuilder();
                        for (int i = 0; i < items.size(); i++) {
                            TextBlock item = items.valueAt(i);
                            stringBuilder.append(item.getValue());
                            stringBuilder.append("\n");
                        }
                        mTextView.setText(stringBuilder.toString());
                    }
                });
            }
        }
    });


        mCameraSource = new CameraSource.Builder(App.getContext(), boxDetector)
                .setFacing(CameraSource.CAMERA_FACING_BACK)
                .setRequestedPreviewSize(height, width)
                .setAutoFocusEnabled(true)
                .setRequestedFps(15.0f)
                .build();

На исполнение выдается это исключение:

Exception thrown from receiver.
java.lang.IllegalStateException: Detector processor must first be set with setProcessor in order to receive detection results.
    at com.google.android.gms.vision.Detector.receiveFrame(com.google.android.gms:play-services-vision-common@@19.0.0:17)
    at com.spectures.shopendings.Helpers.BoxDetector.receiveFrame(BoxDetector.java:62)
    at com.google.android.gms.vision.CameraSource$zzb.run(com.google.android.gms:play-services-vision-common@@19.0.0:47)
    at java.lang.Thread.run(Thread.java:919)

Если у кого-то есть подсказка, в чем моя вина или есть какие-то альтернативы, я бы очень признателен Спасибо!

Это то, чего я хочу достичь, Rect. Сканер текстовой области:

Чего я хочу достичь

Алан
источник

Ответы:

0

Обнаружение видения Google есть входной кадр. Фрейм представляет собой данные изображения и содержит ширину и высоту в качестве связанных данных. Вы можете обработать этот кадр (обрезать его до меньшего по центру кадра), прежде чем передать его детектору. Этот процесс должен быть быстрым и проделывать вдоль камеры обработку изображения. Проверьте мой Github ниже, Поиск FrameProcessingRunnable. Вы можете увидеть ввод кадра там. Вы можете сделать процесс самостоятельно там.

CameraSource

Тхань Ха Ван
источник
Здравствуйте, прежде всего спасибо за ответ! Я увидел твой код и подумал: а что я должен изменить в своем коде? Единственное, что я должен добавить, это часть обработки кадров? (2 частных занятия)?
Алан
Да, вам нужно изменить свой кадр, прежде чем передать его последней операции Детектора: mDetector.receiveFrame(outputFrame);
Thành Hà Văn
Можете ли вы отредактировать свой ответ с помощью кода, который мне нужно добавить, чтобы я мог его кодировать и наградить вас за вознаграждение?
Алан
0

В google-vision вы можете получить координаты обнаруженного текста, как описано в разделе Как получить положение текста на изображении с помощью API Mobile Vision?

Вы получаете TextBlocksот TextRecognizer, затем фильтруете TextBlockпо их координатам, которые могут быть определены методом getBoundingBox()или getCornerPoints()методом TextBlocksкласса:

TextRecognizer

Результаты распознавания возвращаются при обнаружении (Frame). Алгоритм OCR пытается вывести текстовый макет и организует каждый абзац в экземпляры TextBlock. Если какой-либо текст обнаружен, будет возвращен хотя бы один экземпляр TextBlock.

[..]

Публичные методы

public SparseArray<TextBlock> detect (Frame frame)Обнаруживает и распознает текст на изображении. Пока поддерживает только растровое изображение и NV21. Возвращает отображение int в TextBlock, где домен int представляет непрозрачный идентификатор для текстового блока.

источник: https://developers.google.com/android/reference/com/google/android/gms/vision/text/TextRecognizer

TextBlock

public class TextBlock extends Object implements Text

Блок текста (воспринимайте его как абзац) в соответствии с механизмом OCR.

Публичный метод Резюме

Rect getBoundingBox() Возвращает выравнивающий ось ограничивающий прямоугольник TextBlock.

List<? extends Text> getComponents() Меньшие компоненты, которые составляют эту сущность, если таковые имеются.

Point[] getCornerPoints() 4 угловых точки по часовой стрелке, начиная с верхнего левого угла.

String getLanguage() Преобладающий язык в TextBlock.

String getValue() Получить распознанный текст в виде строки.

источник: https://developers.google.com/android/reference/com/google/android/gms/vision/text/TextBlock

Таким образом, вы продолжаете, как в разделе Как получить положение текста на изображении с помощью Mobile Vision API? однако вы не разбиваете ни один блок на строки, а затем на любую строку в словах

//Loop through each `Block`
            foreach (TextBlock textBlock in blocks)
            {
                IList<IText> textLines = textBlock.Components; 

                //loop Through each `Line`
                foreach (IText currentLine in textLines)
                {
                    IList<IText>  words = currentLine.Components;

                    //Loop through each `Word`
                    foreach (IText currentword in words)
                    {
                        //Get the Rectangle/boundingBox of the word
                        RectF rect = new RectF(currentword.BoundingBox);
                        rectPaint.Color = Color.Black;

                        //Finally Draw Rectangle/boundingBox around word
                        canvas.DrawRect(rect, rectPaint);

                        //Set image to the `View`
                        imgView.SetImageDrawable(new BitmapDrawable(Resources, tempBitmap));


                    }

                }
            }

вместо этого вы получаете граничный блок для всех текстовых блоков, а затем выбираете граничный блок с координатами, ближайшими к центру экрана / рамки или прямоугольника, который вы укажете (т.е. как я могу получить центр x, y моего вида в Android? ) Для этого вы используете getBoundingBox()или getCornerPoints()метод TextBlocks...

ralf htp
источник
Я проверю это завтра, спасибо
Алан
Я попробовал это, но я не знал, как правильно это реализовать
Алан