Cours:Classif
Révision datée du 2 février 2026 à 10:40 par Fredmn (discussion | contributions) (→Classifieur plus évolué)
TP Classification : détection d'objet en temps réel par vision
Le travail de cette étape va consister à
- analyser des images acquises en "temps réel" afin de détecter et identifier des objets
- les objets seront
- dans un premier temps des jetons de nain jaune
- dans un second temps des briques lego.
Sommaire
- 1 Technos matérielles et logicielles
- 2 Connexion à la Rpi et test d'acquisition en ligne de commande
- 3 Capture d'image et affichage en temps réel
- 4 Prétraitement
- 5 Reconnaissance simple d'un seul objet, avec descripteurs géométriques élémentaires
- 6 Classifieur plus évolué
- 7 Plusieurs objets
- 8 Bouts de code Python
- 9 Références
Technos matérielles et logicielles
Vous utiliserez :
- Une Rpi 4 que vous programmerez depuis des postes utilisés en terminaux connectés par
ssh, avec redirection graphique (option- X). - Une camera PiCam Wide (grand angle)
- Le langage Python accompagné de
- la librairie libcamera pour les acquisitions :
- PIL et numpy pour les traitements bas niveaux
- les librairies opencv et dlib pour la classification et la reconnaissance :
Étapes :
- Connexion à la Rpi et test d'acquisition en ligne de commande
- Capture d'image et affichage en temps réel, avec Python
- Prétraitement
- Reconnaissance simple d'un seul objet, avec descripteurs géométriques
- Classifieur plus évolué (knn, svm)
- Plusieurs objets
Connexion à la Rpi et test d'acquisition en ligne de commande
- Connecter (si cela n'est pas fait) la PiCam à la Rpi4
- Dans un terminal, se connecter à la Rpi en ssh :
ssh -X root@10.98.33.XX - Tester la PiCam avec
libcamera-hello(la capture en video doit s'afficher sur l'écran de la Rpi). Avec les informations affichées, identifier :- le modèle du capteur,
- ses caractéristiques (résolution, format, cadence, etc ...).
- Tester l'acquisition d'image avec l'éxecutable
libcamera-still- Explorer les options de cette application (
libcamera-still -h), en particulier-n,--immediate,--width,--heightet-o - Voir la page suivante pour le détails des options possibles : https://www.raspberrypi.com/documentation/computers/camera_software.html
- Explorer les options de cette application (
Capture d'image et affichage en temps réel
En exploitant la documentation Picamera2 (principalement section 6 - Capturing images and requests)
- Tester les deux exemples Capturing arrays et Capturing PIL images
- PIL fait référence à Python Imaging Library : une bibliothèque Python de traitement d'images.
- Écrire un script Python qui :
- initialise la camera
- affiche en continu son image
- sur l'appui d'une touche, réalise une capture (dans un objet
arrayouPIL) et sauvegarde l'image dans un fichier
En pratique :
- Vous pouvez lancer un interpréteur Python dans le terminal pour tester des choses
- Vous pouvez accéder aux dossiers de la Rpi depuis votre PC fixe, depuis le navigateur Dolphin avec comme url
sftp://root@10.98.33.83:22/. Ce qui vous permettra par exemple d'éditer le fichier script depuis votre PC fixe. - Dans le terminal,
python monscript.pypour executer votre script - On peut facilement attendre l'appui d'une touche avec
cv2.waitkey() - Référence Python :
Prétraitement
- Modification éventuelle de la zone de capture de la camera (crop).
- Conversion en image niveaux de gris, sur 8 bits.
- Binarisation (en mettant l'objet à 255, le fond à 0).
Reconnaissance simple d'un seul objet, avec descripteurs géométriques élémentaires
- En ne plaçant qu'un seul objet dans le champ de la camera, calculer et afficher ses descripteurs de forme : longueur et largeur de l'objet, cf https://raphael.candelier.fr/?blog=Image%20Moments (calcul de l et w)
- Construire une décision idoine à l'aide de la largeur et de la longueur de l'ellipse englobante, afin de discrimer trois classes d'objets (par exemple : jeton court, jeton long, jeton rond)
Exemple de calcul de l et w à partir d'une image binaire représentée dans un tableau numpy (arr de type ndarray) :
img = arr.astype(np.float64, copy=False)
H, W = img.shape
yy, xx = np.indices((H, W))
M00 = float(np.sum(img))
M10 = float(np.sum(xx * img))
M01 = float(np.sum(yy * img))
M11 = float(np.sum(xx * yy * img))
M20 = float(np.sum((xx * xx) * img))
M02 = float(np.sum((yy * yy) * img))
xm = int(M10 / M00)
ym = int(M01 / M00)
mu20 = M20 / M00 - xm * xm
mu02 = M02 / M00 - ym * ym
mu11 = M11 / M00 - xm * ym
t = math.sqrt(4.0 * mu11 * mu11 + (mu20 - mu02) * (mu20 - mu02))
l = int(math.sqrt(8.0 * (mu20 + mu02 + t)))
w = int(math.sqrt(8.0 * (mu20 + mu02 - t)))
Classifieur plus évolué
- Descripteurs
- Méthodologie :
- image en niveau de gris (éventuellement binarisation) :
cv2.cvtColor() - détection des contours :
cv2.Canny()etv2.findContours() - description des contours :
cv2.ximgproc.fourierDescriptor()
- image en niveau de gris (éventuellement binarisation) :
- Références :
- Exemple :
- Méthodologie :
from picamera2 import Picamera2
import numpy as np
import cv2
picam = Picamera2()
picam.start()
a = picam.capture_array("main")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 100, 200)
contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnt = max(contours, key=cv2.contourArea)
cnt = cnt.astype(np.float32)
# Paramètres utiles :
# nbElt = nombre de points ré-échantillonnés sur le contour
# nbFD = nombre de descripteurs gardés
fd = cv2.ximgproc.fourierDescriptor(cnt, nbElt=128, nbFD=16)
print(fd.shape, fd.dtype)
- KNN
- Redressement de la perspective
- Détecteur de coin de Harris : https://docs.opencv.org/4.5.1/dc/d0d/tutorial_py_features_harris.html
-
cv2.findHomography()etc2.warpPerspective() - ou https://docs.opencv.org/4.5.1/da/d6e/tutorial_py_geometric_transformations.html
- SVM
Plusieurs objets
- Segmentation nécessaire pour séparer les objets.
- Puis une labellisation pour les numéroter.
Bouts de code Python
- Convertir une image couleur img (4 canaux) en image OpenCV :
import cv2
im_cv = cv2.cvtColor(img, cv2.COLOR_RGBA2BGR)
Références
OpenCV :
- OpenCV Tutorials
- Exemples OpenCV en c++
- K-Nearest Neighbour
- Image Segmentation with Watershed Algorithm
- connected Components et son exemple en cpp : https://docs.opencv.org/3.4/de/d01/samples_2cpp_2connected_components_8cpp-example.html#a3
- Introduction to Support Vector Machines
- Fourier Descriptors, voir également Contours example pour obtenir les contours d'un objet.
Archives de cette page :