通过图像的卷积操作,我们可以对图像进行模糊、锐化等处理,以及提取例如边缘等图像梯度特征。除了前面几篇文章里介绍的滤波算子,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)
(2) [ 0 − 1 0 − 1 5 − 1 0 − 1 0 ] \left[ \begin{matrix} 0 & -1 & 0 \\ -1 & 5 & -1 \\ 0 & -1& 0 \end{matrix} \right] \tag{2} ⎣⎡0−10−15−10−10⎦⎤(2)
(3) [ 1 0 0 − 1 ] \left[ \begin{matrix} 1 & 0 \\ 0 & -1 \end{matrix} \right] \tag{3} [100−1](3)
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);
首先定义出上面的三个卷积核(其中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);