之前的学习中接触了很多常用的滤波,不过,如果我们想用自己定义的滤波该怎么办呢?其实也是没问题的。首先回顾一下滤波的工作流程,首先确定滤波的范围,然后确定范围中每个点的权重,然后算出区域的像素加权和,最后替换掉目标点的像素值。我们可以利用filter2D函数来实现。
(1)在使用filter2D之前,我们需要定义一个小Mat对象,相当于滤波范围,这个小Mat对象的内容就是每个点的权重。
Mat kernel = Mat_<数据类型>(小范围的高,小范围的宽) << (按行按列顺序写入数据)
(2)filter2D(源Mat对象,目标Mat对象,输出Mat对象的深度,kernel)//输出Mat的深度通常输入-1,即与输入图像相同
说到滤波就顺带说一下边缘处理,在滤波过程中有个问题,就是区域边缘位置没法滤波,所以在使用时我们应该先把边缘往外延伸,延伸方法有好多种:BORDER_DEFAULT、BORDER_CONSTANT、BORDER_REPLICATE、BORDER_WRAP,默认采用BORDER_DEFAULT。
(3)copyMakeBorder(源Mat对象,目标Mat对象,上边的延伸宽度,下边的延伸宽度,左边的延伸宽度,右边的延伸宽度,延伸方法,边缘颜色Scalar对象)//边缘颜色对象只有在BORDER_CONSTANT方法下才有用。
演示代码:
#include<opencv2\opencv.hpp>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
using namespace std;
using namespace cv;
Mat src, dst;
int main()
{
src = imread("1.jpg", 1);
if (src.empty())
{
printf("cannot load!!\n");
system("pause");
return -1;
}
//自定义滤波
Mat kernel = (Mat_<float>(3, 3) << 1, 1, 1, 1, 1, 1, 1, 1, 1);
kernel /= 9.0;
filter2D(src, dst, -1, kernel);
namedWindow("自定义滤波");
imshow("自定义滤波", dst);
//边缘处理
int width = src.rows / 100;
copyMakeBorder(src, dst, width, width, width, width, BORDER_CONSTANT, Scalar(0, 0, 255));
namedWindow("边缘处理");
imshow("边缘处理", dst);
waitKey(0);
return 0;
}
演示效果: