Google Vision'daki algılama alanını sınırlama, metin tanıma


11

Bütün gün bir çözüm arıyordum. Sorunumla ilgili birkaç konuya baktım.

Ama bana pek yardımcı olmadı. Temel olarak Kamera Önizlemesinin tam ekran olmasını istiyorum, ancak metin yalnızca ekranın ortasında bir Dikdörtgen çizildiği yerde tanınıyor.

Kullandığım teknolojiler:

  • Optik karakter tanıma için Google Mobile Vision API'leri (OCR)
  • Bağımlılığı: play-services-vision

Şu anki durumum: Bir BoxDetector sınıfı oluşturdum:

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

Ve bu sınıfın bir örneğini burada uyguladık:

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

Yürütme sırasında bu İstisna atılır:

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)

Herhangi bir ipucu, benim hatam nedir veya herhangi bir alternatif varsa, gerçekten takdir ediyorum. Teşekkür ederim!

Bunu başarmak istiyorum, bir Rect. Metin alanı tarayıcısı:

Neyi başarmak istiyorum

Yanıtlar:


0

Google vizyon algılama girdisi bir çerçeve var. Çerçeve bir görüntü verisidir ve ilişkili veriler olarak bir genişlik ve yükseklik içerir. U, Dedektöre geçmeden önce bu çerçeveyi işleyebilir (daha küçük ortalanmış çerçeveye kesebilir). Bu işlem hızlı olmalı ve kamera işleme görüntüsü boyunca yapılmalıdır. Aşağıdaki Github'a göz atın, FrameProcessingRunnable'ı arayın. U çerçeve girişini orada görebilir. işlemi orada kendiniz yapabilirsiniz.

CameraSource


Merhaba, her şeyden önce cevap verdiğiniz için teşekkürler! Kodunuzu gördüm ve merak ettim, kodumda neyi değiştirmek zorundayım? Eklemem gereken tek şey Çerçeve işleme kısmı mı? (2 özel sınıf)?
Alan

: Evet, u u Detektör son operasyon geçirmeden önce sizin çerçeveyi değiştirmek zorunda mDetector.receiveFrame(outputFrame);
Thành Ha Van

Cevabınızı ekleyebileceğim kodla düzenleyebilir misiniz, böylece onu kodlayabilir ve size ödül verebilir miyim?
Alan

0

Google-vision'te algılanan bir metnin koordinatlarını, Mobile Vision API'sini kullanarak bir görüntüdeki metnin konumu nasıl elde edilir?

Sen almak TextBlocksden TextRecognizersonra filtre TextBlockile tespit edilebilir onların koordinatlarına göre getBoundingBox()ya getCornerPoints()yöntemine TextBlockssınıfının:

TextRecognizer

Tanıma sonuçları tespit (Çerçeve) ile döndürülür. OCR algoritması metin düzenini çıkarmaya çalışır ve her paragrafı TextBlock örneklerinde düzenler. Herhangi bir metin algılanırsa, en az bir TextBlock örneği döndürülür.

[..]

Kamusal Yöntemler

public SparseArray<TextBlock> detect (Frame frame)Bir görüntüdeki metni algılar ve tanır. Şimdilik yalnızca bitmap ve NV21'i destekliyor. İnt'nin, int etki alanının metin bloğu için opak bir kimliği temsil ettiği TextBlock ile eşleşmesini döndürür.

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

Metin bloğu

public class TextBlock extends Object implements Text

OCR motoru tarafından kabul edilen bir metin bloğu (paragraf olarak düşünün).

Genel Yöntem Özeti

Rect getBoundingBox() TextBlock öğesinin eksene hizalanan sınırlama kutusunu döndürür.

List<? extends Text> getComponents() Varsa, bu varlığı içeren daha küçük bileşenler.

Point[] getCornerPoints() Sol üst köşeden başlayarak saat yönünde 4 köşe noktası.

String getLanguage() TextBlock'ta geçerli dil.

String getValue() Tanınan metni dize olarak alır.

kaynak: https://developers.google.com/android/reference/com/google/android/gms/vision/text/TextBlock

Yani temelde Mobile Vision API'sini kullanarak bir görüntüdeki metnin konumunu nasıl alabilirim? ancak satırları herhangi bir satır ve sonra gibi kelimelerde herhangi bir satır bölmezsiniz

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


                    }

                }
            }

bunun yerine alabilirsiniz sınır kutusunu tüm metin bloklarının ve sonra ekran / karenin ortasında veya belirttiğiniz o dikdörtgenin en yakın koordinatlarla sınır kutusunu seçin (yani i merkezi x nasıl alabilirim, android benim bakış y? ). Bunun için getBoundingBox()veya getCornerPoints()yöntemini kullanın TextBlocks...


Yarın test edeceğim teşekkürler
Alan

Denedim ama doğru bir şekilde nasıl uygulanacağını bilmiyordum
Alan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.