前半部分的几种方法主要将一幅图像变换成只由边缘组成的图像,而后半部分的几种方法是将图像轮廓分离出来。当然这篇文章只是我对图像处理的理解,如果有不妥之处希望大家可以指出来。
卷积
在开始这个专题之前先要讲下卷积。寒假刚刚开始看的时候是一脸懵逼的,不太懂卷积是个什么鬼。虽然现在还是不太懂,不过大概懂了这个函数的用处(顺便一说,在信号与系统的课本里看到了卷积和拉普拉斯,不知道听完信号与系统是否对这些计算能有更深入的理解)。我将图像理解为几个二维数组的组成。例如YUV图像,可以理解成三个二维数组,二维数组的坐标代表像素点位置,其值分别代表该点Y、U和V三维的坐标。卷积则是相当于利用不同的卷积规则实现对图像的数据计算。后面的几种算法都是不同的卷积。
梯度和Sobel
导数计算便是一个基本的卷积。最常用来表示微分的操作是Sobel微分算子。在OpenCV中,使用cvSobel()函数实现
cvSobel(
const CvArr *src,
CvArr *dst,
int xorder,
int yorder,
int aperture_size = 3
);
src和dst分别为输入输出图像,xorder和yorder分别代表求导的阶数,通常不会超过2。aperture_size表示方形滤波器的宽。在OpenCV 1.0中支持1、3、5、7。
拉普拉斯变换
拉普拉斯函数可以用二次导数的形式定义,在OpenCV中计算拉普拉斯算子时直接使用Sobel算子。
void cvLaplace(
const CvArr *src,
CvArr *dst,
int aperture_size = 3
);
拉普拉斯算子可以用于各种情况,通常的一个应用是检测团块。拉普拉斯算子的形式是沿X轴和Y轴二次导数之和,这就意味着周围值更高的单点或者小块会将这个函数值最大化,而周围是更低值的点将会使函数负值最大化。
当我们逼近类似边缘的不连续地方时导数会快速增长,而穿过这些不连续的地方时导数又会快速减小,所以导数在此范围内会有极值。
Canny算子
Canny算子与拉普拉斯算法不同的地方在于它首先求出x和y方向上的一阶导数,然后组合为四个方向上的导数,这些方向导数到达局部最大值的点就是组成边缘的候选点。
Canny算法最重要的一个新的特点是其仕途将独立边的候选像素拼装成轮廓。轮廓的形成是对这些像素运用滞后性阙值。大于上线阙值会被认为是边缘像素,小于下限阙值会被抛弃。OpenCV中的函数如下:
void cvCanny(
const CvArr * img,
CvArr * edges,
double lowThresh,
double highThresh,
int aperture_size = 3
lowThresh和highThresh分别代表上下限阙值。