Ограничение области обнаружения в Google Vision, распознавание текста - PullRequest
12 голосов
/ 07 марта 2020

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

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

Используемые технологии:

  • 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)

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

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

What I want to achieve

Ответы [ 2 ]

0 голосов
/ 23 марта 2020

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

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

TextRecognizer

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

[..]

Publi c Методы

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

source: https://developers.google.com/android/reference/com/google/android/gms/vision/text/TextRecognizer

TextBlock

public class TextBlock extends Object implements Text

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

Publi c Сводка метода

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));


                    }

                }
            }

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

0 голосов
/ 13 марта 2020

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

CameraSource

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...