2016-04-13 23 views
12

Devo rilevare la corsia stradale da un video. Ecco il mio modo di farlo.Python e OpenCV - Miglioramento dell'algoritmo di rilevamento corsia

  1. Determinare la regione di interesse (ROI) da affettare l'immagine (che si concentra la parte centrale)
  2. scala di grigi il ROI
  3. equalizzato il ROI scala di grigi con cv2.equalizeHist
  4. Applicare sfocatura gaussiana a (3)
  5. Threshold (4) utilizzando cv2.adaptiveThreshold
  6. skeletonize (5) utilizzando skimage.morphology.skeletonize
  7. Applicare il 012.su (6)

Per la cv2.HoughLines, ho regolato in modo che:

  1. Se rho è positivo (cioè la retta è inclinata verso destra (bottom-up), sarà disegnare la linea solo se si trova a determinati angoli (ho impostato il raggio dell'angolo))
  2. Se rho è negativo (la linea retta è inclinata a sinistra (dal basso verso l'alto), essa disegna la linea solo se è ad alcuni angoli)

Questo è il mio codice per disegnare le linee:

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)) 

Se non ho fatto quello che ho appena fatto in precedenza per la funzione cv2.HoughLines, credo che ci saranno un sacco di linee disegnate non necessari.

Dopo aver regolato i parametri e così via, ho ottenuto un risultato abbastanza buono, ma questo vale per una sola immagine. Non penso che andrà bene per un video che continuerà a cambiare. Quello che mi infastidisce di più è il mio algoritmo per disegnare le linee necessarie (cioè la corsia). C'è un modo migliore? Almeno meglio del mio.

Questo è il mio risultato:

L'immagine originale: The original image

equalizzato istogramma, thresholded, e l'immagine scheletrato del ROI: Equalized Histogram, thresholded, and skeletonized

Risultato finale: Final result

risposta

6

Ti consiglierei di prendere in considerazione l'utilizzo della Trasformazione della linea Hough probabilistica per la tua applicazione sopra. Nell'API Python di OpenCV, è implementato nella funzione, cv2.HoughLinesP. In questo modo fornirai segmenti di linea in modo da non dover calcolare gli endpoint. È anche molto più veloce della trasformazione Hough Line standard.

Ci sono alcuni compromessi però. Ad esempio, potrebbe essere necessario aggiungere la logica per unire i segmenti di linea. D'altra parte, ho scoperto che non è davvero una brutta cosa. Uno dei miei progetti di giocattoli (un bus miniaturizzato autoguidato), ha utilizzato questo approccio, e avendo segmenti di linea separati da ricucire insieme ha reso più facile affrontare strade curve in cui la trasformazione della linea di taglio standard non ti darà alcuna linea .

Spero che questo aiuti.

MODIFICA: Riguardo ai dettagli del segmento di linea "cuciture", dipende da ciò che si sta cercando di realizzare. Se vuoi solo visualizzare la strada, e sei soddisfatto del fatto che ci siano degli spazi tra i segmenti di linea, potresti non aver bisogno di fare alcuna cucitura - basta visualizzare tutti i segmenti della linea. Nella mia applicazione, avevo bisogno di determinare la curvatura della corsia, quindi ho fatto alcune cuciture per costruire un modello di ogni corsia che includesse la pendenza media della corsia - che è stato usato come input per un modulo responsabile del controllo di un servo per spostare le ruote di conseguenza.

Con "stitching" non intendo nulla di particolarmente sofisticato, ma non sono a conoscenza di particolari funzioni di OpenCV per realizzarlo. Avevo solo bisogno di un modo di segmenti di linea associati che facevano parte della stessa corsia. Quindi ho elaborato i segmenti di linea restituiti da HoughLinesP dalla parte superiore dell'immagine in modo che procedessero verso il basso e utilizzato la pendenza e l'intercetta di ciascun segmento di linea per determinare dove i segmenti di linea si intersecherebbero.

+0

Come posso "cucire" le linee? Scusa, sono ancora un principiante sia nella programmazione che nell'elaborazione delle immagini. – Hilman

+0

Ho aggiunto alcune note. Ci scusiamo per non aver fornito alcun codice. È in C++ e la particolare implementazione è molto diversa dalla tua, in pratica non ho abbastanza tempo per adattarla alla tua applicazione. – Aenimated1