Próbuję znaleźć obwiednie tekstu na obrazie i obecnie stosuję następujące podejście:
// calculate the local variances of the grayscale image
Mat t_mean, t_mean_2;
Mat grayF;
outImg_gray.convertTo(grayF, CV_32F);
int winSize = 35;
blur(grayF, t_mean, cv::Size(winSize,winSize));
blur(grayF.mul(grayF), t_mean_2, cv::Size(winSize,winSize));
Mat varMat = t_mean_2 - t_mean.mul(t_mean);
varMat.convertTo(varMat, CV_8U);
// threshold the high variance regions
Mat varMatRegions = varMat > 100;
Gdy dostaniesz taki obraz:
Następnie, kiedy pokażę varMatRegions
, otrzymuję ten obraz:
Jak widać, w pewnym stopniu łączy lewy blok tekstu z nagłówkiem karty, dla większości kart ta metoda działa świetnie, ale na bardziej zajętych kartach może powodować problemy.
Powodem, dla którego te kontury są złe, jest to, że powoduje, że obwiednia konturu prawie zajmuje całą kartę.
Czy ktoś może zasugerować inny sposób znajdowania tekstu, aby zapewnić prawidłowe wykrywanie tekstu?
200 punktów dla każdego, kto znajdzie tekst na karcie powyżej tych dwóch.
c++
opencv
image-processing
text
bounding-box
Spinacz
źródło
źródło
Odpowiedzi:
Możesz wykryć tekst, znajdując elementy o bliskiej krawędzi (inspirowane LPD):
Stosowanie:
Wyniki:
za. element = getStruifyingElement (cv :: MORPH_RECT, cv :: Size (17, 3));
b. element = getStruifyingElement (cv :: MORPH_RECT, cv :: Size (30, 30));
Wyniki są podobne dla drugiego wymienionego obrazu.
źródło
n
? Dzięki za rozwiązanie działa świetnie!cv::Rect a;
. Powiększona o n:a.x-=n/2;a.y-=n/2;a.width+=n;a.height+=n;
.Użyłem metody opartej na gradiencie w poniższym programie. Dodano powstałe obrazy. Zwróć uwagę, że używam zmniejszonej wersji obrazu do przetwarzania.
wersja c ++
wersja Pythona
źródło
rect
. Jest jeszcze jednapyrdown
, więc pomnożyćx, y, width, height
zrect
przez 4.Oto alternatywne podejście, którego użyłem do wykrywania bloków tekstu:
Poniżej znajduje się kod napisany w Pythonie z pyopencv, powinien być łatwy do przeniesienia do C ++.
Oryginalny obraz to pierwszy obraz w Twoim poście.
Po wstępnym przetworzeniu (skala szarości, próg i dylatacja - czyli po kroku 3) obraz wyglądał następująco:
Poniżej znajduje się obraz wynikowy („contoured.jpg” w ostatnim wierszu); końcowe obwiednie obiektów na obrazku wyglądają następująco:
Możesz zobaczyć, że blok tekstu po lewej stronie jest wykrywany jako oddzielny blok, oddzielony od otoczenia.
Używając tego samego skryptu z tymi samymi parametrami (z wyjątkiem typu progowania, który został zmieniony dla drugiego obrazu, jak opisano poniżej), oto wyniki dla pozostałych 2 kart:
Dostrajanie parametrów
Parametry (wartość progowa, parametry dylatacji) zostały zoptymalizowane dla tego obrazu i tego zadania (znajdowanie bloków tekstu) i można je w razie potrzeby dostosować do innych obrazów kart lub innych typów obiektów.
Do progowania (krok 2) użyłem czarnego progu. W przypadku obrazów, na których tekst jest jaśniejszy niż tło, takich jak drugi obraz w Twoim poście, należy użyć białego progu, więc zastąp tekst typu sholding na
cv2.THRESH_BINARY
). Dla drugiego obrazu również zastosowałem nieco wyższą wartość progu (180). Zmiana parametrów wartości progowej i liczby iteracji dylatacji będzie skutkowała różnymi stopniami czułości przy wyznaczaniu obiektów na obrazie.Znajdowanie innych typów obiektów:
Na przykład zmniejszenie rozszerzenia do 5 iteracji na pierwszym obrazie daje nam dokładniejsze rozgraniczenie obiektów na obrazie, z grubsza znajdując wszystkie słowa na obrazie (zamiast bloków tekstu):
Znając przybliżony rozmiar słowa, tutaj odrzuciłem obszary, które były zbyt małe (poniżej 20 pikseli szerokości lub wysokości) lub zbyt duże (powyżej 100 pikseli szerokości lub wysokości), aby zignorować obiekty, które prawdopodobnie nie są słowami, aby uzyskać wyniki w powyższy obraz.
źródło
cv2.findContours
. MówiValueError: too many values to unpack
.cv2.findContours
zwraca 3 argumenty, a oryginalny kod przechwytuje tylko 2.Podejście @ dhanushka okazało się najbardziej obiecujące, ale chciałem pobawić się w Pythonie, więc poszedłem do przodu i przetłumaczyłem to dla zabawy:
Teraz, aby wyświetlić obraz:
Nie jest to najbardziej Pythonic ze skryptów, ale starałem się jak najbardziej przypominać oryginalny kod C ++, aby czytelnicy mogli go śledzić.
Działa prawie tak dobrze, jak oryginał. Z przyjemnością przeczytam sugestie, jak można to ulepszyć / naprawić, aby w pełni przypominać oryginalne wyniki.
źródło
drawContours
tego stanu „Funkcja rysuje kontury na obrazie, jeśli grubość> 0 lub wypełnia obszar ograniczony konturami, jeśli grubość <0”. Zrobiono to, abyśmy mogli sprawdzić stosunek niezerowych pikseli, aby zdecydować, czy pole prawdopodobnie zawiera tekst.Możesz wypróbować tę metodę opracowaną przez Chucai Yi i Yingli Tian.
Współdzielą również oprogramowanie (które jest oparte na Opencv-1.0 i powinno działać na platformie Windows), z którego możesz korzystać (chociaż nie ma dostępnego kodu źródłowego). Wygeneruje wszystkie pola ograniczające tekst (pokazane w cieniach kolorów) na obrazie. Stosując się do przykładowych obrazów, uzyskasz następujące wyniki:
Uwaga: aby wynik był bardziej wytrzymały, możesz dodatkowo scalić ze sobą sąsiednie pola.
Aktualizacja: Jeśli Twoim ostatecznym celem jest rozpoznanie tekstów na obrazie, możesz dalej wypróbować gttext , który jest darmowym oprogramowaniem OCR i narzędziem Ground Truthing dla kolorowych obrazów z tekstem. Dostępny jest również kod źródłowy.
Dzięki temu możesz uzyskać rozpoznane teksty, takie jak:
źródło
Powyższa wersja kodu JAVA: Dzięki @William
I użyj tego kodu w praktyce:
źródło
Implementacja Pythona dla rozwiązania @ dhanushka:
źródło
To jest wersja C # odpowiedzi z dhanushka przy użyciu OpenCVSharp
źródło
to jest wersja VB.NET odpowiedzi z dhanushka przy użyciu EmguCV .
Kilka funkcji i struktur w EmguCV wymaga innego rozważenia niż wersja C # z OpenCVSharp
źródło