Idée du projet :
Détection et poursuite d’un objet en mouvement par sa couleur avec matlab et Arduino en utilisant deux techniques de détections
Objectifs du projet :
- Savoir comment établir la liaison série entre Matlab & Arduino
- Savoir comment détecter une couleur précise dan l’image
- Savoir comment obtenir une couleur quelconque à partir d’une image RGB
- Savoir calculer le centre de gravité d’une région
- Et autres astuces.
Fonctionnement de la partie 2/2:
Détection et transmission de la donnée à la carte Arduino en temps réel en utilisant la camera de son ordinateur. C’est un exemple concret qui indique la détection ou non d’une couleur en utilisant deux indicateurs. Dans cette partie on va illustrer comment détecter d’autres couleurs et montrer l’importance du centre de gravité d’une région.
Comment détecter une autre composante couleur ?
Nous avons illustré durant notre projet comment détecter la composante rouge dans une image RGB. On peut effectuer la même opération pour la composante verte (G) ou bleue (B) de la façon suivante :
im_G=im_rgb(:,:,2);
im_B=im_rgb(:,:,3);
Le problème se pose quand on veut sélectionner une couleur différente du rouge, bleue ou verte ! Dans ce cas il faut créer une composante im_M qui est le mélange des trois composantes R (Red), G (Green) et B (Bleu). Ci-dessous des exemples pour 3 couleurs supplémentaires : Le problème se pose quand on veut sélectionner une couleur différente du rouge, bleue ou verte ! Dans ce cas il faut créer une composante im_M qui est le mélange des trois composantes R, G et B. Ci-dessous des exemples pour 3 couleurs supplémentaires :
RGB(0, 255,0)
RGB(46, 128, 129)
RGB (145, 255, 156)
RGB (255, 0, 0)
Obtenir plus des couleurs : ICI
C’est quoi le centre de gravité d’une région (ou image) ?
Le centre de gravité consiste à calculer le barycentre d’une image ou d’une région dans l’image. La fonction utilisée sur matlab permet de calculer le centre de gravité pour chaque région dans l’image, les régions dans l’image peuvent être connectées ou non. Pour calculer le barycentre on va utiliser la pondération de chaque pixel qui appartient à la région. Cette pondération va être sa valeur ligne et colonne. On peut calculer le centre de gravité d’une région de la façon suivante : Pour chaque pixel appartenant à la région, on calcule la somme des coordonnées lignes y_i et la somme de l’ensemble des coordonnées colonnes x_i. On obtient les coordonnées du barycentre (x_b, y_b) on divisant les sommes (x_i, y_i) par le nombre total des pixels actifs dans la région.
C’est quoi un pixel actif ?
Les pixels actifs sont les pixels ayant la valeur « 1 » dans une région dans une image binaire. Dans une région avec un périmètre données, il se peut qu’il existe des pixels nuls (veuillez consulter la partie une du projet afin de comprendre la notion du périmètre d’une région). Ci-dessous le programme de base matlab de calcul d’un barycentre d’une image.
x_i=0; y_i=0;
[M N]=size(im_bin)
NumPix=0;
for i = 1 : M
for j = 1 : N
if im_bin(i,j)==1
x_i=x_i+i;
y_i=y_i+j;
NumPix=NumPix+1;
end
end
end
x_b=floor(x_i/NumPix)
y_b=floor(y_i/NumPix)
Dans le cas pratique, dans une image, le nombre de région peuvent être différent de 1. Dans ce cas on fait appel à la fonction matlab regionprops() qui permet de calculer le centre de gravité pour chaque région dans l’image. Vous trouverai ci-dessous des exemples illustrant les centres de gravités dans diverses images et le programme Matlab correspondant.
clear al;
close all;
clc;
% Lecture de l'image
im_rgb=imread('im_3.jpg');
im_gray=rgb2gray(im_rgb);
% Conversion Gray to Binaire
im_bin= im_gray >50;
% Calcul des régions (une ou plusieures)
s = regionprops(im_bin,im_gray, 'WeightedCentroid');
% Affichage
figure(1)
subplot(121); imshow(im_bin); title('Image originale');
subplot(122);imshow(im_bin); title('Image avec les centres de gravite');hold on
numObj = numel(s);
for k = 1 : numObj
plot(s(k).WeightedCentroid(1), s(k).WeightedCentroid(2), 'b*');
end
Pourquoi le centre de gravité ?
Nous avons utilisé le centre de gravité pas uniquement pour embellir l’image ! Mais afin de remplacer toute une région (ensemble des pixels voisins connectés ou non) par UN SEUL pixel ! Pour objectif de faciliter les traitements en aval en tenant compte que d’un pixel à la place d’une région. Cette technique est utile par exemple pour suivre la trajectoire d’un objet en mouvement en affichant uniquement son centre de gravité dans le temps, Etc. le prochain projet (projet 4), on abordera un exemple concret basé sur le même principe de Réalité Augmenté (Augmented Reality (AR)) et la commande des dispositifs avec Arduino.
Note : La fonction matlab regionprops permet de calculer un ensemble des propriétés d’une région en particulier le centre d’un objet, son périmètre, ajouter des cadres, etc. Tapez « help regionprops » pour plus des détails dans l’interface matlab. Ci-dessous une liste non exhaustive des paramètres :
- ‘Area’
- ‘BoundingBox’
- ‘Centroid’
- ‘ConvexArea’
- ‘ConvexHull’
- ‘ConvexImage’
- ‘Eccentricity’
- ‘EquivDiameter’
- ‘EulerNumber’
- ‘Extent’
- ‘Extrema’
- ‘FilledArea’
- ‘FilledImage’
- ‘Image’
- ‘MajorAxisLength’
- ‘MinorAxisLength’
Programme principal Matlab (main_2.m)
close all;
clc;
%% Ouverture du port série
SerialCOM = Open(); % A commenter après la 1ère exécution
%% Création de l'objet vidéo
vid=videoinput('winvideo',1);
set(vid,'ReturnedColorSpace','RGB');
%% Détection de la composante rouge dans l'image
while 1
% Obtenir l'image actuelle
imm=getsnapshot(vid);
im_rgb=imresize(imm,[512 512]);
% Récupérer la composante R
im_gray=rgb2gray(im_rgb);
im_R=im_rgb(:,:,1);
im_r=imsubtract(im_R,im_gray);
%% Seuillage de l'image (Conversion en binaire)
% rr=sort(im_r(:));
% val=mean(rr(end-150:end))
val=abs(max(double(im_r(:)))-20);
seuil=val/255; % Seuil de l'image (variable)
Red_min=80; % Seuil minimal fix (Problème du à l'absence de la couleur cible)
im_bw=im2bw(im_r,seuil);
im_bw1=im_bw & (im_r >Red_min);
se=strel('disk',10);
im_out=imclose(im_bw1,se);
%% Add line
im_line=bwperim(im_out);
im_out1=im_rgb(:,:,2);
im_out1(im_out)=255; % im_line
im_out2=im_rgb;
im_out2(:,:,2)=im_out1;
%% Activation de la LED
% Nombre des pixels de la couleur rouge
taille_red=length(find(im_out(:)==1));
% Activation de la LED par pourcentage (0.5%) ( très dépendant de
% la taille de l'image)
taille_im=length(im_out(:));
Red_perc=100*taille_red/taille_im;
LED1=double(Red_perc>0.5);
% Activation de la LED par le nombre de pixel (indépendant de
% la taille de l'image)
Seuil_detec=100;
LED2=double(taille_red>Seuil_detec);
%% Centre de gravité
figure(1)
imshow(im_rgb);
s = regionprops(im_out, im_gray, {'Centroid','WeightedCentroid'});
title('Weighted (red) and Unweighted (blue) Centroids');
hold on
numObj = numel(s);
for k = 1 : numObj
plot(s(k).WeightedCentroid(1), s(k).WeightedCentroid(2), 'r*');
plot(s(k).Centroid(1), s(k).Centroid(2), 'bo');
end
hold off;
%% Affichage
% figure(2)
% subplot(221); imshow(im_rgb)
% subplot(222); imshow(im_r);
% subplot(223); imshow(im_out);
% subplot(224); imshow(im_out2);
%% Transmission à l'Arduino
% L'état des deux détecteurs
LED=[LED1 LED2]
% Transmission des données
Startt='#'; % Caractère de début de Tx
Endd='*'; % Caractère de fin de Tx
WriteData(LED,Startt,Endd, SerialCOM); % Transmission de données
end
%% Port Delete (Previous port if exist)
Delete(SerialCOM); % A exécuter seule pour libérer le port
Programme Arduino
/*
LED1: PIN 8
LED2: PIN 9
*/
int data_in_1=0;
int data_in_2=0;
void setup() {
/* ******************* LEDs ******************** */
// Configuration
pinMode(8, OUTPUT); // LED1
pinMode(9, OUTPUT); // LED2
// Initialisation
digitalWrite(8, LOW);
digitalWrite(9, LOW);
/* ******************* UART ********************** */
Serial.begin(9600);
}
void loop()
{
// Vous pouvez remplacer l'instruction IF par SWITCH...CASE
if (Serial.read() =='#')
{
while(1)
{
// Get data from serial port and set Red LED
data_in_1 = Serial.parseInt();
data_in_2 = Serial.parseInt();
// LED1
if (data_in_1==1)
digitalWrite(8, HIGH);
else
digitalWrite(8, LOW);
// LED2
if (data_in_2==1)
digitalWrite(9, HIGH);
else
digitalWrite(9, LOW);
if (Serial.read() =='*') break;
}
}
}
Photos du projet
Vidéo illustrative
************
Un petit commentaire de vous ou des belles étoiles, un Grand encouragement pour nous 🙂
************
Téléchargement du projet
************
2 réponses sur « Projets Matlab & Microcontrôleur #3: Reconnaissance des couleurs avec matlab et Arduino 2/2 »
bonjour je vous remercie pour votre projet qui est trop intéressant j’ai essayé de travailler dans le cadre de mon projet fin d’études mais un j’un problème au cours de la compilation votre réponse me serait d’une grande aide merci
voila l’eurreur
Cannot find an exact (case-sensitive) match for ‘Open’
The closest match is: open in F:\pfa\open.m
Error in Untitled3 (line 7)
SerialCOM = Open(); % A commenter après la 1ère exécution
Bonjour, est ce que vous avez bien la fonction Open() dans le dossier projet ?