l'image de fond

fr       en

Traitements d'Images en Niveau de Gris

La Détection de Contours

Méthode

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.
rotation d'une image
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.

Gradient

Une technique simple consiste à regarder le gradient qu'il existe dans l'image en vertical et en 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

Voici un autre gradient possible.

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

Le filtre de Roberts consiste en un gradient d'un masque de taille 2*2.

[ 1 0 0 1 ] et [ 0 1 1 0 ]

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

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

Cette opérateur fait une convolution de deux masques de taille 3*3.

[ - 1 0 1 - 1 0 1 - 1 0 1 ] et [ - 1 - 1 - 1 0 0 0 1 1 1 ]

Ce 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

Sobel

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.

[ - 1 - 1 1 - 2 0 2 - 1 0 1 ] et [ - 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

Laplacien

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

Une autre détection de contours en prenant en compte les diagonales.

[ 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

Il peut aussi être utilisé en ajoutant les diagonales.

[ - 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;

Programme

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

Exemple

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

Laplacien


rotation d'une image

Laplacien 2


rotation d'une image

Freishen


rotation d'une image

Canny


rotation d'une image

Copyright © 2010-2014, tous droits réservés, contact : operationpixel@free.fr