web-dev-qa-db-fra.com

Prétraitement d'image avec OpenCV avant de faire la reconnaissance de caractères (tesseract)

J'essaie de développer une application PC simple pour la reconnaissance des plaques d'immatriculation (Java + OpenCV + Tess4j). Les images ne sont pas vraiment bonnes (en plus elles seront bonnes). Je veux prétraiter l'image pour tesseract, et je suis bloqué sur la détection de plaque d'immatriculation (détection de rectangle).

Mes pas:

1) Image source

True Image

Mat img = new Mat();
img = Imgcodecs.imread("sample_photo.jpg"); 
Imgcodecs.imwrite("preprocess/True_Image.png", img);

2) Échelle de gris

Mat imgGray = new Mat();
Imgproc.cvtColor(img, imgGray, Imgproc.COLOR_BGR2GRAY);
Imgcodecs.imwrite("preprocess/Gray.png", imgGray);

3) Flou gaussien

Mat imgGaussianBlur = new Mat(); 
Imgproc.GaussianBlur(imgGray,imgGaussianBlur,new Size(3, 3),0);
Imgcodecs.imwrite("preprocess/gaussian_blur.png", imgGaussianBlur);  

4) Seuil adaptatif

Mat imgAdaptiveThreshold = new Mat();
Imgproc.adaptiveThreshold(imgGaussianBlur, imgAdaptiveThreshold, 255, CV_ADAPTIVE_THRESH_MEAN_C ,CV_THRESH_BINARY, 99, 4);
Imgcodecs.imwrite("preprocess/adaptive_threshold.png", imgAdaptiveThreshold);

Voici la 5ème étape, qui est la détection de la région de la plaque (probablement même sans réalignement pour l'instant).

J'ai recadré la région nécessaire à partir de l'image (après la 4e étape) avec Paint, et j'ai obtenu:

plate region

Ensuite, j'ai fait l'OCR (via tesseract, tess4j):

File imageFile = new File("preprocess/adaptive_threshold_AFTER_Paint.png");
ITesseract instance = new Tesseract();
instance.setLanguage("eng");
instance.setTessVariable("tessedit_char_whitelist", "acekopxyABCEHKMOPTXY0123456789");
String result = instance.doOCR(imageFile); 
System.out.println(result);

et obtenu (assez bon?) résultat - "Y841ox EH" (presque vrai)

Comment puis-je détecter et recadrer la région de la plaque après la 4e étape? Dois-je apporter des modifications (améliorations) en 1 à 4 étapes? Voudrait voir un exemple implémenté via Java + OpenCV (pas JavaCV).
Merci d'avance.

[~ # ~] modifier [~ # ~] (grâce à la réponse de @Abdul Fatir) Eh bien, je fournis un exemple de code de travail (pour moi au moins) ( Netbeans + Java + OpenCV + Tess4j) pour ceux qui s'intéressent à cette question. Le code n'est pas le meilleur, mais je l'ai fait juste pour étudier.
http://Pastebin.com/H46wuXWn (n'oubliez pas de mettre le dossier tessdata dans votre dossier de projet)

14
DocC

Voici comment je vous suggère de faire cette tâche.

  1. Convertissez en niveaux de gris.
  2. Flou gaussien avec filtre 3x3 ou 5x5.
  3. Appliquez le filtre Sobel pour trouver les bords verticaux.

    Sobel(gray, dst, -1, 1, 0)

  4. Seuil l'image résultante pour obtenir une image binaire.
  5. Appliquer une opération de fermeture morphologique à l'aide d'un élément structurant approprié.
  6. Trouvez les contours de l'image résultante.
  7. Trouvez minAreaRect de chaque contour. Sélectionnez des rectangles en fonction du rapport hauteur/largeur et de la zone minimale et maximale.
  8. Pour chaque contour sélectionné, recherchez la densité des bords. Définissez un seuil pour la densité des bords et choisissez les rectangles dépassant ce seuil comme régions de plaque possibles.
  9. Il restera peu de rectangles après cela. Vous pouvez les filtrer en fonction de l'orientation ou de tout critère que vous jugez approprié.
  10. Coupez ces parties rectangulaires détectées de l'image après adaptiveThreshold et appliquez l'OCR.

a) Résultat après l'étape 5

Result after Step 5

b) Résultat après l'étape 7. Les verts sont tous les minAreaRect et les rouges sont ceux qui satisfont aux critères suivants: Plage de rapport d'aspect (2,12) & Plage de surface (300,10000)

c) Résultat après l'étape 9. Rectangle sélectionné. Critères: Densité de bord> 0,5

enter image description here

[~ # ~] modifier [~ # ~]

Pour la densité des bords, ce que j'ai fait dans les exemples ci-dessus est le suivant.

  1. Appliquez le détecteur Canny Edge directement sur l'image d'entrée. Que l'image en conserve soit Ic.
  2. Multipliez les résultats du filtre Sobel et Ic. Fondamentalement, prenez un ET des images Sobel et Canny.
  3. Flou gaussien l'image résultante avec un grand filtre. J'ai utilisé 21x21.
  4. Seuil l'image résultante en utilisant la méthode OTSU. Vous obtiendrez une image binaire
  5. Pour chaque rectangle rouge, faites pivoter la partie à l'intérieur de ce rectangle (dans l'image binaire) pour le rendre droit. Parcourez les pixels du rectangle et comptez les pixels blancs. ( Comment faire pivoter? )

Densité des bords = nombre de pixels blancs dans le rectangle/nombre total de pixels dans le rectangle

  1. Choisissez un seuil pour la densité des bords.

[~ # ~] note [~ # ~] : Au lieu de passer par les étapes 1 à 3, vous pouvez également utiliser l'image binaire de l'étape 5 pour calculer la densité des bords.

12
Abdul Fatir

En fait, OpenCV a un modèle pré-formé spécialement pour les plaques d'immatriculation russes: haarcascade_russian_plate_number

Il existe également un projet ANPR open source pour les plaques d'immatriculation russes: plate_recognition . Il ne s'agit pas d'utiliser tesseract, mais il possède un assez bon réseau neuronal pré-formé.

2
sibnick
  • Vous trouvez tous les composants connectés (les zones blanches) et déterminez leur contour.
  • Si vous les filtrez en fonction de la taille (dans le cadre de l'image), du rapport (largeur-hauteur) et du rapport blanc/noir pour récupérer les plaques candidates.
  • Annuler la transformation du rectangle
  • Retirez les boulons
  • Passez en image au moteur OCR.
1
RobAu