1、图像卷积:
用一个小于图像的矩阵窗口在图像上按照一定的步长移动,在窗口覆盖的图像对应区域内,将对应像素点与窗口权值进行乘法操作,再将所有的乘积相加再除以窗口尺寸,作为该步移动的输出。
这里的窗口一般被称为卷积核(kernal),卷积核中的元素被称为权值。
注意,当输入图像通道数为多个时,对应的卷积核也有同样的通道数量。
更多解释参考:
(25条消息) 深度学习之卷积_冰激凌啊的博客-CSDN博客_卷积 深度学习
API:
这里的blur函数步长始终为1。
代码:
void QuickDemo::blur_demo(Mat& image)
{
Mat dst;
blur(image, dst, Size(3, 3), Point(-1, -1));
imshow("卷积图像", dst);
}
结果:
2、自定义卷积(滤波)
生成自定义的卷积核进行滤波操作,相关API如下:
filter2D(input_img, output_img, ddepth, kernel, anchor, delta, borderType)
input_img——输入图像
output_img——输出图像
ddepth——所需输出图像的深度,参考如下:
kernel——自定义的卷积核(Mat)
anchor——锚点,卷积核对应输出图像上像素点,默认Point(-1,-1)为卷积核中心
delta——在卷积完成后,生成输出图像前,将输出图像所有像素点值均加上的值(亮度调节)
borderType——边界选取方法(具体看官方文档)。
convertScaleAbs(input_img, output_img)
这个API的作用为将图像格式转为CV_8U格式,并将所有像素值置为正。
简单自定义Mat方法:
Mat mat_1 = (Mat_<数据类型>(高,宽) << 高×宽个对应数据类型的像素值)
代码示例(均值滤波核非均值滤波):
void self_conv(Mat& image)
{
//均值滤波
//定义核
int k = 15;//窗口尺寸
Mat selfkernel = Mat::ones(Size(k, k), CV_32F)/(float)(k*k);//后面除(float)(k*k)让所有权值和为1.
//调用API进行滤波
Mat dst;
filter2D(image, dst, -1, selfkernel, Point(-1, -1), 0, BORDER_DEFAULT);
namedWindow("mean filter img", WINDOW_FREERATIO);
imshow("mean filter img", dst);
//非均值滤波
Mat robot = (Mat_<int>(2, 2) << 1, 0, 0, -1);//自定义Mat核
Mat dst2;
filter2D(image, dst2, CV_32F, robot, Point(-1, -1), 0, BORDER_DEFAULT);
convertScaleAbs(dst2, dst2);//该API将图像格式转为CV_8U格式,并将所有像素值置为正。
namedWindow("non_mean filter img", WINDOW_FREERATIO);
imshow("non_mean filter img", dst2);
}
注意:
当均值滤波时,ddepth使用默认值即可,但当采用非均值滤波时,为防止数据溢出,需采用较大的浮点储存空间模式,如上采用了CV_32F。
输出:
将非均质滤波filter2D里的delta值设为127,有: