20

Próbuję znaleźć poziome i pionowe linie z obrazu pochodzącego z "dokumentu". Dokumenty są skanowane stron z umów, a więc linie wyglądają jak to, co można zobaczyć w tabeli lub w bloku umowy.Wykrywanie linii poziomej za pomocą OpenCV

Próbowałem OpenCV do pracy. Implementacja transformacji Hough w OpenCV wydawała się przydatna do wykonania zadania, ale nie mogłem znaleźć żadnej kombinacji parametrów, które umożliwiałyby jej łatwe znalezienie pionowych i poziomych linii. Próbowałem z wykrywaniem krawędzi i bez niego. Brak szczęścia. Jeśli ktokolwiek zrobił coś podobnego, to chciałbym wiedzieć jak.

Zobacz tutaj obraz moich przed i po eksperymentach z HoughP w OpenCV. To najlepsze co mogłem zrobić, http://dl.dropbox.com/u/3787481/Untitled%201.png

Więc teraz zastanawiam się, czy istnieje inny rodzaj przekształcić można używać które pozwoliłyby mi niezawodnie odnaleźć poziome i pionowe linie (i korzystnie przerywane linie zbyt).

Wiem, że ten problem można rozwiązać, ponieważ mam narzędzia Nuance i ABBYY OCR, które mogą niezawodnie wyodrębniać poziome i pionowe linie i zwracać mi ramkę ograniczającą linii.

Dzięki! Patrick.

Odpowiedz

25

Czy widziałeś próbkę kodu z dokumentacji funkcji HoughLinesP?

Myślę, że możesz go użyć jako punktu wyjścia dla swojego algorytmu. Aby wybrać poziome pionowe linie, musisz odfiltrować inne linie po linii.

UPDATE:

Jak widzę nie trzeba znaleźć wiersze, ale Poziome krawędzie pionowe na stronie. W tym celu należy połączyć kilka etapów przetwarzania, aby uzyskać dobre wyniki.

Dla Twojego obrazu mogę osiągnąć dobre wyniki, łącząc wykrywanie krawędzi Canny z HoughLinesP. Tu jest mój kodu (Użyłem Pythona, ale myślę, że widać pomysł):

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) 

Rezultat wygląda następująco:

+0

Cześć Andrey, dzięki. Tak, próbowałem HoughLinesP z wieloma różnymi zmiennymi. Poprawiłem moje oryginalne pytanie i umieściłem link do najlepszego obrazu, jaki mogłem uzyskać z HoughLinesP. I tak, próbowałem ograniczać się tylko do linii prawie poziomych. –

+0

Świetnie. Najwyraźniej brakowało mi detektora Canny'ego. To dobry wynik. Znalazłem także algorytm zwany Ortogonalnym Zig-Zag, który może przyjąć podane linie, a następnie rozwinąć je, aby określić również szerokość linii (co jest czymś, czego HoughP nie może zrobić). –

+0

brak średników w python;) – mak

5

Można rozważyć pozostawienie wykrywanie linii Hough Od tego metoda szuka linii "globalnych", niekoniecznie segmentów liniowych. Niedawno zaimplementowałem aplikację, która identyfikuje "równoległoboki" - zasadniczo kwadraty, które mogą być obrócone i perspektywa przed skróceniem ze względu na kąt widzenia. Możesz rozważyć coś podobnego.Moja rurociąg był:

  1. konwersji z RGB do skali szarości (cvCvtColor)
  2. Smooth (cvSmooth)
  3. Threshold (cvThreshold)
  4. wykrywać krawędzie (cvCanny)
  5. Znajdź konturów (cvFindContours)
  6. Przybliżone kontury z funkcjami liniowymi (cvApproxPoly)

W swoim aplikacja, wynikowa lista konturów będzie prawdopodobnie duża (w zależności od "agresywności" wygładzania i funkcji poprawy detektora krawędzi Canny'ego. Możesz wyczyścić tę listę za pomocą różnych parametrów: liczba punktów zwróconych przez wyszukiwarkę konturów, obszar konturu (cvContourArea) itp. Z mojego doświadczenia wynika, że ​​"prawidłowe" linie w twoim zgłoszeniu byłyby dobrze zdefiniowane właściwości licznika powierzchni i wierzchołków. Dodatkowo możesz odfiltrować kontury na podstawie odległości między punktami końcowymi, kąta zdefiniowanego przez linię łączącą punkty końcowe, itp.

W zależności od tego ile masz "czasu" CPU, zawsze możesz sparować algorytm Hough'a z taki algorytm jak powyżej, aby silnie identyfikować linie poziome i pionowe.

8

Jeśli chcesz tylko "linie", a nie "segmenty linii", unikałbym używania Canny, Hough, FindContours lub jakiejkolwiek innej takiej funkcji na wypadek, gdybyś potrzebował większej prędkości w swoim kodzie. Jeśli twoje obrazy nie są obrócone, a to, co chcesz znaleźć, jest zawsze pionowe lub poziome, po prostu użyję cv :: Sobel (jeden dla pionu, a drugi dla poziomego) i utworzę tablice akumulacji dla kolumn i rzędów. Następnie możesz szukać maksimów w takich skupieniach lub profilach, na przykład ustawiając próg, a poznasz wiersz lub kolumnę, w której znajdują się pionowe lub poziome linie krawędzi.

+1

Czy znasz parametry, które należy ustawić dla linii poziomej i pionowej w cv :: sobel? –

4

Nie konwertuj RGB na skalę szarości. Czasami różne kolory w RGB mogą być scalone z tą samą wartością skali szarości, więc może brakować niektórych konturów. Należy przeanalizować każdy z kanałów RGB osobno.

Powiązane problemy