Guide Complet d'OpenCV 3 avec Python pour la Vision par Ordinateur

  1. Opérations Fondamentales sur les Images

Avant de plonger dans des traitements complexes, il est essentiel de maîtriser les bases de la manipulation des images numériques.

1.1 Concepts Clés des Images Numériques

Les images numériques sont représentées comme des matrices, où chaque élément (pixel) contient des informations de couleur. Elles peuvent être en niveaux de gris ou en couleur (avec plusieurs canaux).

1.2 Lecture et Affichage d'Images

La première étape consiste à savoir comment charger et visualiser une image. Voici un exemple simple utilisant OpenCV en Python :


import cv2

# Charger une image depuis un fichier
img = cv2.imread('chemin/vers/image.jpg')

# Vérifier si l'image a été chargée correctement
if img is None:
   print("Erreur : Impossible de charger l'image.")
else:
   # Afficher l'image dans une fenêtre
   cv2.imshow('Fenêtre d\'affichage', img)

   # Attendre qu'une touche soit pressée
   cv2.waitKey(0)

   # Fermer toutes les fenêtres ouvertes
   cv2.destroyAllWindows()
   

1.3 Traitements de Base

Apprenons quelques opérations de base comme la conversion en niveaux de gris et la binarisation :


# Assumant que 'img' est une image déjà chargée
# Conversion en niveaux de gris
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Binarisation de l'image
# 127 est le seuil, 255 est la valeur maximale, THRESH_BINARY applique le seuil
seuillage, binary_img = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
   

Ces opérations constituent la base pour des traitements plus avancés.

  1. Techniques de Traitement d'Images

Cette section explore diverses techniques de traitement d'images appliquées dans de nombreux domaines.

2.1 Transformations Géométriques

Les transformations géométriques modifient la position des pixels sans altérer leurs valeurs intrinsèques. Cela inclut la translation, la rotation et la mise à l'échelle.

  • Translation : Déplacement de l'image dans une direction (x, y).
  • Rotation : Pivotement de l'image autour d'un point.
  • Mise à l'échelle : Redimensionnement de l'image (agrandissement ou réduction).

Exemple de translation :


import cv2
import numpy as np

# Charger une image
img = cv2.imread('exemple.jpg')
if img is None:
   print("Erreur lors du chargement de l'image.")
else:
   hauteur, largeur = img.shape[:2]

   # Définir le vecteur de translation (décalage horizontal, décalage vertical)
   decalage_x = 100
   decalage_y = 50
   matrice_translation = np.float32([[1, 0, decalage_x], [0, 1, decalage_y]])

   # Appliquer la transformation affine (translation)
   img_translatee = cv2.warpAffine(img, matrice_translation, (largeur, hauteur))

   # Afficher l'original et l'image traduite
   cv2.imshow('Image Originale', img)
   cv2.imshow('Image Translatee', img_translatee)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

2.2 Filtrage et Réduction du Bruit

Le filtrage est utilisé pour supprimer le bruit ou les informations indésirables des images. Les techniques courantes incluent le filtrage Gaussien, le filtre médian et le filtre bilatéral.

  • Filtrage Gaussien : Atténue le bruit tout en préservant les contours.
  • Filtre Médian : Efficace contre le bruit "poivre et sel".
  • Filtre Bilatéral : Préserve les bords tout en lissant les zones homogènes.

Exemple de filtrage Gaussien :


import cv2
import matplotlib.pyplot as plt

# Charger une image en niveaux de gris
img_bruitee = cv2.imread('bruitee.jpg', cv2.IMREAD_GRAYSCALE)

if img_bruitee is None:
   print("Erreur lors du chargement de l'image bruitée.")
else:
   # Appliquer le filtre Gaussien (taille du noyau 5x5)
   img_adoucie = cv2.GaussianBlur(img_bruitee, (5, 5), 0)

   # Afficher l'image originale et l'image adoucie
   plt.figure(figsize=(10, 5))
   plt.subplot(121), plt.imshow(img_bruitee, cmap='gray')
   plt.title('Image Bruitée'), plt.xticks([]), plt.yticks([])
   plt.subplot(122), plt.imshow(img_adoucie, cmap='gray')
   plt.title('Image Adoucie (Gaussien)'), plt.xticks([]), plt.yticks([])
   plt.show()
   

2.3 Amélioration et Ajustement d'Images

Ces techniques visent à améliorer la qualité visuelle des images, par exemple en ajustant la luminosité, le contraste ou la netteté.

  • Contraste : Augmentation de la différence entre les zones claires et sombres.
  • Luminosité : Ajustement général de l'intensité des pixels.
  • Netteté : Accentuation des détails et des contours.

Exemple d'ajustement de luminosité et contraste :


import cv2
import numpy as np

# Charger une image
img = cv2.imread('faible_contraste.jpg')

if img is None:
   print("Erreur lors du chargement de l'image.")
else:
   # Paramètres d'ajustement
   alpha = 1.5  # Contrôle du contraste (alpha > 1 augmente le contraste)
   beta = 50    # Contrôle de la luminosité (beta > 0 augmente la luminosité)

   # Appliquer l'ajustement
   img_ajustee = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)

   # Afficher l'image originale et ajustée
   cv2.imshow('Image Originale', img)
   cv2.imshow('Image Ajustee', img_ajustee)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   
  1. Détection et Correspondance de Caractéristiques

Cette section aborde la détection de points d'intérêt uniques dans les images et leur utilisation pour trouver des correspondances entre différentes vues.

3.1 Algorithmes de Détection de Caractéristiques

Des algorithmes comme SIFT, SURF et ORB identifient des points saillants dans une image qui sont stables face aux changements d'échelle, de rotation et d'illumination.

3.1.1 SIFT et SURF

SIFT (Scale-Invariant Feature Transform) et SURF (Speeded Up Robust Features) sont des descripteurs puissants mais potentiellement brevetés. Ils détectent des points clés et calculent leurs descripteurs.


import cv2

# Charger une image en niveaux de gris
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

if img is None:
   print("Erreur lors du chargement de l'image.")
else:
   # Initialiser le détecteur SIFT
   sift = cv2.SIFT_create()

   # Détecter les points clés et leurs descripteurs
   keypoints, descriptors = sift.detectAndCompute(img, None)

   # Dessiner les points clés sur l'image
   img_keypoints = cv2.drawKeypoints(img, keypoints, None)

   # Afficher l'image avec les points clés
   cv2.imshow('Points Clés SIFT', img_keypoints)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

3.1.2 ORB

ORB (Oriented FAST and Rotated BRIEF) est une alternative gratuite et performante, combinant la détection rapide des points FAST avec une description basée sur BRIEF, orientée pour la rotation.


import cv2

# Charger une image en niveaux de gris
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)

if img is None:
   print("Erreur lors du chargement de l'image.")
else:
   # Initialiser le détecteur ORB
   orb = cv2.ORB_create()

   # Détecter les points clés et leurs descripteurs
   keypoints, descriptors = orb.detectAndCompute(img, None)

   # Dessiner les points clés
   img_keypoints = cv2.drawKeypoints(img, keypoints, None)

   # Afficher l'image avec les points clés ORB
   cv2.imshow('Points Clés ORB', img_keypoints)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

3.2 Correspondance de Caractéristiques

Une fois les descripteurs calculés, on peut les comparer pour trouver des correspondances entre deux images.

3.2.1 Des exemples de descripteurs

Les descripteurs sont des vecteurs numériques représentant les caractéristiques locales autour d'un point clé.


import cv2
import numpy as np

# Charger l'image et obtenir les descripteurs (exemple avec SIFT)
img = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
sift = cv2.SIFT_create()
kp, des = sift.detectAndCompute(img, None)

# Convertir les descripteurs en float32 pour certains algorithmes
descriptors_float = np.float32(des)

print(f"Nombre de descripteurs: {descriptors_float.shape[0]}, Dimension: {descriptors_float.shape[1]}")
   

3.2.2 Correspondance par force brute et FLANN

Le correspondant par force brute compare chaque descripteur de l'image 1 avec chaque descripteur de l'image 2. FLANN (Fast Library for Approximate Nearest Neighbors) utilise des structures de données indexées pour une correspondance plus rapide.


import cv2

# Charger deux images
img1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE)

if img1 is None or img2 is None:
   print("Erreur lors du chargement des images.")
else:
   # Utiliser ORB pour détecter les caractéristiques
   orb = cv2.ORB_create()
   kp1, des1 = orb.detectAndCompute(img1, None)
   kp2, des2 = orb.detectAndCompute(img2, None)

   # Initialiser le correspondant par force brute (NORM_HAMMING pour ORB)
   bf_matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

   # Effectuer la correspondance
   matches = bf_matcher.match(des1, des2)

   # Trier les correspondances par distance
   matches = sorted(matches, key=lambda x: x.distance)

   # Dessiner les 10 meilleures correspondances
   img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

   # Afficher le résultat
   cv2.imshow('Meilleures Correspondances', img_matches)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

3.3 Applications Pratiques

3.3.1 Assemblage d'Images (Panorama)

L'assemblage d'images utilise la détection et la correspondance de caractéristiques pour aligner et fusionner plusieurs images en une seule vue panoramique.


import cv2
import numpy as np
from matplotlib import pyplot as plt

# Charger deux images pour l'assemblage
img1 = cv2.imread('pan_img1.jpg')
img2 = cv2.imread('pan_img2.jpg')

if img1 is None or img2 is None:
   print("Erreur lors du chargement des images pour le panorama.")
else:
   gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
   gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

   # Utiliser SIFT pour trouver les correspondances
   sift = cv2.SIFT_create()
   kp1, des1 = sift.detectAndCompute(gray1, None)
   kp2, des2 = sift.detectAndCompute(gray2, None)

   bf = cv2.BFMatcher()
   # Utiliser knnMatch pour obtenir les 2 meilleurs voisins pour le ratio test
   matches = bf.knnMatch(des1, des2, k=2)

   # Filtrer les bonnes correspondances (ratio test de Lowe)
   good_matches = []
   for m, n in matches:
       if m.distance < 0.75 * n.distance:
           good_matches.append(m)

   pts1 = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
   pts2 = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)

   # Calculer la matrice d'homographie
   H, mask = cv2.findHomography(pts1, pts2, cv2.RANSAC, 5.0)

   # Appliquer la transformation perspective
   height, width = img2.shape[:2]
   img1_registered = cv2.warpPerspective(img1, H, (width, height))

   # Fusionner les images (simple addition)
   img_merged = cv2.add(img2, img1_registered) # Peut nécessiter un mélange plus sophistiqué

   # Afficher le résultat
   plt.figure(figsize=(10, 5))
   plt.imshow(cv2.cvtColor(img_merged, cv2.COLOR_BGR2RGB))
   plt.title('Image Assemblée')
   plt.show()
   

3.3.2 Reconstruction 3D et Mesure de Distance

En utilisant des paires d'images et les informations de correspondance, il est possible de reconstruire la structure 3D d'une scène et de mesurer des distances.

Le code ci-dessous est un exemple simplifié montrant l'utilisation des paramètres de caméra pour le traitement 3D.


import cv2
import numpy as np
import matplotlib.pyplot as plt

# Paramètres intrinsèques supposés de la caméra
fx = 500.0  # Longueur focale en pixels (axe x)
fy = 500.0  # Longueur focale en pixels (axe y)
cx = 320.0  # Centre optique en pixels (axe x)
cy = 240.0  # Centre optique en pixels (axe y)

camera_matrix = np.array([[fx, 0, cx],
                         [0, fy, cy],
                         [0, 0, 1]], dtype=np.float32)

dist_coeffs = np.zeros((4, 1)) # Pas de coefficients de distorsion

# Charger une image
img = cv2.imread('image_pour_3d.jpg')

if img is not None:
   # Appliquer la correction de distorsion (si nécessaire)
   img_undistorted = cv2.undistort(img, camera_matrix, dist_coeffs)

   # Exemple de points 3D (supposés)
   points_3d_world = np.array([[1.0, 2.0, 5.0], # Point 1 en coordonnées mondiales
                               [3.0, 1.0, 6.0], # Point 2
                               [-1.0, -1.0, 7.0]]) # Point 3

   # Paramètres de pose de la caméra (rotation et translation) - ici, identité et zéro pour simplification
   rotation_vector = np.zeros(3) # Vecteur de rotation
   translation_vector = np.zeros(3) # Vecteur de translation

   # Projeter les points 3D sur l'image 2D
   points_2d_projected, _ = cv2.projectPoints(points_3d_world, rotation_vector, translation_vector, camera_matrix, dist_coeffs)

   # Afficher l'image corrigée
   plt.imshow(cv2.cvtColor(img_undistorted, cv2.COLOR_BGR2RGB))
   # On pourrait ensuite dessiner les points projetés sur l'image
   plt.title("Image après correction de distorsion")
   plt.show()
else:
   print("Erreur : Impossible de charger l'image pour le traitement 3D.")
   
  1. Segmentation d'Images

La segmentation consiste à diviser une image en plusieurs régions ou objets significatifs.

4.1 Segmentation Basée sur le Seuil

Cette méthode classifie les pixels en fonction de leur valeur de luminosité par rapport à un seuil.

4.1.1 Seuil Global et Adaptatif

Le seuil global utilise une valeur unique pour toute l'image. Le seuil adaptatif calcule des seuils différents pour différentes régions, s'adaptant aux variations d'éclairage.


import cv2
import numpy as np

# Charger une image en niveaux de gris
image = cv2.imread('exemple_segmentation.jpg', cv2.IMREAD_GRAYSCALE)

if image is None:
   print("Erreur lors du chargement de l'image.")
else:
   # Seuil global
   ret_global, seuil_global = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)

   # Seuil adaptatif (méthode Moyenne)
   seuil_adaptatif_moy = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C,
                                               cv2.THRESH_BINARY, 11, 4) # 11: taille bloc, 4: constante soustraite

   # Seuil adaptatif (méthode Gaussienne)
   seuil_adaptatif_gauss = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                                 cv2.THRESH_BINARY, 11, 4)

   # Afficher les résultats
   cv2.imshow('Original', image)
   cv2.imshow('Seuil Global', seuil_global)
   cv2.imshow('Seuil Adaptatif (Moyenne)', seuil_adaptatif_moy)
   cv2.imshow('Seuil Adaptatif (Gaussien)', seuil_adaptatif_gauss)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

4.1.2 Algorithme OTSU

L'algorithme OTSU détermine automatiquement le seuil optimal en maximisant la variance inter-classes des pixels.


import cv2

# Charger une image en niveaux de gris
image = cv2.imread('exemple_otsu.jpg', cv2.IMREAD_GRAYSCALE)

if image is None:
   print("Erreur lors du chargement de l'image.")
else:
   # Appliquer le seuillage avec OTSU
   # Le seuil est calculé automatiquement, on met 0 pour le seuil initial
   otsu_threshold, image_otsu = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

   print(f"Seuil OTSU calculé : {otsu_threshold}")
   cv2.imshow('Seuillage OTSU', image_otsu)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

4.2 Segmentation Basée sur les Régions

Ces méthodes regroupent les pixels en régions homogènes basées sur des critères de similarité.

4.2.1 Croissance de Région

Partant de points "graines", cette technique étend les régions en ajoutant les pixels voisins similaires.

4.2.2 Méthode des Niveaux de Gris (Level Sets)

Une approche avancée utilisant des courbes dynamiques qui évoluent pour s'adapter aux contours des objets, capable de gérer des changements topologiques.

4.3 Segmentation Basée sur les Contours

Se concentre sur la détection des discontinuités dans l'intensité de l'image, correspondant aux bords des objets.

4.3.1 Détection et Connexion des Bords

Les algorithmes comme Canny ou Sobel détectent les gradients d'intensité. Des techniques de connexion sont ensuite appliquées pour former des contours complets.

4.3.2 Techniques Avancées (Deep Learning)

Les réseaux neuronaux profonds excellent dans la détection de contours, apprenant des caractéristiques complexes à partir de vastes ensembles de données.

  1. Reconnaissance Faciale

La reconnaissance faciale est un domaine clé de la vision par ordinateur, avec des applications allant de la sécurité aux interactions homme-machine.

5.1 Détection Faciale

Idetnifier la présence et la localisation des visages dans une image.

5.1.1 Classifieurs en Cascade Haar

Une méthode historique et rapide utilisant des caractéristiques Haar pour la détection.


import cv2

# Charger le classifieur Haar pré-entraîné pour les visages
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

# Charger une image
image = cv2.imread('image_avec_visage.jpg')

if image is None:
   print("Erreur : Impossible de charger l'image.")
else:
   # Convertir l'image en niveaux de gris pour la détection
   gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

   # Détecter les visages dans l'image
   # scaleFactor : Réduction de la taille de l'image à chaque échelle
   # minNeighbors : Nombre minimum de voisins pour qu'une détection soit valide
   # minSize : Taille minimale du visage détecté
   faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

   # Dessiner des rectangles autour des visages détectés
   for (x, y, w, h) in faces:
       cv2.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2) # Bleu, épaisseur 2

   # Afficher le résultat
   cv2.imshow('Detection Faciale (Haar)', image)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

5.1.2 Détection par Réseaux Neuronaux Profonds (DNN)

Les modèles DNN offrent une précision supérieure, notamment pour les visages dans des conditions difficiles.


import cv2
import numpy as np

# Charger le modèle DNN pré-entraîné (par exemple, MobileNet SSD)
# Ces chemins doivent correspondre à vos fichiers de modèle
prototxt_path = 'deploy.prototxt'
model_path = 'res10_300x300_ssd_iter_140000.caffemodel'
net = cv2.dnn.readNetFromCaffe(prototxt_path, model_path)

# Charger une image
image = cv2.imread('image_dnn.jpg')

if image is None:
   print("Erreur : Impossible de charger l'image.")
else:
   (h, w) = image.shape[:2]
   # Préparer l'image pour le réseau (création d'un blob)
   blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0, (300, 300), (104.0, 177.0, 123.0))

   # Passer le blob dans le réseau
   net.setInput(blob)
   detections = net.forward()

   # Parcourir les détections
   for i in range(0, detections.shape[2]):
       confidence = detections[0, 0, i, 2]

       # Filtrer les détections avec une confiance faible
       if confidence > 0.5:
           # Calculer les coordonnées du cadre de détection
           box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
           (startX, startY, endX, endY) = box.astype("int")

           # Dessiner le cadre et afficher la confiance
           label = "{:.2f}%".format(confidence * 100)
           cv2.rectangle(image, (startX, startY), (endX, endY), (0, 255, 0), 2) # Vert
           y = startY - 10 if startY - 10 > 10 else startY + 10
           cv2.putText(image, label, (startX, y), cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 255, 0), 2)

   # Afficher le résultat
   cv2.imshow("Detection Faciale (DNN)", image)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

5.2 Extraction et Comparaison de Caractéristiques Faciales

Après détection, des points clés (yeux, nez, bouche) sont extraits pour représenter de manière unique un visage.

5.2.1 Localisation des Points Fiduciels Faciaux

Bibliothèques comme Dlib sont très efficaces pour prédire la position des repères faciaux.


import cv2
import dlib

# Initialiser le détecteur de visage Dlib
detector = dlib.get_frontal_face_detector()

# Charger le modèle de prédiction des points fiduciels (fichier .dat nécessaire)
# Téléchargez "shape_predictor_68_face_landmarks.dat" et placez-le dans le bon répertoire
try:
   predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
except RuntimeError as e:
   print(f"Erreur lors du chargement du modèle predictor : {e}")
   print("Assurez-vous que 'shape_predictor_68_face_landmarks.dat' est dans le bon répertoire.")
   exit()

# Charger une image
image = cv2.imread('image_points_faciaux.jpg')

if image is None:
   print("Erreur : Impossible de charger l'image.")
else:
   gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

   # Détecter les visages
   faces = detector(gray)

   for face in faces:
       # Dessiner un rectangle autour du visage
       x1, y1 = face.left(), face.top()
       x2, y2 = face.right(), face.bottom()
       cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)

       # Obtenir les points fiduciels
       landmarks = predictor(gray, face)

       # Dessiner les points fiduciels
       for n in range(0, 68):
           x = landmarks.part(n).x
           y = landmarks.part(n).y
           cv2.circle(image, (x, y), 2, (255, 0, 0), -1) # Bleu

   # Afficher le résultat
   cv2.imshow('Points Fiduciels Faciaux', image)
   cv2.waitKey(0)
   cv2.destroyAllWindows()
   

5.3 Scénarios d'Application

5.3.1 Systèmes de Contrôle d'Accès par Reconnaissance Faciale

Utilise la détection et l'identification faciale pour vérifier l'identité des personnes et accorder ou refuser l'accès.

5.3.2 Analyse et Reconnaissance des Expressions Faciales

Détecte et classe les émotions humaines (joie, tristesse, colère, etc.) en analysant les expressions faciales.

  1. Traitement Vidéo et Analyse de Mouvement

L'analyse de séquences vidéo permet de comprendre le mouvement et le comportement des objets.

6.1 Lecture et Écriture de Vidéos

6.1.1 Lecture de Flux Vidéo

Utilise cv2.VideoCapture pour lire des fichiers vidéo ou des flux en direct.


import cv2

# Ouvrir le flux vidéo (fichier ou caméra)
cap = cv2.VideoCapture('entree.mp4') # Ou 0 pour la caméra par défaut

if not cap.isOpened():
   print("Erreur : Impossible d'ouvrir le flux vidéo.")
else:
   while True:
       # Lire une image (frame)
       ret, frame = cap.read()

       # Si la lecture échoue ou si la fin du flux est atteinte
       if not ret:
           print("Fin du flux vidéo.")
           break

       # Traiter l'image 'frame' ici...
       # Exemple : Afficher l'image brute
       cv2.imshow('Flux Vidéo', frame)

       # Attendre 25ms et vérifier si la touche 'q' est pressée pour quitter
       if cv2.waitKey(25) & 0xFF == ord('q'):
           break

   # Libérer la capture et fermer toutes les fenêtres
   cap.release()
   cv2.destroyAllWindows()
   

6.1.2 Écriture de Flux Vidéo

Utilise cv2.VideoWriter pour enregistrer des séquences d'images traitées dans un fichier vidéo.


import cv2

# Paramètres du flux de sortie
fourcc = cv2.VideoWriter_fourcc(*'XVID') # Codec
fps = 20.0 # Images par seconde
frame_size = (640, 480) # Taille des images (largeur, hauteur)

out = cv2.VideoWriter('sortie.avi', fourcc, fps, frame_size)

# Boucle de lecture et traitement (similaire à ci-dessus)
# ... lire 'frame' ...
# ... traiter 'frame' pour obtenir 'processed_frame' ...
# out.write(processed_frame)
# ...

# Libérer l'objet VideoWriter
out.release()
   

6.2 Détection et Suivi de Mouvement

6.2.1 Soustraction de Fond

Isole les objets en mouvement en soustrayant un modèle de fond statique.


import cv2

cap = cv2.VideoCapture('entree.mp4')
# Créer un soustracteur de fond (par exemple, MOG2)
fgbg = cv2.createBackgroundSubtractorMOG2(history=500, varThreshold=16, detectShadows=True)

while True:
   ret, frame = cap.read()
   if not ret: break

   # Appliquer le soustracteur de fond pour obtenir un masque de premier plan
   fgmask = fgbg.apply(frame)

   # Améliorer le masque avec des opérations morphologiques
   fgmask = cv2.erode(fgmask, None, iterations=2)
   fgmask = cv2.dilate(fgmask, None, iterations=2)

   cv2.imshow('Masque Premier Plan', fgmask)
   if cv2.waitKey(30) & 0xFF == ord('q'): break

cap.release()
cv2.destroyAllWindows()
   

6.2.2 Calcul de Flux Optique et Filtres de Kalman

Le flux optique estime le mouvement des pixels entre les images, tandis que le filtre de Kalman prédit la trajectoire future des objets suivis.


import cv2
import numpy as np

cap = cv2.VideoCapture('entree.mp4')

# Initialiser le filtre de Kalman (exemple pour un objet 2D simple)
kalman = cv2.KalmanFilter(4, 2) # 4 états (x, y, vx, vy), 2 mesures (x, y)
kalman.measurementMatrix = np.array([[1, 0, 0, 0], [0, 1, 0, 0]], dtype=np.float32)
kalman.transitionMatrix = np.array([[1, 0, 1, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]], dtype=np.float32)
kalman.processNoiseCov = np.eye(4, dtype=np.float32) * 0.03
kalman.measurementNoiseCov = np.eye(2, dtype=np.float32) * 0.5

# Paramètres pour le calcul du flux optique
lk_params = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# Lire la première image et trouver les points initiaux
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# Trouver des points caractéristiques (ex: Harris corners ou Shi-Tomasi)
p0 = cv2.goodFeaturesToTrack(old_gray, maxCorners=100, qualityLevel=0.3, minDistance=7)

while True:
   ret, frame = cap.read()
   if not ret: break
   frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

   # Calculer le flux optique
   p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

   # Sélectionner les bons points
   good_new = p1[st == 1]
   good_old = p0[st == 1]

   # Utiliser les déplacements moyens pour prédire/corriger avec Kalman
   if len(good_new) > 0:
       measurement = np.array([[np.mean(good_new[:, 0] - good_old[:, 0])], [np.mean(good_new[:, 1] - good_old[:, 1])]], dtype=np.float32)
       kalman.correct(measurement)
       prediction = kalman.predict()
       # Dessiner les trajectoires ou utiliser 'prediction' pour le suivi
       # ...

   # Mettre à jour pour la prochaine itération
   old_gray = frame_gray.copy()
   p0 = good_new.reshape(-1, 1, 2) # Les points actuels deviennent les anciens pour la prochaine frame

   cv2.imshow('Flux Optique et Suivi', frame)
   if cv2.waitKey(30) & 0xFF == ord('q'): break

cap.release()
cv2.destroyAllWindows()
   

6.3 Applications en Temps Réel

6.3.1 Suivi et Reconnaissance Faciale en Temps Réel

Combine la détection faciale rapide avec des algorithmes de suivi pour une identification continue.

6.3.2 Reconnaissance d'Actions et Analyse Comportementale

Utilise des modèles d'apprentissage profond (CNN, RNN) pour identifier des actions complexes dans des flux vidéo.

Étiquettes: OpenCV Python vision par ordinateur traitement d'images Détection de Caractéristiques

Publié le 16 juin à 23h54