OpenCV – Détection de Mouvement

la detection de mouvement est une option interressante par exemple dans le cas de video surveillance , ci dessous un programme basique qui fait le boulot.

NOTA: derriere les caractères # des ligne en bleu qui peuvent remplacer la ligne juste avant pour des tests au choix soit sur un fichier video soit sur le livestream d’une camera. et également soit en dessinant des rectangles autour des objets en mouvement soit en dessinant le contour de l’objet.

import cv2
import numpy as np

cap = cv2.VideoCapture(0)
#cap = cv2.VideoCapture('OPENCVmotiondetection.avi')

ret, frame1 = cap.read()
ret, frame2 = cap.read()

while cap.isOpened():
    diff = cv2.absdiff(frame1, frame2)
    gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5,5), 0)
    _, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY)
    dilated = cv2.dilate(thresh, None, iterations=3)
    _, contours, _ = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    for contour in contours:
        (x, y, w, h) = cv2.boundingRect(contour)
        if cv2.contourArea(contour) < 500:
            continue
        cv2.rectangle(frame1, (x, y), (x+w, y+h), (0, 255, 0), 2)
        #cv2.drawContours(frame1, contours, -1, (0, 255, 0), 2)
    cv2.imshow("feed", frame1)
    frame1 = frame2
    ret, frame2 = cap.read()
    if cv2.waitKey(40) == 27:
        break

cv2.destroyAllWindows()
cap.release()

une copie d’ecran du resultat sur une video AVI et avec dessin de rectangles englobants sur les objets en mouvement:

examinons maintenant , une variante du programme précédent utilisant des fonction elaborées de OpenCV ainsi que le principe des masques , qui permet de n’appliquer la detection que sur la partie droite de la video

NOTA: les ligne en bleu sont des variantes du programme par rapport a la ligne en dessous ( il faut remplacer l’une par l’autre).

import cv2
import numpy as np

#cap = cv2.VideoCapture(1)
cap = cv2.VideoCapture('OPENCVmotiondetection.avi')
object_detector = cv2.createBackgroundSubtractorMOG2(history=100, varThreshold=10)

while True:
    ret, frame = cap.read()    
    roi = frame[0:480 , 320:640]        # def Region Off Interest   
    mask = object_detector.apply(roi)   # definission d'un masque avec la ROI
    _, mask = cv2.threshold(mask, 254, 255, 0)   # ne garde que les pixel blancs
    _, contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area > 100 :
            #cv2.drawContours(roi, [cnt], -1, (0, 255, 0), 2)  #dessin contour
            x, y, w, h =cv2.boundingRect(cnt)    # definition rectangle englobant
            cv2.rectangle(roi, (x, y), (x+w, y+h), (0, 255, 0), 3) #dessin rectangle
    
    cv2.imshow("Frame", frame)
    cv2.imshow("ROI", roi)
    cv2.imshow("Mask", mask)
    
    if cv2.waitKey(40) == 27:
        break

cv2.destroyAllWindows()
cap.release()

le resultat avec l’affichage , de la video de base, du ROI et du masque N&B