一、概述
将图像与内核卷积。该函数将任意线性滤波器应用于图像。当内核部分位于图像之外时,该函数会根据指定的边框模式对异常像素值进行插值。
该函数确实计算相关性,而不是卷积:
也就是说,内核不是围绕锚点镜像的。如果您需要真正的卷积,请使用翻转内核并将新锚设置为 (kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1)。
该函数在内核较大(11 x 11 或更大)的情况下使用基于 DFT 的算法,而对于小内核则使用直接算法。
二、filter2D函数
1、函数原型
cv::filter2D (InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1,-1), double delta=0, int borderType=BORDER_DEFAULT)
2、参数详解
src | 输入图像。 |
dst | 输出与 src 大小和通道数相同的图像。 |
ddepth | 目标图像的所需深度,请参阅组合 |
kernel | 卷积核(或者更确切地说是相关核),单通道浮点矩阵; 如果要将不同的内核应用于不同的通道,请使用 split 将图像拆分为单独的颜色平面并单独处理它们。 |
anchor | 内核的锚点,指示内核中过滤点的相对位置; 锚点应位于内核中; 默认值 (-1,-1) 表示锚点位于内核中心。 |
delta | 在将过滤像素存储到 dst 之前添加到过滤像素的可选值。 |
borderType | 像素外推法,请参阅 BorderTypes。 不支持 BORDER_WRAP。 |
三、OpenCV源码
1、源码路径
opencv\modules\imgproc\src\filter.dispatch.cpp
2、源码代码
void filter2D(InputArray _src, OutputArray _dst, int ddepth,
InputArray _kernel, Point anchor0,
double delta, int borderType)
{
CV_INSTRUMENT_REGION();
CV_Assert(!_src.empty());
CV_Assert(!_kernel.empty());
CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2,
ocl_filter2D(_src, _dst, ddepth, _kernel, anchor0, delta, borderType))
Mat src = _src.getMat(), kernel = _kernel.getMat();
if( ddepth < 0 )
ddepth = src.depth();
_dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) );
Mat dst = _dst.getMat();
Point anchor = normalizeAnchor(anchor0, kernel.size());
Point ofs;
Size wsz(src.cols, src.rows);
if( (borderType & BORDER_ISOLATED) == 0 )
src.locateROI( wsz, ofs );
hal::filter2D(src.type(), dst.type(), kernel.type(),
src.data, src.step, dst.data, dst.step,
dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y,
kernel.data, kernel.step, kernel.cols, kernel.rows,
anchor.x, anchor.y,
delta, borderType, src.isSubmatrix());
}
void filter2D(int stype, int dtype, int kernel_type,
uchar * src_data, size_t src_step,
uchar * dst_data, size_t dst_step,
int width, int height,
int full_width, int full_height,
int offset_x, int offset_y,
uchar * kernel_data, size_t kernel_step,
int kernel_width, int kernel_height,
int anchor_x, int anchor_y,
double delta, int borderType,
bool isSubmatrix)
{
bool res;
res = replacementFilter2D(stype, dtype, kernel_type,
src_data, src_step,
dst_data, dst_step,
width, height,
full_width, full_height,
offset_x, offset_y,
kernel_data, kernel_step,
kernel_width, kernel_height,
anchor_x, anchor_y,
delta, borderType, isSubmatrix);
if (res)
return;
/*CV_IPP_RUN_FAST(ippFilter2D(stype, dtype, kernel_type,
src_data, src_step,
dst_data, dst_step,
width, height,
full_width, full_height,
offset_x, offset_y,
kernel_data, kernel_step,
kernel_width, kernel_height,
anchor_x, anchor_y,
delta, borderType, isSubmatrix))*/
res = dftFilter2D(stype, dtype, kernel_type,
src_data, src_step,
dst_data, dst_step,
width, height,
full_width, full_height,
offset_x, offset_y,
kernel_data, kernel_step,
kernel_width, kernel_height,
anchor_x, anchor_y,
delta, borderType);
if (res)
return;
ocvFilter2D(stype, dtype, kernel_type,
src_data, src_step,
dst_data, dst_step,
width, height,
full_width, full_height,
offset_x, offset_y,
kernel_data, kernel_step,
kernel_width, kernel_height,
anchor_x, anchor_y,
delta, borderType);
}
四、效果图像示例

