# 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.

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.
$gradient\left(i,j\right)=\sqrt{{\left(p\left(i,j\right)-p\left(i,j+1\right)\right)}^{2}+{\left(p\left(i,j\right)-p\left(i+1,j\right)\right)}^{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\left(i,j\right)=|p\left(i,j\right)-p\left(i,j+1\right)|+|p\left(i,j\right)-p\left(i+1,j\right)|$

```         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.

$\left[\begin{array}{cc}1& 0\\ 0& 1\end{array}\right]$ and $\left[\begin{array}{cc}0& 1\\ 1& 0\end{array}\right]$

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:

$gradient\left(i,j\right)=\genfrac{}{}{0.1ex}{}{|p\left(i,j\right)-p\left(i+1,j+1\right)|+|p\left(i+1,j\right)-p\left(i,j+1\right)|}{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.

$\left[\begin{array}{ccc}-1& 0& 1\\ -1& 0& 1\\ -1& 0& 1\end{array}\right]$ and $\left[\begin{array}{ccc}-1& -1& -1\\ 0& 0& 0\\ 1& 1& 1\end{array}\right]$

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.

$\left[\begin{array}{ccc}-1& -1& 1\\ -2& 0& 2\\ -1& 0& 1\end{array}\right]$ and $\left[\begin{array}{ccc}-1& -2& -1\\ 0& 0& 0\\ 1& 2& 1\end{array}\right]$

```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}=\left\{1,-2,1\right\}$

$\left[\begin{array}{ccc}0& 0& 0\\ 1& -2& 1\\ 0& 0& 0\end{array}\right]+\left[\begin{array}{ccc}0& 1& 0\\ 0& -2& 0\\ 0& 1& 0\end{array}\right]=\left[\begin{array}{ccc}0& 1& 0\\ 1& -4& 0\\ 0& 0& 0\end{array}\right]$

```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.

$\left[\begin{array}{ccc}0& 0& 0\\ 1& -2& 1\\ 0& 0& 0\end{array}\right]+\left[\begin{array}{ccc}0& 1& 0\\ 0& -2& 0\\ 0& 1& 0\end{array}\right]+\left[\begin{array}{ccc}1& 0& 0\\ 0& -2& 0\\ 0& 0& 1\end{array}\right]+\left[\begin{array}{ccc}0& 0& 1\\ 0& -2& 0\\ 1& 0& 0\end{array}\right]=\left[\begin{array}{ccc}1& 1& 1\\ 1& -8& 1\\ 1& 1& 1\end{array}\right]$

```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.

$\left[\begin{array}{ccc}-1& 0& 1\\ \sqrt{2}& 0& \sqrt{2}\\ -1& 0& 1\end{array}\right]et\left[\begin{array}{ccc}-1& \sqrt{2}& -1\\ 0& 0& 0\\ 1& \sqrt{2}& 1\end{array}\right]$

#### 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```