%Implements Canny edge detection as described in text.
%X=imread('imagefile');TH=???;TL=???;%thresholds(set by trial and error)
%clear;load clown.mat;TH=0.75;TL=0.5;
clear;load letters.mat;TH=0.9;TL=0.5;
X=(X-min(min(X)))/(max(max(X))-min(min(X)));%Scale image pixels to [0,1].
figure,imagesc(X),colormap(gray),title('Original Image')
[M,N]=size(X);MN=M*N;%Convolve with 5X5 Gaussian:
G=[2 4 5 4 2;4 9 12 9 4;5 12 15 12 5;4 9 12 9 4;2 4 5 4 2]/159;
X1=conv2(X,G,'same');HV=[1 2 1;0 0 0;-1 -2 -1];
DV=conv2(X1,HV,'same');DH=conv2(X1,HV','same');%vertical and horizonal edges.
DG=sqrt(DV.*DV+DH.*DH);%gradient image.
figure,imagesc(DG),colormap(gray),title('SOBEL EDGES OF GAUSSIAN BLURRED IMAGE')
%Now thin edges:
DT=atan(DV./(DH+0.001));DT=round(DT/pi*180/45);
%#Degrees: 0,45,-45=135,90,-90=90. Use 0,1,-1,2,-2.
DT1=DT(:);DG1=DG(:);DG3=DG1;%Unwrap 2-D to 1-D to use MATLAB indexing. DG1,DG3: gradient images.
%Shift 1-D by 1 for vertical thinning of horizontal edges:
DG0a=[0;DG3(1:MN-1)];DG0b=[DG3(1:MN-1);0];
%Shift 1-D by M for horizontal thinning of vertical edges:
DG1a=[zeros(M,1);DG3(1:MN-M)];DG1b=[DG3(1:MN-M);zeros(M,1)];
%Shift 1-D by M-1 for 45 degree thinning of 135 degree edges:
DG2a=[zeros(M-1,1);DG3(1:MN-M+1)];DG2b=[DG3(1:MN-M+1);zeros(M-1,1)];
%Shift 1-D by M+1 for 135 degree thinning of 45 degree edges:
DG3a=[zeros(M+1,1);DG3(1:MN-M-1)];DG3b=[DG3(1:MN-M-1);zeros(M+1,1)];
%Now thin edges:
DG3((DT1==0)&((DG1<DG1a)|(DG1<DG1b)))=0;%Thin horizontal edges vertically.
DG3((DT1==-2)&((DG1<DG0a)|(DG1<DG0b)))=0;%Thin vertical edges horizontally.
DG3((DT1==2)&((DG1<DG0a)|(DG1<DG0b)))=0;%Thin vertical edges horizontally.
DG3((DT1==-1)&((DG1<DG2a)|(DG1<DG2b)))=0;%Thin 135 degree edges along 45 degrees.
DG3((DT1==1)&((DG1<DG3a)|(DG1<DG3b)))=0;%Thin 45 degree edges along 135 deg
%Display edge-thinned image (note how much thinner edges are vs. above):
figure,imagesc(reshape(DG3,M,N)),colormap(gray),title('EDGE-THINNED')
%Now check if each edge candidate borders another confirmed edge:
Z(1:MN)=1;Z(DG3<TL)=0;Z(DG3>TH)=2;%Set all gradient edges below TL to 0, and all above TH to 2.
Z2=Z;IZ=(M+1)+find(Z(M+2:MN-M-1)==1);%Find locations of all unclassified edges (TL<DG3<TH).
%Find locations of all unclassified edges with a confirmed-edge neighbor and classify them as edges:
Z2((Z(IZ+1)==2)|(Z(IZ-1)==2)|(Z(IZ+M)==2)|(Z(IZ-M)==2)|(Z(IZ+M+1)==2)|(Z(IZ-M-1)==2)|(Z(IZ+M-1)==2)|(Z(IZ-M+1)==2))=2;
Z3(1:MN)=0;Z3(Z2==2)=Z(Z2==2);Z3(Z2==1)=2;Z3(Z2==0)=0;
Z4=reshape(Z3,M,N);%Form and display Canny edge image
figure,imagesc(Z4),colormap(gray),title('CANNY EDGES')
