限制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。文字区域扫描器:

我想要实现的目标

Answers:


0

Google视觉检测所输入的是框架。帧是图像数据,并包含宽度和高度作为关联数据。在将其传递到检测器之前,U可以对其进行处理(将其剪切为较小的居中框架)。此过程必须快速并且沿着相机处理图像。在下面查看我的Github,搜索FrameProcessingRunnable。U在那里可以看到帧输入。您可以在那里自己进行处理。

CameraSource


您好,首先感谢您的回答!我看到了您的代码并想知道,我必须对代码进行哪些更改?我唯一需要添加的是帧处理部分吗?(两个私人班级)?
艾伦

是的,U面前ü它传递给探测器的最后一次操作修改框架: mDetector.receiveFrame(outputFrame);
清下环

您可以使用我需要添加的代码来编辑答案,以便我将其编码并授予您赏金吗?
艾伦

0

在google-vision中,您可以获取检测到的文本的坐标,如如何使用Mobile Vision API获取图像中文本的位置中所述

TextBlocks从获得TextRecognizer,然后TextBlock通过其坐标过滤,该坐标可以由 getBoundingBox() class或getCornerPoints()方法TextBlocks

文字识别器

识别结果由detect(Frame)返回。OCR算法尝试推断文本布局并将每个段落组织到TextBlock实例中。如果检测到任何文本,将至少返回一个TextBlock实例。

[..]

公开方法

public SparseArray<TextBlock> detect (Frame frame)检测并识别图像中的文本。目前仅支持位图和NV21。返回int到TextBlock的映射,其中int域表示文本块的不透明ID。

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

文字区块

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,我在Android设备上查看Y的?)。为此,请使用...的getBoundingBox()or getCornerPoints()方法TextBlocks


明天我会测试的,谢谢
艾伦

我尝试了它,但是我不知道如何正确实现它
艾伦
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.