基于Canny算子的边缘检测————MATLAB

一、概念
Canny算子是一种非常重要的边缘检测算子,是最优的阶梯型边缘检测算子。它的最优性主要表现在以下三个方面;
好的检测:Canny算子可以尽可能多地标识出原始图像中的实际边缘。
好的定位:它所标记出来的边缘尽可能给你地接近实际图像中的实际边缘。
最小响应:图像中的边缘只能标识一次,并且可能存在的图像噪声不标识成边缘。

二、Canny算子的具体实现步骤如下:
①去噪声:任何边缘检测算法都不可能在没有经过处理的原始图像上很好地处理,所以首先要对原始图像数据与二维高斯滤波模板进行卷积运算,得到的图像与原始图像相比有轻发的模糊,这样可以消除噪声
②梯度计算,利用导数算子(如Prewitt算子和Sobel算子)来找到图像灰度沿着两个方向的导数G、G,然后就可以分别求出梯度的幅值和方向:
|G|=√G;+G2
在这里插入图片描述

③梯度方向确定:求出了边缘的方向,就可以把边缘的梯度方向大略分成几种角度(如0°、45°、90°和135 ), 并可以找到这个像素梯度方向的邻接像素。
④遍历图像:若是某个像素的灰度值与它的梯度方向上前后两个像素的灰度值相比不是最大的,那么这个像素灰度值就置为0,即不是边缘。
⑤用累计直方图来计算两个阈值:凡是大稿阙值的定是边缘)凡是小于低阈值的一定不是边缘。如果检测结果在两个阈值之间,就根据这个像素的印接像素中有没有超过高阈值的边缘像素进行判断,若有,就是边缘;否则就不是边缘。

三、MATLAB代码实现

% 去噪声
clear all;
clc;
image = imread('Lena.jpg');
image = rgb2gray(image);
subplot(221);
imshow(image);
title('原始图像');
image = double(image)/256;
[m,n] = size(image);
w = fspecial('gaussian');
image_1 = imfilter(image,w,'replicate');
subplot(222);
imshow(int8(256*image_1));
title('高斯滤波后的图像');

% 梯度计算
op = fspecial('sobel')/4;  % 用Sobel算子来求导数
x = op';
y =op;
bx = imfilter(image_1,x,'replicate');
by = imfilter(image_1,y,'replicate');
b_abs = sqrt(bx.*bx+by.*by);        % 求梯度的幅值
b_angle = angle(by-i*bx);
b_ang = b_angle/3.1416*180;         % 求梯度的方向

% 梯度方向确定
for r = 1:m
    for c = 1:n
        if((b_ang(r,c)>=22.5 & b_ang(r,c)<67.5)...
                | (b_ang(r,c)>=-157.5 & b_ang(r,c)<-112.5))
            dir(r,c) = 1;
        elseif ((b_ang(r,c)>=67.5 & b_ang(r,c)<112.5)...
                | (b_ang(r,c)>=-112.5 & b_ang(r,c)<-67.5))
            dir(r,c) = 2;
         elseif ((b_ang(r,c)>=112.5 & b_ang(r,c)<157.5)...
                | (b_ang(r,c)>=-67.5 & b_ang(r,c)<-22.5))
            dir(r,c) = 3;
        else
            dir(r,c) = 0;
        end
    end
end

% 遍历图像
b_ab = [zeros(m,1),b_abs,zeros(m,1)];    % 串联矩阵
b_ab = [zeros(1,n+2);b_ab;zeros(1,n+2)];
for r = 2:m+1
    for c = 2:n+1
        switch dir(r-1,c-1)
            case 0
                if((b_ab(r,c)<b_ab(r+1,c))| (b_ab(r,c)<b_ab(r-1,c)))
                    b1(r-1,c-1) = 0;
                else
                    b1(r-1,c-1) = b_ab(r,c);
                end
            case 1
                if((b_ab(r,c)<b_ab(r+1,c-1))| (b_ab(r,c)<b_ab(r-1,c+1)))
                    b1(r-1,c-1) = 0;
                else
                    b1(r-1,c-1) = b_ab(r,c);
                end
            case 2
                if((b_ab(r,c)<b_ab(r,c-1))| (b_ab(r,c)<b_ab(r,c+1)))
                    b1(r-1,c-1) = 0;
                else
                    b1(r-1,c-1) = b_ab(r,c);
                end
            case 3
                if((b_ab(r,c)<b_ab(r-1,c-1))| (b_ab(r,c)<b_ab(r+1,c+1)))
                    b1(r-1,c-1) = 0;
                else
                    b1(r-1,c-1) = b_ab(r,c);
                end
        end
    end
end
for r = 1:m
    for c = 1:n
        if (b1(r,c)>0.24)
            b2(r,c) = 1;
        else
            b2(r,c) = 0;
        end
    end
end

for r = 1:m
    for c = 1:n
        if(b1(r,c)>0.36)
            b3(r,c)=1;
        else
            b3(r,c) = 0;
        end
    end
end

image_2 = b3;
for k = 1:10
    for r = 2:m-1
        for c = 2: n-1
            if (b2(r,c)==1 & (image_2(r,c)==1|image_2(r+1,c)==1 ...
                |image_2(r+1,c-1)==1|image_2(r+1,c+1)==1|image_2(r,c-1)==1 ...
                |image_2(r,c+1)==1|image_2(r-1,c-1)==1|image_2(r-1,c)==1 ...
                |image_2(r-1,c+1)==1))
                image_2(r,c) = 1;
            else
                image_2(r,c) = 0;
            end
        end
    end
end
subplot(223);
imshow(image_2);
title('Canny算子检测后的图像');


四、实验结果如下
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Prince_IT/article/details/90205259