图像分割——边缘检测——Canny算法(Matlab)

clc;
clear all;
close all;
I=im2double(imread('D:\Gray Files\10-26.tif'));
[M,N]=size(I);
%%
%=============================边缘检测(五)=================================
% Canny Edge Detector
%-------------------------用高斯低通滤波器平滑图像-------------------------
%建筑图像所设参数
% n=25;
% sigma=4;
%头颅扫描图像所设参数
n=13;
sigma=2;
%lena测试图像所设参数
% n=5;
% sigma=1;
type='symmetric';
f_s=GaussianBlur(n,I,sigma,type);
% imshow(f_s)
% imwrite(f_s,'D:\Gray Files\lena-test.jpg','jpg');
%-----------------------计算平滑后的图像梯度和角度-------------------------
n_l=1;
%Sobel算子
s_y=[-1 -2 -1;
    0 0 0;
    1 2 1];
s_x=[-1 0 1;
    -2 0 2;
    -1 0 1];
%定义梯度和角度
gx=zeros(M,N);
gy=zeros(M,N);
f_s_pad=padarray(f_s,[n_l,n_l],'replicate');
for i=1:M
    for j=1:N
        Block=f_s_pad(i:i+2*n_l,j:j+2*n_l);
        gx(i,j)=sum(sum(Block.*s_x));
        gy(i,j)=sum(sum(Block.*s_y));        
    end
end
type='replicate';
gx=GaussianBlur(n,gx,sigma,type);
gy=GaussianBlur(n,gy,sigma,type);
M_s=sqrt(gx.^2+gy.^2);
M_s=M_s/max(M_s(:));
a_s=atan2(gy,gx)*180/pi;
% imshow(M_s)
%-----------------------对梯度图像进行非极大值抑制-------------------------
n_l=1;
%定义非极大值抑制图像
g_N=M_s;
M_s_pad=padarray(M_s,[n_l,n_l],'replicate');
for i=1:M
    for j=1:N
        %取出中心点的梯度值
        K=M_s_pad(i+1,j+1);
 
        theta=a_s(i,j);
        if (theta>=0 && theta<=45) ||...
                (theta<-135 && theta>=-180)
            yBot=[M_s_pad(i+1,j+2) M_s_pad(i+2,j+2)];
            yTop=[M_s_pad(i+1,j) M_s_pad(i,j)];
            k=abs(gy(i,j)/M_s_pad(i+1,j+1));
            K1=(yBot(2)-yBot(1))*k+yBot(1);
            K2=(yTop(2)-yTop(1))*k+yTop(1);         
        end    
        if (theta>45 && theta<=90) ||...
                (theta<-90 && theta>=-135)
            yBot=[M_s_pad(i+2,j+1) M_s_pad(i+2,j+2)];
            yTop=[M_s_pad(i,j+1) M_s_pad(i,j)];
            k=abs(gx(i,j)/M_s_pad(i+1,j+1));
            K1=(yBot(2)-yBot(1))*k+yBot(1);
            K2=(yTop(2)-yTop(1))*k+yTop(1);         
        end            
        if (theta>90 && theta<=135) ||...
                (theta<-45 && theta>=-90)
            yBot=[M_s_pad(i+2,j+1) M_s_pad(i+2,j)];
            yTop=[M_s_pad(i,j+1) M_s_pad(i,j+2)];
            k=abs(gx(i,j)/M_s_pad(i+1,j+1));
            K1=(yBot(2)-yBot(1))*k+yBot(1);
            K2=(yTop(2)-yTop(1))*k+yTop(1);         
        end                  
        if (theta>135 && theta<=180) ||...
                (theta<0&& theta>=-45)
            yBot=[M_s_pad(i+1,j) M_s_pad(i+2,j)];
            yTop=[M_s_pad(i+1,j+2) M_s_pad(i,j+2)];
            k=abs(gy(i,j)/M_s_pad(i+1,j+1));
            K1=(yBot(2)-yBot(1))*k+yBot(1);
            K2=(yTop(2)-yTop(1))*k+yTop(1);         
        end                      
        if KT_H);
g_N_pad(ind_H)=1;
ind_Zeros=find(g_N_pad

高斯模糊GaussianBlur函数:

function [g]=GaussianBlur(n,I,sigma,type)
    [M,N]=size(I);
    %生成高斯核函数
    G=GaussianKernelG(n,sigma);
    %平滑图像
    n_l=n-1;
    g=zeros(M,N);
    %对原图进行扩展,方便处理边界
    I_pad=padarray(I,[n_l,n_l],type);
    for i=1:M
        for j=1:N
            %获得图像子块区域
            Block=I_pad(i:i+n_l,j:j+n_l);
            %用Kirsch内核对子区域卷积     
            g(i,j)=sum(sum(Block.*G));
        end
    end
    %归一化
    g=g/max(g(:));
end
%生成高斯核函数
% n 核函数的大小
function G=GaussianKernelG(n,sigma)
    n_l=floor(n/2);
    %初始化
    G=zeros(n,n);
    %产生高斯核矩阵
    for i=-n_l:n_l
        for j=-n_l:n_l  
            d=i^2+j^2;
            G(i+n_l+1,j+n_l+1)=exp(-(d)/(2*sigma^2));
        end
    end
    %寻找最小值
    m=sum(G(:));
    %取整
    G=G/m;
    %将大于3*delta的取值置零
    for i=-n_l:n_l
        for j=-n_l:n_l 
            d=sqrt(i^2+j^2);
            if d>3*sigma
                G(i+n_l+1,j+n_l+1)=0;
            end
        end
    end
end

查找8连通函数,FindConnected_8:

%查找所有8连通的点
% p为中心点,ind_L为有效矩阵,Conn为连通矩阵,M为图像矩阵的行数
function [ind_L,Conn]=FindConnected_8(p,ind_L,Conn,M)
    %查找p点是否有连通点,即在ind_L中是否有值
    %上
    c=find(ind_L==p-1);
    if ~isempty(c)
        Conn=cat(1,Conn,p-1);
        ind_L(c)=[];
    end
    %下
    c=find(ind_L==p+1);
    if ~isempty(c)
        Conn=cat(1,Conn,p+1);
        ind_L(c)=[];
    end    
    %左
    c=find(ind_L==p-M);
    if ~isempty(c)
        Conn=cat(1,Conn,p-M);
        ind_L(c)=[];
    end        
    %左上
    c=find(ind_L==p-M-1);
    if ~isempty(c)
        Conn=cat(1,Conn,p-M-1);
        ind_L(c)=[];
    end  
    %左下
    c=find(ind_L==p-M+1);
    if ~isempty(c)
        Conn=cat(1,Conn,p-M+1);
        ind_L(c)=[];
    end      
    %右
    c=find(ind_L==p+M);
    if ~isempty(c)
        Conn=cat(1,Conn,p+M);
        ind_L(c)=[];
    end        
    %右上
    c=find(ind_L==p+M-1);
    if ~isempty(c)
        Conn=cat(1,Conn,p+M-1);
        ind_L(c)=[];
    end  
    %右下
    c=find(ind_L==p+M+1);
    if ~isempty(c)
        Conn=cat(1,Conn,p+M+1);
        ind_L(c)=[];
    end
    
end

图像细化函数,ImageThinning如下:

%图像细化,目前只对二值图像进行处理
function [g]=ImageThinning(I)
n_l=1;
%对边界图进行扩充,四周各加1行、1列0(与结构元素的大小相对应),目的是为了处理边界点
I_pad=padarray(I,[n_l,n_l]);
%获得扩充图像大小
[M,N]=size(I_pad);
%寻找图像中的亮点,即值为1的点
ind=find(I_pad==1);
ind_c=[];
while ~isequal(ind_c,ind)
    %备份赋值,以便下一次循环开始进行比较
    ind_c=ind;
    %保存ind中符合条件的下标
    ind_sub=[];
    %按照B1结构元素搜索
    for i=1:length(ind)
        p=ind(i,1);
        if ~isempty(find(ind==p+1)) && ~isempty(find(ind==p-M+1)) && ~isempty(find(ind==p+M+1)) &&...
                isempty(find(ind==p-1)) && isempty(find(ind==p-M-1)) && isempty(find(ind==p+M-1))
            ind_sub=cat(1,ind_sub,i);
        end
    end
    %将下标符合条件的数值,从ind中清除,以下类似
    if ~isempty(ind_sub)
        ind(ind_sub)=[];
    end
    ind_sub=[];
    %按照B2结构元素搜索
    for i=1:length(ind)
        p=ind(i,1);
        if ~isempty(find(ind==p+1)) && ~isempty(find(ind==p-M)) && ~isempty(find(ind==p-M+1)) &&...
                isempty(find(ind==p-1)) && isempty(find(ind==p+M)) && isempty(find(ind==p+M-1))
            ind_sub=cat(1,ind_sub,i);
        end
    end
    if ~isempty(ind_sub)
        ind(ind_sub)=[];
    end   
    ind_sub=[];
    %按照B3结构元素搜索
    for i=1:length(ind)
        p=ind(i,1);
        if ~isempty(find(ind==p-M-1)) && ~isempty(find(ind==p-M)) && ~isempty(find(ind==p-M+1)) &&...
                isempty(find(ind==p+M-1)) && isempty(find(ind==p+M)) && isempty(find(ind==p+M+1))
            ind_sub=cat(1,ind_sub,i);
        end
    end
    if ~isempty(ind_sub)
        ind(ind_sub)=[];
    end
    ind_sub=[];
    %按照B4结构元素搜索
    for i=1:length(ind)
        p=ind(i,1);
        if ~isempty(find(ind==p-1)) && ~isempty(find(ind==p-M)) && ~isempty(find(ind==p-M-1)) &&...
                isempty(find(ind==p+1)) && isempty(find(ind==p+M)) && isempty(find(ind==p+M+1))
            ind_sub=cat(1,ind_sub,i);
        end
    end
    if ~isempty(ind_sub)
        ind(ind_sub)=[];
    end    
    ind_sub=[];
    %按照B5结构元素搜索
    for i=1:length(ind)
        p=ind(i,1);
        if ~isempty(find(ind==p-M-1)) && ~isempty(find(ind==p-1)) && ~isempty(find(ind==p+M-1)) &&...
                isempty(find(ind==p-M+1)) && isempty(find(ind==p+1)) && isempty(find(ind==p+M+1))
            ind_sub=cat(1,ind_sub,i);
        end
    end
    if ~isempty(ind_sub)
        ind(ind_sub)=[];
    end     
    ind_sub=[];
    %按照B6结构元素搜索
    for i=1:length(ind)
        p=ind(i,1);
        if ~isempty(find(ind==p-1)) && ~isempty(find(ind==p+M-1)) && ~isempty(find(ind==p+M)) &&...
                isempty(find(ind==p+1)) && isempty(find(ind==p-M+1)) && isempty(find(ind==p-M))
            ind_sub=cat(1,ind_sub,i);
        end
    end
    if ~isempty(ind_sub)
        ind(ind_sub)=[];
    end    
    ind_sub=[];
    %按照B7结构元素搜索
    for i=1:length(ind)
        p=ind(i,1);
        if ~isempty(find(ind==p+M-1)) && ~isempty(find(ind==p+M)) && ~isempty(find(ind==p+M+1)) &&...
                isempty(find(ind==p-M-1)) && isempty(find(ind==p-M)) && isempty(find(ind==p-M+1))
            ind_sub=cat(1,ind_sub,i);
        end
    end
    if ~isempty(ind_sub)
        ind(ind_sub)=[];
    end   
    ind_sub=[];
    %按照B8结构元素搜索
    for i=1:length(ind)
        p=ind(i,1);
        if ~isempty(find(ind==p+1)) && ~isempty(find(ind==p+M)) && ~isempty(find(ind==p+M+1)) &&...
                isempty(find(ind==p-1)) && isempty(find(ind==p-M)) && isempty(find(ind==p-M-1))
            ind_sub=cat(1,ind_sub,i);
        end
    end
    if ~isempty(ind_sub)
        ind(ind_sub)=[];
    end 
end            
%m连通检测
ind_c=[];
while ~isequal(ind_c,ind)
    ind_c=ind;    
    ind_back=ind;    
    while ~isempty(ind_back)
        p=ind_back(1,:);
        %如果p点四联通中有三个值为1,则将该点置为零
        if (~isempty(find(ind==p+1)) && ~isempty(find(ind==p+M)) && ~isempty(find(ind==p-M))) ||...
                (~isempty(find(ind==p-1)) && ~isempty(find(ind==p+M)) && ~isempty(find(ind==p-M))) ||...
                (~isempty(find(ind==p+1)) && ~isempty(find(ind==p-1)) && ~isempty(find(ind==p-M))) ||...
                (~isempty(find(ind==p+1)) && ~isempty(find(ind==p-1)) && ~isempty(find(ind==p+M)))
            c=find(ind==p);
            ind(c)=[];

        end
        %如果p点四联通中有两个值为1,且其对角为0,则将该点置为零
        if (~isempty(find(ind==p+1)) && ~isempty(find(ind==p+M)) && isempty(find(ind==p-M-1))) ||...
                (~isempty(find(ind==p-1)) && ~isempty(find(ind==p+M)) && isempty(find(ind==p-M+1))) ||...
                (~isempty(find(ind==p+1)) && ~isempty(find(ind==p-M)) && isempty(find(ind==p+M-1))) ||...
                (~isempty(find(ind==p-1)) && ~isempty(find(ind==p-M)) && isempty(find(ind==p+M+1)))
            c=find(ind==p);
            ind(c)=[];
        end             
        ind_back(1,:)=[];
    end       
end

%删除扩展的边缘
g=zeros(size(I_pad));
g(ind)=1;
g=g(2:M-1,2:N-1);
end

 

你可能感兴趣的:(图像处理,图像分割,边缘检测,Canny算法)