2016-04-13 11 views
12

Muszę wykryć pas drogowy z wideo. Oto mój sposób robienia tego.Python i OpenCV - Poprawa algorytmu wykrywania pasa ruchu

  1. Ustalanie obszaru zainteresowania (ROI) przez cięcie obrazu (Focus środkową część)
  2. Grayscale ROI
  3. wyrówna³o grayscaled ROI z cv2.equalizeHist
  4. Zastosuj Gaussian blur do (3)
  5. progową (4) za pomocą cv2.adaptiveThreshold
  6. szkieletować (5) za pomocą skimage.morphology.skeletonize
  7. Zastosować cv2.HoughLines na (6)

Dla cv2.HoughLines, założyłem więc, że:

  1. Jeśli rho jest dodatni (co oznacza, że ​​linia prosta jest nachylona w prawo (bottom-up), to będzie narysuj linię tylko pod pewnymi kątami (ustawiłem zakres kąta))
  2. Jeśli rho jest ujemny (linia prosta jest nachylona w lewo (od dołu do góry), narysuje tylko linię, jeśli pod pewnymi kątami)

To jest mój kod do rysowania linii:

lines = cv2.HoughLines(image_bin, 1, np.pi/180, 50) 
    try: 
     range = lines.shape[0] 
    except AttributeError: 
     range = 0 

    for i in xrange(range): 
     for rho, theta in lines[i]: 
      if rho > 0 and (np.pi*1/10 < theta < np.pi*4/10): 
       a = np.cos(theta) 
       b = np.sin(theta) 
       x0 = a * rho 
       y0 = b * rho 
       x1 = int(x0 + 1000 * (-b)) 
       y1 = int(y0 + 1000 * (a)) 
       x2 = int(x0 - 1000 * (-b)) 
       y2 = int(y0 - 1000 * (a)) 

       cv2.line(roi, (x1, y1), (x2, y2), (0, 255, 0)) 

      if rho < 0 and (np.pi*7/10 < theta < np.pi*9/10): 
       a = np.cos(theta) 
       b = np.sin(theta) 
       x0 = a * rho 
       y0 = b * rho 
       x1 = int(x0 + 1000 * (-b)) 
       y1 = int(y0 + 1000 * (a)) 
       x2 = int(x0 - 1000 * (-b)) 
       y2 = int(y0 - 1000 * (a)) 

       cv2.line(roi, (x1, y1), (x2, y2), (0, 255, 0)) 

Gdybym tego nie zrobił, co właśnie zrobiłem powyżej funkcji cv2.HoughLines, wierzę, że będzie dużo niepotrzebnych liniami.

Po dostosowaniu parametrów i tak, mam całkiem dobry wynik, ale jest to tylko jedno zdjęcie. Nie sądzę, że będzie to dobre dla filmu, który będzie się ciągle zmieniać. Co przeszkadza mi najbardziej, to mój algorytm do rysowania potrzebnych linii (to jest drogi). Czy istnieje lepszy sposób? Co najmniej lepsze niż moje.

To jest mój wynik:

oryginalnego obrazu: The original image

Równa histogram, progowaniu i szkiele- obraz ROI: Equalized Histogram, thresholded, and skeletonized

wynik końcowy: Final result

Odpowiedz

6

Polecam, biorąc pod uwagę użycie probabilistycznej transformacji linii twardej do twoich zastosowań na. W Pythonie API OpenCV zaimplementowano go w funkcji, cv2.HoughLinesP. To faktycznie da ci segmenty linii, więc nie będziesz musiał obliczać punktów końcowych. Jest także znacznie szybszy niż standardowa transformacja linii Hough.

Istnieje jednak kilka kompromisów. Na przykład może być konieczne dodanie logiki, aby połączyć razem segmenty linii. Z drugiej strony, stwierdziłem, że to nie jest takie złe. Jeden z moich zabawkowych projektów (miniaturowy autobus z własnym napędem) wykorzystał to podejście i mając oddzielne segmenty linii do połączenia razem, łatwiej było sobie poradzić z zakrzywionymi drogami, w których standardowa transformacja linii hough nie daje żadnych linii w ogóle .

Nadzieję, że pomaga.

EDYCJA: Odnośnie szczegółów "szwy" segmentu linii, zależy to od tego, co chcesz osiągnąć. Jeśli chcesz wyświetlić drogę i jesteś zadowolony z faktu, że między segmentami linii występują luki, nie musisz wykonywać żadnych szwów - wystarczy wyświetlić wszystkie segmenty linii. W mojej aplikacji musiałem określić krzywiznę linii, więc wykonałem kilka szwów, aby zbudować model każdego pasa drogowego, który obejmowałby średnie nachylenie linii - który był używany jako wejście do modułu odpowiedzialnego za sterowanie servo, aby odpowiednio przesunąć koła.

Przez "szycie" nie mam na myśli niczego szczególnie wyrafinowanego, ale nie znam żadnych szczególnych funkcji OpenCV, aby to osiągnąć. Po prostu potrzebowałem sposobu powiązanych segmentów linii, które były częścią tego samego pasa. Przetworzyłem więc segmenty linii zwrócone od HoughLinesP od góry obrazu pracującego w dół i wykorzystałem nachylenie i interlinię każdego segmentu linii, aby określić, gdzie będą przecinać się odcinki linii.

+0

Jak mogę "zszyć" linie? Niestety, wciąż początkujący zarówno w programowaniu, jak i przetwarzaniu obrazów. – Hilman

+0

Dodałem kilka notatek. Przepraszam, że nie podałem żadnego kodu. Jest w C++, a konkretna implementacja bardzo różni się od twojej - po prostu nie mam wystarczająco dużo czasu, aby dostosować ją do twojej aplikacji. – Aenimated1

Powiązane problemy