Quelle est la meilleure façon de détecter les coins d'une facture / d'un reçu / d'une feuille de papier sur une photo? Ceci doit être utilisé pour la correction de perspective ultérieure, avant l'OCR.
Mon approche actuelle a été:
RVB> Gris> Détection de Canny Edge avec seuillage> Dilater (1)> Supprimer les petits objets (6)> Effacer les objets de la frontière> choisir un grand blog basé sur la zone convexe. > [détection de coin - Non implémenté]
Je ne peux m'empêcher de penser qu'il doit y avoir une approche «intelligente» / statistique plus robuste pour gérer ce type de segmentation. Je n'ai pas beaucoup d'exemples de formation, mais je pourrais probablement rassembler 100 images.
Contexte plus large:
J'utilise matlab pour prototyper et je prévois d'implémenter le système dans OpenCV et Tesserect-OCR. C'est le premier d'un certain nombre de problèmes de traitement d'image que je dois résoudre pour cette application spécifique. Je cherche donc à lancer ma propre solution et à me re-familiariser avec les algorithmes de traitement d'image.
Voici un exemple d'image que j'aimerais que l'algorithme gère: Si vous souhaitez relever le défi, les grandes images sont à http://madteckhead.com/tmp
(source: madteckhead.com )
(source: madteckhead.com )
(source: madteckhead.com )
(source: madteckhead.com )
Dans le meilleur des cas, cela donne:
(source: madteckhead.com )
(source: madteckhead.com )
(source: madteckhead.com )
Cependant il échoue facilement sur d'autres cas:
(source: madteckhead.com )
(source: madteckhead.com )
(source: madteckhead.com )
Merci d'avance pour toutes les bonnes idées! J'aime tellement!
EDIT: Progrès de la transformation de Hough
Q: Quel algorithme regrouperait les lignes hough pour trouver des coins? En suivant les conseils des réponses, j'ai pu utiliser la transformation de Hough, choisir des lignes et les filtrer. Mon approche actuelle est plutôt grossière. J'ai fait l'hypothèse que la facture sera toujours à moins de 15 degrés hors d'alignement avec l'image. Je me retrouve avec des résultats raisonnables pour les lignes si tel est le cas (voir ci-dessous). Mais je ne suis pas tout à fait sûr d'un algorithme approprié pour regrouper les lignes (ou voter) à extrapoler pour les coins. Les lignes de Hough ne sont pas continues. Et dans les images bruyantes, il peut y avoir des lignes parallèles, donc une certaine forme ou une certaine distance par rapport aux métriques d'origine de la ligne sont nécessaires. Des idées?
(source: madteckhead.com )
Réponses:
Je suis l'ami de Martin qui travaillait là-dessus plus tôt cette année. C'était mon tout premier projet de codage, et s'est un peu terminé dans un peu de précipitation, donc le code a besoin d'errr ... décodage ... je vais donner quelques conseils de ce que je vous ai déjà vu faire, puis trier mon code le jour de mon congé de demain.
Premier conseil,
OpenCV
et vouspython
êtes génial, passez à eux dès que possible. :RÉAu lieu de supprimer les petits objets et / ou le bruit, abaissez les contraintes astucieuses, de sorte qu'il accepte plus d'arêtes, puis trouvez le plus grand contour fermé (dans OpenCV, utilisez
findcontour()
des paramètres simples, je pense que j'ai utiliséCV_RETR_LIST
). pourrait encore avoir du mal quand c'est sur un morceau de papier blanc, mais fournissait certainement les meilleurs résultats.Pour la
Houghline2()
transformation, essayez avec leCV_HOUGH_STANDARD
plutôt que leCV_HOUGH_PROBABILISTIC
, cela donnera des valeurs rho et thêta , définissant la ligne en coordonnées polaires, puis vous pourrez regrouper les lignes dans une certaine tolérance à celles-ci.Mon regroupement fonctionnait comme une table de recherche, pour chaque ligne sortie de la transformation hough, cela donnerait une paire rho et thêta. Si ces valeurs se situaient dans, disons 5% d'une paire de valeurs du tableau, elles étaient ignorées, si elles étaient en dehors de ces 5%, une nouvelle entrée était ajoutée au tableau.
Vous pouvez alors faire l'analyse des lignes parallèles ou de la distance entre les lignes beaucoup plus facilement.
J'espère que cela t'aides.
la source
Un groupe d'étudiants de mon université a récemment démontré une application iPhone (et une application Python OpenCV) qu'ils avaient écrite pour faire exactement cela. Si je me souviens bien, les étapes ressemblaient à ceci:
Cela semblait assez bien fonctionner et ils ont pu prendre une photo d'un morceau de papier ou d'un livre, effectuer la détection des coins, puis mapper le document de l'image sur un plan plat presque en temps réel (il y avait une seule fonction OpenCV à exécuter la cartographie). Il n'y avait pas d'OCR quand je l'ai vu fonctionner.
la source
Voici ce que j'ai trouvé après un peu d'expérimentation:
Pas parfait, mais fonctionne au moins pour tous les échantillons:
la source
for line in lines[0]: cv2.line(edges, (line[0], line[1]), (line[2], line[3]), (255,0,0), 2, 8) # finding contours contours, _ = cv2.findContours(edges.copy(), cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_TC89_KCOS) contours = filter(lambda cont: cv2.arcLength(cont, False) > 100, contours) contours = filter(lambda cont: cv2.contourArea(cont) > 10000, contours)
Au lieu de partir de la détection des bords, vous pouvez utiliser la détection des coins.
Marvin Framework fournit une implémentation de l'algorithme de Moravec à cet effet. Vous pouvez trouver les coins des papiers comme point de départ. Ci-dessous la sortie de l'algorithme de Moravec:
la source
Vous pouvez également utiliser MSER (régions extrêmes maximales stables) sur le résultat de l'opérateur Sobel pour trouver les régions stables de l'image. Pour chaque région renvoyée par MSER, vous pouvez appliquer une coque convexe et une approximation poly pour en obtenir comme ceci:
Mais ce type de détection est utile pour la détection en direct de plus d'une seule image qui ne renvoie pas toujours le meilleur résultat.
la source
Après la détection des bords, utilisez la transformation de Hough. Ensuite, mettez ces points dans une SVM (machine à vecteurs de support) avec leurs étiquettes, si les exemples ont des lignes lisses sur eux, SVM n'aura aucune difficulté à diviser les parties nécessaires de l'exemple et les autres parties. Mon conseil sur SVM, mettez un paramètre comme la connectivité et la longueur. Autrement dit, si les points sont connectés et longs, ils sont susceptibles d'être une ligne du reçu. Ensuite, vous pouvez éliminer tous les autres points.
la source
Voici le code de @Vanuan utilisant C ++:
la source
std::vector<cv::Vec4i> lines;
est déclaré dans une portée globale dans mon projet.Convertir en espace de laboratoire
Utiliser le cluster kmeans segment 2
la source