Exercices Computer Vision Projet : pipeline de traitement d'image
🎉

Bravo!

Avancé 🧠 Fondamentaux 30 XP 0 personnes ont réussi

Projet : pipeline de traitement d'image

C'est ici que tout se rejoint. Dans l'industrie, un pipeline de vision par ordinateur comme celui-ci tourne en boucle sur des caméras de production pour compter des pièces sur un tapis roulant, détecter des défauts, ou vérifier qu'un assemblage est complet. En biologie, le même type de pipeline compte des cellules au microscope ou des colonies de bactéries sur une boîte de Petri. En agriculture de précision, on compte les fruits sur un arbre depuis des images drone.

Pense à une chaîne de montage dans une usine. Chaque poste fait une opération précise : le premier nettoie la pièce, le deuxième la découpe, le troisième la ponce, le quatrième la vérifie. Ton pipeline de traitement d'image fonctionne pareil : chaque étape prépare l'image pour la suivante, et le résultat final est une information exploitable (combien d'objets il y a).

En pratique, tu utiliserais cv2.cvtColor() pour le gris, cv2.blur() pour le flou, cv2.threshold() pour le seuillage, cv2.erode() pour l'érosion, et cv2.connectedComponents() pour le comptage. Ici tu combines tout ce que tu as appris dans les exercices précédents pour construire un pipeline complet à la main.

Le pipeline classique pour compter des objets clairs sur un fond sombre :

Étape 1 : Convertir en niveaux de gris (réduire à une seule valeur par pixel)
Étape 2 : Appliquer un flou (réduire le bruit)
Étape 3 : Seuiller (séparer objets et fond)
Étape 4 : Éroder (supprimer les petits artefacts)
Étape 5 : Compter les composantes connexes (chaque groupe de pixels blancs connectés = un objet)

Pour compter les composantes connexes, on utilise un algorithme de flood fill : on parcourt l'image, et à chaque fois qu'on trouve un pixel blanc non encore visité, on le marque et on marque tous ses voisins blancs (et les voisins de ses voisins, etc.). Chaque groupe marqué est un objet.

Écris une fonction pipeline_comptage(image_bgr, seuil, taille_flou, taille_erosion) qui prend :
image_bgr : une image couleur BGR (3D, uint8)
seuil : la valeur de seuillage (int)
taille_flou : la taille du kernel de flou (int impair)
taille_erosion : la taille du kernel d'érosion (int impair)

Elle renvoie un dictionnaire avec :
'image_gris' : l'image convertie en niveaux de gris (2D)
'image_floutee' : l'image après flou
'image_seuillee' : l'image après seuillage
'image_erodee' : l'image après érosion
'nb_objets' : le nombre de composantes connexes blanches (int)

Pour la conversion en gris, utilise la formule de luminance : 0.299*R + 0.587*G + 0.114*B.
Pour le comptage de composantes connexes, utilise une approche simple : parcours l'image, et quand tu trouves un pixel blanc non visité, compte un objet et marque tous les pixels connectés comme visités (flood fill avec une pile).

Exemple :
Une image avec 3 cercles blancs séparés sur fond noir donnera nb_objets = 3.

Ce que tu devrais voir sur ta machine : affiche chaque étape intermédiaire pour comprendre comment le pipeline transforme l'image progressivement.

Tests (5/5)

Cles presentes dans le résultat
import numpy as np
img = np.zeros((10, 10, 3), dtype=np.uint8)
result = pipeline_comptage(img, 128, 3, 3)
assert 'image_gris' in result
assert 'image_floutee' in result
assert 'image_seuillee' in result
assert 'image_erodee' in result
assert 'nb_objets' in result
Image noire zero objets
import numpy as np
img = np.zeros((10, 10, 3), dtype=np.uint8)
result = pipeline_comptage(img, 128, 3, 3)
assert result['nb_objets'] == 0, 'Une image noire ne doit contenir aucun objet'
Un objet
import numpy as np
img = np.zeros((20, 20, 3), dtype=np.uint8)
img[5:15, 5:15] = [255, 255, 255]
result = pipeline_comptage(img, 50, 3, 3)
assert result['nb_objets'] == 1, f'Un seul bloc blanc devrait donner 1 objet, obtenu {result["nb_objets"]}'
Deux objets séparés
import numpy as np
img = np.zeros((20, 40, 3), dtype=np.uint8)
img[5:15, 3:12] = [255, 255, 255]
img[5:15, 22:32] = [255, 255, 255]
result = pipeline_comptage(img, 50, 3, 3)
assert result['nb_objets'] == 2, f'Deux blocs séparés devraient donner 2 objets, obtenu {result["nb_objets"]}'
Image gris est 2D
import numpy as np
img = np.full((8, 8, 3), 100, dtype=np.uint8)
result = pipeline_comptage(img, 50, 3, 3)
assert len(result['image_gris'].shape) == 2, 'L image en gris doit etre 2D'
assert result['image_gris'].dtype == np.uint8

Indices (3 disponibles)

solution.py