Giới hạn khu vực phát hiện trong Google Vision, nhận dạng văn bản


11

Tôi đã tìm kiếm cả ngày cho một giải pháp. Tôi đã kiểm tra một số Chủ đề liên quan đến vấn đề của tôi.

Nhưng nó không giúp tôi nhiều. Về cơ bản tôi muốn Camera Preview ở chế độ toàn màn hình nhưng văn bản chỉ được nhận dạng ở giữa màn hình, nơi hình chữ nhật được vẽ.

Công nghệ tôi đang sử dụng:

  • API tầm nhìn di động của Google dành cho nhận dạng ký tự quang học (OCR)
  • Phụ thuộc: play-services-vision

Trạng thái hiện tại của tôi: Tôi đã tạo một lớp 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);
    }
}

Và thực hiện một thể hiện của lớp này ở đây:

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

Khi thực hiện Ngoại lệ này được ném:

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)

Nếu bất cứ ai có manh mối, lỗi của tôi là gì hoặc có bất kỳ sự thay thế nào tôi sẽ thực sự đánh giá cao nó. Cảm ơn bạn!

Đây là những gì tôi muốn đạt được, một Rect. Máy quét vùng văn bản:

Những gì tôi muốn đạt được

Câu trả lời:


0

Google phát hiện tầm nhìn có đầu vào là một khung. Khung là dữ liệu hình ảnh và chứa chiều rộng và chiều cao như dữ liệu liên quan. Bạn có thể xử lý khung này (Cắt nó thành khung trung tâm nhỏ hơn) trước khi chuyển nó đến Máy dò. Quá trình này phải nhanh và thực hiện cùng với hình ảnh xử lý camera. Kiểm tra Github của tôi dưới đây, Tìm kiếm FrameProcessingRunnable. Bạn có thể thấy đầu vào khung ở đó. bạn có thể tự làm quá trình ở đó

Nguồn camera


Xin chào, trước tiên cảm ơn bạn đã trả lời! Tôi thấy mã của bạn và tự hỏi, tôi phải thay đổi gì trong mã của mình? Điều duy nhất tôi phải thêm là phần xử lý Khung? (2 lớp riêng)?
Alan

Có, bạn phải sửa đổi khung của mình trước khi bạn chuyển nó sang hoạt động cuối cùng của Máy dò: mDetector.receiveFrame(outputFrame);
Thành Hà Văn

Bạn có thể chỉnh sửa câu trả lời của mình với mã tôi cần thêm để tôi có thể viết mã ra và trao thưởng cho bạn tiền thưởng không?
Alan

0

Trong google-Vision, bạn có thể lấy tọa độ của văn bản được phát hiện như được mô tả trong Cách nhận vị trí của văn bản trong hình ảnh bằng API Tầm nhìn di động?

Bạn nhận được TextBlockstừ TextRecognizer, sau đó bạn lọc TextBlocktheo tọa độ của chúng, có thể được xác định bởi getBoundingBox()hoặc getCornerPoints()phương thức của TextBlockslớp:

Trình nhận dạng văn bản

Kết quả nhận dạng được trả về bằng cách phát hiện (Khung). Thuật toán OCR cố gắng suy ra bố cục văn bản và sắp xếp từng đoạn vào các trường hợp TextBlock. Nếu bất kỳ văn bản nào được phát hiện, ít nhất một phiên bản TextBlock sẽ được trả về.

[..]

Phương pháp công cộng

public SparseArray<TextBlock> detect (Frame frame)Phát hiện và nhận dạng văn bản trong một hình ảnh. Hiện tại chỉ hỗ trợ bitmap và NV21. Trả về ánh xạ của int vào TextBlock, trong đó miền int biểu thị ID mờ cho khối văn bản.

nguồn: https://developers.google.com/android/reference/com/google/android/gms/vision/text/TextRecognizer

TextBlock

public class TextBlock extends Object implements Text

Một khối văn bản (nghĩ về nó như một đoạn văn) được coi là của công cụ OCR.

Tóm tắt phương pháp công khai

Rect getBoundingBox() Trả về hộp giới hạn căn chỉnh trục của TextBlock.

List<? extends Text> getComponents() Các thành phần nhỏ hơn bao gồm thực thể này, nếu có.

Point[] getCornerPoints() 4 điểm góc theo chiều kim đồng hồ bắt đầu từ trên cùng bên trái.

String getLanguage() Ngôn ngữ ưu tiên trong TextBlock.

String getValue() Lấy văn bản được công nhận dưới dạng một chuỗi.

nguồn: https://developers.google.com/android/reference/com/google/android/gms/vision/text/TextBlock

Vì vậy, về cơ bản, bạn tiến hành như thế nào để có được vị trí của văn bản trong hình ảnh bằng cách sử dụng API Tầm nhìn di động? tuy nhiên bạn không phân chia bất kỳ khối nào trong các dòng và sau đó bất kỳ dòng nào trong các từ như

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


                    }

                }
            }

thay vào đó, bạn nhận được hộp ranh giới của tất cả các khối văn bản và sau đó chọn hộp ranh giới có tọa độ gần trung tâm của màn hình / khung hoặc hình chữ nhật mà bạn chỉ định (ví dụ: Làm thế nào tôi có thể lấy tâm x, y của chế độ xem của tôi trong Android? ). Đối với điều này, bạn sử dụng getBoundingBox()hoặc getCornerPoints()phương pháp TextBlocks...


Tôi sẽ kiểm tra nó vào ngày mai cảm ơn
Alan

Tôi đã thử nó nhưng tôi không biết làm thế nào để thực hiện nó một cách chính xác
Alan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.