Projets
Data ScienceSystèmes Embarqués

Triage automatique de haricots par CNN embarqué

Système de classification binaire de haricots blancs (bonne/mauvaise graine) en temps réel via un CNN Keras déployé sur ESP32-CAM. Projet de fin d'études L2 Génie Industriel, IST Antananarivo.

Par Sehenonirina Elisa Randriamasinoro, M1 Cybersécurité des Systèmes Embarqués, UBS Lorient

Code source20247 stack
[PYTHON][KERAS][TENSORFLOW][CNN][ESP32-CAM][C++][HTTP]

Contexte

Projet de fin d'études réalisé en L2 Génie Industriel à l'Institut Supérieur de Technologie d'Antananarivo. Première approche complète alliant mécanique, systèmes embarqués et machine learning.

Objectif : concevoir une machine compacte et économique pour trier automatiquement les haricots blancs (bonnes vs mauvaises graines) en remplaçant le tri manuel par une classification CNN en temps réel via ESP32-CAM.

Dataset

340 images de haricots blancs capturées en conditions contrôlées (luminosité constante, même angle, même appareil) :

ClasseImages
Mauvaise graine209
Bonne graine131
Total340

Split : 60% entraînement / 30% validation / 10% test. Les images sont redimensionnées à 224×224 pixels avant entraînement.

Architecture du modèle CNN

Réseau convolutif binaire avec extracteur de caractéristiques (blocs Conv2D + MaxPooling) suivi d'un classifieur dense. Sortie : 1 neurone sigmoïde (classification binaire). 31 561 441 paramètres entraînables.

model = Sequential([
    Conv2D(32, (3, 3), activation='relu', input_shape=(224, 224, 3)),
    MaxPooling2D(2, 2),
    Conv2D(64, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    Conv2D(128, (3, 3), activation='relu'),
    MaxPooling2D(2, 2),
    Flatten(),
    Dense(512, activation='relu'),
    Dropout(0.5),
    Dense(1, activation='sigmoid')
])

model.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy']
)
PYTHON

Entraînement

10 époques sur les 204 images d'entraînement, avec validation en temps réel sur les 102 images de validation.

ÉpoqueLossAccuracyVal LossVal Accuracy
12.39080.44790.62650.6250
20.66370.59380.58010.6146
30.55580.69790.50580.9792
40.44340.91670.31620.9583
50.26510.97400.24640.9062
60.14850.95830.07460.9792
70.05660.99480.09190.9688
80.05020.99480.01611.0000
90.02070.98960.01021.0000
Courbes loss et val_loss sur 10 époques
Courbes loss / val_loss, convergence jusqu'à l'époque 6, légère divergence ensuite

Résultats

98% d'accuracy sur le jeu de test (34 images non vues pendant l'entraînement). Le modèle est sauvegardé sous image_model.h5 et rechargé par le script d'inférence Python qui pilote la bascule via HTTP.

model = load_model('image_model.h5')

resp = requests.get('http://192.168.1.100/capture')
img = preprocess(resp.content)          # resize 224x224, normalize
pred = model.predict(img)[0][0]         # sigmoid → [0, 1]

direction = 'droite' if pred > 0.5 else 'gauche'  # seuil 0.5 — version fonctionnelle initiale
requests.get(f'http://192.168.1.100/servo?dir={direction}')
PYTHON

Seuil de décision fixé à 0.5, frontière naturelle de la fonction sigmoid pour une classification binaire. Valeur choisie pour cette première version fonctionnelle.

Pipeline système

Tas de haricots
      ↓
Cylindre + disque perforé
(alimentation unitaire — 1 haricot à la fois)
      ↓
Plateau d'acquisition
      ↓
ESP32-CAM capture l'image
      ↓ HTTP GET /capture.jpg
Ordinateur (Python)
      ↓
Prétraitement (resize 224×224, normalisation)
      ↓
CNN — image_model.h5
      ↓
Prédiction sigmoid → valeur entre 0 et 1
      ↓ HTTP POST /prediction
ESP32-CAM reçoit la décision
      ↓
Servomoteur SG90
  ├── prédiction > 0.5 → bascule droite (bonne graine)
  └── prédiction ≤ 0.5 → bascule gauche (mauvaise graine)

Limites

  • Dataset limité, 340 images au total, jeu de test de seulement 34 images. La valeur de 98% d'accuracy est statistiquement fragile sur un si petit échantillon de test.
  • Conditions contrôlées, luminosité fixe, angle fixe, même appareil. La robustesse du modèle en conditions réelles (variations d'éclairage, position des graines) n'a pas été testée.
  • Modèle surdimensionné, 31 561 441 paramètres pour une classification binaire simple. Un modèle beaucoup plus léger serait suffisant et plus adapté à un contexte embarqué.
  • Métriques basiques, seule l'accuracy a été mesurée. Matrice de confusion, F1-score et courbe ROC n'ont pas été calculés dans le cadre de ce projet L2.

Perspectives

  • Data augmentation, rotations, variations de luminosité, flips pour enrichir le dataset sans nouvelles captures
  • Transfer learning, remplacer le CNN custom par MobileNetV2, 10× plus léger et plus robuste sur petits datasets
  • Edge AI, déployer le modèle directement sur l'ESP32 via TensorFlow Lite pour éliminer la dépendance à l'ordinateur
  • Métriques complètes, calculer la matrice de confusion, précision et rappel par classe pour mieux évaluer les erreurs réelles du modèle

Système embarqué et mécanique

Un cylindre + disque perforé alimente les haricots un par un sur un plateau d'acquisition. L'ESP32-CAM capture la photo, l'ordinateur fait l'inférence CNN, puis commande le servomoteur SG90 qui bascule à droite (bonne graine) ou à gauche (mauvaise graine).

L'ESP32-CAM est programmée en C++ et configurée en point d'accès WiFi agissant comme serveur HTTP. L'ordinateur Python se connecte comme client.

Communication :

  • GET /capture.jpg, ESP32-CAM déclenche la rotation du disque, capture l'image et la retourne au PC
  • POST /prediction, PC envoie la décision CNN (0 ou 1), ESP32-CAM commande le servomoteur en conséquence

Composants partie opérative :

ComposantRôle
Moteur CC JgA25-370 (12V, 10 RPM)Rotation du disque perforé
Driver L298NRégulation vitesse et sens du moteur
Servomoteur SG90 (0°–180°)Bascule de tri droite/gauche
Vue éclatée du système
Vue éclatée, nomenclature des 9 pièces du mécanisme d'alimentation
Vue assemblée du système
Vue assemblée, cylindre et disque perforé montés
Système complet avec ESP32-CAM et servomoteur
Système complet, ESP32-CAM et servomoteur SG90 intégrés

Projets similaires

Tous les projets
Systèmes EmbarquésCybersécurité

Analyse et injection sur bus CAN automobile

Reverse engineering des trames CAN d'une maquette véhicule, cartographie des bus, décodage des signaux moteur/éclairage/confort, base DBC et DLL d'injection en C simulant un système ADAS.

2026
Systèmes Embarqués

DriveInsight, Gestion de parc automobile connecté

Plateforme web de réservation de véhicules couplée à un système embarqué de télémétrie IoT en temps réel. Particle Boron + GPS + capteurs physiques + tableau de bord admin.

2025