第5章 图像处理

平滑处理(模糊处理)

平滑处理的用途有很多,最常见的是用来减少图像上的噪声或者失真。降低图像分辨率时,平滑处理很重要。目前OpenCV可提供五种不同的平滑操作,分别为简单模糊,简单无缩放变换的模糊,中值模糊,高斯模糊以及双边滤波。

1
2
// 平滑操作实现函数
void cvSmooth(const CvArr* src, CvArr* dst, int smoothtype=CV_GAUSSIAN, int param1=3, int param2=0, double param3=0, double param4=0);

图像形态学

  • 膨胀和腐蚀

膨胀是指将一些图像(或图像中的一部分区域,称之为A)与核(称之为B)进行卷积。通常情况下,核是一个小的中间带有参考点的实心正方形或圆盘。核可以视为模板或掩码,膨胀是求局部最大值的操作。核B与图像卷积,即计算核B覆盖的区域的像素点最大值,并把这个最大值赋值给参考点指定的像素。这样就会使图像中的高亮区域逐渐增长。
腐蚀是膨胀的反操作。腐蚀操作要计算核区域像素的最小值。当核B与图像卷积时,计算被B覆盖区域的最小像素值,并把这个值放到参考点上。腐蚀能够消除细的凸起。

1
2
3
4
5
6
7
8
// 膨胀操作
void cvErode(IplImage* src, IplImage* dst, IplConvKernel* B=NULL, int iterations=1);
// 腐蚀操作
void cvDilate(IplImage* src, IplImage* dst, IplConvKernel* B=NULL, int iterations=1);
// 自定义核B
IplConvKernel* cvCreateStructuringElementEx(int cols, int rows, int anchor_x, int anchor_y, int shape, int* values=NULL);
// 释放自定义的核
void cvReleaseStructuringElement(IplConvKernel** element);

形态核与卷积核不同,不需要任何的数值填充核,它只是标明了计算最大值或最小值的范围。

  • 更通用的形态学

基本的腐蚀和膨胀操作通常用于处理布尔图像和图像掩码。然而,在处理灰度或彩色图像时,往往需要一些额外的操作。
开运算:先腐蚀再膨胀,通常可以用来统计二值图像中的区域数。开运算消除高于其邻近点的孤立点。
闭运算:先膨胀再腐蚀,对于连通区域分析,通常先采用闭运算来消除纯粹由噪声引起的部分,然后用开运算来连接邻近的区域。闭运算消除低于其邻近点的孤立点。
形态学梯度:对二值图像,可以将团块的边缘突出出来。能够描述图像亮度变化的剧烈程度。
礼帽和黑帽:两者分别用于分离比邻近的点亮或暗的一些斑块。当试图孤立的部分相对于其邻近的部分有亮度变化时,就可以使用这些方法。礼帽操作是从A中减去了A的开运算。黑帽操作是A的闭运算减去A。

1
2
// 通用的形态学操作函数
void cvMorphologyEx(const CvArr* src, CvArr* dst, CvArr* temp, IplConvKernel* element, int operation, int iterations=1);
  • 漫水填充法

漫水填充法经常被用来标记或分离图像的一部分以便对其进行进一步处理或分析;也可以用来从输入图像获取掩码区域,掩码会加速处理过程,或只处理掩码指定的像素点。

1
2
// 填充算法函数原型
void cvFloodFill(Iplimage* img, CvPoint seedPoint, CvScalar newVal, CvScalar loDiff=cvScalarAll(0), CvScalar upDiff=cvScalarAll(0), CvConnectedComp* comp=4, CvArr* mask=NULL);
  • 尺寸调整

cvResize()函数用于放大或缩小图像。该函数可以将源图像精确转换为目标图像的尺寸。如果源图像中设置了ROI,那么cvResize()将会对ROI区域调整尺寸,以匹配目标图像,同样,如果目标图像中已经设置ROI的值,那么cvResize()将会源图像进行尺寸调整并填充到目标图像的ROI中。

1
2
// cvRsize()函数原型
void cvResize(const CvArr* src, CvArr* dst, int interpolation=CV_INTER_LINEAR);
  • 图像金字塔

图像金字塔是一个图像集合,集合中所有的图像都源于同一个原始图像,而且是通过对原始图像连续降采样获得,直到达到某个终止条件才停止降采样。在应用中常有两种类型的图像金字塔:高斯金字塔和拉普拉斯金字塔。高斯金字塔用来向下降采样图像,而拉普拉斯金字塔则用来从金字塔底层图像中向上采样重建一个图像。

1
2
3
4
5
6
// 从金字塔中上一级图像生成下一级图像,新图像面积会变为源图像的1/4
void cvPyrDown(IplImage* src, IplImage* dst, IplFilter filter=CV_GAUSSIAN_5×5));
// 将现有的图像在每个维度都放大2倍
void cvPyrUp(IplImage* src, IplImage* dst, IplFilter filter=CV_GAUSSIAN_5×5);
// 利用金字塔实现图像分割
void cvPySegmentation(IplImage* src, IplImage* dst, CvMemStorage* storage, CvSeg** comp, int level, double threshold1, double threshold2);
  • 阈值化

基本思想:给定一个数组和一个阈值,然后根据数组中的每个元素的值是低于还是高于阈值而进行一些处理。

1
double cvThreshold(CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type);

对于有很强照明或反射梯度的图像,需要根据梯度进行阈值化时,往往需要自适应阈值技术。

1
2
// 自适应阈值函数原型
void cvAdaptiveThreshold(CvArr* src, CvArr* dst, double max_val, int adaptive_method=CV_ADAPTIVE_THRESH_MEAN_C, int threshold_type=CV_THRESH_BINARY, int block_size=3, double param1=5);