由于某种原因,我不得不自己编写过滤器函数。下面是我的卷积函数。
void Convolve (cv::Mat& f, cv::Mat& w, cv::Mat& output)
{
output = f.clone();
int height = f.rows;
int width = f.cols;
int a = (w.rows - 1) / 2;
int b = (w.cols- 1) / 2;
cv::Mat f2 = f.clone();
for (int x = a; x < height - a; ++x)
{
for (int y = b; y < width - b; ++y)
{
float sum = 0.0;
for (int s = -a; s <= a; ++s)
{
for (int t = -b; t <= b; ++t)
{
sum += w.at<float>(s+a, t+b) * f2.at<float>(x+s, y+t);
}
}
output.at<float>(x, y) = sum;
}
}
}
然后我比较了使用这个函数和cv::filter2D函数,发现它们在过滤后是不同的。当θ和psi为零时,滤波后的图像几乎相同,但其他图像则不同。
int main()
{
cv::Mat in = cv::imread("something.jpg", 0);
cv::Mat dest, dest1;
cv::Mat src_f;
in.convertTo(src_f, CV_32F);
int kernel_size = 31;
double sig = 1.0, th = 0.2, lm = 1.0, gm = 0.02, ps = 0.0;
cv::Mat kernel = cv::getGaborKernel(cv::Size(kernel_size,kernel_size), sig, th, lm, gm, ps);
cv::filter2D(src_f, dest1, CV_32F, kernel);
Convolve(src_f, kernel, dest);
cv::Mat viz;
dest.convertTo(viz, CV_8U, 1.0/255.0);
cv::Mat viz1;
dest1.convertTo(viz1, CV_8U, 1.0/255.0);
imshow("my dest", viz);
imshow("k dest", viz1);
cv::waitKey();
}
关于自包含卷积有什么建议吗?忽略零填充部分。
您在卷积实现中以浮点矩阵的形式访问内核,但它由doubles组成(根据文档,默认情况下ksize
设置为CV_64F
)。看起来OpenCV足够聪明,可以在矩阵与不同元素类型的卷积过程中检测到它,并自行执行转换/正确的内存访问,这就是它产生正确结果的原因。
为了修复你的代码片段,我添加了一行
kernel.convertTo(kernel, CV_32F);
这将产生视觉上等效的结果(直到填充)。
另一种选择是将ktype
显式地设置为CV_32F
。
此外,当使用大内核(~11x11及更大)时,OpenCV的filter2D
实现使用基于DFT的算法(在频域中)执行卷积,因此您可能会得到略有不同的结果和时序。