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


11

Я цілий день шукав рішення. Я перевірив кілька тем щодо моєї проблеми.

Але це мені не дуже допомогло. В основному я хочу, щоб попередній перегляд камери був повноекранним, але текст розпізнається лише в центрі екрана, де намальований Прямокутник.

Технології, якими я користуюся:

  • API Google Mobile Vision для оптичного розпізнавання символів (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)

Якщо хтось має підказку, в чому моя вина чи є якісь альтернативи, я б дуже цінував це. Дякую!

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

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

Відповіді:


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

Результати розпізнавання повертаються методом detect (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.