OpenCV Android (java) détection de caractères et reconnaissance de polices


Je travaille sur l'application Android, qui détermine quelle police est utilisée sur une image texte. J'ai donc besoin d'extraire chaque caractère de l'image et je ne sais pas comment le faire précisément. De plus, lorsque j'essaie de traiter une image, j'ai un résultat...mais mon camarade de classe a différent (par exemple, plus ou moins de bruit). Le problème avec la détection de caractères est que:

1) il détecte également des taches de bruit sur l'image et le montre en rectangles (j'ai pensé à detectMultiScale... mais j'ai des doutes à ce sujet, il existe peut-être des moyens les plus simples de détecter les caractères)

2) il détecte plusieurs contours d'un caractère (par exemple rayon intérieur et rayon extérieur de la lettre "o")

Et question pour l'avenir: je vais créer une base de données avec des images (pour l'instant seulement 3 polices) de différentes lettres de polices et les comparer avec une image de lettres de photo. Peut-être que quelqu'un pourrait recommander une meilleure façon de le faire.
Cela fait donc partie du code avec traitement d'image(je joue toujours avec des valeurs de flou, seuil et Prudente... mais il n'y a pas eu de résultat vraiment positif):

Imgproc.cvtColor(sImage, grayImage, Imgproc.COLOR_BGR2GRAY); //градации серого
Imgproc.GaussianBlur(grayImage,blurImage,new Size(5, 5),0); //размытие
        Imgproc.adaptiveThreshold(blurImage, thresImage, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 101, 39);
        List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
        Mat hierarchy = new Mat();

        Imgproc.Canny(thresImage, binImage, 30, 10, 3, true); //контур
        Imgproc.findContours(binImage, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));

        hierarchy.release();
        Imgproc.drawContours(binImage, contours, -1, new Scalar(255, 255, 255));//, 2, 8, hierarchy, 0, new Point());


        MatOfPoint2f approxCurve = new MatOfPoint2f();

        //For each contour found
        for (int i = 0; i < contours.size(); i++) {
            //Convert contours(i) from MatOfPoint to MatOfPoint2f
            MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
            //Processing on mMOP2f1 which is in type MatOfPoint2f
            double approxDistance = Imgproc.arcLength(contour2f, true) * 0.02;
            Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);

            //Convert back to MatOfPoint
            MatOfPoint points = new MatOfPoint(approxCurve.toArray());


            // Get bounding rect of contour
            Rect rect = Imgproc.boundingRect(points);

            // draw enclosing rectangle (all same color, but you could use variable i to make them unique)
            Imgproc.rectangle(binImage, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(255, 255, 255), 5);

        }

Et écran (pas réellement avec des valeurs de traitement du code, juste un avec de meilleurs résultats): entrez la description de l'image ici . Original: entrez la description de l'image ici (malheureusement, je ne peux pas ajouter plus de 2 liens pour afficher plus d'exemples)
Il y avait des situations, quand l'image de cet écran avait l'air assez bon, mais une autre image ressemblait à des taches informes.

Author: FinsterEule, 2017-06-22

1 answers

Votre code est correct, il vous suffit de faire quelques ajustements mineurs pour le faire fonctionner correctement.

  • Tout d'Abord, la taille de l'image est très grande, vous pouvez la réduire à 20% de la taille actuelle sans subir une perte importante de précision. En raison de la taille de l'image plus grande, toutes les fonctions fonctionneraient plus lentement.

  • Vous n'avez pas besoin d'effectuer un seuil adaptatif avant Canny, canny fonctionne également parfaitement sur les images en échelle de gris, Vous devez ajuster les paramètres comme:

    Canny(img, threshold1=170, threshold2=250)
    

    Qui donne une image de:entrez la description de l'image ici

  • [Facultatif] Si vous voulez de bruit de l'image, alors vous pouvez essayer avec les opérations morphologiques comme erode et dilate.

  • Maintenant, vous êtes prêt à trouver les contours. L'erreur dans votre code utilisait Imgproc.RETR_TREE flag vous devez utiliser Imgproc.RETR_EXTERNAL flag pour obtenir uniquement les contours externes et non les contours internes imbriqués.

    A cette étape, vous pouvez avoir quelques petits contours indésirables, qui peuvent être filtrés comme:

    // ** Below code if for reference purposes only, consult OpenCV docs for proper API methods
    int character_area_lower_thresh = 10;
    for (Contour c:contours) {
         if (Imgproc.contourArea(c) > character_area_lower_thresh) {
             // Desired contour, do what ever you want to do
             Rect r = Imgproc.boundingRect(c);
         }
    }
    

    entrez la description de l'image ici

 2
Author: ZdaR, 2017-06-22 17:50:48