จำกัด ขอบเขตการตรวจจับใน Google Vision การรับรู้ข้อความ


11

ฉันค้นหาวิธีแก้ปัญหาทั้งวัน ฉันได้ตรวจสอบหลายหัวข้อเกี่ยวกับปัญหาของฉัน

แต่มันก็ไม่ได้ช่วยอะไรฉันมากนัก โดยทั่วไปฉันต้องการให้ Camera Preview เป็นแบบเต็มหน้าจอ แต่ข้อความจะได้รับการยอมรับเฉพาะตรงกลางหน้าจอที่มีการวาดรูปสี่เหลี่ยมผืนผ้า

เทคโนโลยีที่ฉันใช้:

  • Google Mobile Vision API สำหรับการจดจำอักขระด้วยแสง (OCR)
  • dependecy: 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 มีอินพุตเป็นเฟรม เฟรมเป็นข้อมูลภาพและมีความกว้างและความสูงตามข้อมูลที่เกี่ยวข้อง คุณสามารถประมวลผลเฟรมนี้ (ตัดไปที่เฟรมกึ่งกลางที่เล็กกว่า) ก่อนส่งไปยังเครื่องตรวจจับ กระบวนการนี้จะต้องรวดเร็วและทำตามการประมวลผลภาพของกล้อง ตรวจสอบ Github ของฉันด้านล่างค้นหา FrameProcessingRunnable คุณสามารถเห็นอินพุตเฟรมที่นั่น คุณสามารถทำกระบวนการด้วยตัวเองที่นั่น

CameraSource


สวัสดีก่อนอื่นขอขอบคุณที่ตอบ! ฉันเห็นรหัสของคุณและสงสัยว่าฉันต้องเปลี่ยนอะไรในรหัสของฉัน เป็นสิ่งเดียวที่ฉันต้องเพิ่มคือส่วนการประมวลผลของเฟรม? (2 คลาสส่วนตัว)?
อลัน

ใช่คุณต้องแก้ไขเฟรมของคุณก่อนที่จะผ่านไปยังการทำงานล่าสุดของ Detector: mDetector.receiveFrame(outputFrame);
ThànhHàVăn

คุณสามารถแก้ไขคำตอบของคุณด้วยรหัสที่ฉันต้องการเพิ่มเพื่อให้ฉันสามารถเขียนมันออกมาและให้รางวัลแก่คุณได้หรือไม่?
Alan

0

ใน google-vision คุณสามารถรับพิกัดของข้อความที่ตรวจพบเช่นที่อธิบายไว้ในวิธีรับตำแหน่งของข้อความในภาพโดยใช้ Mobile Vision API?

คุณได้รับTextBlocksจากจากTextRecognizerนั้นคุณกรองTextBlockตามพิกัดที่สามารถกำหนดโดย getBoundingBox()หรือgetCornerPoints()วิธีการTextBlocksเรียน:

TextRecognizer

ผลการรู้จำจะถูกส่งคืนโดย detect (Frame) อัลกอริทึม OCR พยายามอนุมานเค้าโครงข้อความและจัดระเบียบแต่ละย่อหน้าลงในอินสแตนซ์ของ TextBlock หากตรวจพบข้อความใด ๆ อินสแตนซ์ TextBlock อย่างน้อยหนึ่งรายการจะถูกส่งคืน

[ .. ]

วิธีการสาธารณะ

public SparseArray<TextBlock> detect (Frame frame)ตรวจจับและจดจำข้อความในภาพ รองรับเฉพาะบิตแมปและ NV21 เท่านั้น ส่งคืนการแม็พของ int ไปยัง TextBlock โดยที่ int โดเมนแทน opaque 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));


                    }

                }
            }

แต่คุณจะได้รับกล่องขอบเขตของบล็อคข้อความทั้งหมดแล้วเลือกกล่องขอบเขตที่มีพิกัดใกล้เคียงกับกึ่งกลางของหน้าจอ / กรอบหรือสี่เหลี่ยมผืนผ้าที่คุณระบุ (เช่นฉันจะรับ x กลาง y จากมุมมองของฉันใน android ได้อย่างไร ). สำหรับสิ่งนี้คุณใช้getBoundingBox()หรือgetCornerPoints()วิธีการของTextBlocks...


ฉันจะทดสอบในวันพรุ่งนี้ขอบคุณ
Alan

ฉันลองแล้ว แต่ฉันไม่รู้วิธีใช้อย่างถูกต้อง
อลัน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.