学习OPENCV笔记(2): 第四章 图像处理

1 平滑处理

平滑处理也称作模糊处理(blurring),其用途很多,最常见的是用来减少图像上的噪声或者失真。

目前,OpenCV支持五种平滑处理,他们都通过 cvSmooth 函数实现:

CVAPI(void) cvSmooth( const CvArr* src, CvArr* dst,
                      int smoothtype CV_DEFAULT(CV_GAUSSIAN),
                      int size1 CV_DEFAULT(3),
                      int size2 CV_DEFAULT(0),
                      double sigma1 CV_DEFAULT(0),
                      double sigma2 CV_DEFAULT(0));

通过参数 smoothtype来确定对输入图像采取何种平滑处理:

平滑类型名称IN-PLACE输入类型输出类型简要说明
CV_BLUE简单模糊(均值滤波)Y8U, 32F8U, 32F对每个像素size1*size2邻域求和,并做缩放1/(size1*size2)
CV_BLUE_NO_SCALE简单无缩放变化的模糊N8U`16S/32F对每个像素size1*size2邻域求和
CV_MEDIAN中值模糊N8U8U对源图像进行核大小为size1*size2的中值滤波
CV_GAUSSIAN高斯模糊Y8U,32F8U, 32F对源图像进行核大小为size1*size2的高斯卷积
CV_BILATERAL双边滤波N8U8U应用双线性3*3滤波

 

1.1 中值滤波

将中心像素的正方形邻域内的每个像素值用中间像素表示。

他相较简单模糊(均值滤波),对图像中孤立的噪声点不是那么敏感:均值滤波时,即使有极少量的点存在较大的差异,也会导致平均值有明显的波动,而中值滤波可以通过选择中间值来避免这些点的影响

 

1.2  高斯滤波

高斯滤波其实就是对邻域内的每个像素点进行加权平均,同时,离中心越近的像素权重越高,相对于均值滤波,他的平滑效果更加柔和,且能够更号的保留边缘;具体的做法是用卷积核和输入图像的每个点进行卷积。

OpenCV为高斯滤波提供了几个常见的核以提高性能:具有标准sigma值的3*3, 5*5, 7*7比其他的核具有更高的性能。

一维高斯分布的公式如下:

二维高斯高斯分布的公式如下:

高斯滤波后被平滑的图像取决于标准差。函数cvSmooth的参数三代表了高斯卷积核的sigma值,如果没有指定的化,函数将会通过如下的公式自动获取:

\sigma x = (sizex / 2 - 1) * 0.3 +0.8

\sigma y = (sizey / 2 - 1) * 0.3 + 0.8

1.3 边缘滤波

高斯滤波在保留信号的条件下,减少了噪声。但是,这种方法在接近边缘的地方就无效了,在边缘,你不希望像素和相邻像素有关。因此,高斯滤波会磨平边缘,而双边滤波能够提供一种不会将边缘平滑掉的方法。但是作为代价,需要更多的处理时间。

和高斯滤波类似,双边滤波会依据每个像素及其邻域构造一个加权平均,加权计算包括两个部分,其中第一部分加权方式和高斯平滑中的相同,第二部分也属于高斯加权 ,但是不是基于基于中心像素点与其他像素点的空间距离之上的加权,而是基于与中心像素的亮度值的加权。可以将双边滤波视为高斯平滑,对相似的像素赋予较高的权重,不相似的赋予较小的权重。

双边滤波的公式如下图所示:

其中w取决与定义域和和值域核的乘积:

定义域核:

值域核:

权重系数:

 

 

2. 图像形态学

2.1 膨胀操作

膨胀操作是求局部最大值的操作。在对邻域求最大值之后,相当于前景(亮的部分)大了一圈。膨胀操作能够使图像中的高亮区域逐渐增长。

void cvDilate( const CvArr* srcarr, CvArr* dstarr, IplConvKernel* element, int iterations )

2.2 腐蚀操作

腐蚀操作要计算核区域像素的最小值。是膨胀操作的反操作。

void cvErode( const CvArr* srcarr, CvArr* dstarr, IplConvKernel* element, int iterations )

膨胀操作可以填补凹洞,而腐蚀操作能够消除细的凸起腐蚀操作通常用来消除图像中的斑点噪声,而在试图找到联通分支的时候,通常需要用到膨胀操作,因为一个大的区域,可能因为噪声,阴影等类似的东西而分割成多个部分,而膨胀操作,能够将其重新融合在一起

膨胀和腐蚀函数的第三个参数是IplCovKernel,我们也可以自定义核。通常,通过如下函数进行核的创建和释放:

IplConvKernel *
cvCreateStructuringElementEx( int cols, int rows,
                              int anchorX, int anchorY,
                              int shape, int *values );

void
cvReleaseStructuringElement( IplConvKernel ** element );

创建的时候,可以通过参数决定核的形状:

CV_SHAPE_RECT矩形
CV_SHAPE_CROSS十字交叉形
CV_SHAPE_ELLIPSE椭圆形
CV_SHAPE_CUSTOM用户自定义的值

如果不是二值图像,膨胀和腐蚀的操作结果往往不是很明显。在很多情况下,我们需要一些更加通用的形态学操作:

void
cvMorphologyEx( const void* srcarr, void* dstarr, void*,
                IplConvKernel* element, int op, int iterations );

op的可选标记有:

操作形态学操作是否需要临时图像
CV_MOP_OPEN开运算
CV_MOP_CLOSE闭运算
CV_MOP_GRADIENT形态梯度
CV_MOP_TOPHAT礼帽in-place下需要
CV_MOP_BLACKHAT黑帽in-place下需要

 

2.3 开运算和闭运算

运算操作说明
开运算先腐蚀,再膨胀消除了高于临近点的孤立点。通常用来统计二值图像中的区域数。
闭运算先膨胀,再腐蚀消除了低于临近点的孤立点。

 

 

从上图中可以看出,膨胀操作先其了邻域内的最大点,再对其进行腐蚀得到最终的图形,可以消除像素值低于临近点的孤立的点

从上图中可以看出,腐蚀操作取邻域内的最小值,再对其进行膨胀得到最终图像。可以消除像素值高于临近点的孤立点

 

需要注意,在开运算和闭运算下,函数cvMorphologyEx的iterations参数并不表示膨胀-腐蚀-膨胀-腐蚀的次数,而是表示膨胀-膨胀-...-腐蚀-腐蚀...这样的过程的次数。

 

2.4 形态学梯度

形态学梯度的表达式如下:

gradient(src) = dialate(src) - erode(src)

从上图中可以看出形态学梯度的过程,从原图像的膨胀减去了源图像的收缩,就得到了图像的边缘。

 

2.5 礼帽和黑帽

同以上的形态学操作类似,礼貌和黑帽操作也是基本操作的组合,公式如下:

TopHat(src) = src - open(src)

BlackHat(src) = close(src) - src

从2.3的阐述中,我们可以知道,开运算消除了高于临近点的孤立的点,如果我们用原图像减去开运算的结果;得到的就是开运算消除的部分,即高于临近点的部分。所以礼帽操作突出了比周围区域更加明亮的部分

相反,闭运算消除了低于临近点的孤立的点,如果我们用闭运算的结果加你去源图像,得到的就是闭运算消除的部分,即低于临近点的部分。所以黑帽操作突出了比周围区域更加黯的部分

 

3. 漫水填充算法

漫水填充算法的思路很简单,就是从一个种子点开始,如果周围的点和目标点相同或者相似,就往周围扩散;就像水往周围漫开一样。它经常被用来标记或者分离图像的一部分,以便对其进行进一步的处理或者分析。

void
cvFloodFill( CvArr* arr, CvPoint seed_point,
             CvScalar newVal, CvScalar lo_diff, CvScalar up_diff,
             CvConnectedComp* comp, int flags, CvArr* maskarr )

该函数的入参比较复杂,下面我们来进行说明:

arr源图像
seedPoint种子点,从哪个点开始漫水
newVal像素点被染色的值
lo_diff, up_diff范围,如果目的像素点的值在lo_diff和up_diff之间,将会被染色成newVal
comp如果该参数不是NULL,那么该cvConnectedComp结构将被设置为填充区域的统计属性
maskarr掩码,即代表函数的输入值,也代表输出值。如果maskarr非空,那么他一定要是一个单通道,8位,宽度和高度均比源图像大2个像素的图像。mask图像的(x+1, y+1)和原图像的(x,y)对应。cvFoodFill 不会覆盖mask的非0的点
flags

低8位:4/8,填充算法考虑四邻域或者8邻域

高8位:CV_FLOODFILL_FIXED_RANGE - 目的像素和种子像素点比较。CV_FLOODFILL_MASK_ONLY - 函数不填充源图像,只填充mask图像。

中间8位:填充掩码图像的值,如果中间是0,则掩码图像用1填充。

eg:

flags = 8

        | CV_FLOODFILL_MASK_ONLY

        | CV_FLOODFILL_FIXED_RANGE

        | (47 << 8)

 

4. 图像的尺寸调整

我们使用函数 cvResize 来对图像进行方法或者缩小:

void cvResize( const CvArr* srcarr, CvArr* dstarr, int method )

如果源图像中设置了ROI,那么函数将会对源图像的ROI进行尺寸调整。同样,如果目的图像设置了ROI,那么将源图像调整之后,填充到目的图像的ROI中。

当图像被缩小时,目标像素的图像会被映射到源图像中的多个像素,这个时候需要进行插值。当放大图像时,目标图像上的像素可能无法在源图像中找到精确的对应像素,这个时候也需要进行插值。cvResize函数的method参数提供了选择插值方式的入口:

插值方式含义说明
CV_INTER_NN最近邻插值将图像各点的像素值设为源图形中与其距离最近的像素点。
CV_INTER_LINER线性插值将根据源图像附近的2*2范围的四个点的像素的线性加权得出。权重由这四个点到目的点的距离决定。
CV_INTER_AREA区域插值用新的像素点映射到源图像的像素点,然后取覆盖区域的平均值。
CV_INTER_CUBIC三次样条插值对源图像附近的4*4个临近像素进行三次样条拟合,然后将目标像素对应的三次样条值作为目标图像对应像素值的点。

 

5. 图像金字塔

图像金子塔是一个图像的集合,集合中所有的图像都源于同一个图像,而且是通过对源图像进行连续的降采样得到的。

有两种金子塔经常用到:高斯金子塔和拉普拉斯金字塔。高斯金子塔用来向下采样,而拉普拉斯金子塔用来从金子塔的底层向上重建一个图像。要想用金子塔的第i层获得第i+1层,我们要用高斯核对其进行卷积,然后删除偶数行和偶数列。

void cvPyrDown( const void* srcarr, void* dstarr, int _filter )

目前_filter只支持 CV_GAUSSIAN_5x5。

我们也可以使用下面相似的函数,将图像在每个维度上都放大两倍:

void cvPyrUp( const void* srcarr, void* dstarr, int _filter )

这个函数将元图下个的每个维度都扩大为原来的两倍,新增的偶数行以0填充,然后使用给定的滤波器进行卷积(实际上是一个在每一个维度上都扩大为两倍的过滤器)来估计丢失像素的近似值。

很容易开出up操作并不是down操作的逆操作。为了恢复原来的图像,我们需要获得又降采样操作丢失的信息,这些数据形成了拉普拉斯金子塔。

Li = Gi - PyrUp(Gi+1)

我们可以利用图像金字塔实现图像的分割,在图像金字塔的基础上,快速分割可以在低分辨率的图像上完成,然后逐层对分割图图像进行优化。

 

6. 图像的阈值化

图像的阈值化就是给定一个阈值,并对像素上的点是高于或者低于该阈值进行一定的操作:

double cvThreshold( const void* srcarr, void* dstarr, double thresh, double maxval, int type )

type可以取值如下:

CV_THRESH_BINARY

大于阈值:maxval

小于阈值:0

CV_THRESH_BINARY_INV大于阈值:0
小于阈值:maxval
CV_THRESH_TRUNC

大于阈值:maxval

小于阈值:值不变

CV_THRESH_TOZERO_INV大于阈值:0
小于阈值:值不变
CV_THRESH_TOZERO

大于阈值:值不边

小于阈值:0

通常情况下,阈值并不是很好确定,或者如果图像本身光照不均匀的前提下,阈值需要针对不同的部分不同处理。在OpenCV中,提供了自适应阈值化函数:

void
cvAdaptiveThreshold( const void *srcIm, void *dstIm, double maxValue,
                     int method, int type, int blockSize, double delta )

当前有两种类型的自适应:

CV_ADAPTIVE_THRESH_MEAN_C:对于blockSize*blockSize区域内的像素点平均加权 - delta,来作为阈值。

CV_ADAPTIVE_THRESH_GAUSSIAN_C: 对blockSize*blockSize区域的所有像素按照高斯函数按照他们的中心距离进行加权计算。

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值