由于基于边缘检测的分析不易受到整体光照强度变化的影响,许多图像理解方法都以边缘为基础。边缘检测强调的是图像的对比度。检测对比度,即亮度上的差别,可以增图像中的边界特征,这些边界正是图像对比度出现的地方。这就是人类视觉感知目标周界的机制,因为目标表现的就是与他周围的亮度差别。目标边界实际上时亮度级的梯度变化,而边缘是梯度变化的位置。
亮度变化可以通过对相邻点进行差分处理来增强。对水平方向上的相邻点进行差分处理可以检测垂直方向上的亮度变化,称为水平边缘检测算子。把它用于图像P时,水平边缘检测算子的处理结果会形成两个水平相邻点的差值,这样就检测出垂直边缘,Ex,如:
为了检测水平边缘,我们需要一个垂直边缘检测算则对垂直方向上的相邻点进行差分处理。这样可以确定水平方向上而不是垂直方向上的亮度变化,因此垂直边缘检测算子检测的是水平边缘,Ey,如:
将这两个算子合并得出算子E,它可以同时检测垂直和水平边缘,即:
由此得出:
式(1-4)给出了差分模板的系数,它可以与图像做卷积运算检测所有边缘点。该式对应的模板如图1-1所示。
边缘检测类似于微分处理。由于它检测的是变化,必然对噪声以及图像亮度的阶梯式变化都有响应。因此把均值处理加入到边缘检测过程一定要非常谨慎。把垂直模板Mx扩展成三行,把水平模板My扩展成三列,这样就得到Prewitt边缘检测算子。它由两个模板组成,如图1-2.
Prewitt算子给出两个结果:沿每个坐标轴的亮度变化率,边缘强度M是向量的长度,而边缘方向θ是向量的角度。
如果使两个Prewitt模板中心像素的权重取2倍的值,便是Sobel边缘检测算子。Sobel算子的模板如图1-3所示:
OpenCV代码实例:
void Edge_Sobel()
{
Mat img = imread("../ImageSet/wgj_1.jpg");
if(img.empty())
{
cout<<"Read image failed"<
Sobel边缘检测效果:
Canny边缘检测由三个主要目标形成:
第一个目标是减少噪声响应,可以通过最优平滑处理来实现,一般用高斯滤波。第二个目标是正确性,可以通过非极大值抑制处理来实现;非极大值抑制的输出是正确位置上边缘点连成的细线。第三个目标限制是单个边缘点对于亮度变化的定位。
Canny算法一般分5步实现:
(1) 高斯模糊。主要作用是去除噪声,高斯模板的半径选择很重要,过大的半径容易模糊边缘,过小无法滤除噪声,OpenCV推荐使用5*5大小。
(2) 计算梯度幅度和方向。一般采用Sobel算子实现。
(3) 非极大值抑制。非极大值抑制是一种边缘稀疏技术,非极大值抑制的作用在于“瘦”边。对图像进行梯度计算后,仅仅基于梯度值提取的边缘仍然很模糊。对于标准3,对边缘有且应当只有一个准确的响应。而非极大值抑制则可以帮助将局部最大值之外的所有梯度值抑制为0。
非极大值抑制实质上是找到边缘强度数据中的最高点。它利用边缘方向信息来处理,验证所有点是否是峰值。假设有一个3*3区域,如果一个点两侧的梯度小于该点上的梯度,那么它为极大值。图1-5显示的是兴趣点Px,y的相邻点,在Px,y处的边缘方向以及Px,y处边缘方向的法线。如果梯度Px,y大于点M1和M2,那么点M(x,y)被标记为极大值。由于相邻点都是离散的,需要对M1和M2进行插值,利用Mx,My对其值进行一阶插值,得出:
和
(4) 双阈值检测。在施加非极大值抑制之后,剩余的像素可以更准确地表示图像中的实际边缘。然而,仍然存在由于噪声和颜色变化引起的一些边缘像素。为了解决这些杂散响应,必须用弱梯度值过滤边缘像素,并保留具有高梯度值的边缘像素,可以通过选择高低阈值来实现。如果边缘像素的梯度值高于高阈值,则将其标记为强边缘像素;如果边缘像素的梯度值小于高阈值并且大于低阈值,则将其标记为弱边缘像素;如果边缘像素的梯度值小于低阈值,则会被抑制。阈值的选择取决于给定输入图像的内容。
(5) 滞后边界跟踪。到目前为止,被划分为强边缘的像素点已经被确定为边缘,因为它们是从图像中的真实边缘中提取出来的。然而,对于弱边缘像素,将会有一些争论,因为这些像素可以从真实边缘提取也可以是因噪声或颜色变化引起的。为了获得准确的结果,应该抑制由后者引起的弱边缘。通常,由真实边缘引起的弱边缘像素将连接到强边缘像素,而噪声响应未连接。为了跟踪边缘连接,通过查看弱边缘像素及其8个邻域像素,只要其中一个为强边缘像素,则该弱边缘点就可以保留为真实的边缘。
OpenCV代码示例:
#include
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
using namespace std;
using namespace cv;
#define IMAGE_PATH "../ImageSet/wgj_1.jpg"
int main()
{
Mat img = imread(IMAGE_PATH);
if(img.empty())
{
cout<<"Read image failed"<
边缘提取效果如图1-6所示。
图像的亮度变化也可以用二阶导数表示,当信号变化比例最大时其值也最大,二阶导数的过零位置是一阶导数的峰值变化位置。
Laplacian算子是一个实现二阶微分的模板。二阶微分可以利用两个相邻一阶微分的差值来近似:
将水平二阶算子和垂直二阶算子结合起来可以得到全Laplacian模板。
将四邻点扩展到八邻点,可以得到图2-1 (c)中的模板。
将源图像和拉普拉斯图像叠加在一起的简单方法,可以复原背景特性并保持拉普拉斯锐化处理的效果。