Etude statistique d`histogrammes en image

Transcription

Etude statistique d`histogrammes en image
Master MAD 1ere année
Université d’Orléans 2005-2006
MARTIN Benjamin
Etude statistique
d’histogrammes en image
Maı̂tre de stage : Maitine BERGOUNIOUX
Tuteur : Jean-Pierre LAMARCHE
Université d’Orléans - Faculté des Sciences
1, Rue de Chartres BP 6759
45067 Orléans cedex 2
Téléphone : (+33) 02.38.41.73.16
Téléphone : ( +33) 02.38.41.71.71
1
1
Remerciements
Je tiens à remercier particulièrement Madame Maitine Bergounioux,
sans qui je n’aurais jamais pu faire ce stage, pour sa disponibilité et son
aide continuelle durant ces deux mois.
Je remercie également Monsieur ROZENBAUM et Monsieur ROUET,
pour m’avoir fait découvrir leur travail au sein de l’ISTO.
Et un grand merci à Amandine, Caroline et Xavier pour toutes les
pauses durant le stage.
2
Table des matières
1 Introduction
4
2 Analyse des images
2.1 Préliminaires . . . . . . . . .
2.1.1 Rappels . . . . . . . .
2.1.2 Problème de contraste
2.1.3 Problème du cache . .
2.2 Algorithme de démélange . .
2.3 Test de Kolmogorov-Smirnov
2.4 Automatisation . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
5
6
6
9
11
18
20
3 Conclusion
22
4 Références
23
5 Annexes
24
3
1
Introduction
Ce rapport présente le travail effectué durant 2 mois au sein du
laboratoire MAPMO (Mathématiques et Applications, Physique
Mathématique d’Orléans) pour l’ISTO (Institut des Sciences de la Terre
d’Orléans) dans le cadre du stage de première année de Master
Mathématiques pour l’Aide à la Décision, qui s’est déroulé du 10 mai au 10
juillet 2006.
Le travail effectué contribue à l’étude de l’Altération des pierres du
patrimoine bâti, sujet de recherche au sein de l’ISTO. Le but de ce stage
était d’analyser les histogrammes des images de coupe de tuffeau, estimer
les paramètres statistiques des histogrammes et ainsi, fournir les bases
pour une segmentation en régions de la pierre.
4
2
Analyse des images
2.1
Préliminaires
Pour l’ensemble du stage, on va analyser des microtomographies de
tuffeaux obtenues à l’ESRF. Toutes les images de tuffeaux sont de même
résolution 512x512 pour une question de rapidité des algorithmes. Celles
d’origine sont en 2048x2048.
Les résultats seront les mêmes que sur les images non retaillées, la
compression étant quasi-sans perte.
Toutes les fonctions ont été écris sous MATLAB.
Le logiciel MATLAB
Le nom MATLAB provient de la contraction de MATrix LABoratory.
C’est un langage de calcul scientifique basé sur le type de variable
matricielle. Ses grandes capacités de calcul numérique lui permet d’être
appliqué à différents domaines scientifiques tels traitement du signal,
automatisme, etc.
L’utilisation de MATLAB peut se faire de façon interactive en exécutant
des commandes directement après le prompt ou par des scripts. Ces
dernier peuvent être des simples programmes ou des fonctions avec des
paramètres d’appel et de retour.
Malgré un prix élevé et une concurrence des logiciels gratuits (scilab en
tête) grandissante, MATLAB reste le plus complet, et surtout le
performant des logiciels de calcul matriciel.
Les fonctions sont placés en annexe mais sont aussi en ligne :
http://alainparaponaris.free.fr/stageisto/
5
2.1.1
Rappels
Chaque image (en niveau de gris) peut être représentée comme une
matrice où chaque élément correspond au niveau de gris du pixel (picture
element) de l’image. Une image de résolution 512x512 est donc une matrice
de dimension 512x512 où le premier pixel est le premier élément de la
matrice. Chaque élément sont compris en 0 (correspondant au noir) à 255
(correspondant au blanc)
Pour éviter les confusions, élément, pixel ou encore niveau de gris désigne
la même chose.
Par convention on va appeller M la matrice image.
2.1.2
Problème de contraste
On suppose que les photos des coupes de tuffeaux ont été prise en même
temps. Malgré celà, on peut avoir des images avec un contraste différent.
Exemple d’une même image avec deux contrastes différents :
M(1,1)=102
M(1,1)=161
6
Histogramme associé aux deux images :
4
6
4
x 10
6
5
5
4
4
3
3
2
2
1
1
0
−50
0
50
100
150
200
250
x 10
0
−50
300
0
50
100
150
200
250
300
On remarque que pour deux contrastes différents sur une même image
on obtient deux histogrammes différents. On va donc utiliser une fonction
d’uniformisation du contraste sur toutes les images :
autocontraste(nom,type)
Où nom est le nom de base de l’image (ici ′ ndrp_′ ) et type est le format de
l’image (ici ′ png′ ) .
Pour être certain d’avoir le même niveau de gris, on prend comme repère
le premier élément de la matrice de chaque image. Il correspond à celui du
cache.
On fait fait la moyenne sur toutes les images et on ajuste le contraste
pour celles qui n’ont pas le même que le niveau de gris moyen. Puis on
écrase les anciennes images en les remplaçant par les nouvelles.
Exemple d’utilisation
On prend deux images dont on change le contraste :
7
Puis on lance la fonction d’autocontraste :
On vérifie maintenant que toutes les images sont au même contraste :
8
2.1.3
Problème du cache
Comme on a pu le constater sur les histogrammes précédent, il y a un
pic sur un niveau de gris. C’est celui qui correspond au cache.
L’analyse de l’image sera faussée si on garde ce cache, on propose donc une
fonction qui transforme la matrice image en un vecteur dont on aura
enlevé au préalable les éléments du cache :
[H,N]=histogramme3(M,cadre)
Où M est la matrice image, cadre est le premier élément de la matrice (ici
M(1,1)) , N est le vecteur de la matrice image sans le cache et H est un
vecteur de taille 256 qui comptabilise les niveaux de gris pour afficher
l’histogramme.
Etant limité par les capacités de la machine, au préalable on fait un test
pour connaitre la taille moyenne du vecteur image (sans le cache). Ce
vecteur moyen à 204774 éléments. En initialisant le vecteur on gagne plus
de temps que si l’on crée le vecteur au fur et à mesure.
On part toujours du principe que le premier et dernier élément de la
matrice fait partie du cache (ce qui est toujours le cas).
On parcourt donc chaque vecteur ligne de la matrice des deux cotés et
prend en compte les élement dès qu’ils sont différent du cadre. Comme on
parcourt de chaque coté, les élément restant ne font pas parti du cadre
donc on passe à la ligne suivante.
De plus si l’image possède plus d’élément que le vecteur initialisé, on
rajoute à la fin du vecteur les éléments manquant. Au contraire si le
vecteur initialisé est trop grand, on le tronque à la bonne taille (donnée
par un compteur).
Exemple d’utilisation
On teste la fonction sur une image :
9
ici le vecteur image est de taille 204772, on affiche l’histogramme de
l’image sans le cache avec bar(H) :
2500
2000
1500
1000
500
0
0
50
100
150
10
200
250
300
En comparrant aux histogrammes précédent, on voit bien la disparition
du pic dûe au cache. Sur cet histogramme, on remarque trois bosses du
mélange des trois gaussiennes. On va maintenant étudier les histogrammes
de toutes les images.
2.2
Algorithme de démélange
On va maintenant supposer que l’histogramme est issue d’un mélange de
trois gaussiennes.
C’est à dire l’histogramme est une fonction d’une somme de densités de 3
gaussiennes :
11
C’est à dire :
f (x) =
3
P
i=1
αi N (µi , σi2 )
On va estimer les paramètres :
- αi qui correspond au poids de la la gaussienne i.
- µi qui correspond à la moyenne de la gaussienne i.
- σi2 qui correspond à l’écart type au carré de la gaussienne i.
On utilise la méthode du maximum de vraissemblance :
On pose : P (x, θj ) = N (µi , σi2 )
et pour chaque itération k = 1..3 on calcule
αkj P (xi ,θjk )
3
P
αkl P (xi ,θlk )
P k (j, xi ) =
avec θjk = (µi , (σik )2 )
l=1
αik+1 = n1 P k (j, xi )
µk+1
i
n
P
=
avec j = 1..3
et n = card(N )
avec j = 1..3
et n = card(N )
avec j = 1..3
et n = card(N )
xi P k (j,xi )
i=1
n
P
P k (j,xi )
i=1
(σik+1 )2
n
P
=
i=1
(xi −µk+1
)2 P k (j,xi )
i
n
P
P k (j,xi )
i=1
ϕk+1 = (αik+1 , µk+1
, (σik+1 )2 )
j
On s’arrète quand ϕk+1 − ϕk ≤ ǫ
On propose un algorithme sous MATLAB pour estimer les différents
parametres :
[a,mu,sigma]= demelange(a0,mu0,sig0,N)
Avec N le vecteur image, a0,mu0,sig0 les paramètres de départ, leur
valeur n’a pas réellement d’importance, mais la limitation de la machine
fait qu’on se doit de les choisir.
12
Dans ce cas on pose :
- a0=[0.45,0.25,0.3]
- mu0=[104,132,172]
- sig0=[8,9,6]
Exemple d’utilisation
On teste l’algorithme sur une image :
13
Maintenant que l’on a les trois gaussiennes :
0.4761 ∗ N (131.4743, 46.1035)
0.3662 ∗ N (103.6867, 18.9493)
0.1577 ∗ N (172.1166, 13.2387)
On peut désormais comparer le graphe des gaussiennes avec l’histogramme :
2500
2000
1500
1000
500
0
0
50
100
150
200
250
300
0
50
100
150
200
250
300
0.012
0.01
0.008
0.006
0.004
0.002
0
14
On remarque que les deux graphes sont similaires. on peut ainsi tester
l’algorithme de démélange sur l’ensemble des images pour savoir s’il est
robuste et surtout si l’ensemble des histogrammes des images suit un
mélange de gaussiennes.
Pour cela, on va le tester sur 10 lots de 15 images contigues et en faire la
moyenne (en tout 150 images), puis sur la concaténation de ses mêmes lots
d’images. on propose donc la fonction suivante :
[amoy,mumoy,sigmamoy,a,mu,sigma]=compare2
Où amoy, mumoy, sigmamoy sont les moyennes des paramètres α, µ et
σ, et a, mu, sigma sont les mêmes paramètres des concaténations des
images.
15
Les moyennes des paramètres sont proches, voir les mêmes que les
paramètres des concaténations des images.
On va le mettre en évidence en faisant la moyenne des écarts de chaque
paramètre des gaussiennes :
ecarta
=
-0.0974
0.0628
0.0346
ecartmu
=
0.2237
1.6306
-1.0458
ecartsigma =
1.5585
2.1616
1.8364
Pour les 3 gaussiennes on voit bien que si l’on concatène les images ou si
l’on fait la moyenne, on obtient quasiment les mêmes paramètres.
L’algorithme de démélange est bien robuste. On peut ainsi faire une
classification en trois dimensions des images de tuffeaux.
Pour vérifier si l’algorithme de démélange est robuste pour les 150
images, il faut environ 2h (sur un pc portable de puissance moyenne). En
imaginant que l’on manque de temps ou plus que 150 images, on aurait pu
tirer au hasard (par exemple suivant une loi uniforme) un nombre d’image
définie. Par exemple 60 images pour un lot total de 300 images. Mais il ne
faut pas oublier que le but de cette étude est de pouvoir recréer en 3 D le
réseau poreaux. Il faut donc que les images soient contigues. On peut tirer
alors une image au hasard puis de tester un nombre d’image donné par
avance (au choix de l’utilisateur).
16
On propose la fonctions suivant :
[amoy,mumoy,sigmamoy,a,mu,sigma]=comparehasard
Où amoy, mumoy, sigmamoy sont les moyennes des paramètres α, µ et
σ, et a, mu, sigma sont les mêmes paramètres des concaténations des
images. Exemple d’utilisation
On le teste sur 30 images
On obtient les mêmes résultats que précédement. C’est suffisant pour
17
vérifier la robustesse de l’algorithme de démélange tant que le nombre d’image
à tester est suffisament grand.
Depuis le début on a supposé que l’histogramme des images suivait un
mélange de gaussiennes. Maintenant que l’on a déterminé les paramètres,
montrons que les histogrammes suivent bien les 3 gaussiennes en utilisant
un test statistique.
2.3
Test de Kolmogorov-Smirnov
Le but est de calculer, pour un lot d’image tiré au hasard, la distance
maximale entre les 3 gaussiennes avec les paramètres estimés et son
histogramme.
On compare cette distance avec une certaine valeur, que l’on calcule,
alors on peut accepter ou non que l’echantillon (l’histogramme) est issu
d’un mélange gaussien.
1) On tire une image au hasard parmi 150
2) On calcule la distance maximale Dsk
3) On détermine la valeur critique Dn suivant le seuil α = 5%
4) Si Dsk < Dn , on peut accepter que l’échantillon est un mélange
gaussien.
Pour cela on va utiliser la fonction suivant :
[I]=gaussiennehasard
Où I est le vecteur qui garde en mémoire les différentes images testées.
Exemple d’utilisation
18
Pour gagner du temps on fait le test sur 30 images tirées au hasard
suivant une loi uniforme sur un paquet de 150 images contigues.
19
Au seuil α = 5% on peut accepter l’hypothèse Ho : Les images sont
issues d’un mélange gaussien.
2.4
Automatisation
Pour finir, on a fait un script qui utilise toutes les fonctions précédents.
il suffit de lancer :
automatisme
L’utilisateur suit les instructions pour obtenir les paramètres des images
et la vérification des résultats.
20
Exemple d’utilisation
21
3
Conclusion
Ce stage est une petite pierre à l’édifice du projet de recherche :
”Altération des pierres du patrimoine bâti”. Ce travail sera utilisé pour
faire une segmentation en région des pierres. Une fois cette étape effectuée,
on pourra quantifier le milieu à l’aide de différents estimateurs : porosité,
surface spécifique etc. Ces outils permettront de comparer
quantitativement une zone altérée d’une zone intacte (ou provenant
directement d’une carrière) et ainsi de caractériser l’évolution du réseau
poreux causée par l’altération.
Pour réaliser ce stage, j’ai eu l’opportunité de travailler sous MATLAB.
Cette expérience enrichissante m’a donné gout à ce type de logiciel et ses
différents domaines d’utilisation.
Enfin, ce stage m’a offert la possibilité de découvrir une autre dicipline que
les mathématiques et la passion qui peut en découler.
22
4
Références
[1] J-T. LAPRESTE. Introduction à MATLAB. ÉD. ellipses.
[2] J-T. LAPRESTE. aide-mémoire MATLAB. ÉD. ellipses.
[3] M. Rautureau. Tendre comme la pierre. ÉD. Région Centre.
[3] Wikipedia. Algorithme espérance-maximisation.
http://fr.wikipedia.org/wiki/Expectation-Maximization.
23
5
Annexes
Programmation
autocontraste
function autocontraste(nom,type)
code=zeros(1,150);
for i=0:149
if i<10
M=imread([nom,’00’,int2str(i),’.’,type]);
elseif i>9 & i<100
M=imread([nom,’0’,int2str(i),’.’,type]);
else
M=imread([nom,int2str(i),’.’,type]);
end
code(i+1)=M(1,1);
end
moy=sum(code)/150
cont=find(code==int8(moy));
test=0;
if max(size(cont))~=max(size(code))
test=1;
cont=find(code~=int8(moy));
texte=[’Il y a ’,int2str(max(size(cont))),’ image(s) mal contrastées’];
disp(texte);
for j=1:max(size(cont))
i=cont(j)-1
if i<10
M=imread([nom,’00’,int2str(i),’.’,type]);
elseif i>9 & i<100
M=imread([nom,’0’,int2str(i),’.’,type]);
else
M=imread([nom,int2str(i),’.’,type]);
end
diff=double(int8(moy)-int8(M(1,1)))
M(:,:)=M(:,:)+diff;
p=find(M<0);
M(p)=0;
24
g=find(M>255);
M(g)=255;
if i<10
image=[nom,’00’,int2str(i),’.’,type];
elseif i>9 & i<100
image=[nom,’0’,int2str(i),’.’,type];
else
image=[nom,int2str(i),’.’,type];
end
imwrite(M,image,type);
end
end
if test==0
[’Les images sont bien contrastées’]
end
25
histogramme3
function [H,N]=histogramme3(M,cadre)
H=zeros(256,1);
nblig=size(M,1);
nbcol=size(M,2);
N=zeros(1,204774);
l=0;
for u=1:nblig
stop=0;
i=1;
while(i<=nbcol & M(u,i)==cadre)
i=i+1;
end;
if i<nbcol
k=i;
while (k<=nbcol & stop==0)
j=k;
if M(u,k)==cadre
while (j<nbcol & M(u,j)==cadre)
j=j+1;
end;
if j<nbcol
l=l+1;
if l>max(size(N));
N=[N M(u,k)];
else
N(l)=M(u,k);
end;
H(M(u,k)+1)=H(M(u,k)+1)+1;
else
stop=1;
end;
else
l=l+1;
if l>max(size(N))
N=[N M(u,k)];
26
else
N(l)=M(u,k);
end;
H(M(u,k)+1)=H(M(u,k)+1)+1;
end;
k=k+1;
end;
end;
end;
if l<max(size(N))
N=N(1:l);
end;
H=H’;
bar(H);
N=double(N);
27
demelange
function [a,mu,sigma]= demelange(a0,mu0,sig0,N)
n=size(N,2);
k=3;
it=0;
itmax=300;
tol=1/100;
erreur=1;
Proba=zeros(k,n);
a=a0;
mu=mu0;
sigma=sig0;
while (it < itmax)&( erreur > tol)
sp=0;
for j=1:k
Proba(j,:)= a0(j)*normpdf(N,mu0(j),sig0(j) );
sp=sp+Proba(j,:);
end;
for j=1:k
Proba(j,:)=Proba(j,:)./sp;
S=sum(Proba(j,:));
a(j)=S/n ;
mu(j)=sum(N.*Proba(j,:))/S ;
sigma(j)=sum((N-mu(j)).^2.*Proba(j,:))/S;
sigma(j)=sqrt(sigma(j));
end;
e=[norm(mu -mu0) norm(sigma-sig0) norm(a-a0)];
erreur=norm(e);
a0=a;
mu0=mu;
sig0=sigma;
it=it+1;
end
y=0;
for j=1:k
y=y+a(j)*normpdf([0:255],mu(j),sigma(j) );
28
end;
clf();
plot([0:255],y)
a
mu
sigma
29
compare2
function [amoy,mumoy,sigmamoy,a,mu,sigma]=compare2
amoy=[];
a=[];
mumoy=[];
mu=[];
sigmamoy=[];
sigma=[];
depart=0;
arrive=14;
for j=1:10
j
aD =[0.45,0.25,0.3];
muD=[104,130,172];
sigmaD=[8,9,6];
tempa=[];
tempmu=[];
tempsigma=[];
Ntemp=[];
it=0;
a0=aD;
mu0=muD;
sigma0=sigmaD;
for i=depart:arrive
it=it+1;
if i<10
M=imread([’ndrp_00’,int2str(i),’.png’]);
elseif i>9 & i<100
M=imread([’ndrp_0’,int2str(i),’.png’]);
else
M=imread([’ndrp_’,int2str(i),’.png’]);
end
[H,N]=histogramme3(M,M(1,1));
[a0,mu0,sigma0]= demelange(a0,mu0,sigma0,N);
tempa=[tempa;a0];
tempmu=[tempmu;mu0];
30
tempsigma=[tempsigma;sigma0];
Ntemp=[Ntemp,N];
end
aa=[sum(tempa(:,1)),sum(tempa(:,2)),sum(tempa(:,3))]/15
amu=[sum(tempmu(:,1)),sum(tempmu(:,2)),sum(tempmu(:,3))]/15
asigma=[sum(tempsigma(:,1)),sum(tempsigma(:,2)),sum(tempsigma(:,3))]/15
amoy=[amoy;aa];
mumoy=[mumoy;amu];
sigmamoy=[sigmamoy;asigma];
[ademel,mudemel,sigmademel]= demelange(aD,muD,sigmaD,Ntemp)
a=[a;ademel];
mu=[mu;mudemel];
sigma=[sigma;sigmademel];
depart=arrive+1;
arrive=arrive+15;
end;
erreura=a-amoy
erreurmu=mu-mumoy
erreursigma=sigma-sigmamoy
31
comparehasard
function [a,mu,sigma,amoy,mumoy,sigmamoy]=comparehasard
image=input(’Nombre d"image à tester : ’);
aD =[0.45,0.25,0.3];
muD=[104,130,172];
sigmaD=[8,9,6];
tempa=[];
tempmu=[];
tempsigma=[];
it=0;
tempN=[];
i=int8(rand*(149-image));
for j=i:(i+image-1)
j
if i<10
M=imread([’ndrp_00’,int2str(j),’.png’]);
elseif i>9 & i<100
M=imread([’ndrp_0’,int2str(j),’.png’]);
else
M=imread([’ndrp_’,int2str(j),’.png’]);
end
[H,N]=histogramme3(M,M(1,1));
[a0,mu0,sigma0]= demelange(aD,muD,sigmaD,N);
tempa=[tempa;a0];
tempmu=[tempmu;mu0];
tempsigma=[tempsigma;sigma0];
tempN=[tempN,N];
end
amoy=[sum(tempa(:,1)),sum(tempa(:,2)),sum(tempa(:,3))]/image;
mumoy=[sum(tempmu(:,1)),sum(tempmu(:,2)),sum(tempmu(:,3))]/image;
sigmamoy=[sum(tempsigma(:,1)),sum(tempsigma(:,2)),sum(tempsigma(:,3))]/image;
[a,mu,sigma]= demelange(aD,muD,sigmaD,tempN);
32
gaussiennehasard
function [I]=gaussiennehasard
compte=0;
I=[];
it=0;
image=input(’Nombre d"image à tester : ’);
alpha= 0.05;
for j=1:image
toto=0;
i=int8(rand*149);
if j>1
while toto==0
toto=1;
i=int8(rand*149);
for k=1:max(size(I))
if I(k)==i
toto=0*toto;
end;
end;
end;
end;
I=[I,i];
numimage=I(j)
it=it+1;
if i<10
M=imread([’ndrp_00’,int2str(i),’.png’]);
elseif i>9 & i<100
M=imread([’ndrp_0’,int2str(i),’.png’]);
else
M=imread([’ndrp_’,int2str(i),’.png’]);
end
[H,N]=histogramme3(M,M(1,1));
a0 =[0.45,0.25,0.3];
mu0=[104,134,174];
sigma0=[8,9,6];
[a,mu,sigma]= demelange(a0,mu0,sigma0,N);
33
[Dn,Dsk]=Smirnov_Kolmogorov(a,mu,sigma,alpha,H,N)
if Dsk<=Dn
compte=compte+1;
end;
end;
if compte==image
disp(’Pour toutes les images on obtient un mélange de 3 gaussiennes’);
else
erreur=image-compte;
if erreur>1
texte=[’Il y a ’,int2str(erreur),’ images qui ne sont pas un mélange gaussie
else
texte=[’Il y a une image qui n"est pas un mélange gaussien’];
end;
disp(texte);
end;
34
automatisme
function automatisme
disp(’1˚. Placez les images dans le m^
eme dossier que la fonction ’);
pause
type=input(’2˚. Donnez le type d"image (entre apostrophes) : ’);
nom=input(’3˚. Donnez le nom commun a images (entre apostrophes) : ’);
autocontraste(nom,type)
[amoy,mumoy,sigmamoy,a,mu,sigma]=autocompare(nom,type)
[I]=gaussiennehasard
35