Détection de ligne horizontale avec OpenCV

j'essaie de trouver des lignes horizontales et verticales à partir d'une image qui vient d'un "document". Les documents sont des pages scannées à partir de contrats et de sorte que les lignes ressemblent à ce que vous verriez dans une table ou dans un bloc de contrat.

J'ai essayé OpenCV pour le travail. La mise en œuvre de la transformation à OpenCV semblait utile pour le travail, mais je n'ai pas pu trouver de combinaison de paramètres qui lui permettraient de trouver proprement les lignes verticales et horizontales. J'ai essayé avec et sans détection de bord. Pas de chance. Si quelqu'un a fait quelque chose de semblable, je veux savoir comment.

voir ici une image de mon avant et après expérimentation avec HoughP à OpenCV. C'est le mieux que j'ai pu faire, http://dl.dropbox.com/u/3787481/Untitled%201.png

alors maintenant je me demande s'il y a un autre type de transformation que je pourrais utiliser qui me permettrait de trouver de façon fiable des lignes horizontales et verticales (et de préférence des lignes pointillées) trop.)

je sais que ce problème peut être résolu parce que J'ai des outils OCR de Nuance et D'ABBYY qui peuvent à la fois extraire de façon fiable les lignes horizontales et verticales et me rendre la boîte de limite des lignes.

Merci! Patrick.

21
demandé sur hippietrail 2011-08-29 11:01:43

4 réponses

avez-vous vu un exemple de code de HoughLinesP documentation des fonctions?

je pense que vous pouvez l'utiliser comme point de départ de votre algorithme. Pour choisir des lignes verticales horizontales vous avez juste besoin de filtrer les autres lignes par l'angle de ligne.

mise à jour:

comme je vois que vous devez trouver non pas les lignes mais les bords horizontaux et verticaux de la page. Pour cette tâche, vous devez combiner plusieurs étapes de traitement pour obtenir de bons résultat.

pour votre image je suis capable d'obtenir de bons résultats en combinant la détection de bord Canny avec HoughLinesP. Voici mon code (j'ai utilisé python, mais je pense que vous voyez l'idée):

img = cv2.imread("C:/temp/1.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 80, 120)
lines = cv2.HoughLinesP(edges, 1, math.pi/2, 2, None, 30, 1);
for line in lines[0]:
    pt1 = (line[0],line[1])
    pt2 = (line[2],line[3])
    cv2.line(img, pt1, pt2, (0,0,255), 3)
cv2.imwrite("C:/temp/2.png", img)

Résultat ressemble à ceci:

27
répondu Andrey Kamaev 2018-08-10 17:01:39

si vous voulez simplement les " lignes "et non les" segments de ligne", je éviterais D'utiliser Canny, Hough, FindContours ou toute autre fonction de ce genre au cas où vous voudriez plus de vitesse dans votre code. Si vos images ne sont pas tournées et que ce que vous voulez trouver est toujours vertical ou horizontal, j'utiliserais simplement cv::Sobel (un pour vertical, et un autre pour horizontal) et je créerais des tableaux d'accumulation pour les colonnes et les rangées. Ensuite, vous pouvez rechercher des maxima dans de telles accumulations ou profils, par exemple en seuil, et vous connaîtrez la rangée ou la colonne dans laquelle il y a des lignes de bord verticales ou horizontales.

8
répondu marcos.nieto 2012-07-27 12:46:59

vous pourriez envisager de quitter la détection de ligne de Hough puisque cette méthode recherche des lignes" globales", pas nécessairement des segments de ligne. J'ai récemment mis en œuvre une application qui a identifié des "parallélogrammes" - essentiellement des carrés qui pourraient être tournés et la perspective avant-raccourci en raison de l'angle de vue. Vous pourriez considérer quelque chose de similaire. Mon pipeline était:

  1. Convertir RVB en niveaux de gris (cvCvtColor)
  2. Lisse (cvSmooth)
  3. Seuil (cvThreshold)
  4. Détecter les bords (cvCanny)
  5. Trouver contours (cvFindContours)
  6. contours approximatifs avec caractéristiques linéaires (cvApproxPoly)

dans votre application, la liste de contours résultante sera probablement grande (selon l ' "agressivité" du lissage et l'amélioration des caractéristiques du détecteur de bord Canny. Vous pouvez affiner cette liste par une variété de paramètres: nombre de points retournés par le capteur de contour, surface du contour (cvContourArea), etc. D'après mon expérience, je m'attendrais à ce que les lignes "valides" dans votre application aient des propriétés de superficie et de nombre de vertex bien définies. De plus, vous pouvez filtrer les contours en fonction de la distance entre les points terminaux, de l'angle défini par les points terminaux de connexion de la ligne, etc.

selon la quantité de "temps" CPU que vous avez, vous pouvez toujours jumeler l'algorithme de Hough avec un algorithme comme celui ci-dessus pour identifier robustement les lignes horizontales et verticales.

5
répondu Throwback1986 2011-08-29 18:30:40

ne convertissez pas le RVB en échelle de gris. Parfois, différentes couleurs en RGB peuvent être fusionnées à la même valeur de niveaux de gris, de sorte qu'il pourrait manquer certains contours. Vous devriez analyser chaque canal du RVB séparément.

5
répondu fzec 2013-02-25 15:24:36