令 f ( x , y ) 表 示 数 据 ( 输 入 源 数 据 ) , G ( x , y ) 表 示 二 维 高 斯 函 数 ( 卷 积 操 作 数 ) , f s ( x , y ) 令f(x,y)表示数据(输入源数据),G(x,y)表示二维高斯函数(卷积操作数),f_s(x,y) 令f(x,y)表示数据(输入源数据),G(x,y)表示二维高斯函数(卷积操作数),fs(x,y)为卷积平滑后的图像。
G ( x , y ) = 1 2 π σ 2 e − ( x 2 + y 2 ) 2 σ 2 G(x,y)=\frac{1}{2\pi\sigma^2}e^\frac{-(x^2+y^2)}{2\sigma^2} G(x,y)=2πσ21e2σ2−(x2+y2)
f s ( x , y ) = f ( x , y ) ∗ G ( x , y ) f_s(x,y)=f(x,y)\ast G(x,y) fs(x,y)=f(x,y)∗G(x,y)
补充:求变化率时,对于一元函数,即求导;对于二元函数,求偏导。
数字图像处理中,用一阶有限差分近似求取灰度值的梯度值(变化率)。
(即:使差商( Δ f / Δ x \Delta {f} / \Delta {x} Δf/Δx) 近似取代微商( ∂ f / ∂ x \partial{f} / \partial{x} ∂f/∂x)。求灰度的变化率,分别取x和y方向上相邻像素做差,代替求取x和y方向一阶偏导)
例:计算一点 x 方 向 和 y x方向和y x方向和y方向的梯度幅值和方向
上图中显示一段直的边缘线段放大后一部分,每个方块代表一个像素点,用一个方框强调点处边缘的幅值和方向。令灰色像素值为0,白色像素值为1.
如图关于一点为中心的 3 × 3 3 \times 3 3×3 邻域,使用 P r e w i t t Prewitt Prewitt卷积模板进行计算:
p x = [ − 1 − 1 − 1 0 0 0 1 1 1 ] , p y = [ − 1 0 1 − 1 0 1 − 1 0 1 ] p_x= \begin{bmatrix} -1&-1&-1\\ 0&0&0\\ 1&1&1 \end{bmatrix} , p_y= \begin{bmatrix} -1&0&1\\ -1&0&1\\ -1&0&1 \end{bmatrix} px=⎣⎡−101−101−101⎦⎤,py=⎣⎡−1−1−1000111⎦⎤
根据 x 方 向 和 y x方向和y x方向和y方向的卷积模板,可知,在 3 × 3 3 \times 3 3×3邻域中从底部一行像素值减去顶部一行的像素,得到 x x x方向的偏导数(梯度);同样,从右边一列像素值减去左边一列的像素,得到 y y y方向的偏导数。
x x x方向的梯度: g x = ∂ f / ∂ x = ( 0 − 0 ) + ( 0 − 1 ) + ( 0 − 1 ) = − 2 g_x=\partial{f}/\partial{x}=(0-0)+(0-1)+(0-1)=-2 gx=∂f/∂x=(0−0)+(0−1)+(0−1)=−2
y y y方向的梯度: g y = ∂ f / ∂ x = ( 1 − 0 ) + ( 1 − 0 ) + ( 0 − 0 ) = 2 g_y=\partial{f}/\partial{x}=(1-0)+(1-0)+(0-0)=2 gy=∂f/∂x=(1−0)+(1−0)+(0−0)=2
由此,可以得到该点梯度的幅值和方向:
M ( x , y ) = g x 2 + g y 2 = 2 2 M(x,y)=\sqrt{g_x^2+g_y^2}=2\sqrt{2} M(x,y)=gx2+gy2=22
α ( x , y ) = a r c t a n [ g y / g x ] = 135 ° \alpha(x,y)=arctan[g_y/g_x]=135° α(x,y)=arctan[gy/gx]=135°
如下图表示了中心点的梯度向量、方位角以及边缘方向。(任一点的边缘与梯度向量正交)
注意:
Canny 算子卷积模板:
p x = [ − 1 − 1 1 1 ] , p y = [ 1 − 1 1 − 1 ] p_x= \begin{bmatrix} -1&-1\\ 1&1 \end{bmatrix} , p_y= \begin{bmatrix} 1&-1\\ 1&-1 \end{bmatrix} px=[−11−11],py=[11−1−1]
p [ i , j ] = ( f [ i , j + 1 ] − f [ i , j ] + f [ i + 1 , j + 1 ] − f [ i + 1 , j ] ) / 2 p[i,j]=(f[i,j+1]-f[i,j]+f[i+1,j+1]-f[i+1,j])/2 p[i,j]=(f[i,j+1]−f[i,j]+f[i+1,j+1]−f[i+1,j])/2
Q [ i , j ] = ( f [ i + 1 , j ] − f [ i , j ] + f [ i + 1 , j + 1 ] − f [ i , j + 1 ] ) / 2 Q[i,j]=(f[i+1,j]-f[i,j]+f[i+1,j+1]-f[i,j+1])/2 Q[i,j]=(f[i+1,j]−f[i,j]+f[i+1,j+1]−f[i,j+1])/2
M [ i , j ] = p [ i , j ] 2 + Q [ i , j ] 2 M[i,j]=\sqrt{p[i,j]^2+Q[i,j]^2} M[i,j]=p[i,j]2+Q[i,j]2
θ = a r c t a n ( Q [ i , j ] / p [ i , j ] ) \theta=arctan(Q[i,j]/p[i,j]) θ=arctan(Q[i,j]/p[i,j])
步骤:
1. 对角度在四个方向进行划分,形成新的角度图;
2. 根据角度图(表征着梯度的方向),对幅值进行非极大值抑制。
做法:若中心点(即:访问点)在沿其方向上邻域的梯度幅值最大,则保留;否则,抑制。
注意:双阈值做法是将候选像素点拼接成轮廓,轮廓的形成时对这些像素运用滞后性阈值。
clear all;
clc;
I = imread('rice.png');%读图
% I = rgb2gray(I);%灰度转换
I = double(I);%转化为双精度
[H,W] = size(I);%获取图像大小
%% Step1:使用高斯滤波平滑图像
B = [1 2 1;2 4 2;1 2 1];%高斯滤波系数
B = 1/16.*B;%高斯滤波模板 方差=0.8
A = conv2(I,B,'same');%使用高斯模板进行卷积.计算二维卷积,结果与原图像大小相同
%% Step2:计算梯度的幅值图像,角度图像.
%Prewitt梯度模板
dx = [-1 0 1;-1 0 1;-1 0 1];%x方向的梯度模板
dy = [1 1 1; 0 0 0;-1 -1 -1];%y方向的梯度模板
gx = conv2(A,dx,'same');%获取x方向的梯度图像.使用梯度模板进行二维卷积,结果与原图像大小相同
gy = conv2(A,dy,'same');%获取y方向的梯度图像.使用梯度模板进行二维卷积,结果与原图像大小相同
M = sqrt((gx.^2) + (gy.^2));%获取幅值图像.大小与原图像相等.(.^)表示数组乘方
a = atan2(gy,gx);%获取弧度,范围:-pi~pi
a = a*180/pi;%将弧度转换为角度,得到角度图像,与原图像大小相等.
%% Step3:对幅值图像进行应用非极大值抑制
%首先将角度划分成四个方向范围:水平(0°)、-45°、垂直(90°)、+45°
for i = 1:H
for j = 1:W
if((a(i,j) >= -22.5) && (a(i,j) < 0)||(a(i,j) >= 0) && (a(i,j) < 22.5) || (a(i,j) <= -157.5) && (a(i,j) >= -180)||(a(i,j) >= 157.5)&&(a(i,j) <= 180))
a(i,j) = 0;
elseif((a(i,j) >= 22.5) && (a(i,j) < 67.5) || (a(i,j) <= -112.5) && (a(i,j) > -157.5))
a(i,j) = -45;
elseif((a(i,j) >= 67.5) && (a(i,j) < 112.5) || (a(i,j) <= -67.5) && (a(i,j) >- 112.5))
a(i,j) = 90;
elseif((a(i,j) >= 112.5) && (a(i,j) < 157.5) || (a(i,j) <= -22.5) && (a(i,j) > -67.5))
a(i,j) = 45;
end
end
end
%讨论对 3x3 区域的四个基本边缘方向进行非极大值抑制.获取非极大值抑制图像
Nms = zeros(H,W);%定义一个非极大值图像
for i = 2:H-1
for j= 2:W-1
if (a(i,j) == 0 && M(i,j) == max([M(i,j), M(i,j+1), M(i,j-1)]))
Nms(i,j) = M(i,j);
elseif (a(i,j) == -45 && M(i,j) == max([M(i,j), M(i+1,j-1), M(i-1,j+1)]))
Nms(i,j) = M(i,j);
elseif (a(i,j) == 90 && M(i,j) == max([M(i,j), M(i+1,j), M(i-1,j)]))
Nms(i,j) = M(i,j);
elseif (a(i,j) == 45 && M(i,j) == max([M(i,j), M(i+1,j+1), M(i-1,j-1)]))
Nms(i,j) = M(i,j);
end;
end;
end;
%% Step4:双阈值检测和连接边缘
DT = zeros(H,W);%定义一个双阈值图像
TL = 0.1 * max(max(Nms));%低阈值
TH = 0.3 * max(max(Nms));%高阈值
for i = 1 : H
for j = 1 : W
if (Nms(i, j) < TL)
DT(i,j) = 0;
elseif (Nms(i, j) > TH)
DT(i,j) = 1 ;
%对TL < Nms(i, j) < TH 使用8连通区域确定
elseif ( Nms(i+1,j) > TH || Nms(i-1,j) >TH || Nms(i,j+1) > TH || Nms(i,j-1) > TH || Nms(i-1, j-1) > TH || Nms(i-1, j+1) > TH || Nms(i+1, j+1) > TH || Nms(i+1, j-1) > TH)
DT(i,j) = 1;
end;
end;
end;
figure, imshow(DT); %最终的边缘检测为二值图像