Outils pour utilisateurs

Outils du site


diy:projets:approximationvitesse

Ceci est une ancienne révision du document !


Approximation de vitesse en Python

Idée générale

Avec ce nouveau projet, nous allons estimer la vitesse d'un objet se déplaçant perpendiculairement à la caméra de notre Raspberry à une distance donnée, comme illustré par le schéma ci-dessous.

Pour estimer cette vitesse, nous aurons besoin de:

  • mesurer le déplacement d'un objet en pixels entre deux images capturées par la caméra.
  • calculer à partir de ce déplacement et de la distance “caméra/trajectoire” la vitesse qu'on cherche.

Mesure du déplacement

Pour mesurer le déplacement, on va utiliser de la détection de mouvement.

Pour cette partie du projet, je vous recommande de consulter ce site pour des détails précis sur l'implémentation, mais vous allez voir, l'idée est simple.

On va simplement prendre une image de référence et à partir des différences qu'on observera avec les nouvelles images, on déduira la nouvelle position de notre objet.

# Notre image de référence 
firstFrame = cv2.cvtColor(firstFrame, cv2.COLOR_BGR2GRAY)
firstFrame = cv2.GaussianBlur(firstFrame, (21, 21), 0)
firstFrame = firstFrame.astype("float")
 
# ...
 
while frame_count < 400: 
    # On capture l'image suivante
    grabbedAFrame, frame = cam.read()
 
    if not grabbedAFrame: 
        continue
 
    frame_count = frame_count + 1
 
    # On passe en niveau de gris et on floute pour éviter les différences ponctuelles
    grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    greyFrame = cv2.GaussianBlur(grayFrame, (21, 21), 0)
 
    # On fait une moyenne pondérée des images précédentes et de l'image actuelle (dans firstFrame) pour rendre le programme moins sensible aux variations de lumière
    cv2.accumulateWeighted(greyFrame, firstFrame, 0.5)
    diff = cv2.absdiff(cv2.convertScaleAbs(firstFrame), greyFrame)
    # On seuille la différence entre notre image moyenne et l'image capturée (pour limiter le bruit)
    thresh = cv2.threshold(diff, 24, 255, cv2.THRESH_BINARY)[1]
 
    # On dilate un peu le résultat et on récupère les contours, parmis ces contours, on aura notre objets en mouvement (si le seuillage qu'on a choisi est adapté)
    thresh = cv2.dilate(thresh, None, iterations=2)
    _, contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

On récupèrera ensuite les coordonnées de notre objets en mouvement en passant par une boîte enveloppante, de cette façon:

x, y, w, h = cv2.boundingRect(cnt_m)

En mesurant le temps écoulé entre chaque mesure du déplacement, on est en mesure d'obtenir une vitesse en pixels par seconde. Reste maintenant à se ramener à une vitesse en m/s (ou autre, au choix).

Calcul de la vitesse

On a désormais la vitesse parcouru par notre objet en pixels par seconde, il nous reste simplement à appliquer la formule du schéma donné précédemment pour obtenir notre vitesse en m/s.

# On calcule au préalable la distance en mètre que va représenté un pixel de l'image (fov: field of view, voyez les specs de votre caméra pour avoir la bonne valeur)
fov = math.radians(53.5)
meters_per_pixel = 2 * math.sin(fov/2) * float(sys.argv[1])/width

Bilan et sources du projet


Auteur: S. Durand

diy/projets/approximationvitesse.1531945924.txt.gz · Dernière modification : 2018/07/18 20:32 de sdurand