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