2016-04-30 17 views
6

Robię wykrywanie ucznia dla mojego projektu szkolnego. Pierwszy raz pracuję z OpenCV i Pythonem, używając Pythona w wersji 3.4.2 i OpenCV 3.1.0.wykrywanie ucznia w OpenCV & Python

Używam kamery Noir Raspberry Pi i otrzymuję dobre obrazy. .

ale nie mogę wykryć ucznia ładnie (ze względu na błysk, rzęs i cienie odsyłam do pewnego kodu w internecie i po to część tego kodu

... 

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) 

# capture frames from the camera 
for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True): 

    image = frame.array 
    cv2.imshow("image", image) 


    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 
    retval, thresholded = cv2.threshold(gray, 80, 255, 0) 
    cv2.imshow("threshold", thresholded) 

    closed = cv2.erode(cv2.dilate(thresholded, kernel, iterations=1), kernel, iterations=1) 
    #closed = cv2.morphologyEx(close, cv2.MORPH_CLOSE, kernel) 

    cv2.imshow("closed", closed) 

    thresholded, contours, hierarchy = cv2.findContours(closed, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) 

    drawing = np.copy(image) 
    cv2.drawContours(drawing, contours, -1, (255, 0, 0), 2) 

    for contour in contours: 

     area = cv2.contourArea(contour) 
     bounding_box = cv2.boundingRect(contour) 

     extend = area/(bounding_box[2] * bounding_box[3]) 

     # reject the contours with big extend 
     if extend > 0.8: 
      continue 

     # calculate countour center and draw a dot there 
     m = cv2.moments(contour) 
     if m['m00'] != 0: 
      center = (int(m['m10']/m['m00']), int(m['m01']/m['m00'])) 
      cv2.circle(drawing, center, 3, (0, 255, 0), -1) 

     # fit an ellipse around the contour and draw it into the image 
     try: 
      ellipse = cv2.fitEllipse(contour) 
      cv2.ellipse(drawing, box=ellipse, color=(0, 255, 0)) 
     except: 
      pass 

    # show the frame 
    cv2.imshow("Drawing", drawing) 

    ... 

obrazu wejściowego.: obraz

enter image description here

wyjściowa:

enter image description here

Jak usunąć części obrazu, które nie są związane ze źrenicą, jak pokazano powyżej?

Oprócz odpowiedzi, wszelkie wskazówki są również mile widziane.

+0

pokrewne [Przyspieszenie vectorized algorytm śledzenia oczu w numpy] (https://stackoverflow.com/questions/35996257/speeding-up-vectorized-eye-tracking-algorithm-in-numpy) . Możesz także sprawdzić, czy nie ma kolizji ([przykładowy kod] (https://github.com/Itseez/opencv/blob/3.1.0/modules/features2d/src/blobdetector.cpp#L222)). – Catree

+0

Inne opcje: wykryj bezpośrednio koło za pomocą [HoughCircles] (http://docs.opencv.org/3.1.0/dd/d1a/group__imgproc__feature.html#ga47849c3be0d0406ad3ca45db65a25d2d) i/lub zachowaj kontur, jeśli obszar wewnątrz jest ciemniejszy niż na zewnątrz. Jeśli oko jest zawsze wyśrodkowane i znajduje się w tej samej odległości, możesz również zdefiniować obszar zainteresowania (ROI) + korzystać z tego obszaru. – Catree

+0

Chciałbym użyć [erode] (http://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html?highlight=erode#erode) na obrazie binarnym, a następnie po prostu [HoughCircles] (http: //docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_circle/hough_circle.html) w celu wykrycia najbardziej znaczącego okręgu na obrazie. – 0x90

Odpowiedz

4

Jest kilka rzeczy, które możesz zrobić. To, jak dobrze działają, zależy od tego, jaka jest różnica w obrazach, na których chcesz zastosować algorytm. Możesz dokonać kilku założeń, a następnie odrzucić wszystkich kandydatów, którzy ich nie spełniają.

usunąć małe wykrycia

Na początku chciałbym rozważyć usunięcie kandydatów, które są zbyt małe, dodając tę ​​linię na początku swojej pętli:

if area < 100: 
    continue 

Próg został wybrany losowo i działa dobrze dla tego określony obraz. Usunięto prawie wszystkie fałszywe wykrycia. Pozostaje tylko największy. Ale musisz sprawdzić to na tle innych obrazów i dostosować je do swoich potrzeb.

enter image description here

usunąć wskazania, które nie są okrągłe

Kolejnym założeniem można zrobić jest to, że uczniowie są zwykle okrągłe i można usunąć każdy wykrywanie, że nie jest wystarczająco „okrągłe”. Prostą miarą okrągłości jest spojrzenie na stosunek obwodu do obszaru.

circumference = cv2.arcLength(contour,True) 
circularity = circumference ** 2/(4*math.pi*area) 

Okrągłość wynosi około 2,72 dla cienia z prawej strony i 1,31 dla źrenicy.

poprawy okrągłości

Można zauważyć, że kontur swojego ucznia nie jest idealnie okrągły z powodu odbicia. Możesz to poprawić, obliczając wypukły kadłub konturów.

contour = cv2.convexHull(contour) 

Jeśli zrobisz to przed obliczeniem obszaru i obwodu, otrzymasz wartości kołowe o wartości 1,01 i 1,37. (Idealne koło ma kołowość 1) Oznacza to, że defekt z odbicia został niemal idealnie naprawiony. To może nie być konieczne w tym przypadku, ale może być użyteczne w przypadku większej liczby refleksów.

enter image description here

+0

dzięki! ustawiam ograniczoną cyrkulację 1.1 i działam ładnie. Chcę uczynić ten projekt "w czasie rzeczywistym". ze względu na morfologię (moim zdaniem) FPS staje się coraz mniejszy, gdy rozmiar jądra staje się większy. czy mogę poprawić wydajność morfologiczną? –