OpenCV
各模块函数使用实例(4)
F
、主要滤波函数(
Image Filtering
)
此处描述的函数和类是用于在
2D
图像上
(
表示为
Mat
)
执行线性和非线性滤波操作的。意思是,对源图像(正常情况下是矩形)的每一个像素位置
(
x
,
y
)
,其邻域是被关注的焦点并且对该邻域计算其结果。对线性滤波器,它是一个像素值的权重和。对形态操作,它是最小或最大值等。计算结果存储在目标图像的某个位置
(
x
,
y
)
。也就是说,输出图像与输入图像有相同的尺寸。正常情况下,这些函数支持多通道数组,此时每个通道都单独处理。因而,输出图像与输入图像也有相同的通道数。
这里的函数和类的另一个普遍的属性是,与简单的算数函数不同,这些函数需要推断某些不存在像素的值。例如,使用
Gaussian
3
×
3
滤波器平滑一个图像,则在处理每一行的最左像素时,需要其左边的像素,此时,已经超出了图像范围。可以假设这些像素与图像最左像素相同
(”
边框复制
”
推断法
)
,或假设所有不存在像素均为
0(”
常量边框
”
推断法
)
等。
OpenCV
允许操作时指定使用的推断法。详细,参见
BorderTypes
//
各种边框插值法标志
BorderTypes
enum
{
BORDER_REPLICATE
=
IPL_BORDER_REPLICATE
,
BORDER_CONSTANT
=
IPL_BORDER_CONSTANT
,
BORDER_REFLECT
=
IPL_BORDER_REFLECT
,
BORDER_WRAP
=
IPL_BORDER_WRAP
,
BORDER_REFLECT_101
=
IPL_BORDER_REFLECT_101
,
BORDER_REFLECT101
=
BORDER_REFLECT_101
,
BORDER_TRANSPARENT
=
IPL_BORDER_TRANSPARENT
,
BORDER_DEFAULT
=
BORDER_REFLECT_101
,
BORDER_ISOLATED
=16
};
深度组合(图像深度的可用组合,
-1
是通用的)
|
|
|
|
|
|
|
|
|
|
注意
当
ddepth=-1
时,输出图像与输入图像有相同深度。
(1)、
void cv::bilateralFilter
(
InputArray
src,
OutputArray
dst,int d,double sigmaColor,double sigmaSpace,int borderType=
BORDER_DEFAULT
);
对图像进行双边滤波。
该函数对输入图像进行双边滤波,可以很好地减少不必要的噪声,同时保持边缘相对锐利。然而,与大多数过滤器相比,它的速度相当的慢。
西格玛值:为简单起见,调用时可以设置两个西格玛值相同。如果它们很小
(< 10)
,滤波不会有太大的效果,然而如果很大
(> 150)
,它们将有一个非常强的效果,使图像看上去有点“卡通化”。
过滤器尺寸:大过滤器
(d > 5)
非常慢,因此推荐
d=5
用于实时应用,而
d=9
可用于离线应用,在需要强噪声过滤的场合下使用。
这个过滤器不支持源图像直接操作,因为先运行的操作步改变了源图像。
参数
|
源8位或浮点,1通道或3通道图像。 |
|
与源图像同尺寸和类型的目标图像。 |
|
滤波期间使用的像素邻域直径。如果非正值,则从西格玛空间计算。 |
|
滤镜颜色空间的西格玛值。该参数的值越大,意味着像素邻域内更远的颜色(参见sigmaSpace)将混合在一起,从而产生更大的半相等颜色区域。 |
|
滤镜坐标空间的西格玛值。参数值越大,越远的像素将相互影响,只要它们的颜色足够接近(请参阅sigmaColor)。当d>0时,d值指定邻域大小,而不考虑sigmspace参数。否则,d与sigmaSpace成比例。 |
|
用于推断图像外边框像素所使用的模式标志,参见 |
⑵、
void cv::blur
(
InputArray
src,
OutputArray
dst,
Size
ksize,
Point
anchor=
Point
(-1,-1),int borderType=
BORDER_DEFAULT
);
使用标准的方箱滤镜模糊图像。
这个函数使用下面的核对图像进行平滑处理:
调用
blur(src, dst, ksize, anchor, borderType)
等价于
boxFilter(src, dst, src.type(), anchor, true, borderType)
.
参数
|
输入图像;可以由任意数目的通道,通道都单独处理,但是深度应该是CV_8U,CV_16U,CV_16S,CV_32F 或CV_64F。 |
|
与源同尺寸和类型的输出图像。 |
|
模糊化核的大小。 |
|
锚点;默认值是Point(-1,-1),意指锚点在核的中心。 |
|
边框模式,用于外推图像以外的像素,参见 |
参见
boxFilter
,
bilateralFilter
,
GaussianBlur
,
medianBlur
⑶
、
void
cv::boxFilter
(
InputArray
src,
OutputArray
dst,int ddepth,
Size
ksize,
Point
anchor=
Point
(-1,-1),bool
normalize
=true,int borderType=
BORDER_DEFAULT
);
使用方箱滤镜模糊图像。
这个函数使用下面的核平滑图像:
其中:
非标准化方箱滤镜用于计算每一个像素邻域的整体特征,如派生图像的协方差矩阵
(
用于稠密光流算法,等
)
。如果需要在变尺寸窗口上计算像素的和,需使用
integral
函数。
Parameters
|
输入图像 |
|
输出图像,与源图同尺寸和类型 |
|
输出图像的深度(-1则用 |
|
模糊核大小 |
|
锚点;默认值Point(-1,-1) 表示锚点在核的中心 |
|
标志,指定核是否为归一化的核 |
|
边框模式,用于外推图像外的边框像素,参见 |
参见
blur
,
bilateralFilter
,
GaussianBlur
,
medianBlur
,
integral
⑷、
void
cv::GaussianBlur
(
InputArray
src,
OutputArray
dst,
Size
ksize,double sigmaX,double sigmaY=0,int borderType=
BORDER_DEFAULT
);
使用高斯滤镜模糊图像。
这个函数使用特定的高斯核对图像进行卷积操作。支持源图像直接滤波操作。
参数
|
输入图像;图像可以有任何数目的通道,每个通道单独处理,但深度应该是CV_8U,CV_16U,CV_16S,CV_32F 或CV_64F。 |
|
输出图像,与原图同尺寸和类型。 |
|
高斯核尺寸,ksize.width 和ksize.height 可以不同但必须是正的奇数值。或,可以是0,此时由sigma参数计算。 |
|
高斯核X方向的标准差。 |
|
高斯核Y方向的标准差;如果sigmaY 为0,设置其等于sigmaX,如果两个sigmas均为0,则分别从ksize.width和ksize.height中计算,(参见 |
|
像素外推方法,见 |
参见
sepFilter2D
,
filter2D
,
blur
,
boxFilter
,
bilateralFilter
,
medianBlur
⑸、
void
cv::medianBlur
(
InputArray
src,
OutputArray
dst,int ksize);
使用中值滤镜模糊图像。
这个函数使用孔径为
ksize
×
ksize
的中值滤镜平滑图像。对于多通道图像的每一个通道都单独处理。支持源图像直接操作。
注意
中值滤波内部使用
BORDER_REPLICATE
拷贝边框像素,见
BorderTypes
参数
|
输入的1-, 3-, 或 4-通道图像;当ksize 为 3 或 5时,图像深度应该为CV_8U,CV_16U,或CV_32F,对于较大孔径尺寸,仅可以是CV_8U类型图像。 |
|
目标图像,与原图像同尺寸和类型。 |
|
孔径线性尺寸;必须是奇数且大于1,例如:3,5,7 …。 |
参见
bilateralFilter
,
blur
,
boxFilter
,
GaussianBlur
(6)、
void
cv::filter2D
(
InputArray
src,
OutputArray
dst,int ddepth,
InputArray
kernel,
Point
anchor=
Point
(-1,-1),double delta=0,int borderType=
BORDER_DEFAULT
);
使用指定的核对图像做卷积操作。
这个函数将任意线性滤波器作用于图像。支持源图像直接操作。当孔径的一部分超出图像范围时,函数依据特定的边框模式插值计算超出的像素值。
这个函数实际上计算的是相关性,而不是卷积:
即,核不环绕锚点镜像。如果需要卷积,使用
flip
函数翻转核,并且设置新锚点到
(kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1)
。
这个函数对于充分大的核
(~
11 x 11
或更大
)
使用基于
DFT
的算法,而较小的核使用直接算法。
参数
|
输入图像 |
|
输出图像,与原图像有相同的尺寸和相同数量的通道。 |
|
目标图像期望的深度,见 |
|
卷积核(或核),一种单通道浮点矩阵;如果希望对不同的通道使用不同的核,分离图像为不同的彩色平面,并分别进行处理。 |
|
核的锚点,表示滤波点在核内的相对位置;这个锚点应该落在核内;默认值为(-1,-1) 意指锚点在核的中心。 |
|
在存储滤波像素到dst之前,选择的附加值(平移参数)。 |
|
像素外推方法,见 |
参见
sepFilter2D
,
dft
,
matchTemplate
(7)、
void
cv::sepFilter2D
(
InputArray
src,
OutputArray
dst,Int ddepth,
InputArray
kernelX,
InputArray
kernelY,
Point
anchor=
Point
(-1,-1),double delta=0,int borderType=
BORDER_DEFAULT
);
使用可分线性滤波器作用于图像。
这个函数使用可分线性滤波器作用于图像。即,首先,对原图像的每一行使用
1D
核
kernelX
进行滤波,然后对结果的每一列使用
1D
核
kernelY
进行滤波,最后结果由
delta
进行位移(变换)并存储到
dst
。
参数
|
源图像 |
|
目标图像,与原图像有相同的尺寸和通道数 |
|
目标图像深度,见 |
|
每一行的滤波系数(核) |
|
每一列的滤波系数(核) |
|
核内的锚点位置。默认为(−1,−1) 意指锚点在核的中心 |
|
附加到滤波结果的值(平移值) |
|
像素外推法,见 |
参见
filter2D
,
Sobel
,
GaussianBlur
,
boxFilter
,
blur
(8)、
void
cv::erode
(
InputArray
src,
OutputArray
dst,
InputArray
kernel,
Point
anchor=
Point
(-1,-1),int iterations=1,int borderType=
BORDER_CONSTANT
,const
Scalar
&borderValue=
morphologyDefaultBorderValue
());
使用特定的构件元素来腐蚀图像。
这个函数使用特定的结构元素来腐蚀源图像,它决定了取最小值的像素邻域形状:
这个函数支持源图像直接模式。腐蚀可以作用多次(迭代)。对于多通道图像,每个通道都单独处理。
参数
|
输入图像;可以有任意通道,但深度必须是CV_8U,CV_16U,CV_16S,CV_32F 或 CV_64F类型之一。 |
|
输出图像,与原图同尺寸和类型。 |
|
用于腐蚀的结构元素;如果使用 |
|
结构元素内的锚点位置;默认为(-1, -1) 意指锚点在元素中心。 |
|
腐蚀作用的次数。 |
|
像素的外推法,见 |
|
常量边框时边框像素的取值。 |
参见
dilate
,
morphologyEx
,
getStructuringElement
(9)、
void
cv::dilate
(
InputArray
src,
OutputArray
dst,
InputArray
kernel,
Point
anchor=
Point
(-1,-1),int iterations=1,int borderType=
BORDER_CONSTANT
,const
Scalar
&borderValue=
morphologyDefaultBorderValue
());
用特定的构件元素膨胀(扩张)图像。
这个函数使用特定的结构元素来膨胀源图像,它取决于取最大值的像素邻域形状:
这个函数支持源图像直接模式。膨胀可以作用多次(迭代)。对于多通道图像,每个通道都单独处理。
参数
|
输入图像;可以有任意数目的通道,但深度必须是CV_8U,CV_16U,CV_16S,CV_32F 或CV_64F类型之一 |
|
输出图像,与原图像同尺寸和类型。 |
|
用于膨胀的结构元素;如果使用Mat(),3 x 3矩形结构元素,Kernel可以用 |
|
结构元素内的锚点位置;默认为(-1, -1) 意指锚点在元素中心。 |
|
膨胀作用的次数。 |
|
元素外推法,见 |
|
常量边框时边框像素的取值。 |
参见
erode
,
morphologyEx
,
getStructuringElement
(10)、
void
cv::Laplacian
(
InputArray
src,
OutputArray
dst,int ddepth,int ksize=1,double scale=1,double delta=0,int borderType=
BORDER_DEFAULT
);
计算图像的拉普拉斯变换。
该函数通过使用
Sobel
算子计算的
x
和
y
二阶导数相加来计算源图像的拉普拉斯变换:
这是
ksize > 1
时的情况,当
ksize == 1
时,这个
Laplacian
变换使用下面的
3
×
3
滤镜滤波图像:
参数
|
源图像。 |
|
目标图像,与原图像同尺寸和通道数。 |
|
目标图像期望的深度。 |
|
滤镜尺寸,用于计算二阶导数滤波器,详细见 |
|
可选比例因子,计算Laplacian值。默认,没有放大操作,详细见 |
|
可选delta值,存储之前附加到结果dst上的偏移值。 |
|
像素外推法,见 |
参见
Sobel
,
Scharr
(11)、
void
cv::Sobel
(
InputArray
src,
OutputArray
dst,int ddepth,int dx,int dy,int ksize=3,double scale=1,double delta=0,int borderType=
BORDER_DEFAULT
)
使用扩展的
Sobel
算子计算图像的一阶、二阶、三阶或混合导数。
在除了一阶的所有情况下,使用
ksize
×
ksize
可分离核计算导数。在
ksize = 1
时,使用
3
×
1
或
1
×
3
核
(
即,做非高斯平滑
)
。
ksize = 1
仅可用于一阶或二阶
x-
或
y-
方向导数。
有一个特殊的
ksize =
FILTER_SCHARR
(-1)
值,对应于
3
×
3
Scharr
滤波,可以给出比
3
×
3
Sobel
更精确的结果。这个
Scharr
核为:
是
x-
方向的导数,其转置为
y-
方向的导数。
这个函数通过使用适当的核卷积图像计算图像的导数:
Sobel
算子组合了高斯平滑和差分,因此其结果或多或少地抑制了图像的噪声。通常,这个函数使用
(xorder = 1, yorder = 0, ksize = 3)
或
( xorder = 0, yorder = 1, ksize = 3)
参数来计算图像一阶的
x-
或
y-
方向导数。头一种情况对应的核是:
第二种情况对应的核是:
参数
|
输入图像 |
|
输出图像,与原图像同尺寸和通道数 |
|
输出图像深度,见 |
|
x方向导数的阶 |
|
y方向导数的阶 |
|
扩展Sobel核的尺寸;必须是1,3,5或7 |
|
可选的导数计算值的比例因子;默认,不计算(详见 |
|
可选的delta值,存储之前加到结果dst上的偏移值 |
|
像素外推法,见 |
参见
Scharr
,
Laplacian
,
sepFilter2D
,
filter2D
,
GaussianBlur
,
cartToPolar
(12)、
void
cv::Scharr
(
InputArray
src,
OutputArray
dst,int ddepth,int dx,int dy,double scale=1,double delta=0,int borderType=
BORDER_DEFAULT
)
使用
Scharr
算子计算图像的一阶
x-
或
y-
方向的导数。
这个函数使用
Scharr
算子计算图像的一阶
x-
或
y-
导数。下面调用
Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType)
等价于
Sobel(src, dst, ddepth, dx, dy, FILTER_SCHARR, scale, delta, borderType)
参数
|
输入图像 |
|
输出图像,与源图像同尺寸和通道数 |
|
输出图像深度,见 |
|
x方向的导数阶数 |
|
y方向的导数阶数 |
|
可选的计算导数值的比例因子;默认,无比例因子(详见 |
|
可选的delta值,附加到dst的偏移值 |
|
像素外推法,见 |
参见
cartToPolar
(13)、
void
cv::spatialGradient
(
InputArray
src,
OutputArray
dx,
OutputArray
dy,int ksize=3,int borderType=
BORDER_DEFAULT
)
使用
Sobel
算子计算图像在
x
和
y
方向上的一阶导数。等价于调用:
Sobel
( src, dx,
CV_16SC1
, 1, 0, 3 );
Sobel
( src, dy,
CV_16SC1
, 0, 1, 3 );
参数
|
输入图像 |
|
x方向一阶导数的输出图像 |
|
y方向一阶导数的输出图像 |
|
Sobel核尺寸。必须是3 |
|
像素外推法,见 |
参见
Sobel
(14)、
void
cv::sqrBoxFilter
(
InputArray
src,
OutputArray
dst,int ddepth,
Size
ksize,
Point
anchor=
Point
(-1, -1),bool
normalize
=true,int borderType=
BORDER_DEFAULT
)
计算与正则滤波器重叠像素的平方和。
对源图中的每一个像素
(
x
,
y
)
,这个函数计算那些与滤波器重叠的邻域像素的平方和。
将邻域中的像素值先平方再求和,可以用来计算图片的统计参数。
非正则滤波器也可用于计算局部图像的统计特征,例如围绕一个像素邻域的局部方差和标准差。所谓非正则滤镜实际上就是交叉形或十字形
nxn
矩阵,正则就是方框形的。
参数
|
输入图像 |
|
输出图像,与源图像同尺寸和类型 |
|
输出图像的深度(-1则使用 |
|
核尺寸 |
|
核的锚点。默认为(-1, -1)表示锚点在核的中心 |
|
标志,表示核是否为指定大小的正则核 |
|
边框模式,用于外推图像外边框像素,见 |
参见
boxFilter
(15)、
void
cv::buildPyramid
(
InputArray
src,
OutputArrayOfArrays
dst,int maxlevel,int borderType=
BORDER_DEFAULT
)
构建图像的高斯锥体(图像堆叠)。
这个函数构建一个图像矢量。通过递归使用
pyrDown
函数到前一个建立的图像锥层建立高斯锥图像矢量,从
dst[0]==src
开始。
参数
|
源图像。需要注意pyrDown函数列出的支持类型 |
|
结果图像矢量,maxlevel+1,与原图同类型,dst[0]等于src,dst[1]是椎体下一层,是原图平滑并缩小尺寸的图像,dst[2]…等等。 |
|
基于0的索引,最后一层(最小)锥体层索引。必须非负 |
|
像素外推法,见 |
(16)、
Mat
cv::getGaussianKernel
(int ksize
,
double sigma
,
int ktype=
CV_64F
)
返回高斯滤波器的核系数。
这个函数计算并返回
ksize
×
1
矩阵的高斯滤波器系数:
其中
i
=
0..
ksize
−
1
且
α
是比例因子,满足
∑
i
G
i
=
1
。
有两类这样生成的核可以传递给
sepFilter2D
函数。那些能够自动识别平滑核
(
一种权重和为
1
的对称核
)
并做相应的处理函数可以使用生成的核。生成的核也可用于
GaussianBlur
函数。
参数
|
孔径尺寸。应该为奇数(ksize mod 2 = 1)并且为正值 |
|
高斯标准差。如果非正,则从ksize计算得出,如 |
|
滤波器系数类型。可以是CV_32F 或 CV_64F |
参见
sepFilter2D
,
getDerivKernels
,
getStructuringElement
,
GaussianBlur
(17)、
void
cv::getDerivKernels
(
OutputArray
kx,
OutputArray
ky,int dx,int dy,int ksize,bool
normalize
=false,int ktype=
CV_32F
)
计算并返回图像空间导数的滤波器系数。
这个函数计算并返回图像空间导数的滤波器系数。当
ksize=FILTER_SCHARR
,生成
Scharr
3
×
3
核
(
见
Scharr
)
。否则,生成
Sobel
核
(
见
Sobel
)
。这个滤波器一般传递给
sepFilter2D
。
参数
|
输出行滤波器系数矩阵。具有ktype指定的类型 |
|
输出列滤波器系数矩阵。具有ktype指定的类型 |
|
对应x方向的导数阶 |
|
对应y方向的导数阶 |
|
空净尺寸。可以是FILTER_SCHARR,1,3,5,或7 |
|
正则化标志,表示是否正则化(等比下降)滤波器系数。理论上,这个系数应该有一个分母= |
|
滤波器系数类型。可以是CV_32f 或CV_64F |
(18)、
Mat
cv::getStructuringElement
(int shape,
Size
ksize,
Point
anchor=
Point
(-1,-1))
返回形态学操作上特定尺寸和形状的结构元素。
这个函数创建并返回结构元素,这个元素可以进一步传递给
erode
,
dilate
或
morphologyEx
,当然,也可以创建任意的二值屏蔽元素,并把它当作为结构元素。
参数
|
元素形状,可以是 |
|
构 |
|
元素内的锚点位置。默认值(−1,−1) 表示锚点在中心。注意, 只有十字形状的元素依赖于锚点位置,其他场合锚点只能调节形态操作结果位移了多少。 |
(19)、
void
cv::
morphologyEx
(
InputArray
src
,
OutputArray
dst
,
Int
op
,
InputArray
kernel
,
Point
anchor
=
Point
(-1,-1)
,
int
iterations
=
1
,int
borderType
=
BORDER_CONSTANT
,
const
Scalar
&
borderValue
=
morphologyDefaultBorderValue
()
);
执行高级形态变换。
函数
cv::morphologyEx
使用腐蚀和膨胀基本操作执行高级形态变换。所有操作都可以直接在源图上执行。对于多通道图像每个通道单独处理。
参数
|
源图像,通道数可任意。深度因该是CV_8U,CV_16U,CV_16S,CV_32F或CV_64F之一。 |
|
目标图像,与源图像同尺寸和类型。 |
|
形态操作类型,参见 |
|
结构元素。可以由 |
|
Kernel的锚点位置。负值意指锚点在核的中心。 |
|
执行腐蚀核膨胀操作的次数。 |
|
像素外延法,见 |
|
常量边框时的边框值。其默认值有特殊意义。 |
参见
dilate
,
erode
,
getStructuringElement
注意
迭代次数是腐蚀或膨胀操作的次数。例如开操作
(
MORPH_OPEN
)
有两次迭代等价于:
erode -> erode -> dilate -> dilate(
而不是
erode -> dilate -> erode -> dilate)
。
G
、滤波函数示例
本节对上节中提到的部分函数做程序上的示例说明和图像处理效果分析,以及各个参数的意义说明。
void cv::bilateralFilter()
;
//对图像进行双边滤波
双边滤波器可以有很好的边缘保护,可以在去噪的同时,保护图像的边缘特征。它是一种非线性的滤波方法,是结合图像的
空间邻近度
和
像素值相似度
的一种折衷处理。同时考虑了
空域信息
和
灰度相似性
,达到保边去噪的目的。
参数:Scr 源图像,8位或浮点,1或3通道
Dst
结果图像,与源图像同尺寸和类型
d
像素邻域直径
Sigmacolor
滤镜颜色空间的西格玛值
SigmaSpace 滤镜坐标空间的西格玛值
其中d、
Sigmacolor
和
SigmaSpace是控制参数,d是像素的关联邻域尺寸,一般选择奇数,越大计算的时间越长,图像越模糊:
图中,1为原图,2为d=9,3为d=15,4为d=30。
Sigmacolor
和
SigmaSpace参数则是对边缘和颜色进行操作:
尽管对图像进行了模糊处理(此处设定两个Sigma值相等),1为Sigma=128,基本上等同于原图,2为Sigma=256,3为Sigma=512,4为Sigma=1024。从图的效果可以看到颜色过渡过程和边缘保持过程,模糊过程较好地保持了边缘特征,使颜色过渡更偏于柔和。
空间域的核计算公式:
灰值域的核计算公式:
而
sigmaSpace
值就相当于
,
sigmaColor
就相当于
。当d > 0时,邻域大小由d确定。
详细信息参见
http://www.360doc.com/content/19/0925/15/496343_863149083.shtml
上图是在d=9,sigma=150时处理结果,左边是原图(灰度图),右边是双边滤波后的结果图。
void cv::blur()
;
//使用标准的方箱滤镜模糊图像
使用标准核对图像进行模糊处理:
blur(src, dst, ksize, anchor, borderType)
等价于
boxFilter(src, dst, src.type(), anchor, true, borderType)
左图为原图,右图为ksize = 3时的模糊图像,在图中可以看出黄色的麻面部分模糊的比较明显,blur()函数的作用就是过滤高频噪声。
void cv::boxFilter()
;
//使用方箱滤镜模糊图像
使用核:
平滑图像,其中
α
为:
即,normalize = true时,该滤波函数等价于blur()函数。boxFilter()函数效果如图:
采用ksize = 5的正则滤波,相当于blur的ksize=5。对于非正则滤波,得到的是白图片,因为α= 1。因此boxFilter只能使用正则核,对图像进行模糊操作。
Ksize = 7
void cv::GaussianBlur()
;//使用高斯滤镜模糊图像
这个函数使用特定的高斯核对图像进行卷积操作。
对图像邻域内像素进行平滑时,邻域内不同位置的像素被赋予不同的权值,能够更多的保留图像的总体灰度分布特征。
高斯函数:
在σ=0.8时计算的高斯核:
等比变换为:
取整后得:
前边需要加上一个比率系数1/16。注意,使用其它的标准差σ或可得到其他的核,对于ksize=5,也可以如此计算高斯核:
其中,中心像素点(锚点41)坐标为(0,0)。函数参数有ksize为核尺寸,取3,5,7,…。sigma为核的x,y方向标准差,y方向如果为0,则设置其等于x方向的。如果二者均为0,则通过ksize使用
getGaussianKernel
函数计算标准的高斯核。使用高斯平滑处理图像,如图:
左边是源图,右边是ksize=3,sigmax/y=0.8的滤波图。
左边是ksize=3,sigmax/y=2的滤波图,右边是ksize=3,sigmax/y=10的滤波图。
Sigma参数对图像有作用,但是不明显,一般取值为0.8(高斯函数的标准差)。根据双边滤波的参数规则sigmaspace,可以参考设置sigmax/y,在值>=150后随着ksize增大,平滑效果比较显著。
左图为源图,右图为ksize=3,sigma=150的滤波图。
左图ksize=5,右图ksize=7。
void cv::medianBlur()
;
//使用中值滤镜模糊图像
中值滤波是一种典型的非线性滤波,是基于排序统计理论的一种能够有效抑制噪声的非线性信号处理技术,基本思想是用像素点邻域灰度值的中值来代替该像素点的灰度值,让周围的像素值接近真实的值从而消除孤立的噪声点。该方法在去除脉冲噪声、椒盐噪声的同时能保留图像的边缘细节。这些优良特性是线性滤波所不具备的。
中值滤波首先也得生成一个滤波模板,将该模板内的各像素值进行排序,生成单调上升或单调下降的二维数据序列,二维中值滤波输出为
g(x, y)=medf{f(x-k, y-l),(k, l
∈
w)}
,其中
f(x,y)
和
g(x,y)
分别是原图像和处理后图像
, w
为输入的二维模板,能够在整幅图像上滑动,通常尺寸为
3*3
或
5*5
区域,也可以是不同的形状如线状、圆形、十字形、圆环形等。通过从图像中的二维模板取出奇数个数据进行排序,用排序后的中值取代要处理的数据即可。
中值滤波对消除椒盐噪声非常有效,能够克服线性滤波器带来的图像细节模糊等弊端,能够有效保护图像边缘信息,是非常经典的平滑噪声处理方法。在光学测量条纹图像的相位分析处理方法中有特殊作用,但在条纹中心分析方法中作用不大。
中值滤波相较于线性滤波中的均值滤波优点在前面已经提到,取得良好滤波效果的代价就是耗时的提升,可能达到均值滤波的数倍,而且对于细节较多的图像也不太适用。
使用中值滤波处理图像,如图:
左图为源图,右图为ksize=3的滤波图。
左图为ksize=5的滤波图,右图为ksize=7的滤波图。
void cv::filter2D()
;
//使用核对图像做卷积操作
该函数
利用滤波核实现对图像的卷积运算。该函数可使用任意线性滤波器作用于图像,实质上是计算
kernel
与图像的相关性而不是真正的卷积:
也就是说kernel并不是中心点的镜像,如果需要一个标准的卷积,应该使用函数flip(),并将锚点设置为(kernel.cols – anchor.x – 1, kernel.rows – anchor.y -1)。该函数在大核(11×11或更大)的情况下使用基于DFT的算法,而在小核情况下使用直接算法(createLinearFilter()检索得到)。以下图例使用核(在实际情况中可以自己定义适当的核):
Mat
cnstKnl
[6]= {(
Mat_
<
char
>(3,3) << -1,-1,-1,//3×3,方框
-1, 9,-1,
-1,-1,-1),
(
Mat_
<
char
>(3,3) << 0,-1, 0,//3×3,十字
-1, 5,-1,
0,-1, 0),
(
Mat_
<
char
>(3,3) << -1, 0,-1,//3×3,交叉
0, 5, 0,
-1, 0,-1),
(
Mat_
<
char
>(5,5) << -1,-1,-1,-1,-1,//5×5,方框
-1,-1,-1,-1,-1,
-1,-1,25,-1,-1,
-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1),
(
Mat_
<
char
>(5,5) << 0, 0,-1, 0, 0,//5×5,十字
0, 0,-1, 0, 0,
-1,-1, 9,-1,-1,
0, 0,-1, 0, 0,
0, 0,-1, 0, 0),
(
Mat_
<
char
>(5,5) << -1, 0, 0, 0,-1,//5×5,交叉
0,-1, 0,-1, 0,
0, 0, 9, 0, 0,
0,-1, 0,-1, 0,
-1, 0, 0, 0,-1)};
使用上述核卷积图像,如图:
左边为源图,右边为3×3,方框卷积图。
左边为3×3,十字核卷积图,右边为3×3,交叉核卷积图。
注:此处使用的和为自定义的nxn矩阵,图像处理效果是依据核计算得出的。一般根据不同的处理方式,可以自己定义相关的核,已可以使用openCV提供的函数获得相关的核。
void cv::sepFilter2D()
;
//使用可分线性滤波器作用于图像
分别用一维核对图像做卷积。首先,图像的每一行与一维的核
kernelX
做卷积;然后,运算结果的每一列与一维的核
kernelY
做卷积,生成结果图像,其中
kernelx
和
kernely
为自定义一维向量。本文采用如下核向量:
Mat
cnstKnl
[4]= {(
Mat_
<
char
>(3,1) << 0,1,0),//3×1,向量(正向)
(
Mat_
<
char
>(3,1) << 1,0,1),//3×1,
(
Mat_
<
char
>(5,1) << 0,0,1,0,0),//5×1向量(正向)
(
Mat_
<
char
>(5,5) << 1,1,0,1,1),
卷积图像,如图:
左图,kernelx = (0,1,0),kernely=(1,0,1),右图kernelx=(1,0,1),kernely=(0,1,0),因为kernel为自定义,没有数学意义,结果图像不具有任何可分析性,根据矢量点积原理,使用kernel=(0,1,0)不改变图像属性,使用kernel=(1,0,1)是将邻域直接左右(上下)像素相加作为当前像素值。此处的说明仅作为函数操作图像时的参考。
void cv::erode()
;
//使用特定的构件元素来腐蚀图像
该函数可以对输入图像使用特定的构件元素进行腐蚀操作,该构件元素确定腐蚀操作过程中的邻域的形状,各点像素值将被替换为对应邻域上的最小值。本例使用构件元素(构件元素为邻域屏蔽标志)为:
Mat
cnstErodeKnl
[3]= {(
Mat_
<
char
>(3,3) << 1,1,1,
1,1,1,
1,1,1),
//3×3
(
Mat_
<
char
>(5,5) << 1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1,
1,1,1,1,1),
//5×5
,
(
Mat_
<
char
>(7,7) << 1,1,1,1,1,1,1,
1,1,1,1,1,1,1,
1,1,1,1,1,1,1,
1,1,1,1,1,1,1,
1,1,1,1,1,1,1,
1,1,1,1,1,1,1,
1,1,1,1,1,1,1)
//7×7
};
可以根据实际处理图像的特征选择十字形,米字型或圆形核。
图像处理结果如图:
左图为源图,右图为kernel=3×3的腐蚀后图,边缘被腐蚀。
左图腐蚀核kernel=5×5,右图腐蚀核kernel=7×7。
使用iterations参数,多次迭代后相当于对图像增加马赛克。
void cv::dilate()
;
//用特定的构件元素膨胀图像
该函数与
erode()
相反,使用特定构件元素对图像进行扩张操作,该构件元素确定扩张操作过程中的邻域的形状,各点像素值将被替换为对应邻域上的最大值。本例使用构件元素(构件元素为邻域屏蔽标志)为
Mat
cnstErodeKnl
[3],与腐蚀函数一样。图像处理结果如图:
分别是源图,3×3膨胀(扩张)图,5×5膨胀图,7×7膨胀图。
void cv::Laplacian()
;
//计算图像的拉普拉斯变换
Laplace
算子是一种各向同性的二阶微分算子,在
只关心边缘的位置而不考虑其周围的象素灰度差值时
比较合适。
Laplace
算子对孤立象素的响应要比对边缘或线的响应要更强烈,因此
只适用于无噪声图象
。
存在噪声情况
下,使用
Laplacian
算子检测边缘之前
需要先进行低通滤波
。
图像处理结果如图:
左图为laplacian函数核ksize=1时的图像,右图为filter2D核为3×3十字的滤波图像,可见,在filter2D函数中使用laplacian核也可以得到同样的效果。因此,若使用第二个滤波核,可在filter2D下选择3×3方框即可获得laplacian结果。
在使用laplacian变换前使用blur平滑去除噪声:
背景噪声明显下降,因此一般在做图像处理时,首先要使用blur或
gaussianblur
进行平滑操作。
void cv::Sobel()
;
//使用扩展的Sobel 算子计算图像的一阶、二阶、三阶或混合导数
索贝尔算子(
Sobeloperator
)主要用作是边缘检测,在技术上,它是一种离散性差分算子,用来运算图像的灰度之近似值。在图像的任何一点使用此算子,将会产生对应点的法矢量。
Sobel
算子根据像素点上下、左右邻域点灰度加权差在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息。图像如下:
左图为源图,右图为dx=1,dy=0,ksize=3的sobel滤波图。
左图为dx=0,dy=1,ksize=3的sobel滤波图,右图为dxy=1,ksize=3的sobel滤波图。
void cv::Scharr()
;
//使用Scharr 算子计算图像的一阶x- 或y-方向的导数
scharr
算子是对
sobel
算子的改进,一般
用
3*3
滤波器在实现图像梯度检测时都使用
Scharr
滤波器
。图像如下:
左图为dx=1,右图为dy=1。两图相加可得dx=1,dy=1的scharr滤波图。因为在openCV的scharr()函数中有一个assert(dx>=0 && dy>=0 && dx+dy == 1)的判断,因此不能设置dx=1 && dy=1调用cv.Schar(),只能分别调用,然后手动相加。如图:
左图为scharr算子的dx=1,dy=1,ksize=3滤波图,右图为sobel同参数的滤波图。
左:scharr滤波图,中:经过
Gaussian
平滑的
shcarr
滤波图,右:
sobel
滤波图。
void
cv::spatialGradient
();
//
计算图像x,y方向上的一阶导数
使用
Sobel
算子计算图像在
x
和
y
方向上的一阶导数。这个函数等价于调用:
Sobel
( src, dx,
CV_16SC1
, 1, 0, 3 );
Sobel
( src, dy,
CV_16SC1
, 0, 1, 3 );
void cv::sqrBoxFilter()
;
//
计算与正则方框滤波器重叠的像素的和
对源图中的每一个像素
(
x
,
y
)
,这个函数计算那些与滤波器重叠的邻域像素的平方和。
将邻域中的像素值先平方再求和,可以用来计算图片的统计参数(与计算统计参数的方法类似)。
void cv::buildPyramid()
;
//构建图像的高斯锥体
通过向下采样缩小图像构建高斯锥层的叠层图像,该函数返回图像数组dst[n],其中dst[0]为源图像。函数多次调用
pyrDown()
函数。如图:
Mat cv::getGaussianKernel()
;
//返回高斯滤波器的系数
按照:
计算尺寸为ksize的高斯核,其中ksize、sigma为函数参数,获得的高斯核在ksize=3,sigma = 1时:3行1列的数据 = (0.2741,0.4519,0.2741)。
void cv::getDerivKernels()
;
//计算并返回图像空间导数的滤波器系数
这个函数计算并返回图像空间导数的滤波器系数。当
ksize=FILTER_SCHARR
,生成
Scharr
3
×
3
核
(
见
Scharr
)
。否则,生成
Sobel
核
(
见
Sobel
)
。其中
FILTER_SCHARR = -1
。
Ksize=3
的
sobel
核:
dx=1
,
{-1
,
0,1}
,
dy=1
,
{-1,0,1}
。
Ksize=5
的
sobel
核:
dx=1
,
{-1
,
-2,0,2,1}
,
dy=1
,
{-1
,
-2,0,2,1}
。
Ksize=-1
的
scharr
核:
dx=1
,
{3,10
,
3}
,
dy=1
,
{-1,0,1}
。
Mat cv::getStructuringElement()
;
//返回形态操作上特定尺寸和形状的结构元素
这个函数建立常用的结构元素(核)的形状:矩形(包括线形)、椭圆(包括圆形)及十字形(
MORPH_RECT
,
MORPH_ELLIPSE
,
MORPH_CROSS
)。这种形态学元素(核)作用于
erode
和
dilate
。形态学各种功能实现,归结为腐蚀
erode
与膨胀
dilate
的组合。对于
5×5
矩阵,结构元素如下:
1
,
1
,
1
,
1
,
1 0
,
0
,
1
,
0
,
0 0
,
0
,
1
,
0
,
0
1
,
1
,
1
,
1
,
1 0
,
0
,
1
,
0
,
0 1
,
1
,
1
,
1
,
1
1
,
1
,
1
,
1
,
1 1
,
1
,
1
,
1
,
1 1
,
1
,
1
,
1
,
1
1
,
1
,
1
,
1
,
1 0
,
0
,
1
,
0
,
0 1
,
1
,
1
,
1
,
1
1
,
1
,
1
,
1
,
1 0
,
0
,
1
,
0
,
0 0
,
0
,
1
,
0
,
0
void
cv::
morphologyEx()
;
//
执行高级形态变换。
高级形态学变换:
开运算:先腐蚀,再膨胀,可清除一些小东西(亮的),放大局部低亮度的区域
闭运算:先膨胀,再腐蚀,可清除小黑点
形态学梯度:膨胀图与腐蚀图之差,提取物体边缘
顶帽:原图像-开运算图,突出原图像中比周围亮的区域
黑帽:闭运算图-原图像,突出原图像中比周围暗的区域
左起:源图,开运算图,闭运算图。
左起:MORPH_GRADIENT图,MORPH_TOPHAT图,MORPH_BLACKHAT图。