l'image de fond

fr       en

Gray Level Image Processing

Contours Detection

Method

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.
rotation d'une image
In the code when using the variable named 'distance' it means the removal of pixels included in the masks used.

Gradient

A simple technique is to look at the gradient that exists in the image in vertical and in horizontal.
g r a d i e n t ( i , j ) = ( p ( i , j ) - p ( i , j + 1 ) ) 2 + ( p ( i , j ) - p ( i + 1 , j ) ) 2

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

Gradient 2

Another possible gradient.

g r a d i e n t ( i , j ) = | p ( i , j ) - p ( i , j + 1 ) | + | p ( i , j ) - p ( i + 1 , j ) |

         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

Roberts filter is a gradient of size 2*2.

[ 1 0 0 1 ] and [ 0 1 1 0 ]

The 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:

g r a d i e n t ( i , j ) = | p ( i , j ) - p ( i + 1 , j + 1 ) | + | p ( i + 1 , j ) - p ( i , j + 1 ) | 2

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

Prewitt

This operator do the convolution between txo mask 3*3.

[ - 1 0 1 - 1 0 1 - 1 0 1 ] and [ - 1 - 1 - 1 0 0 0 1 1 1 ]

This 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

Sobel

The Sobel filter is very similar to Prewitt, except: The filter applied is Gaussian, the noise is better filtered than Prewitt masks.

[ - 1 - 1 1 - 2 0 2 - 1 0 1 ] and [ - 1 - 2 - 1 0 0 0 1 2 1 ]

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

Laplacian

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: 2 = { 1 , - 2 , 1 }

[ 0 0 0 1 - 2 1 0 0 0 ] + [ 0 1 0 0 - 2 0 0 1 0 ] = [ 0 1 0 1 - 4 0 0 0 0 ]

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

Laplacien 2

Another conrour detection with diagonals.

[ 0 0 0 1 - 2 1 0 0 0 ] + [ 0 1 0 0 - 2 0 0 1 0 ] + [ 1 0 0 0 - 2 0 0 0 1 ] + [ 0 0 1 0 - 2 0 1 0 0 ] = [ 1 1 1 1 - 8 1 1 1 1 ]

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

Freishen

It can also been used with diagonals.

[ - 1 0 1 2 0 2 - 1 0 1 ] e t [ - 1 2 - 1 0 0 0 1 2 1 ]

Canny

 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;

Program

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

Example

Gradient


rotation d'une image

Gradient 2


rotation d'une image

Roberts


rotation d'une image

Prewitt


rotation d'une image

Sobel


rotation d'une image

Laplacian


rotation d'une image

Laplacian 2


rotation d'une image

Freishen


rotation d'une image

Canny


rotation d'une image

Copyright © 2010-2014, all rights reserved, contact: operationpixel@free.fr