空间域图像增强:OpenCV中的自定义滤波器
0.综述
通过图像的卷积操作可以对图像进行模糊、锐化等处理,以及提取例如边缘等图像梯度特征。除了前面几篇文章里介绍的滤波算子,OpenCV
中还可以通过相应的API
来自定义卷积操作,也就是设定自定义的卷积算子。
下面三个自定义的卷积核就分别可以实现均值模糊、图像锐化和图像梯度的功能:
[
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)
\left[ \begin{matrix} 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 \end{matrix} \right] \tag{1}
⎣⎢⎢⎢⎢⎡1111111111111111111111111⎦⎥⎥⎥⎥⎤(1)
[
0
−
1
0
−
1
5
−
1
0
−
1
0
]
(2)
\left[ \begin{matrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1& 0 \end{matrix} \right] \tag{2}
⎣⎡0−10−15−10−10⎦⎤(2)
[
1
0
0
−
1
]
(3)
\left[ \begin{matrix} 1 & 0 \\ 0 & -1 \end{matrix} \right] \tag{3}
[100−1](3)
1.相应API介绍
C++
函数原型:
void filter2D( InputArray src,
OutputArray dst,
int ddepth,
InputArray kernel,
Point anchor = Point(-1,-1),
double delta = 0,
int borderType = BORDER_DEFAULT );
其中ddepth
就是输出图像的图像深度,kernel
就是卷积核的大小,anchor
是卷积锚点(所谓卷积锚,就是卷积输出哪一个位置的像素值,例如对于一个3x3的卷积核,[-1,-1]就是输出到其中心点的位置)。
这里要注意ddepth
,它默认为-1,此时表示输入与输出图像类型一致。当涉及到浮点数计算或者计算会产生负值的时候,需要将ddepth
设为CV_32F
类型,在滤波完成之后在使用下面的convertScaleAbs
函数将图像从浮点型转为字节类型。
void convertScaleAbs(InputArray src,
OutputArray dst,
double alpha = 1,
double beta = 0);
2.代码实践自定义滤波器
首先定义出上面的三个卷积核,其中kernel1
后面除以25时进行归一化处理,而后面的两个kernel
定义则使用了重载:
Mat conv_kernel1 = Mat::ones(5, 5, CV_32F) / (float)(25);
Mat conv_kernel2 = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
Mat conv_kernel3 = (Mat_<int>(2, 2) << 1, 0, 0, -1);
然后使用filter2D()
函数对图像进行卷积计算:
filter2D(input,Blur_output1,-1,conv_kernel1);
filter2D(input, Blur_output2, -1, conv_kernel2);
filter2D(input, Blur_output3, CV_32F, conv_kernel3);
convertScaleAbs(Blur_output3, Blur_output3);
imshow("1", Blur_output1);
imshow("2", Blur_output2);
imshow("3", Blur_output3);
运行结果如下: