Idée du projet :
Détection et poursuite d’un objet en mouvement par sa couleur avec matlab et Arduino
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 utiliser un seuil optimal d’une image
- Savoir utiliser quelques fonctions de morphologie mathématique
- Savoir extraire le contour d’une région dans l’image
- Et autres astuces.
Fonctionnement:
Le projet dans sa globalité permet de détecter une couleur précise dans un flux vidéo différé ou dans un flux issu d’une camera de son ordinateur. La détection de la couleur est indiquée par l’allumage d’une LED branchée avec la carte Arduino. La sensibilité du détecteur est définie par des variables dans le programme matlab. La transmission des données entre l’interface matlab et la carte Arduino est obtenue grâce à l’interface série (voir le projet 1 et 2 pour plus des détails sur la trame des données et l’interface série).
Le projet est subdivisé en deux parties :
- Partie 1 : Détection d’une couleur dans un flux vidéo déféré. Dans cette partie uniquement l’interface matlab est utilisée pour le traitement et l’analyse de flux vidéo.
- Partie 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. Dans les deux parties on va se focaliser sur la détection de la couleur rouge, mais vous pouvez choisir n’importe quelle couleur grâce à une astuce pratique de détermination de la couleur.
Principe de la méthode de détection :
Le principe de la méthode utilisée dans ce projet est relativement simple. Il consiste à soustraire la couleur qu’on veut détecter de l’image en niveau de gris issue de l’image originale (image RGB) ! Exemple : On considère une image couleur nommée RGB, et im_gray l’image en niveau de gris obtenue à partir de l’image RGB en utilisant la fonction de conversions rgb2gray (im_gray=rgb2gray(RGB)). On considère im_r l’image résultante obtenue à partir de la composante rouge im_R. L’image im_r est obtenue comme suit :
Im_r=im_R-im_gray
Les pixels les plus clairs de l’image im_r indiquent la présence de la couleur rouge dans l’image. Les pixels sombres montrent l’absence de la cette dernière. L’image ci-dessous montre effectivement dans l’image résultante que la zone du marqueur est plus claire (valeur proche du blanche ou 255) en revanche les autres pixels de l’image on tendance à avoir des valeurs proches de 0 (noirs). Il sera ensuite plus simple d’extraire uniquement la zone la plus claire de l’image et mettre à zéros le reste des pixels grâce au choix d’un seuil « optimal ».
% Lecture de l'image
RGB=imread('im_1.jpg');
% Récupérer la composante R
im_gray=rgb2gray(RGB);
im_R=RGB(:,:,1);
% Calcul de l'image résultante
im_r=imsubtract(im_R,im_gray);
% Affichage
figure(1)
subplot(221); imshow(RGB); title('Image couleur RGB');
subplot(222); imshow(im_gray); title('Image au NG');
subplot(223); imshow(im_R); title('Composante Rouge');
subplot(224); imshow(im_r); title('Image résultante');
L’image résultante contient des valeurs variées entre 0 et 255, autrement dit 256 niveaux. L’opération de seuillage permet d’obtenir une image binaire (ou logique) qui contient uniquement deux valeurs 0 (pixel noir) ou 1 (pixel blanc). Elle consiste à mettre à 1 tous les pixels ayant des valeurs supérieures au seuil et à 0 les autres pixels de l’image. Donc il est important de bien choisir le seuil afin de filtrer les zones inutiles dans l’image. L’image ci-dessous montre l’exemple d’une image binaire pour divers seuils accompagnée du code matlab.
% Effet de seuil
im_s1= im_r>10;
im_s2= im_r>50;
im_s3= im_r>100;
im_s4= im_r>250;
% Affichage
figure(2)
subplot(221); imshow(im_s1); title('Seuil=10');
subplot(222); imshow(im_s2); title('Seuil=50');
subplot(223); imshow(im_s3); title('Seuil=100');
subplot(224); imshow(im_s4); title('Seuil=250');
Pourquoi c’est important de choisir un bon seuil ?
La ligne du code im_s1= im_r>10 (voir le code ci après) indique la conversion de l’image im_r en une image binaire im_s1 avec un seuil égal à 10. La fonction matlab im2bw permet de réaliser la même opération (Exemple : im_s1 =im2bw(im_r,10)). Il est clair qu’un mauvais choix du seuil peut faire disparaitre tous les pixels dans l’image ou capter les zones intitules. En résumé, la robustesse de la technique dépond du bon choix du seuil.
Comment choisir un seuil optimal ?
L’idée qui vient à l’esprit est de maintenir les pixels ayant des valeurs importantes et d’éliminer les autres. Mais comment décider des pixels ayant des grandes valeurs et quand ce qu’on peut décider d’éliminer les autres? L’approche le plus simple est de déterminer la valeur maximale des pixels de l’image qui peut être différente de 255, elle dépend de degré de ressemblance de l’image et la couleur qu’on décide de détecter, par exemple si les deux couleurs sont parfaitement identiques( dans notre cas le rouge), la valeur maximale sera égale à 255, mais si la couleur est proche du rouge, la valeur sera forcement importante mais inférieure à 255. L’astuce de la première technique consiste à calculer la valeur maximale et de soustraire une valeur fixe qui garantie une bonne détection des valeurs ayant la couleur rouge ou « presque rouge ». Le seuil peut être défini de la façon suivante:
Seuil=max(im_r)-R_min, R_min: valeur fixe
On constate que la valeur du seuil change pour différente image, qui rend notre seuil adaptatif à l’image ! La valeur R_min garantie la détection d’une fourchette des couleurs au voisinage du rouge. Dans notre cas on utilisera une valeur modérée de R_min égale à 20. Voir l’image ci-dessous pour savoir l’effet du choix de R_min.
% Effet de seuil
im_s1= im_r>max(double(im_r(:)))-0;
im_s2= im_r>max(double(im_r(:)))-20;
im_s3= im_r>max(double(im_r(:)))-50;
im_s4= im_r>max(double(im_r(:)))-100;
% Affichage
figure(3)
subplot(221); imshow(im_s1); title('R_{min}=0');
subplot(222); imshow(im_s2); title('R_{min}=20');
subplot(223); imshow(im_s3); title('R_{min}=50');
subplot(224); imshow(im_s4); title('R_{min}=100');
Autre astuce du choix de seuil:
La deuxième approche consiste à trier tous les pixels par ordre décroissant, puis on prend la moyenne de N premières valeurs. Par exemple N=100. L’avantage de cette technique est qu’on est sure de choisir un seuil moyenne dans la fourchette de la couleur ciblée. L’inconvénient de la technique et le temps important dédiée à l’opération du tri de l’image surtout quand la taille de l’image est importante.
Note : On peut également soustraire une valeur R_min pour la deuxième technique afin de garantir une bonne détection (voir le programme principal à la fin de l’article).
C’est quoi la solution ?
On peut ajouter une condition supplémentaire au moment du seuillage de l’image. Il suffit d’ajouter un autre seuil minimal FIXE limitant la valeur minimal de la couleur à détectée. La nouvelle image binaire im_bin_new peut être définit comme suit en fonction de l’ancienne image im_bin_old et le seuil fixe seuil_fixe:
im_bin_new=im_bin_old & (im_r >seuil_fixe)
Dans ce cas on est sure d’avoir une image nulle durant l’absence de la couleur cible.
Comment obtenir le périmètre d’une région ?
Il s’avère important dans les systèmes de détection et de suivi d’un objet de s’intéresser uniquement au périmètre d’une région. Il consiste à maintenir uniquement le contour de la région à la place de l’ensemble des ses pixels. On peut utiliser la fonction Matlab bwperim() pour cet effet. Les exemples ci-dessous illustreent le principe de fonctionnement de la fonction.
Comment calculer le taux d’une région dans une image?
Après l’opération de détection de la couleur il faut bien décider de la présence ou non de cette dernière dans l’image. Il faut définir une limite de détection, dans notre cas on va considérer le pourcentage de présence d’une couleur dans l’image. Il est définit comme étant le rapport entre le nombre de pixels actifs (ayant la valeur 1 dans l’image binaire) par rapport au nombre total des pixels de l’image (hauteur x longueur). Une valeur de 1% peut être raisonnable pour décider de la présence ou non d’une couleur.
Taux=100*num_pixReg/taille_im
Le programme principal matlab (main_1.m):
clear all;
close all;
clc;
%% Lecture de la vidéo
vid=vision.VideoFileReader('v1.mp4');
%% Détection de la composante rouge de l'image
% Masque pour la fonction imclose (voir help strel)
se=strel('disk',10);
% Acquisition, traitement & affichage
while ~isDone(vid)
% Etraction d'une image dans le flux vidéo
RGB=step(vid);
RGB=uint8(255.0*double(RGB));
im_rgb=imresize(RGB,[256 256]);
% Récupérer la composante R
im_gray=rgb2gray(im_rgb);
im_R=im_rgb(:,:,1);
% Calcul de l'image résultante
im_r=imsubtract(im_R,im_gray);
% Seuillage de l'image (binérisation)
% rr=sort(im_r(:));
% val=mean(rr(end-150:end))
r_min=40;
val=abs(max(double(im_r(:)))-r_min);
seuil=val/255; % Seuil de l'image (variable)
seuil_fixe=100; % Seuil minimal fixe ( Problème absence de la couleur cible)
im_bw=im2bw(im_r,seuil);
im_bw1=im_bw & (im_r >seuil_fixe);
im_out=imclose(im_bw1,se);
% Détecter le périmètre d'une région (NG +Périmètre)
im_line=bwperim(im_out);
im_out1=im_rgb(:,:,2);
im_out1(im_line)=255;
% RGB + Périmètre
im_out2=im_rgb;
im_out2(:,:,2)=im_out1;
% RGB + Région
im_out3=im_rgb;
im_30=find(im_out==1);
im_out3(im_30)=0;
% Calcul du pourcentage de la couleur rouge dans l'image
taille_red=length(find(im_out(:)==1));
taille_im=length(im_out(:));
Red_perc=100*taille_red/taille_im
%% Affichage
figure(1)
% imshow(im_out);
% imshow(im_out1);
subplot(121); imagesc(im_out2);
subplot(122); imagesc(im_out3);
end
Photos du projet:
************
Un petit commentaire de vous, un Grand encouragement pour nous 🙂
************
Téléchargement du projet
************
Vidéo illustrative
************