Membatasi area deteksi di Google Vision, pengenalan teks

11

Saya telah mencari solusi untuk sepanjang hari. Saya telah memeriksa beberapa Thread mengenai masalah saya.

Tapi itu tidak banyak membantu saya. Pada dasarnya saya ingin Pratinjau Kamera fullscreen tetapi teks hanya akan dikenali di tengah layar, di mana Rectangle diambil.

Teknologi yang saya gunakan:

  • Google Mobile Vision API untuk Pengenalan karakter Optik (OCR)
  • Ketergantungan: play-services-vision

Keadaan saya saat ini: Saya membuat kelas 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);
    }
}

Dan mengimplementasikan instance kelas ini di sini:

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

Pada pelaksanaan Pengecualian ini dilemparkan:

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)

Jika ada yang tahu, apa kesalahan saya atau memiliki alternatif, saya akan sangat menghargainya. Terima kasih!

Inilah yang ingin saya capai, sebuah kotak. Pemindai area teks:

Apa yang ingin saya capai

Alan
sumber

Jawaban:

0

Google vision detection memiliki input berupa bingkai. Bingkai adalah data gambar dan berisi lebar dan tinggi sebagai data terkait. Anda dapat memproses bingkai ini (Potong ke bingkai tengah yang lebih kecil) sebelum meneruskannya ke Detektor. Proses ini harus cepat dan dilakukan di sepanjang gambar pemrosesan kamera. Lihat Github saya di bawah ini, Cari FrameProcessingRunnable. Anda dapat melihat input frame di sana. kamu dapat melakukan proses sendiri di sana.

CameraSource

Thành Hà Văn
sumber
Halo, pertama-tama terima kasih telah menjawab! Saya melihat kode Anda dan bertanya-tanya, apa yang harus saya ubah dalam kode saya? Apakah satu-satunya hal yang harus saya tambahkan adalah bagian pemrosesan Frame? (2 kelas privat)?
Alan
Ya, Anda harus memodifikasi bingkai Anda sebelum mengirimkannya ke operasi Detektor terakhir: mDetector.receiveFrame(outputFrame);
Thành Hà Văn
Bisakah Anda mengedit jawaban Anda dengan kode yang perlu saya tambahkan, sehingga saya bisa mengodekannya dan memberi Anda bountie?
Alan
0

Di google-vision Anda bisa mendapatkan koordinat teks yang terdeteksi seperti dijelaskan dalam Cara mendapatkan posisi teks dalam gambar menggunakan Mobile Vision API?

Anda mendapatkan TextBlocksdari TextRecognizer, lalu memfilter TextBlockmenurut koordinatnya, yang dapat ditentukan oleh getBoundingBox()atau getCornerPoints()metode TextBlockskelas:

TextRecognizer

Hasil pengakuan dikembalikan oleh deteksi (Frame). Algoritma OCR mencoba menyimpulkan tata letak teks dan mengatur setiap paragraf ke dalam instance TextBlock. Jika ada teks yang terdeteksi, setidaknya satu instance TextBlock akan dikembalikan.

[..]

Metode Umum

public SparseArray<TextBlock> detect (Frame frame)Mendeteksi dan mengenali teks dalam gambar. Hanya mendukung bitmap dan NV21 untuk saat ini. Mengembalikan pemetaan int ke TextBlock, di mana domain int mewakili ID buram untuk blok teks.

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

TextBlock

public class TextBlock extends Object implements Text

Blok teks (anggap sebagai paragraf) yang dianggap oleh mesin OCR.

Ringkasan Metode Publik

Rect getBoundingBox() Mengembalikan kotak pembatas sumbu-rata TextBlock.

List<? extends Text> getComponents() Komponen yang lebih kecil yang terdiri dari entitas ini, jika ada.

Point[] getCornerPoints() 4 titik sudut searah jarum jam mulai dari kiri atas.

String getLanguage() Bahasa yang berlaku di TextBlock.

String getValue() Ambil kembali teks yang dikenal sebagai string.

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

Jadi, Anda pada dasarnya melanjutkan seperti di Cara mendapatkan posisi teks dalam gambar menggunakan Mobile Vision API? namun Anda tidak memecah blok apa pun dalam garis dan kemudian garis apa pun dalam kata-kata seperti

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


                    }

                }
            }

alih-alih Anda mendapatkan kotak batas semua blok teks dan kemudian memilih kotak batas dengan koordinat terdekat ke tengah layar / bingkai atau persegi panjang yang Anda tentukan (yaitu Bagaimana saya bisa mendapatkan pusat x, y dari pandangan saya di android? ). Untuk ini, Anda menggunakan getBoundingBox()atau getCornerPoints()metode TextBlocks...

ralf htp
sumber
Saya akan mengujinya besok terima kasih
Alan
Saya mencobanya tetapi saya tidak tahu bagaimana cara mengimplementasikannya dengan benar
Alan