Contour detection is identifying large variations in color between pixels close. The aim is to make appear the edges of
objects present in an image. Indeed, the differences between an object and a background are their quantifications. Example,
a black object on white background. To detect the contours of the object we observe the difference between neighboring pixels
of the image. If the difference is large then we have detected an edge.
In the code when using the variable named 'distance' it means the removal of pixels included in the masks used.
A simple technique is to look at the gradient that exists in the image in vertical and in 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
Another possible gradient.
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
Roberts filter is a gradient of size 2*2.
andThe gradients are made ??on the two possible diagonals of the mask. Edge detection will be the color variations on the diagonals. We have the following equation:
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
This operator do the convolution between txo mask 3*3.
andThis filter combines edge detection with a mean filter, which allow to be much less dependent to the noise than Roberts filter.
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
The Sobel filter is very similar to Prewitt, except: The filter applied is Gaussian, the noise is better filtered than Prewitt masks.
and
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
The estimate of the Laplacian of an image is made in the same way by convolution of the image with a mask. The Laplacian is approximated by finite differences:
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
Another conrour detection with diagonals.
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
It can also been used with diagonals.
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, all rights reserved, contact: operationpixel@free.fr