您的位置:首页 > 运维架构

(原+转)使用opencv的DFT计算卷积

2016-05-05 17:31 309 查看
转载请注明出处:

http://www.cnblogs.com/darkknightzh/p/5462665.html

参考网址:

http://blog.csdn.net/lichengyu/article/details/18848281

貌似还有其他的,记不清了

convolveDFT函数是从官方文档中抄录并做了修改,因为原来的程序有问题。一是输出Mat C应声明为引用;二是其中的mulSpectrums函数的第四个参数flag值没有指定,应指定为DFT_COMPLEX_OUTPUT或是DFT_REAL_OUTPUT.

main函数中首先按灰度图读入图像,然后创造一个平滑核kernel,将输入图像转换成float类型(注意这步是必须的,因为dft只能处理浮点数),在调用convolveDFT求出卷积结果后,将卷积结果归一化方便显示观看。

(180205:_XieLei 指出valid的时候结果不对,大家辩证的看待代码哈)

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;

enum ConvolutionType                     // 函数 conv2 卷积时参数的类型
{
CONVOLUTION_FULL,                    // 卷积时的参数,和 matlab 的 full 一致
CONVOLUTION_SAME,                    // 卷积时的参数,和 matlab 的 same 一致
CONVOLUTION_VALID                    // 卷积时的参数,和 matlab 的 valid 一致
};
void Conv2DFT(Mat& convRes, const Mat& img, const Mat& kernel, ConvolutionType type, int ddepth)
{
int dft_M = getOptimalDFTSize(img.rows + kernel.rows - 1);   // 行数
int dft_N = getOptimalDFTSize(img.cols + kernel.cols - 1);   // 列数

Mat imagePad(dft_M, dft_N, CV_32FC1, Scalar(0));
Mat imagePadROI = imagePad(Rect(0, 0, img.cols, img.rows));
img.convertTo(imagePadROI, CV_32FC1, 1, 0);

Mat kernelPad(dft_M, dft_N, CV_32FC1, Scalar(0));
Mat kernelPadROI = kernelPad(Rect(0, 0, kernel.cols, kernel.rows));
kernel.convertTo(kernelPadROI, CV_32FC1, 1, 0);

dft(imagePad, imagePad, 0, imagePad.rows);
dft(kernelPad, kernelPad, 0, kernelPad.rows);

// set the last parameter to false to compute convolution instead of correlation
mulSpectrums(imagePad, kernelPad, imagePad, DFT_COMPLEX_OUTPUT, false);  // false: A.*B;true:xf.*conj(yf)
idft(imagePad, imagePad, cv::DFT_SCALE | cv::DFT_REAL_OUTPUT, imagePad.rows);

Rect r;
switch (type)
{
case CONVOLUTION_FULL:  // full
r = Rect(0, 0, img.cols + kernel.cols - 1, img.rows + kernel.rows - 1);
break;
case CONVOLUTION_SAME:  // same
r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols, img.rows);
break;
case CONVOLUTION_VALID:  // valid
r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols - kernel.cols + 1, img.rows - kernel.rows + 1);
break;
default:  // same
r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols, img.rows);
break;
}

imagePad(r).convertTo(convRes, ddepth, 1, 0);
}


说明:

不确定矩形框是否正确。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: