====== Piège Photographique ====== Le piège photographique consiste à prendre des photos uniquement lorsqu'on capte un mouvement. l'intégralité du code se trouve [[https://github.com/RenoRincevent/BePython/blob/master/piegePhoto.py|ici]] Pour ce programme, non seulement il nous faudra importer les librairie //cv2// et //numpy// mais nous avons aussi besoin de la librairie //time// et //Thread// ainsi que //Event//, ces trois dernières librairie seront utile dans le thread pour prendre les photos lors de mouvement dans la capture de vidéo. import cv2 import time import numpy as np from threading import Thread, Event ===== Capture du mouvement ===== Le début du programme ce fait exactement comme la [[diy:projets:motiondetection|détection de mouvement]]. Avant la boucle while, on crée un thread //myThread// pour la fonction //takePicture()// qui va nous servir par la suite à prendre la photo. Dans le début de la boucle while on exécute un flou gaussien et un seuillage (comme vu dans Motion Detection): capture = cv2.VideoCapture(0) prevFrame = None myThread = takePicture() while True: (grabbed,frame) = capture.read() if not grabbed: break gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) gray = cv2.GaussianBlur(gray,(25,25), 0) if prevFrame is None: prevFrame = gray 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) Puis lors des recherches de contours de l'image dilaté, on crée une variable //area//, qu'on initialise à 0. Cela va nous servir par la suite à voir s'il y a un contour dans l'image, et donc du mouvement. Lors du parcours des contours: tout les petits objets sont ignorés, et on enregistre l'aire du contour pour la suite. Enfin, si il y a une aire dans l'image, et donc un mouvement, et que le thread n'est pas déjà en train de prendre une photo, alors on peut en relancer un autre pour prendre une photo. (img,contr,hrchy) = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) area = 0 for c in contr: if cv2.contourArea(c) < 1500: continue area = cv2.contourArea(c) if area != 0 and not(myThread.is_alive()): myThread = takePicture() myThread.start() ===== Prise de la photo ===== On crée un thread pour la prise de la photo alors que le programme principale est encore en train de s’exécuter en parallèle Le thread //takePicture()// va écrire l'image en cours dans un format spécifique (ici .png) puis on lance un sleep(), cela permet, si il y a du mouvement en continue de prendre uniquement des photos toute les n secondes (ici on à choisi toute les 1 seconde). De plus, on crée une variable globale qui s’incrémente à chaque fois que l'on prend une nouvelle photo, Cela permet de ne pas écraser les anciennes photos prise lors de la capture vidéo. img_counter = 0 class takePicture(Thread): def __init__(self): Thread.__init__(self) self._stop_event = Event() def run(self): global img_counter imgName = ("frame_{}.png".format(img_counter)) cv2.imwrite(imgName,frame) #print("{} ecrit".format(imgName)) img_counter += 1 time.sleep(1)