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