/ / opencv findContours brakuje jakiegoś obszaru. [nie wszystkie poprawne ramki ograniczające] - python, opencv, przetwarzanie obrazu, ekstrakt, rozpoznawanie obrazów

opencv findContours brakuje jakiegoś obszaru. [nie wszystkie poprawne ramki ograniczające] - python, opencv, przetwarzanie obrazu, wyciąg, rozpoznawanie obrazów

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:

  1. Mam oryginalny obraz (już skalowany do dużego rozmiaru): wprowadź opis obrazu tutaj

  2. przekonwertować do skali szarości i użyć cv2.threshold czysty: wprowadź opis obrazu tutaj

  3. posługiwać się cv2.findContours aby uzyskać ramki ograniczające:

wprowadź opis obrazu tutaj 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:

  1. znalezisko było do powiedzenia cv2.findContours potrzebuję 4 pudełka ograniczające w pewnym rozmiarze
  2. 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 № 1

Moż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:

wprowadź opis obrazu tutaj

Dilated:

wprowadź opis obrazu tutaj

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 wprowadź opis obrazu tutaj

Wynik końcowy: (Dodano krok rozmycia wcześniej)

wprowadź opis obrazu tutaj

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.