Limitation de la zone de détection dans Google Vision, reconnaissance de texte


11

J'ai cherché toute la journée une solution. J'ai vérifié plusieurs discussions concernant mon problème.

Mais cela ne m'a pas beaucoup aidé. Fondamentalement, je veux que l'aperçu de la caméra soit en plein écran, mais le texte n'est reconnu qu'au centre de l'écran, où un rectangle est dessiné.

Technologies que j'utilise:

  • API Google Mobile Vision pour la reconnaissance optique de caractères (OCR)
  • Dépendance: play-services-vision

Mon état actuel: j'ai créé une classe 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);
    }
}

Et implémenté une instance de cette classe ici:

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

Lors de l'exécution, cette exception est levée:

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)

Si quelqu'un a un indice, quelle est ma faute ou a des alternatives, je l'apprécierais vraiment. Je vous remercie!

C'est ce que je veux réaliser, un Rect. Scanner de zone de texte:

Ce que je veux réaliser

Réponses:


0

La détection de vision de Google a l'entrée est un cadre. Un cadre est une donnée d'image et contient une largeur et une hauteur en tant que données associées. U peut traiter ce cadre (le couper en un cadre centré plus petit) avant de le passer au détecteur. Ce processus doit être rapide et faire le long de l'image de traitement de la caméra. Consultez mon Github ci-dessous, Rechercher FrameProcessingRunnable. U peut y voir l'entrée de trame. vous pouvez faire le processus vous-même là-bas.

CameraSource


Bonjour, tout d'abord merci d'avoir répondu! J'ai vu votre code et je me suis demandé, que dois-je changer dans mon code? Est-ce que la seule chose que je dois ajouter est la partie traitement d'images? (Les 2 cours privés)?
Alan

Oui, vous devez modifier votre cadre avant de le passer à la dernière opération de Détecteur: mDetector.receiveFrame(outputFrame);
Thành Hà Văn

Pouvez-vous modifier votre réponse avec le code que je dois ajouter, afin que je puisse le coder et vous attribuer la prime?
Alan

0

Dans google-vision, vous pouvez obtenir les coordonnées d'un texte détecté comme décrit dans Comment obtenir la position du texte dans une image à l'aide de l'API Mobile Vision?

Vous obtenez le TextBlocksde TextRecognizer, puis vous filtrez le TextBlockpar leurs coordonnées, qui peuvent être déterminées par la méthode getBoundingBox()ou getCornerPoints()de la TextBlocksclasse:

TextRecognizer

Les résultats de reconnaissance sont retournés par detect (Frame). L'algorithme OCR essaie de déduire la disposition du texte et organise chaque paragraphe en instances TextBlock. Si du texte est détecté, au moins une instance TextBlock sera retournée.

[..]

Méthodes publiques

public SparseArray<TextBlock> detect (Frame frame)Détecte et reconnaît le texte dans une image. Ne prend en charge que bitmap et NV21 pour l'instant. Renvoie le mappage d'int à TextBlock, où le domaine int représente un ID opaque pour le bloc de texte.

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

TextBlock

public class TextBlock extends Object implements Text

Un bloc de texte (pensez-y comme un paragraphe) tel que jugé par le moteur OCR.

Résumé de la méthode publique

Rect getBoundingBox() Renvoie la zone de délimitation alignée sur l'axe du TextBlock.

List<? extends Text> getComponents() Les composants plus petits qui composent cette entité, le cas échéant.

Point[] getCornerPoints() 4 points d'angle dans le sens horaire en commençant par le coin supérieur gauche.

String getLanguage() Langue dominante dans TextBlock.

String getValue() Récupérez le texte reconnu sous forme de chaîne.

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

Donc, vous procédez essentiellement comme dans Comment obtenir la position du texte dans une image à l'aide de l'API Mobile Vision? mais vous ne divisez aucun bloc en lignes, puis aucune ligne de mots comme

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


                    }

                }
            }

au lieu de cela, vous obtenez la zone de délimitation de tous les blocs de texte, puis sélectionnez la zone de délimitation avec les coordonnées les plus proches du centre de l'écran / du cadre ou du rectangle que vous spécifiez (c'est-à-dire comment puis-je obtenir le centre x, y de ma vue dans Android? ). Pour cela, vous utilisez la méthode getBoundingBox()ou getCornerPoints()de TextBlocks...


Je vais le tester demain merci
Alan

Je l'ai essayé mais je ne savais pas comment l'implémenter correctement
Alan
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.