Ограничение области обнаружения в 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...


Я проверю это завтра, спасибо
Алан

Я попробовал это, но я не знал, как правильно это реализовать
Алан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.