pour pouvoir utiliser openCV en Python , il faut installer la bibliothèque adéquate. ci dessous la procédure .
première chose a faire vérifier que tout est a la dernière version coté systeme .
donc lancer les classiques commandes shell suivantes:
sudo apt update
sudo apt upgrade
avant de continuer , verifier que python3 est installé. puis pour l’installation d’openCV , pas de grosses difficultés , taper dans le shell la ligne de commande suivante:
explications du programme
import cv2
# connection a la camera
cap = cv2.VideoCapture(0)
while (True):
# lecture d'une image (frame) du flux video
ret, frame = cap.read()
# affichage de l'image (frame) dans une fenetre nommée "Video"
cv2.imshow('Video', frame)
# test appui clavier et si touche ESC arret boucle while
if cv2.waitKey(1) == 27:
break
# arret flux camera
cap.release
# fermeture des toutes les fenetres d'affichage
cv2.destroyAllWindows()
en resultat , le flux des images s’affiche dans une fenêtre comme ci dessous:
améliorons le programme en ajoutant l’enregistrement du flux vidéo dans un fichier :
import cv2
cap = cv2.VideoCapture(0)
i=1
while (True):
ret, frame = cap.read()
cv2.imwrite('captureImg'+str(i)+'.jpg', frame)
cv2.imshow('Video', frame)
i+=1
if cv2.waitKey(1) == 27:
break
cap.release()
cv2.destroyAllWindows()
a partir des ces quelques bases il est ensuite possible d’imaginer des développements, par exemple des boutons dans une fenetre Tkinter permettant de déclencher la prise d’une photo ou l’enregistrement vidéo a la demande et non pas en permanence .
l’utilisation de camera USB ou de PIcamera avec Open CV peut necessiter de regler les parametres video tels que taille d’image, debit d’image , luminosité, contraste, saturation, etc ..
voyons avec un petit programme python comment faire ce type de reglage .
le programme ci dessous permet de regler les parametres classiques : luminosite , contraste, saturation, teinte d’une petite camera USB 640×480 ou d’une PIcam.
import cv2
cap1=cv2.VideoCapture(1) #sortie 1 Webcam USB
USBcamwin="USBcam" # nom de la fenetre Webcam
while True:
ret, frame1 = cap1.read()
cap1.set(10,60) #luminosité
cap1.set(11,60) #contraste
cap1.set(12,60) #saturation
cap1.set(13,60) #teinte
cv2.imshow(USBcamwin, frame1)
key=cv2.waitKey(1)
if key & 0xFF == ord('q'):
cv2.destroyAllWindows
break
la liste des parametres complets est disponible ici : flags video
la structure du paramètre est la suivante: cap1. set ( n° flag , valeur )
on trouve la liste des valeurs de flag dans le lien au dessus , les plus courants sont les suivants:
10 = luminosité
11 = contraste
12 = saturation
13 = teinte
14 = gain
20 = finesse
22 = gamma
30 = ISO
pour la valeur du parametre , il n’y a malheureusement pas de regle, elle depends de la camera utilisée , par exemple pour une PIcam :
luminosité: de 0 a 100
contrast de -100 a 100
saturation de -100 a 100
en fonction de votre camera , il vous faudra donc faire soit une recherche sur le web soit tout simplement faire des essais .
et comme souvent , vous pourrez par exemple associer les valeurs a des parametres pilotés par des sliders ou des widgets TKinter au travers d’une fenetre de menu comme dans la vignette de cette page.
la boucle “if + break ” permet d’arrêter l’affichage de la vidéo en appuyant sur la touche “Echap” du clavier ( code ascii 27). voici le résultat de ce bout de programme:
évolution du programme de base , on transforme le flux video RGB en nuance de gris et on affiche les 2 vidéos ensembles pour comparer le résultat:
import cv2
capture = cv2.VideoCapture(0)
while True:
# extraction des images
(ret, frame) = capture.read()
# conversion en nuance de grisgrayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# affichage des 2 videos
cv2.imshow('video original', frame)
cv2.imshow('video grey', grayFrame)
# fin du programme par appui de la touche Echap
if cv2.waitKey(1) == 27:
break
capture.release()
cv2.destroyAllWindows()
voila ce que ça donne:
variante suivante du deuxième programme , on récupère le flux vidéo de la webcam USB , on le transforme en nuance de gris et en noir et blanc binaire et on affiche les 3 vidéos ensembles pour comparer le résultat:
import cv2
capture = cv2.VideoCapture(0)
while (True):
(ret, frame) = capture.read()
grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# conversion en noir et blanc
(thresh, blackAndWhiteFrame) = cv2.threshold(grayFrame, 127, 255, cv2.THRESH_BINARY)
# recherche du controurcontours = cv2.findContours(blackAndWhiteFrame, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) [-2]# dessin du contour en rougefor c in contours:
cv2.drawContours(frame, [c], -1, (0,0,255), 2)
cv2.imshow('contour', frame)
if cv2.waitKey(1) == 27:
break
capture.release()
cv2.destroyAllWindows()
copie d’ecran du resultat:
petite variante du traitement précédent , juste en remplaçant le 2 en fin de la ligne de commande “drawContour” par -2 on remplis le contour au lieu de dessiner le contour.
import cv2 #import de la librairie openCV
import numpy #import de la librairie numpy (maths sur les matrices d'ordre N)# les images sont traitées comme des matrices d'ordre 3 (X,Y,couleurRGB)
# x pixels en largeur + Y pixels en hauteur + 3 bits de couleurs (RGB)
# fonction qui defini les reactions aux evenements souris
def click_event(event,x,y,flags,param):
if event == cv2.EVENT_RBUTTONDOWN:
cv2.circle(img,(x,y),20,(0,255,0),3)
strXY = str(x) + ',' + str(y)
cv2.putText(img, strXY, (x+21,y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,0),1)
elif event == cv2.EVENT_LBUTTONDOWN:
cv2.rectangle(img,(x-20,y-20),(x+20,y+20),(255,0,0),3)
strXY = str(x) + ',' + str(y)
cv2.putText(img, strXY, (x+21,y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,0),1)
# creation d'un fond noir (img)dans une fenetre('image')et liaison de la fonction setmoussecallback
img = numpy.zeros((480,640,3), numpy.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',click_event)
while(1):
cv2.imshow('image',img)
if cv2.waitKey(1) == 27:
break
cv2.destroyAllWindows()
ce qui donne comme exemple de résultat un programme qui ouvre une fentre a fond noir et dessine un rectangle bleu ou un cercle vert a l’endroit de la souris suivant qu’on clique sur le bouton droit ou gauche de la souris. il affiche en plus a droite de la figure les coordonnées (X,Y ) de la position de souris dans l’image ( coordonnées en pixels).
prenons quelques instants pour détailler et comprendre ce qui se passes:
au milieu de lignes de codes on trouve les 3 lignes suivantes :
la première ligne défini une variable tableau “img” a partir de la librairie numpy qui met a zéro (numpy.zeros) les valeurs de la matrices d’ordre 3 définissant en fait une image de 480pixels de hauteur, par 640 pixels de largeur et 3 valeurs de couleurs BGR pour chaque pixel . les valeurs sont codées sur 8bits via le code ‘numpy.uint8’ . comme les valeur BGR sont mises a zéro par la fonction numpy, cela fait une image en noir
la deuxième ligne crée une fenêtre OpenCV dont le nom est ‘image’
la troisieme ligne affecte les évènements de la souris à la fenêtre ‘Image’ et a la fonction ‘clik_event’
faisant appel a une fonction ‘click_event’, il faut définir celle ci , c’est l’objet des lignes suivantes:
la premiere boucle if correspondant au bouton droit enfoncé , elle dessine un cercle dans la fenetre ‘img’ , dont le centre est aux coordonnées x,Y retournées par la souris , d’un rayon de 20 pixels, de la couleur BGR (0,255,0) soit le Vert (G). puis retourne une variable string ‘strXY’ constituée des coordonnées XY du pointeur de souris avec une virgule au milieu. et affiche le texte dans la fenetre’img’ constitué de la variable ‘strXY’ , affichée aux coordonnées (x+21,Y) en ulisant la police de caracteres arial taille 0.5 en couleur (255,255,0) soit un bleu clair et d’epaisseur 1 .
la deuxieme boucle If fait la meme chose si le bouton Gauche est enfoncé et dessine un rectangle bleu cantré sur la position de la souris de largeur et hauteur identique (20 pixels) de couleur bleu foncé et affiche a droite les coordonnées XY.
la derniere partie du programme :
while(1):
cv2.imshow('image',img)
if cv2.waitKey(1) == 27:
break
cv2.destroyAllWindows()
effectue une boucle permanente qui affiche l’image ‘img’ resultante de toutes les operations dans la fenetre ‘image’ puis teste l’appui de touche au clavier et termine le programme si ‘echap” est appuyée la dernier ligne de commande ferme la fenêtre du programme .
SimpleBlobDetector est un utilitaire d’OpenCV permettant la détection automatique des “Blobs”. en Anglais un Blob est une tache . cet utilitaire est donc intéressant pour la détection de formes basiques circulaires, elliptiques ou rectangulaire. il trouve son intérêt par exemple en astronomie pour la détection d’étoiles sur un ciel noir avec une camera.
pour illustrer , ses possibilités , commençons par un programme simple utilisant une camera USB et une feuille blanche avec quelques taches faites au marqueur noir.
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
while (True):
ret, frame = cap.read()
# entrée des parametres de SimpleBlobDetector
params = cv2.SimpleBlobDetector_Params()
params.minThreshold = 10; # Change thresholds
params.maxThreshold = 300;
params.filterByColor = False # Filter by color.
params.BlobColor = 0 # 0 for darkcolor & 255 for light colors
params.filterByArea = True # Filter by Area.
params.minArea = 200
params.maxArea = 600
params.filterByCircularity = False # Filter by Circularity
params.minCircularity = 0.1
params.maxCircularity = 1
params.filterByConvexity = False # Filter by Convexity
params.minConvexity = 0.87
params.maxConvexity = 2
params.filterByInertia = False # Filter by Inertia
params.minInertiaRatio = 0.01
params.maxInertiaRatio = 0.1
# utilisation de SimpleBlobDetector
detector = cv2.SimpleBlobDetector_create(params)
keypoints = detector.detect(frame)
im_with_keypoints = cv2.drawKeypoints(frame, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('frame', im_with_keypoints)
if cv2.waitKey(1) == 27:
break
voici le resultat avec les parametres saisis.
toutes les taches faites au feutre ne sont pas entourées , c’est tout simplement le resultat de la definition des lignes de filtre ci dessous qui fixent la taille mini et maxi des zone de pixels a choisir ( entre 200 et 600 pixels):
on active les differents type de filtre en mettant la valeur a ” True” ( pour desactiver , il faut mettre “False“) et en choisissant une valeur pour les 2 lignes de seuils mini et maxi.
pour illustrer la fonction de chaque filtre , ci dessous une petite image de synthese:
nous allons maintenant sur le meme principe , determiner les coordonnées d’une tache blanche sur une feuille sombre . voici le programme:
l’evolution majeure par rapport au premier programme , est l’activation du mode couleur et la prise en compte de couleurs lumineuses ( ici la tache blanche sur fond sombre) dans les 2 lignes en rouge. et l’ajout d’une boucle imprimant les coordonnées (en pixel de l’image) dans les 2 lignes bleues. si on fait tourner ce programme dans thonny python , et que l’on fait bouger l’image ou la camera voici 2 exemples du resultat ( a gauche les coordonnées qui s’affichent dans la fenêtre shell de thonny python):
nous avons ici les bases d’un programme python pour de l’autoguidage sur une monture équatoriale astronomique… ne reste qu’a transformer ces coordonnées “pixels” en deplacements AD/DEC au fur et a mesure du déplacement de l’étoile de référence dans l’image ….
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.
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