Jestem nowy w opencv, zacznij go uczyć przez rozpakowanie char z simple captcha. Po pewnym wysiłku dostałem findContours
i pewna metoda czyszczenia obrazu, czasami działała, ale nie częściej.
Na przykład:
przekonwertować do skali szarości i użyć
cv2.threshold
czysty:posługiwać się
cv2.findContours
aby uzyskać ramki ograniczające:
W
pokrywają tylko połowę, a nie dostają b
.
Mój kod:
from StringIO import StringIO
import string
from PIL import Image
import requests
import cv2
import numpy as np
import matplotlib.pyplot as plt
def get_ysdm_captcha():
url = "http://www.ysdm.net/common/CleintCaptcha"
r = requests.get(url)
img = Image.open(StringIO(r.content))
return img
def scale_image(img, ratio):
return img.resize((int(img.width*ratio), int(img.height*ratio)))
def draw_rect(im):
im = np.array(im)
if len(im.shape) == 3 and im.shape[2] == 3:
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
else:
imgray = im
#plt.imshow(Image.fromarray(imgray), "gray")
pilimg = Image.fromarray(imgray)
ret,thresh = cv2.threshold(imgray,127,255,0)
threimg = Image.fromarray(thresh)
plt.figure(figsize=(4,3))
plt.imshow(threimg, "gray")
plt.xticks([]), plt.yticks([])
contours, hierarchy = cv2.findContours(np.array(thresh),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
areas = []
for c in contours:
rect = cv2.boundingRect(c)
area = cv2.contourArea(c)
areas.append(area)
x,y,w,h = rect
if area > 2000 or area < 200 : continue
cv2.rectangle(thresh,(x,y),(x+w,y+h),(0,255,0),1)
plt.figure(figsize=(1,1))
plt.imshow(threimg.crop((x,y,x+w,y+h)), "gray")
plt.xticks([]), plt.yticks([])
plt.figure(figsize=(10,10))
plt.figure()
plt.imshow(Image.fromarray(thresh), "gray")
plt.xticks([]), plt.yticks([])
image = get_ysdm_captcha()
im = scale_image(image, 3)
im = np.array(im)
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
imgray = cv2.GaussianBlur(imgray,(5,5),0)
# im = cv2.medianBlur(imgray,9)
# im = cv2.bilateralFilter(imgray,9,75,75)
draw_rect(imgray)
Starałem się napisać powyżej kod. Rozwiązania, które wyobrażam sobie:
- znalezisko było do powiedzenia
cv2.findContours
potrzebuję4
pudełka ograniczające w pewnym rozmiarze - wypróbowałem inny parametr (próbowałem wszystkiego z http://docs.opencv.org/2.4/modules/imgproc/doc/structural_analysis_and_shape_descriptors.html?highlight=findcontours#findcontours , ale wciąż nie działa)
Teraz utknąłem, nie mam pojęcia, jak poprawić cv2.findContours
...
Odpowiedzi:
2 dla odpowiedzi № 1Możesz użyć operacji morfologicznych, aby na przykład zmodyfikować swój obraz i wypełnić luki erode
i dilate
Spójrz tutaj: http://docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html
Oryginalny:
Dilated:
Tak poza tym: Zaimplementowałem krok separacji HSV na oryginalnym obrazie, usuwając całą zawartość „biały / szary / czarny” (niskie nasycenie). Zmniejszy to liczbę plamek. Zrób to przed konwersją do skali szarości.
Oto filtrowanie wyników: nasycenie> 90
Wynik końcowy: (Dodano krok rozmycia wcześniej)
Ponadto, jeśli zawsze występuje gradient, można to wykryć i odfiltrować jeszcze więcej kolorów. Ale to trochę za dużo, jeśli właśnie rozpocząłeś przetwarzanie obrazu;)
0 dla odpowiedzi nr 2
findCountours działa poprawnie, ponieważ znajduje wszystkopodłączony komponent twojego obrazu. Twój warunek obszaru prawdopodobnie nie pozwala ci na przykład uzyskać ramki ograniczającej wokół litery b. Oczywiście, jeśli umieścisz obwiednię wokół każdego połączonego komponentu, nie będziesz miał obwiedni wokół każdej postaci, ponieważ masz wiele dziur w literach.
Jeśli chcesz podzielić na części litery, najpierwspróbuj grać z operacjami otwierania (ponieważ twoje litery są czarne na białym tle, byłoby zamykanie, gdyby było odwrotnie), aby wypełnić otwory, które masz w swoich literach. Następnie projektowałem pionowo piksele i analizowałem otrzymany kształt. Jeśli znajdziesz punkty doliny w tym rzutowanym kształcie, otrzymasz pionowe granice między postaciami. Możesz zrobić to samo w poziomie, aby uzyskać górne i dolne granice swoich znaków. Takie podejście działa tylko wtedy, gdy tekst jest poziomy. Jeśli tak nie jest, powinieneś znaleźć główny kąt osi swojego ciągu i odpowiednio obrócić obraz. Aby znaleźć główny kąt osi, możesz dopasować elipsę do tekstu i znaleźć jego główny kąt osi lub możesz obracać obraz o określony kąt, aż do momentu, gdy projekcja pozioma będzie maksymalna.