2016-04-13 2 views
12

Je dois détecter la voie de circulation d'une vidéo. Voici ma façon de le faire.Python et OpenCV - Amélioration de mon algorithme de détection de voie

  1. Déterminer en découpant l'image (focus la partie centrale)
  2. Niveaux de gris le retour sur investissement
  3. Equalized le retour sur investissement en niveaux de gris avec cv2.equalizeHist
  4. Appliquer le flou gaussien (3)
  5. la région d'intérêt (ROI)
  6. seuil (4) à l'aide cv2.adaptiveThreshold
  7. squelettisent (5) à l'aide de skimage.morphology.skeletonize
  8. Appliquer le cv2.HoughLines sur (6)

Pour le cv2.HoughLines, je mis en place afin que:

  1. Si rho est positif (ce qui signifie que la ligne droite est en pente vers la droite (bottom-up), il ne tracez la ligne que si elle est à certains angles (j'établis la plage de l'angle))
  2. Si rho est négatif (la ligne droite est inclinée vers la gauche (bottom-up), elle ne tracera la ligne que si elle est est à certains angles)

Ceci est mon code pour dessiner les lignes:

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

Si je ne fais pas ce que je viens de faire ci-dessus pour la fonction cv2.HoughLines, je crois qu'il y aura beaucoup de lignes inutiles tirées. Après avoir réglé les paramètres et autres, j'ai obtenu un très bon résultat, mais pour une seule image. Je ne pense pas que ce soit aussi bon pour une vidéo qui continuera à changer. Ce qui me dérange le plus, c'est mon algorithme pour dessiner les lignes nécessaires (c'est la voie de la route). Y a-t-il une meilleure façon? Au moins mieux que le mien.

Ceci est mon résultat:

L'image originale: The original image

histogramme égalisées, seuillée, et l'image squeletté du ROI: Equalized Histogram, thresholded, and skeletonized

Résultat final: Final result

Répondre

6

Je recommande d'envisager d'utiliser la Transformée probabiliste Hough Line pour votre applicati sur. Dans l'API Python d'OpenCV, elle est implémentée dans la fonction cv2.HoughLinesP. Cela vous donnera réellement des segments de ligne, vous n'aurez donc pas besoin de calculer les points de terminaison. C'est aussi beaucoup plus rapide que la Hough Line Transform standard.

Cependant, il y a quelques compromis. Par exemple, vous devrez peut-être ajouter une logique pour assembler des segments de ligne. D'un autre côté, j'ai trouvé que ce n'était pas vraiment une mauvaise chose. Un de mes projets de jouets (un bus miniature auto-piloté) a utilisé cette approche, et avoir des segments de ligne séparés pour assembler rendait plus facile la gestion de routes courbes dans lesquelles la ligne de transformation standard ne vous donnerait aucune ligne. .

Espérons que ça aide.

EDIT: En ce qui concerne les détails du "segment" de segment de ligne, cela dépend de ce que vous cherchez à accomplir. Si vous voulez juste afficher la route, et que vous êtes satisfait de l'existence de quelques espaces entre les segments de ligne, vous n'aurez peut-être pas besoin de faire de couture - affichez simplement tous les segments de ligne. Dans mon application, j'avais besoin de déterminer la courbure de la voie, donc j'ai fait quelques piqûres pour construire un modèle de chaque voie de route qui inclurait la pente moyenne de la voie - qui a été utilisée comme entrée d'un module chargé de contrôler un servo pour déplacer les roues en conséquence. Par «assemblage», je ne veux rien dire de particulièrement sophistiqué, mais je ne connais aucune fonction particulière d'OpenCV pour l'accomplir. J'avais juste besoin d'un moyen de segments de lignes associés qui faisaient partie de la même voie. J'ai donc traité les segments de ligne renvoyés par HoughLinesP depuis le haut de l'image vers le bas, et utilisé la pente et l'ordonnée à l'origine de chaque segment de ligne pour déterminer l'intersection des segments de ligne.

+0

Comment puis-je 'broder' les lignes? Désolé, toujours un débutant dans la programmation et le traitement d'image. – Hilman

+0

J'ai ajouté quelques notes. Désolé de ne pas fournir de code. C'est en C++, et l'implémentation particulière est très différente de la vôtre - en fait, je n'ai tout simplement pas assez de temps pour l'adapter à votre application. – Aenimated1