转自:OpenCV 教程
另附:计算机视觉:算法与应用(2012),Learning OpenCV(2009)
平滑图像:滤波器
平滑 也称 模糊, 是一项简单且使用频率很高的图像处理方法。平滑处理的用途有很多, 但是在本教程中我们仅仅关注它减少噪声的功用 (其他用途在以后的教程中会接触到)。平滑处理时需要用到一个 滤波器 。最常用的滤波器是 线性 滤波器。不妨把 滤波器 想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口滑过图像。
归一化滤波器 (Normalized Box Filter)
最简单的滤波器,输出像素值是核窗口内像素值的 均值 ( 所有像素加权系数相等)。
blur( src, dst, Size( i, i ), Point(-1,-1) );
- src: 输入图像
- dst: 输出图像
- Size( w,h ): 定义内核大小( w 像素宽度, h 像素高度)
- Point(-1, -1): 指定锚点位置(被平滑点), 如果是负值,取核的中心为锚点。
高斯滤波器 (Gaussian Filter)
最有用的滤波器 (尽管不是最快的)。 高斯滤波是将输入数组的每一个像素点与 高斯内核 卷积将卷积和当作输出像素值。
GaussianBlur( src, dst, Size( i, i ), 0, 0 );
- src: 输入图像
- dst: 输出图像
- Size(w, h): 定义内核的大小(需要考虑的邻域范围)。 和 必须是正奇数,否则将使用 和 参数来计算内核大小。
- : x 方向标准方差, 如果是 则 使用内核大小计算得到。
- : y 方向标准方差, 如果是 则 使用内核大小计算得到。.
中值滤波器 (Median Filter)
中值滤波将图像的每个像素用邻域 (以当前像素为中心的正方形区域)像素的 中值 代替 。
medianBlur ( src, dst, i );
- src: 输入图像
- dst: 输出图像, 必须与 src 相同类型
- i: 内核大小 (只需一个值,因为我们使用正方形窗口),必须为奇数。
双边滤波 (Bilateral Filter)
目前我们了解的滤波器都是为了 平滑 图像, 问题是有些时候这些滤波器不仅仅削弱了噪声, 连带着把边缘也给磨掉了。为避免这样的情形 (至少在一定程度上 ), 我们可以使用双边滤波。类似于高斯滤波器,双边滤波器也给每一个邻域像素分配一个加权系数。 这些加权系数包含两个部分, 第一部分加权方式与高斯滤波一样,第二部分的权重则取决于该邻域像素与当前像素的灰度差值。
详细的解释可以查看 链接。
bilateralFilter ( src, dst, i, i*2, i/2 );
- src: 输入图像
- dst: 输出图像
- d: 像素的邻域直径
- : 颜色空间的标准方差
- : 坐标空间的标准方差(像素单位)
利用掩码(kernel mask)简单滤波:filter2D
矩阵的掩码操作很简单。其思想是:根据掩码矩阵(也称作核)重新计算图像中每个像素的值。掩码矩阵中的值表示近邻像素值(包括该像素自身的值)对新像素值有多大影响。从数学观点看,我们用自己设置的权值,对像素邻域内的值做了个加权平均。
以下是利用filter2D函数实现Laplace filter来加强图像对比度的实例(samples\cpp\tutorial_code\core\mat_mask_operations):
Mat kern = (Mat_<char>(3,3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
filter2D(I, K, I.depth(), kern );
filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
- src: 源图像
- dst: 目标图像
- ddepth: dst 的深度。若为负值(如 -1),则表示其深度与源图像相等。
- kernel: 用来遍历图像的核
- anchor: 核的锚点的相对位置,其中心点默认为 (-1, -1) 。
- delta: 在卷积过程中,该值会加到每个像素上。默认情况下,这个值为 。
- BORDER_DEFAULT: 这里我们保持其默认值,更多细节将在其他教程中详解
形态学操作之:腐蚀与膨胀(Eroding and Dilating)
形态学操作就是基于形状的一系列图像处理操作。通过将 结构元素 作用于输入图像来产生输出图像。最基本的形态学操作有二:腐蚀与膨胀(Erosion 与 Dilation)。 他们的运用有:
- 消除噪声
- 分割(isolate)独立的图像元素,以及连接(join)相邻的元素。
- 寻找图像中的明显的极大值区域或极小值区域。
膨胀dilate
将图像 与任意形状的内核 (),通常为正方形或圆形,进行卷积。内核 有一个可定义的 锚点, 通常定义为内核中心点。将内核 划过图像,将内核 覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展” (因此有了术语膨胀 dilation )。
腐蚀erode
将内核 划过图像,将内核 覆盖区域的最小相素值提取,并代替锚点位置的相素。相应地,暗区会开始“腐蚀”。
Mat element = getStructuringElement( dilation_type,
Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) ); dilate( src, dilation_dst, element );
erode( src, erosion_dst, element );
dilate和erode参数相同:
- src: 原图像
- erosion_dst: 输出图像
- element: 腐蚀操作的内核。如果不指定,默认为一个简单的 矩阵。否则,我们就要明确指定它的形状,可以使用函数getStructuringElement
- dilation_type = 矩形: MORPH_RECT 或者 交叉形: MORPH_CROSS 或者 椭圆形 MORPH_ELLIPSE
- 内核大小
- 锚点位置(若不指定,则默认为中心位置)
更多形态学变换
更直观的图参见此处。
开运算 (Opening)
通过先对图像腐蚀再膨胀实现的。能够排除小团块物体(假设物体较背景明亮)。
闭运算(Closing)
通过先对图像膨胀再腐蚀实现的。能够排除小型黑洞(黑色区域)。
形态梯度(Morphological Gradient)
膨胀图与腐蚀图之差,能够保留物体的边缘轮廓。
顶帽(Top Hat)与黑帽(Black Hat)
顶帽:原图像与开运算结果图之差
黑帽:闭运算结果图与原图像之差
调用函数:morphologyEx
Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) ); /// 运行指定形态学操作
morphologyEx( src, dst, operation, element );
参数列表:
- src : 原 (输入) 图像
- dst: 输出图像
-
operation: 需要运行的形态学操作。 我们有5个选项(注意:取值范围为2~6):
- Opening: MORPH_OPEN : 2
- Closing: MORPH_CLOSE: 3
- Gradient: MORPH_GRADIENT: 4
- Top Hat: MORPH_TOPHAT: 5
- Black Hat: MORPH_BLACKHAT: 6
- element: 内核,可以使用函数:get_structuring_element:getStructuringElement <> 自定义。