Google Visionの検出領域の制限、テキスト認識


11

私は一日中解決策を模索してきました。私の問題に関していくつかのスレッドをチェックアウトしました。

しかし、それは私にはあまり役に立ちませんでした。基本的に私はカメラプレビューがフルスクリーンであることを望みますが、テキストは四角形が描画される画面の中央でのみ認識されます。

私が使用しているテクノロジー:

  • 光学式文字認識(OCR)用のGoogle Mobile Vision API
  • 依存関係: 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ビジョン検出は、入力がフレームです。フレームは画像データであり、関連データとして幅と高さを含みます。Uは、Detectorに渡す前に、このフレームを処理(中央の小さいフレームにカット)できます。このプロセスは高速で、カメラ処理画像に沿ったものでなければなりません。以下のGithubをチェックして、FrameProcessingRunnableを検索してください。ここでフレーム入力を見ることができます。あなたはそこで自分でプロセスを行うことができます。

CameraSource


こんにちは、まずはお返事ありがとうございます!私はあなたのコードを見て、コードで何を変更する必要があるのか​​疑問に思いましたか?追加しなければならないのはフレーム処理部分だけですか?(2つのプライベートクラス)?
アラン

はい、フレームを変更してからDetectorの最後の操作に渡す必要があります。 mDetector.receiveFrame(outputFrame);
ThànhHàVăn

追加する必要があるコードで回答を編集して、コードアウトして賞金を授与できるようにできますか?
アラン

0

google-vision では、Mobile Vision APIを使用して画像内のテキストの位置を取得する方法で説明されているように、検出されたテキストの座標を取得できます。

TextBlocksfromを取得し、座標でTextRecognizerフィルタリングします。これは、クラスのまたはメソッドでTextBlock決定できます 。getBoundingBox()getCornerPoints()TextBlocks

TextRecognizer

認識結果は、detect(Frame)によって返されます。OCRアルゴリズムはテキストレイアウトを推測し、各段落をTextBlockインスタンスに編成します。テキストが検出された場合、少なくとも1つの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

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


                    }

                }
            }

代わりに、すべてのテキストブロックの境界ボックスを取得してから、画面/フレームの中心に最も近い座標を持つ境界ボックスまたは指定した長方形を選択します(つまり、Androidで私のビューの中心x、yを取得するにはどうすればよいですか?)。このためには、getBoundingBox()またはのgetCornerPoints()方法を使用しますTextBlocks...


私は明日のおかげでそれをテストします
アラン・

試しましたが、正しく実装する方法がわかりませんでした
Alan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.