Outils pour utilisateurs

Outils du site


diy:projets:motiondetection

Ceci est une ancienne révision du document !


Motion Detection

(En construction)

Note: Ce code a été lancé sous python 2.7.6 avec openCV 2.4

Programme

Ce programme va permettre de capturer une scène à l'aide d'une caméra et de détecter chaque objets en mouvement dans celle ci, ainsi que la couleur dominante dans ces objets, et de les encadrer.

L'intégralité du code se trouve ici

On a donc le début de code suivant:

capture = cv2.VideoCapture(0)
prevFrame = None

Dans un premier temps, on capture la vidéo du device. Puis on créé une variable prevFrame qu'on initialise à None, celle ci va nous servir plus tard a faire la différence entre l'image actuelle et l'image précédente, pour voir si il y a eu du mouvement.

Nous arrivons ensuite dans l'essentielle du code, la boucle While, ici nous lisons chaque image une par une, si l'image n'est pas lu correctement dans le buffer, alors on quitte la boucle. Cela nous donne :

while True:
    (grabbed,frame) = capture.read()
    if not grabbed:
        break

Flou Gaussien

On récupère l'image en cour qu'on transforme en niveau de gris puis on lui applique un flou gaussien pour atténuer le bruit, sans se flou on repérerez par la suite tout les bruits comme étant du mouvement. Appliquer un flou gaussien est donc indispensable pour la suite du programme.

Cela ce fait grace au code suivant et on obtient l'image ci dessous:

gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray,(25,25), 0)

Flou Gaussien Enfin, si cette image est la première, alors la variable prevFrame prend la valeur de cette image:

if prevFrame is None:
        prevFrame = gray

Seuillage

Après avoir obtenu l'image avec le flou gaussien, on fait la différence absolue entre l'image en cours et l'image précédente, cela nous permet de voir les pixels uniquement en mouvement. Ensuite on fait un seuillage binaire sur cette nouvelle image et tout les pixels qui on un certain niveau de gris sont placé à 255. Ici on choisi 7 pour pouvoir repérer même les petit mouvement. Puis on dilate cette image pour avoir bien tout l'objet si possible en mouvement (des fois c'est un échec…); et à l'aide du code suivant on obtient l'image ci dessous:

frameDelta = cv2.absdiff(prevFrame,gray)
thresh = cv2.threshold(frameDelta, 7, 255, cv2.THRESH_BINARY)[1]
kernel = np.ones((11,11),np.uint8)
thresh = cv2.dilate(thresh, kernel, iterations=2)

Contours et Masque

Une fois que tout cela est fait, on cherche les contours des objets de l'image dilaté et on créé un masque qui va nous servir a encadrer l'objet de la couleur de celui ci:

(img,contr,hrchy) = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
mask = np.zeros(frame.shape[:2],np.uint8)

Pour chaque contours trouver: -Si c'est un contours trop petit (valeur fixé) on l'ignore. -Sinon on crée on rectangle a partir à partir de ce contour, et un masque de la taille du rectangle qui va nous permettre d'obtenir la couleur de l'objet. Pour avoir la couleur de l'objet, on récupere la couleur du pixel du milieu du rectangle, on supose qu'on est dans le cas ou l'objet a une couleur uniforme.

Le rectangle prend ensuite la couleur de l'objet et les nuance de bleu,vert,rouge sont affiché sur le cotté du rectangle. Tout cela se fait avec le code suivant:

    for c in contr:
        if cv2.contourArea(c) < 1500:
			continue
 
        (x,y,w,h) = cv2.boundingRect(c) 
        mask[y:y+h, x:x+w] = 255
 
        (bl,gr,re) = frame[y+(h/2),x+(w/2)]
        bl = int(bl) 
        gr = int(gr)
        re = int(re)
        couleur ='B:'+ str(bl) + 'G:' + str(gr) + 'R:' + str(re)
 
        font = cv2.FONT_HERSHEY_SIMPLEX
        cv2.putText(frame,couleur,(x+w,y), font, 1, (255,255,255), 2, cv2.LINE_AA)
        cv2.rectangle(frame,(x,y),(x+w,y+h),(bl,gr,re),3)
 
    masked_img = cv2.bitwise_and(frame,frame,mask=mask)    
 
    cv2.imshow('contour',frame)

Resultat final:

diy/projets/motiondetection.1527166701.txt.gz · Dernière modification : 2018/05/24 12:58 de ecausse