2020-2021学年——图像图形编程实践实验4_Canny图像边缘检测

Canny图像边缘检测

实验目的

  1. 了解并掌握使用微分算子进行图像边缘检测的基本原理;
  2. 了解Canny边缘检测原理与实现,进一步理解图像锐化的实质。

实验设备

PC机、matlab2018b

实验原理

  图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是高频滤波。我们知道微分运算是求信号的变化率,具有加强高频分量的作用。在空域运算中来说,对图像的锐化就是计算微分。由于数字图像的离散信号,微分运算就变成计算差分或梯度。图像处理中有多种边缘检测(梯度)算子,常用的包括普通一阶差分,Robert算子(交叉差分),Sobel算子等等,是基于寻找梯度强度。拉普拉斯算子(二阶差分)是基于过零点检测。通过计算梯度,设置阀值,得到边缘图像。
  Canny边缘检测算子是一种多级检测算法。1986年由John F. Canny提出,同时提出了边缘检测的三大准则:
  低错误率的边缘检测:检测算法应该精确地找到图像中的尽可能多的边缘,尽可能的减少漏检和误检。
  最优定位:检测的边缘点应该精确地定位于边缘的中心。
  图像中的任意边缘应该只被标记一次,同时图像噪声不应产生伪边缘。
  进而,Canny的工作本质是,从数学上表达前面的三个准则。因此Canny的步骤如下:
  对输入图像进行高斯平滑,降低错误率。
  计算梯度幅度和方向来估计每一点处的边缘强度与方向。
  根据梯度方向,对梯度幅值进行非极大值抑制。本质上是对Sobel、Prewitt等算子结果的进一步细化。
  用双阈值处理和连接边缘。

问题描述

  编程实现Canny图像边缘检测方法,对不同参数进行验证。
1.对灰度图像,–实现Canny的计算过程,(matlab, python, opencv)
2.Canny里面有大小2个阈值,分析这两个值对结果的影响。

计算方法

  选用图片如下图所示:

在这里插入图片描述

图4-1

高斯滤波器平滑

(1)读取实验用图像记为img:使用imread函数将图像读入Matlab;
(2)将图像转为double类型;
(3)如果图像是彩色图像,转为灰度图像;
(4)获取输入图像的行和列;
(5)计算图像中每一个点距频率矩形中心的距离矩阵;
(6)在本次实验中直接使用Matlab内置函数imfilter()进行高斯滤波如下图所示,记图像为img1:

在这里插入图片描述

图4-2

计算图像梯度

(1)定义检测竖直边缘模板[-1,0,1;-2,0,2;-1,0,1]和检测水平边缘模板[-1,-2,-1;
0,0,0;1,2,1]对图像进行遍历得到竖直方向梯度矩阵Gy和水平方向梯度矩阵Gx;
(2)使用公式得到图像幅值矩阵Gmag,如下图所示;

在这里插入图片描述

图4-3

(3)使用公式2得到梯度方向矩阵,因为arctanx函数的值域为 [ − π / 2 , π / 2 ] [-\pi / 2, \pi/ 2] [π/2,π/2],将其按照如下关系映射到 [ 0 , 2 π ] [0, 2 \pi] [0,2π],得到的结果单位为弧度制;

G x > 0 , G y > 0 , θ 不 变 G_{x} > 0 , G_{y} > 0, \theta 不变 Gx>0,Gy>0,θ
G x < 0 , G y > 0 , θ + π G_{x} < 0 , G_{y} > 0, \theta + \pi Gx<0,Gy>0,θ+π
G x < 0 , G y < 0 , θ + π G_{x} < 0 , G_{y} < 0, \theta + \pi Gx<0,Gy<0,θ+π
G x > 0 , G y < 0 , θ + 2 π G_{x} > 0 , G_{y} < 0, \theta + 2\pi Gx>0,Gy<0,θ+2π

梯度非极大值抑制

(1)初始化N(x, y)=Gmag(x, y);
(2)对于每个点,在梯度方向和反梯度方向各找n个像素点。
若Gmag(x, y)不是这些点中的最大点,则将N(x, y)置零,否则保持N(x, y)不变;
(3)为简单起见,我们使用梯度可能的四个方向[0,45,90,135],当梯度方向不在该四个方向上时,使用的方向取梯度方向最接近的方向,如下图所示

在这里插入图片描述

图4-4

(4)我们使用3*3的区域,若在梯度方向上的三个点的最大值为中心点,则保留该点,否则,置0,结果Gmag1如下图所示:

在这里插入图片描述

图4-5

双阈值提取边缘点图像

(1)选择低阈值ThresholdLow = 0.1 * max(max(Gmag1)),高阈值ThresholdHigh = 0.12* max(max(Gmag1));
(2)对Gmag1中的点,若大于ThresholdHigh,将该值置为1,若小于ThresholdLow,将该值置为0,若大于ThresholdLow并且小于ThresholdHigh,进行步骤3;
(3)对于该点的8连通区域,若该区域存在大于ThresholdHigh的点,该点置为1;
(4)进行如上处理得到的结果Gmag2如下图所示;

在这里插入图片描述

图4-6

使用Matlab内置函数对图像进行Canny边缘检测如下图所示:

在这里插入图片描述

图4-7

(5)选择低阈值ThresholdLow = 0.01 * max(max(Gmag1)),高阈值ThresholdHigh = 0.05* max(max(Gmag1)),得到图像如下图所示:

在这里插入图片描述

图4-8

(6)选择低阈值ThresholdLow = 0.2 * max(max(Gmag1)),高阈值ThresholdHigh = 0.22* max(max(Gmag1)),得到图像如下图所示:

在这里插入图片描述

图4-9

结果分析

  使用小的阈值,保留的像素值过多,将得到大量的边缘点,出现大量的错误检测如图4-8。
  使用大的阈值,保留的像素值不足,得到少量的边缘点,出现许多空隙如图4-9。

实验代码

function [img_0,Gmag,Gmag1,Gmag2] = ex4_MyCanny_2(img)
% Canny图像边缘检测
% img:待检测图像
% img_0:高斯滤波后图像,Gmag:图像梯度幅值图像,Gmag1:非极大值抑制抑制后图像,Gmag2:双阈值提取边缘点图像
 
% 转为灰度图像
img = rgb2gray(img);
% 高斯滤波器平滑
W = fspecial('gaussian',[5,5],1); 
img_0 = imfilter(img, W, 'replicate');
 
% 梯度幅值和梯度方向计算
[Gmag,Gdir] = ex4_MyImgradient_1(img_0);
 
% 非极大值抑制
Gmag1 = ex4_MyNMS_2(Gmag,Gdir);
% figure,imshow(Gmag1),title("非极大值抑制");
 
% 双阈值提取边缘点
Gmag2 = ex4_MyDoubleThreshold(Gmag1);

function [grad,theta] = ex4_MyImgradient_1(img)
% grad:图像梯度,theta:图像梯度方向
% img:待处理图像
% img = rgb2gray(img);
% 获取图像大小
[m,n]=size(img);
% % 检测竖直边缘模板
template_col = [-1,0,1;-2,0,2;-1,0,1];
% 检测水平边缘模板
template_row = [-1,-2,-1;0,0,0;1,2,1];
 
% 利用自定义均值滤波函数进行计算
grad_col_double = ex4_MyFilter_1(img,template_col,1);
grad_row_double = ex4_MyFilter_1(img,template_row,1);
 
% 梯度幅值
grad = (grad_col_double .^2 + grad_row_double .^2) .^(0.5);
% 梯度方向
theta = atan(grad_col_double ./ grad_row_double);
for i = 1:m
    for j = 1:n
        if grad_row_double(i,j) == 0 && grad_col_double(i,j) >= 0
            theta(i,j) = pi/2;
        elseif grad_row_double(i,j) == 0 && grad_col_double(i,j) <= 0
            theta(i,j) = 3 * pi/2;
        end
    end
end
% arctan(x)函数值域为(-pi/2,pi/2),根据grad_col_double和grad_row_double将其映射到[0,2pi]
for i = 2 : m - 1
    for j = 2 : n - 1
        % 方向在第二象限
        if grad_row_double(i,j) < 0 && grad_col_double(i,j) >= 0
            theta(i,j) = theta(i,j) + pi;
        % 方向在第三象限
        elseif grad_row_double(i,j) < 0 && grad_col_double(i,j) <= 0
            theta(i,j) = theta(i,j) + pi;
        % 方向在第四象限
        elseif grad_row_double(i,j) > 0 && grad_col_double(i,j) <= 0
            theta(i,j) = theta(i,j) + 2 * pi;
        end
    end
end
% 转为角度制
theta = rad2deg(theta);

function Gmag1 = ex4_MyNMS_2(Gmag,Gdir)
% Gmag1:非极大值抑制后图像梯度
% Gmag:图像梯度,Gdir:图像梯度方向
template_0 = [0,0,0;1,1,1;0,0,0];
template_45 = [0,0,1;0,1,0;1,0,0];
template_90 = [0,1,0;0,1,0;0,1,0];
template_135 = [1,0,0;0,1,0;0,0,1];
[m,n] = size(Gmag);
Gmag1 = Gmag;
for i = 2:m - 1
    for j = 2:n - 1
        id = ex4_MyDir_2(Gdir(i,j)); 
        temp = Gmag(i - 1:i + 1,j - 1:j + 1);
        if id == 1
            result = template_0 .* temp;
        elseif id == 2
            result = template_45 .* temp;
        elseif id == 3
            result = template_90 .* temp;
        elseif id ==4
            result = template_135 .* temp;
        end
        if max(max(result)) ~= Gmag(i,j)
            Gmag1(i,j) = 0;
        end
    end
end

function Gmag2 = ex4_MyDoubleThreshold(Gmag1)
% Gmag1:图像梯度
% Gmag2:经过双阈值检测后的图像梯度
[m,n] = size(Gmag1);
Gmag2 = zeros(m,n);%定义一个双阈值图像
Coef = [0.1,0.12];
% Coef = [0.01,0.05];
% Coef = [0.2,0.22];
ThresholdLow = Coef(1) * max(max(Gmag1));%低阈值
ThresholdHigh = Coef(2) * max(max(Gmag1));%高阈值
for i = 2  : m - 1
    for j = 2 : n - 1
        if (Gmag1(i, j) < ThresholdLow)
            Gmag2(i,j) = 0;
        elseif (Gmag1(i, j) > ThresholdHigh)
            Gmag2(i,j) = 1 ;
        %对ThresholdLow < Nms(i, j) < ThresholdHigh 使用8连通区域确定
        elseif (Gmag1(i, j) < ThresholdHigh && Gmag1(i, j) > ThresholdLow)
            su =[Gmag1(i-1,j-1), Gmag1(i-1,j), Gmag1(i-1,j+1);
                       Gmag1(i,j-1),    Gmag1(i,j),   Gmag1(i,j+1);
                       Gmag1(i+1,j-1), Gmag1(i+1,j), Gmag1(i+1,j+1)];
            Max = max(su);
            if Max>=ThresholdHigh
                Gmag2(i,j) = 1 ;
            end
        end
    end
end
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值