La détection de contours consiste à repérer les grandes variations de couleur entre des pixels proches.
Le but étant de faire apparaitre les contours des objets présents sur une image. En effet, Ce qui différencie
un objet d'un fond, c'est leurs quantifications. Exemple, un objet noir sur fond blanc. Afin de détecter les contours de
l'objet nous allons observer la différence entre les pixels voisins de l'image. Si la différence est grande alors nous
avons détecté un contour.
Dans le code lorsque j'utilise la variable nommée 'distance' ça signifie l'éloignement des pixels pris en compte dans les masques utilisés.
Une technique simple consiste à regarder le gradient qu'il existe dans l'image en vertical et en horizontal.
for i = 1:ligne-distance
for j = 1:colonne-distance
img2(i,j) = ((img(i,j)-img(i,j+distance))^2 + (img(i,j)-img(i+distance,j))^2)^0.5;
end
end
Voici un autre gradient possible.
for i = 1:ligne-distance
for j = 1:colonne-distance
img2(i,j) = abs(img(i,j)-img(i,j+distance)) + abs(img(i,j)-img(i+distance,j));
end
end
Le filtre de Roberts consiste en un gradient d'un masque de taille 2*2.
etLes gradients sont faits sur les deux diagonales possibles du masque. La détection de contour se fera donc sur les variations de couleurs sur les diagonales. On a l'équation suivante :
for i = 1:ligne-distance
for j = 1:colonne-distance
img2(i,j) = (abs((img(i,j)-img(i+distance,j+distance)) + (img(i+distance,j)-img(i,j+distance))))/2;
end
end
Cette opérateur fait une convolution de deux masques de taille 3*3.
etCe filtre combine une détection de contours avec un filtre moyenneur, ce qui permet d'être beaucoup moins dépendant aux bruits que le filtre de Roberts.
for i = 1:ligne-(distance+1)
for j = 1:colonne-(distance+1)
img2(i,j) = abs( (-img(i,j)-img(i+1,j)-img(i+2,j)+img(i,j+distance)+img(i+1,j+distance)+img(i+2,j+distance))+...
(-img(i,j)-img(i,j+1)-img(i,j+2)+img(i+distance,j)+img(i+distance,j+1)+img(i+distance,j+2)));
end
end
Le filtre de Sobel ressemble beaucoup à celui de Prewitt à ceci près : le filtre qui est appliqué est gaussien, le bruit est donc mieux filtré qu'avec les masques de prewitt.
et
for i = 1:ligne-(distance+1)
for j = 1:colonne-(distance+1)
img2(i,j) = abs( (-img(i,j)-2*img(i+1,j)-img(i+2,j)+img(i,j+distance)+2*img(i+1,j+distance)+img(i+2,j+distance))+...
(-img(i,j)-img(i,j+1)-2*img(i,j+2)+img(i+distance,j)+2*img(i+distance,j+1)+img(i+distance,j+2)));
end
end
L’estimation du laplacien d’une image se fait de la même manière : par convolution de l’image avec un masque. Le laplacien est approximé par différences finies :
for i = 1:ligne-2
for j = 1:colonne-2
img2(i,j) = img(i+1,j) ...
+img(i,j)-4*img(i+1,j+1)+img(i+2,j+2)+...
+img(i+1,j+1) ;
end
end
Une autre détection de contours en prenant en compte les diagonales.
for i = 1:ligne-2
for j = 1:colonne-2
img2(i,j) = img(i,j)+img(i+1,j)+img(i+2,j)+...
+img(i,j)-8*img(i+1,j+1)+img(i+2,j+2)+...
+img(i,j)+img(i+1,j+1)+img(i+2,j+2);
end
end
Il peut aussi être utilisé en ajoutant les diagonales.
r=[cos(theta_v) -sin(theta_v);
sin(theta_v) cos(theta_v)];
for i = 1 : n
for j = 1 : n
u = r * [j-(n+1)/2 i-(n+1)/2]';
h(i,j) = (exp(-u(1)^2/(2*s^2)) / (s*sqrt(2*pi)))*(-u(2) * ((exp(-u(2)^2/(2*s^2)) / (s*sqrt(2*pi))) / s^2));
end
end
frontvert= conv2(img,h,'same');
r=[cos(theta_h) -sin(theta_h);
sin(theta_h) cos(theta_h)];
for i = 1 : n
for j = 1 : n
u = r * [j-(n+1)/2 i-(n+1)/2]';
h(i,j) = (exp(-u(1)^2/(2*s^2)) / (s*sqrt(2*pi)))*(-u(2) * ((exp(-u(2)^2/(2*s^2)) / (s*sqrt(2*pi))) / s^2));
end
end
fronthor= conv2(img,h,'same');
% normalisation
contour=sqrt(frontvert.*frontvert+fronthor.*fronthor);
% Thresholding
alfa=0.1;
contour_max=max(max(contour));
contour_min=min(min(contour));
seuil=alfa*(contour_max-contour_min)+contour_min;
seuillage=contour;
seuillage(seuillage<seuil) = seuil;
%Ibw=max(NVI,level.*ones(size(NVI)));
[n,m]=size(seuillage);
X=[-1,0,+1;-1,0,+1;-1,0,+1];
Y=[-1,-1,-1;0,0,0;+1,+1,+1];
for i=1:n-2,
for j=1:m-2,
if seuillage(i+1,j+1) > seuil,
Z=seuillage(i:i+2,j:j+2);
XI=[frontvert(i+1,j+1)/contour(i+1,j+1), -frontvert(i+1,j+1)/contour(i+1,j+1)];
YI=[fronthor(i+1,j+1)/contour(i+1,j+1), -fronthor(i+1,j+1)/contour(i+1,j+1)];
ZI=interp2(X,Y,Z,XI,YI);
if seuillage(i+1,j+1) >= ZI(1) && seuillage(i+1,j+1) >= ZI(2)
contour_final(i,j)=contour_max;
else
contour_final(i,j)=contour_min;
end
else
contour_final(i,j)=contour_min;
end
end
end
img2=contour_final;
function guicontour
clear all;
close all;
figure( 'name','détection de contour',...
'NumberTitle','off',...
'MenuBar','none',...
'color',[0.3137 0.3137 0.5098]);
a(1)=axes('units','normalized',...
'position',[0.05 0.4 0.4 0.4]);
a(2)=axes('units','normalized',...
'position',[0.5 0.4 0.4 0.4]);
uicontrol( 'style','pushbutton',...
'string','load',...
'Position', [10 10 50 20],...
'callback',@loadimage);
ctr(1)=uicontrol( 'style','popup',...
'string','gradian|gradian2|roberts|prewitt|sobel|laplacien|laplacien2|freishen|canny',...
'Min',0,'Max',8,...
'Position', [90 10 100 20],...
'callback',{@choixtxt,'typecontour'});
text(1)=uicontrol( 'style','text',...
'string','Type de contour ',...
'Position', [90 30 100 20]);
ctr(2)=uicontrol( 'style','popup',...
'string','1|2|3|4|5',...
'Min',0,'Max',4,...
'Position', [200 10 50 20],...
'callback',{@choix,'distance'});
text(2)=uicontrol( 'style','text',...
'string','distance ',...
'Position', [200 30 50 20]);
ctr(3)=uicontrol( 'style','popup',...
'string','non|oui',...
'Min',0,'Max',4,...
'Position', [260 10 50 20],...
'callback',{@choixseuil,'seuillage'});
text(3)=uicontrol( 'style','text',...
'string','seuillage?',...
'Position', [260 30 50 20]);
ctr(4)=uicontrol( 'style','slider',...
'string','seuil',...
'Min' ,0,'Max',255, ...
'Position', [320 10 100 20],...
'Value', 0,...
'SliderStep',[1/255 10/255], ...
'callback',{@choix,'seuil'});
text(4)=uicontrol( 'style','text',...
'string','seuil',...
'Position', [320 30 100 20]);
uicontrol( 'style','pushbutton',...
'string','appliquer',...
'Position', [500 10 50 20],...
'callback',@appliquer);
ctr(5)=uicontrol( 'style','edit',...
'string','10',...
'Position', [200 10 50 20],...
'callback',{@choixnb,'n'});
text(5)=uicontrol( 'style','text',...
'string','distance',...
'Position', [200 30 50 20]);
ctr(6)=uicontrol( 'style','edit',...
'string','1',...
'Position', [260 10 50 20],...
'callback',{@choixnb,'s'});
text(6)=uicontrol( 'style','text',...
'string','sigma',...
'Position', [320 30 50 20]);
ctr(7)=uicontrol( 'style','edit',...
'string','1.5708',...
'Position', [320 10 50 20],...
'callback',{@choixnb,'theta_v'});
text(7)=uicontrol( 'style','text',...
'string','theta_v',...
'Position', [380 30 50 20]);
ctr(8)=uicontrol( 'style','edit',...
'string','0',...
'Position', [380 10 50 20],...
'callback',{@choixnb,'theta_h'});
text(8)=uicontrol( 'style','text',...
'string','theta_h',...
'Position', [260 30 50 20]);
%parametre initial
setappdata(gcf,'distance',1);
setappdata(gcf,'seuillage','non');
setappdata(gcf,'seuil',0);
setappdata(gcf,'x',1);
setappdata(gcf,'typecontour','gradian');
setappdata(gcf,'n',10);
setappdata(gcf,'s',1);
setappdata(gcf,'theta_v',1.5708);
setappdata(gcf,'theta_h',0);
set(ctr(5),'Enable','off');
set(ctr(5),'Visible','off');
set(ctr(6),'Enable','off');
set(ctr(6),'Visible','off');
set(ctr(7),'Enable','off');
set(ctr(7),'Visible','off');
set(ctr(8),'Enable','off');
set(ctr(8),'Visible','off');
set(text(5),'Enable','off');
set(text(5),'Visible','off');
set(text(6),'Enable','off');
set(text(6),'Visible','off');
set(text(7),'Enable','off');
set(text(7),'Visible','off');
set(text(8),'Enable','off');
set(text(8),'Visible','off');
function loadimage(~,~)
% appeler quand appui check box
[filename, pathname] = uigetfile({'*.jpg;*.tif;*.PNG;*.gif;*.bmp','All Image Files';...
'*.*','All Files' },'mytitle',...
'C:\Work\myfile.jpg')
x = imread(filename);
if (length(size(x))>2)
x=x(:,:,1);% on prend une seul plan image noir et blanc chaque plan sont egaux
end
k = whos('x');
if k.class == 'uint8'
k=8;
end
setappdata(1,'k',k);
setappdata(1,'x',x);
axes(a(1))
imshow(x)
axes(a(2))
imshow(x)
end
function choixtxt(hObj,~,name)
% Called when user activates popup menu
val = get(hObj,'Value'); %0|1=ligne, 2=colonne, 3=croix, 4=carre
set(ctr(2),'Enable','on');
set(ctr(2),'Visible','on');
set(ctr(3),'Enable','on');
set(ctr(3),'Visible','on');
set(ctr(4),'Enable','on');
set(ctr(4),'Visible','on');
set(text(2),'Enable','on');
set(text(2),'Visible','on');
set(text(3),'Enable','on');
set(text(3),'Visible','on');
set(text(4),'Enable','on');
set(text(4),'Visible','on');
set(ctr(5),'Enable','on');
set(ctr(5),'Visible','off');
set(ctr(6),'Enable','off');
set(ctr(6),'Visible','off');
set(ctr(7),'Enable','off');
set(ctr(7),'Visible','off');
set(ctr(8),'Enable','off');
set(ctr(8),'Visible','off');
set(text(5),'Enable','off');
set(text(5),'Visible','off');
set(text(6),'Enable','off');
set(text(6),'Visible','off');
set(text(7),'Enable','off');
set(text(7),'Visible','off');
set(text(8),'Enable','off');
set(text(8),'Visible','off');
if ( val == 0 || val == 1 )
setappdata(1,name,'gradian');
elseif ( val == 2 )
setappdata(1,name,'gradian2');
elseif ( val == 3 )
setappdata(1,name,'roberts');
elseif ( val == 4 )
setappdata(1,name,'prewitt');
elseif ( val == 5 )
setappdata(1,name,'sobel');
elseif ( val == 6 )
setappdata(1,name,'laplacien');
set(ctr(2),'Visible','off');
set(text(2),'Visible','off');
elseif ( val == 7 )
setappdata(1,name,'laplacien2');
set(ctr(2),'Visible','off');
set(text(2),'Visible','off');
elseif ( val == 8 )
setappdata(1,name,'freishen');
elseif ( val == 9 )
setappdata(1,name,'canny');
set(ctr(5),'Enable','on');
set(ctr(5),'Visible','on');
set(ctr(6),'Enable','on');
set(ctr(6),'Visible','on');
set(ctr(7),'Enable','on');
set(ctr(7),'Visible','on');
set(ctr(8),'Enable','on');
set(ctr(8),'Visible','on');
set(text(5),'Enable','on');
set(text(5),'Visible','on');
set(text(6),'Enable','on');
set(text(6),'Visible','on');
set(text(7),'Enable','on');
set(text(7),'Visible','on');
set(text(8),'Enable','on');
set(text(8),'Visible','on');
set(ctr(2),'Enable','off');
set(ctr(2),'Visible','off');
set(ctr(3),'Enable','off');
set(ctr(3),'Visible','off');
set(ctr(4),'Enable','off');
set(ctr(4),'Visible','off');
set(text(2),'Enable','off');
set(text(2),'Visible','off');
set(text(3),'Enable','off');
set(text(3),'Visible','off');
set(text(4),'Enable','off');
set(text(4),'Visible','off');
end
end
function choixseuil(hObj,~,name)
% Called when user activates popup menu
val = get(hObj,'Value'); %0|1=ligne, 2=colonne, 3=croix, 4=carre
if ( val == 0 || val == 1 )
setappdata(1,name,'non');
elseif ( val == 2 )
setappdata(1,name,'oui');
end
end
function choix(hObj,~,Name)
% Called when user activates popup menu
val = get(hObj,'Value'); %0|1=ligne, 2=colonne, 3=croix, 4=carre
setappdata(1,Name,val);
if(strcmp(Name,'seuil'))
val=round(val);
setappdata(1,Name,val);
set( text(4), 'string' , strcat('seuil = ',num2str(val)));
end
end
function choixnb(hObj,~,Name)
% Called when user activates popup menu
val = get(hObj,'string');
setappdata(1,Name,str2double(val));
end
% function variable(hObj,~,name)
% val = round(get(hObj,'Value'));
% setappdata(1,name,val);
% end
function appliquer(hObj,~,name)
typecontour = getappdata(1,'typecontour');
distance = getappdata(1,'distance');
img = double(getappdata(1,'x'));
[ligne colonne]=size(img);
img2=zeros(ligne,colonne);
if (strcmp(typecontour,'gradian'))
for i = 1:ligne-distance
for j = 1:colonne-distance
img2(i,j) = ((img(i,j)-img(i,j+distance))^2 + (img(i,j)-img(i+distance,j))^2)^0.5;
end
end
elseif (strcmp(typecontour,'gradian2'))
for i = 1:ligne-distance
for j = 1:colonne-distance
img2(i,j) = abs(img(i,j)-img(i,j+distance)) + abs(img(i,j)-img(i+distance,j));
end
end
elseif (strcmp(typecontour,'roberts'))
for i = 1:ligne-distance
for j = 1:colonne-distance
img2(i,j) = (abs((img(i,j)-img(i+distance,j+distance)) + (img(i+distance,j)-img(i,j+distance))))/2;
end
end
elseif (strcmp(typecontour,'prewitt'))
for i = 1:ligne-(distance+1)
for j = 1:colonne-(distance+1)
img2(i,j) = abs( (-img(i,j)-img(i+1,j)-img(i+2,j)+img(i,j+distance)+img(i+1,j+distance)+img(i+2,j+distance))+...
(-img(i,j)-img(i,j+1)-img(i,j+2)+img(i+distance,j)+img(i+distance,j+1)+img(i+distance,j+2)));
end
end
elseif (strcmp(typecontour,'sobel'))
for i = 1:ligne-(distance+1)
for j = 1:colonne-(distance+1)
img2(i,j) = abs( (-img(i,j)-2*img(i+1,j)-img(i+2,j)+img(i,j+distance)+2*img(i+1,j+distance)+img(i+2,j+distance))+...
(-img(i,j)-img(i,j+1)-2*img(i,j+2)+img(i+distance,j)+2*img(i+distance,j+1)+img(i+distance,j+2)));
end
end
elseif (strcmp(typecontour,'laplacien'))
for i = 1:ligne-2
for j = 1:colonne-2
img2(i,j) = img(i+1,j) ...
+img(i,j)-4*img(i+1,j+1)+img(i+2,j+2)+...
+img(i+1,j+1) ;
end
end
elseif (strcmp(typecontour,'laplacien2'))
for i = 1:ligne-2
for j = 1:colonne-2
img2(i,j) = img(i,j)+img(i+1,j)+img(i+2,j)+...
+img(i,j)-8*img(i+1,j+1)+img(i+2,j+2)+...
+img(i,j)+img(i+1,j+1)+img(i+2,j+2);
end
end
f=img2;
for i = 1:ligne-2
for j = 1:colonne-2
img2(i,j) = f(i,j)+f(i+1,j)+f(i+2,j)+...
+f(i,j)-8*f(i+1,j+1)+f(i+2,j+2)+...
+f(i,j)+f(i+1,j+1)+f(i+2,j+2);
end
end
elseif (strcmp(typecontour,'freishen'))
for i = 1:ligne-distance-1
for j = 1:colonne-distance-1
img2(i,j) = abs( (1/(2+sqrt(2)))*(-img(i,j)-sqrt(2)*img(i+1,j)-img(i+2,j)+img(i,j+distance)+sqrt(2)*img(i+1,j+distance)+img(i+2,j+distance))+...
(1/(2+sqrt(2)))*(-img(i,j)-img(i,j+1)-sqrt(2)*img(i,j+2)+img(i+distance,j)+sqrt(2)*img(i+distance,j+1)+img(i+distance,j+2)));
end
end
elseif (strcmp(typecontour,'canny'))
n=getappdata(1,'n')
s=getappdata(1,'s')
theta_v=getappdata(1,'theta_v')
theta_h=getappdata(1,'theta_h')
r=[cos(theta_v) -sin(theta_v);
sin(theta_v) cos(theta_v)];
for i = 1 : n
for j = 1 : n
u = r * [j-(n+1)/2 i-(n+1)/2]';
h(i,j) = (exp(-u(1)^2/(2*s^2)) / (s*sqrt(2*pi)))*(-u(2) * ((exp(-u(2)^2/(2*s^2)) / (s*sqrt(2*pi))) / s^2));
end
end
frontvert= conv2(img,h,'same');
r=[cos(theta_h) -sin(theta_h);
sin(theta_h) cos(theta_h)];
for i = 1 : n
for j = 1 : n
u = r * [j-(n+1)/2 i-(n+1)/2]';
h(i,j) = (exp(-u(1)^2/(2*s^2)) / (s*sqrt(2*pi)))*(-u(2) * ((exp(-u(2)^2/(2*s^2)) / (s*sqrt(2*pi))) / s^2));
end
end
fronthor= conv2(img,h,'same');
% normalisation
contour=sqrt(frontvert.*frontvert+fronthor.*fronthor);
% Thresholding
alfa=0.1;
contour_max=max(max(contour));
contour_min=min(min(contour));
seuil=alfa*(contour_max-contour_min)+contour_min;
seuillage=contour;
seuillage(seuillage<seuil) = seuil;
%Ibw=max(NVI,level.*ones(size(NVI)));
[n,m]=size(seuillage);
X=[-1,0,+1;-1,0,+1;-1,0,+1];
Y=[-1,-1,-1;0,0,0;+1,+1,+1];
for i=1:n-2,
for j=1:m-2,
if seuillage(i+1,j+1) > seuil,
Z=seuillage(i:i+2,j:j+2);
XI=[frontvert(i+1,j+1)/contour(i+1,j+1), -frontvert(i+1,j+1)/contour(i+1,j+1)];
YI=[fronthor(i+1,j+1)/contour(i+1,j+1), -fronthor(i+1,j+1)/contour(i+1,j+1)];
ZI=interp2(X,Y,Z,XI,YI);
if seuillage(i+1,j+1) >= ZI(1) && seuillage(i+1,j+1) >= ZI(2)
contour_final(i,j)=contour_max;
else
contour_final(i,j)=contour_min;
end
else
contour_final(i,j)=contour_min;
end
end
end
img2=contour_final;
end
seuillage = getappdata(1,'seuillage');
if (strcmp(typecontour,'canny') == 0)
if strcmp(seuillage,'oui')
img2 = uint8(img2);
seuil = getappdata(1,'seuil');
img2(img2<seuil) = 0;
img2(img2>=seuil) = 255;
end
end
axes(a(2))
imshow(img2,[min(min(img2)) max(max(img2))])
end
end
Copyright © 2010-2014, tous droits réservés, contact : operationpixel@free.fr