2016-05-18 24 views
11

Próbuję opracować prostą aplikację na PC do rozpoznawania tablic rejestracyjnych (Java + OpenCV + Tess4j). Obrazy nie są naprawdę dobre (w dalszej kolejności będą dobre). Chcę wstępnie przetworzyć obraz dla tesseract i utknąłem na wykryciu tablicy rejestracyjnej (wykrywanie prostokąta).Przygotowanie obrazu z OpenCV przed wykonaniem rozpoznawania znaków (tesseract)

Moje kroki:

1) Źródło zdjęcia

True Image

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

2) Skala szarości

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

3) Gaussian Blur

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

4) adaptacyjnego progu

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); 

tu będzie 5-te etap, który jest wykrywanie obszarze części płytowej (prawdopodobnie nawet bez pochylenia teraz).

I croped potrzebne region z obrazem (po 4. etapie) z Paint, i otrzymała:

plate region

Potem zrobiłem OCR (poprzez tesserakt, tess4j):

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

i dostał (wystarczająco dobry?) wynik - "Y841ox EH" (prawie prawda)

Jak mogę wykryć i przyciąć region płytki po 4 kroku? Czy muszę wprowadzić pewne zmiany (poprawki) w 1-4 krokach? Chciałbym zobaczyć przykład implementowany przez Javę + OpenCV (nie JavaCV).
Z góry dziękuję.

EDIT (dzięki za odpowiedź @Abdul Fatir) Cóż, zapewniają pracę (dla mnie conajmniej) próbki kodu (Netbeans + Java + OpenCV + Tess4j) dla tych, którzy interesują się tym pytaniem. Kod nie jest najlepszy, ale zrobiłem to tylko dla nauki.
http://pastebin.com/H46wuXWn (nie zapomnij umieścić tessdata folderu do folderu projektu)

+1

Możesz spróbować analizować kontury. Jednak bardziej wiarygodne może być użycie [klasyfikatora kaskadowego] (http://docs.opencv.org/2.4/modules/objdetect/doc/cascade_classification.html) w celu zlokalizowania tablicy rejestracyjnej (przetestuj swój algorytm za pomocą białego samochodu i Zobacz jak to działa). Wyrównaj płytę, aby była horyzontalna. Powinieneś również dodać dodatkową fazę przed tesseract - posegmentuj tablicę rejestracyjną na pojedyncze znaki (projekcja pionowa prawdopodobnie będzie dobrze działać, biorąc pod uwagę jakość twojego obrazu) i karm ją tylko dla tesseract .. –

+0

Czy możesz opublikować zdjęcie po kroku 4 jako dobrze? Myślę, że powinieneś być w stanie wykryć granicę płyty poprzez wyodrębnianie konturów i filtrowanie ich na rozmiarze i proporcji h/w. Jeśli masz kontur (ponieważ wiesz, że jest to prostokąt, możesz cofnąć przekształcenie rzutowania) – RobAu

+0

@RobAu, Tak, oczywiście: http://i.imgur.com/chrNMYX.png – DocC

Odpowiedz

6

Oto jak sugeruję, należy wykonać to zadanie.

  1. Konwersja do skali szarości.
  2. Rozmycie gaussowskie z filtrem 3x3 lub 5x5.
  3. Zastosuj filtr Sobel, aby znaleźć pionowe krawędzie.

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

  4. Próg wynikowy obraz, aby uzyskać obraz binarny.
  5. Zastosuj zamknięcie morfologiczne za pomocą odpowiedniego elementu strukturyzującego.
  6. Znajdź kontury wynikowego obrazu.
  7. Znajdź minAreaRect każdego konturu. Wybierz prostokąty na podstawie współczynnika kształtu i obszaru minimalnego i maksymalnego.
  8. Dla każdego wybranego konturu znajdź gęstość krawędzi. Ustaw próg dla gęstości krawędzi i wybierz prostokąty naruszające ten próg jako możliwe obszary płyt.
  9. Po tym pozostanie niewiele prostokątów. Możesz je filtrować według orientacji lub dowolnych kryteriów, które uznasz za stosowne.
  10. Po usunięciu zaznaczonych prostokątnych części obrazu po adaptiveThreshold zastosuj OCR.

a) Wynik po etapie 5

Result after Step 5

b) wynik po Etap 7. zielone są wszystkie minAreaRect S i czerwone są te, które spełniają następujące kryteria: Zakres proporcji (2,12) & zasięg (300,10000)

c) Wynik po kroku 9. Wybrany prostokąt. Kryteria: Gęstość krawędź> 0,5

enter image description here

EDIT

krawędziowo gęstości, to, co miało miejsce w przykładach powyżej jest następujące.

  1. Zastosuj detektor Canny Edge bezpośrednio do obrazu wejściowego. Niech obraz cannyED będzie Ic.
  2. Pomnóż wyniki filtra Sobel i Ic. Zasadniczo, weź obraz ORAB i Sobny.
  3. Gaussian Zamaż wynikowy obraz z dużym filtrem. Użyłem 21x21.
  4. Próg uzyskanego obrazu za pomocą metody OTSU. Dostaniesz obraz binarny. Dla każdego czerwonego prostokąta przekręć część wewnątrz tego prostokąta (na obrazie binarnym), aby była wyprostowana. Przeprowadź pętlę przez piksele prostokąta i zliczaj białe piksele. (How to rotate?)

Gęstość krawędzi = liczba białych pikseli w prostokącie/suma nr.Pikseli w prostokącie

  1. Wybierz próg dla gęstości krawędzi.

UWAGA: Zamiast przeżywa krokach od 1 do 3, można również skorzystać z obrazu binarnego z etapu 5 do obliczania gęstości krawędzi.

+0

Niż za tak szczegółową odpowiedź! Zrobiłem wszystko, co opisałeś oprócz kroku "c", który jest "gęstością krawędzi". Do tego etapu algorytm działał dobrze - trochę grałem z progami i wskaźnikami (dzięki "Mastering OpenCV Rozdział 5" https://github.com/MasteringOpenCV/code/blob/master/Chapter5_NumberPlateRecognition/DetectRegions.cpp w szczególności "verifySizes" funkcja) i dla niektórych zdjęć działało wystarczająco dobrze bez kryteriów Edge Density. Czy możesz wyjaśnić, w jaki sposób mogę sprawdzić RotatedRec (który jest podany przez _minAreaRect_) dla kryteriów Edge Density? – DocC

+0

Cześć! Sprawdź edytowaną odpowiedź. Proszę wznowić i oznaczyć jako odpowiedź, jeśli działa ona dla Ciebie. :) –

+0

Tak, pominąłem 1-4 kroki (z ** Edit ** paragraph) i zmusiłem do kroku 5. Przycinałem każdy otrzymany prostokąt (zwykle są to 1-3 "możliwe" płytki) z obrazu (_adaptiveThreshold_ Mat object) . Następnie liczę się z białymi pikselami (_countNoZero_) i całkowitą ilością pikseli; ma gęstość (> = ~ 0.6 ++ gęstość jest dobra) i potrzebny prostokąt. Tesseract dobrze się spisał (myślę, że podzielę każdą indywidualną postać na tabliczkę, by lepiej ją rozpoznać, np. @Dan). – DocC

1
  • znaleźć wszystkie podłączone komponenty (białe obszary) oraz określenia ich zarys.
  • Jeśli filtrujesz je w oparciu o rozmiar (jako część obrazu), stosunek (szerokość-wysokość) i stosunek bieli/czerni do pobierania kandydujących płyt.
  • Cofnij transformacja prostokąta
  • wyjąć śruby
  • Pass w obrazie do silnika OCR.
2

Właściwie OpenCV ma wstępnie przeszkoleni specjalnie dla modelu tablic rejestracyjnych rosyjskich: haarcascade_russian_plate_number

Ponadto istnieje projekt ANPR open source dla tablic rejestracyjnych rosyjskich: plate_recognition. To nie jest użycie tesseract, ale ma dość dobrze wcześniej wyszkoloną sieć neuronową.

+0

Cóż, dziękuję za odpowiedź. Widziałem już ten projekt - jest dobry, ale dużo C++ i QT (nie jestem w tym dobry). Domyślam się, że kadrowanie każdego symbolu z płyty (która jest wykryta przez kaskadę) i przekazanie jej do silnika tesseract również może działać i jest łatwe do zrobienia przy pomocy Javy. Chciałbym interpetować ten projekt C++ (lub powiązać JNI) dla Javy, ale nie mam teraz zbyt wiele czasu. – DocC