Jaki jest najlepszy sposób na wykrycie narożników faktury / paragonu / kartki papieru na zdjęciu? Ma to służyć do późniejszej korekty perspektywy, przed OCR.
Moje obecne podejście jest następujące:
RGB> Gray> Canny Edge Detection with proging> Dilate (1)> Remove small objects (6)> clear border objects> pick larges Blog based on Convex Area. > [wykrywanie narożników - nie zaimplementowano]
Nie mogę pomóc, ale myślę, że musi istnieć bardziej solidne, „inteligentne” / statystyczne podejście do obsługi tego typu segmentacji. Nie mam wielu przykładów szkoleniowych, ale prawdopodobnie mógłbym zebrać razem 100 zdjęć.
Szerszy kontekst:
Używam Matlaba do prototypowania i planuję wdrożenie systemu w OpenCV i Tesserect-OCR. Jest to pierwszy z wielu problemów związanych z przetwarzaniem obrazu, które muszę rozwiązać dla tej konkretnej aplikacji. Dlatego chcę rozwinąć własne rozwiązanie i ponownie zapoznać się z algorytmami przetwarzania obrazu.
Oto przykładowy obraz, który powinien obsługiwać algorytm: Jeśli chcesz podjąć wyzwanie, duże obrazy znajdują się pod adresem http://madteckhead.com/tmp
(źródło: madteckhead.com )
(źródło: madteckhead.com )
(źródło: madteckhead.com )
(źródło: madteckhead.com )
W najlepszym przypadku daje to:
(źródło: madteckhead.com )
(źródło: madteckhead.com )
(źródło: madteckhead.com )
Jednak łatwo zawodzi w innych przypadkach:
(źródło: madteckhead.com )
(źródło: madteckhead.com )
(źródło: madteckhead.com )
Z góry dziękuję za wszystkie świetne pomysły! Tak kocham!
EDYCJA: Hough Transform Progress
P: Jaki algorytm grupowałby linie kresek, aby znaleźć narożniki? Zgodnie z radami zawartymi w odpowiedziach udało mi się użyć transformacji Hough, wybrać linie i je filtrować. Moje obecne podejście jest raczej surowe. Założyłem, że faktura będzie zawsze mniej niż 15 stopni odbiegająca od obrazu. W takim przypadku otrzymuję rozsądne wyniki dla linii (patrz poniżej). Ale nie jestem całkowicie pewien odpowiedniego algorytmu do grupowania linii (lub głosowania) w celu ekstrapolacji na rogi. Linie Hougha nie są ciągłe. A na zaszumionych obrazach mogą występować równoległe linie, więc wymagana jest pewna forma lub metryka początku linii. Jakieś pomysły?
(źródło: madteckhead.com )
źródło
Odpowiedzi:
Jestem przyjacielem Martina, który pracował nad tym na początku tego roku. To był mój pierwszy projekt kodowania i skończył się trochę w pośpiechu, więc kod wymaga jakiegoś błędu ... dekodowania ... Dam kilka wskazówek na temat tego, co już widziałem, a potem posortuj mój kod w jutrzejszy dzień wolny.
Pierwsza wskazówka
OpenCV
ipython
są świetne, przejdź do nich jak najszybciej. :REZamiast usuwać małe obiekty i / lub szum, zmniejsz sprytne ograniczenia, aby akceptował więcej krawędzi, a następnie znajdź największy zamknięty kontur (w użyciu OpenCV
findcontour()
z kilkoma prostymi parametrami, myślę, że użyłemCV_RETR_LIST
). może nadal walczyć, gdy jest na białej kartce papieru, ale zdecydowanie zapewniał najlepsze wyniki.W przypadku
Houghline2()
Transform, spróbuj z the,CV_HOUGH_STANDARD
a nie z theCV_HOUGH_PROBABILISTIC
, da to wartości rho i theta , definiując linię we współrzędnych biegunowych, a następnie możesz zgrupować linie z pewną tolerancją.Moje grupowanie działało jako tabela przeglądowa, dla każdej linii wyprowadzonej z transformacji hough dałoby to parę rho i theta. Jeśli te wartości mieściły się w, powiedzmy, 5% pary wartości w tabeli, zostały odrzucone, a jeśli były poza tymi 5%, do tabeli został dodany nowy wpis.
Możesz wtedy znacznie łatwiej przeprowadzić analizę równoległych linii lub odległości między liniami.
Mam nadzieję że to pomoże.
źródło
Grupa studentów na moim uniwersytecie niedawno zademonstrowała aplikację na iPhone'a (i aplikację Python OpenCV), którą napisali właśnie w tym celu. O ile pamiętam, kroki wyglądały mniej więcej tak:
Wydawało się, że działa to całkiem dobrze i byli w stanie zrobić zdjęcie kartki papieru lub książki, wykonać wykrywanie narożników, a następnie zmapować dokument na obrazie na płaską płaszczyznę w czasie prawie rzeczywistym (była jedna funkcja OpenCV do wykonania mapowanie). Kiedy zobaczyłem, że działa, nie było OCR.
źródło
Oto, co wymyśliłem po krótkich eksperymentach:
Nie jest idealny, ale działa przynajmniej dla wszystkich próbek:
źródło
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)
Zamiast rozpoczynać od wykrywania krawędzi, możesz użyć wykrywania narożników.
W tym celu Marvin Framework zapewnia implementację algorytmu Moravec. Punktem wyjścia mogą być rogi dokumentów. Poniżej wyników algorytmu Moraveca:
źródło
Możesz także użyć MSER (Maksymalnie stabilne regiony ekstremalne) nad wynikiem operatora Sobela, aby znaleźć stabilne obszary obrazu. Dla każdego regionu zwróconego przez MSER można zastosować wypukłe kadłub i aproksymację poli, aby uzyskać takie:
Ale ten rodzaj wykrywania jest przydatny do wykrywania na żywo więcej niż pojedynczego obrazu, który nie zawsze daje najlepszy wynik.
źródło
Po wykryciu krawędzi użyj Transformacji Hougha. Następnie umieść te punkty w SVM (wspomagającej maszynie wektorowej) z ich etykietami, jeśli przykłady mają na nich gładkie linie, SVM nie będzie miał trudności z podzieleniem niezbędnych części przykładu i innych części. Moja rada dotycząca SVM, podaj parametr taki jak łączność i długość. Oznacza to, że jeśli punkty są połączone i długie, prawdopodobnie będą to linia paragonu. Następnie możesz wyeliminować wszystkie pozostałe punkty.
źródło
Tutaj masz kod @Vanuan w C ++:
źródło
std::vector<cv::Vec4i> lines;
jest zadeklarowany w zakresie globalnym w moim projekcie.Konwertuj na przestrzeń laboratoryjną
Użyj klastra kmeans segment 2
źródło