知识储备
在学习自定义线性滤波前,需要了解卷积的相关概念
图像中的卷积
常见算子(卷积核)
Robert算子
最常见的算子
Sobel算子
在边缘检测中经常用到,是canny边缘检测中重要的一步,通过Sobel算子得到梯度
Laplance算子
锐化的掩膜中间是5,拉普拉斯算子中间是4
拉普拉斯算子和Sobel算子被用来寻找梯度、寻找图像的边缘
自定义线性滤波
和掩膜其实是一样的,只是用的核不一样
API
void filter2D(
InputArray src,
OutputArray dst,
int ddepth,
InputArray kernel,
Point anchor = Point(-1,-1),
double delta = 0,
int borderType = BORDER_DEFAULT
);
(1)InputArray类型的src ,输入图像。
(2)OutputArray类型的dst ,输出图像,图像的大小、通道数和输入图像相同。
(3)int类型的ddepth,目标图像的所需深度。
(4)InputArray类型的kernel,卷积核(或者更确切地说是相关核)是一种单通道浮点矩阵;如果要将不同的核应用于不同的通道,请使用split将图像分割成不同的颜色平面,并分别对其进行处理。。
(5)Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。。
(6)double类型的delta,在将筛选的像素存储到dst中之前添加到这些像素的可选值。说的有点专业了其实就是给所选的像素值添加一个值delta。
(7)int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT。
一般来说,第三个参数使用-1
第五个参数使用Point(-1,-1)来默认锚点为中心
第六个0
第七个不写,使用默认
代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src, dstx, dsty;
src = imread("C:/Users/86176/Pictures/pics/camera.tiff");
if (!src.data)
{
cout << "could not load image..." << endl;
return -1;
}
imshow("show image", src);
namedWindow("x img", CV_WINDOW_AUTOSIZE);
namedWindow("y img", CV_WINDOW_AUTOSIZE);
//卷积核可自己定义,这里定义的是Robert算子
Mat kernel_x = (Mat_<int>(2, 2) << 1, 0, 0,-1);
Mat kernel_y = (Mat_<int>(2, 2) << -1, 0, 0, 1);
filter2D(src, dstx, -1, kernel_x, Point(-1,-1), 0.0);
imshow("x img", dstx);
filter2D(src, dsty, -1, kernel_y, Point(-1, -1), 0.0);
imshow("y img", dsty);
waitKey(0);
return 0;
}
效果
x,y方向分别更注重他们本方向上的差异