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

转载请注明出处:

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的时候结果不对,大家辩证的看待代码哈)

 1 #include <opencv2/opencv.hpp>
 2 #include <opencv2/highgui/highgui.hpp>
 3 #include <opencv2/imgproc/imgproc.hpp>
 4 using namespace cv;
 5 
 6 enum ConvolutionType                     // 函数 conv2 卷积时参数的类型
 7 {
 8     CONVOLUTION_FULL,                    // 卷积时的参数,和 matlab 的 full 一致
 9     CONVOLUTION_SAME,                    // 卷积时的参数,和 matlab 的 same 一致
10     CONVOLUTION_VALID                    // 卷积时的参数,和 matlab 的 valid 一致
11 };
12 void Conv2DFT(Mat& convRes, const Mat& img, const Mat& kernel, ConvolutionType type, int ddepth)
13 {
14     int dft_M = getOptimalDFTSize(img.rows + kernel.rows - 1);   // 行数
15     int dft_N = getOptimalDFTSize(img.cols + kernel.cols - 1);   // 列数
16 
17     Mat imagePad(dft_M, dft_N, CV_32FC1, Scalar(0));
18     Mat imagePadROI = imagePad(Rect(0, 0, img.cols, img.rows));
19     img.convertTo(imagePadROI, CV_32FC1, 1, 0);
20 
21     Mat kernelPad(dft_M, dft_N, CV_32FC1, Scalar(0));
22     Mat kernelPadROI = kernelPad(Rect(0, 0, kernel.cols, kernel.rows));
23     kernel.convertTo(kernelPadROI, CV_32FC1, 1, 0);
24 
25     dft(imagePad, imagePad, 0, imagePad.rows);
26     dft(kernelPad, kernelPad, 0, kernelPad.rows);
27 
28     // set the last parameter to false to compute convolution instead of correlation
29     mulSpectrums(imagePad, kernelPad, imagePad, DFT_COMPLEX_OUTPUT, false);  // false: A.*B;true:xf.*conj(yf)
30     idft(imagePad, imagePad, cv::DFT_SCALE | cv::DFT_REAL_OUTPUT, imagePad.rows);
31 
32     Rect r;
33     switch (type)
34     {
35     case CONVOLUTION_FULL:  // full
36         r = Rect(0, 0, img.cols + kernel.cols - 1, img.rows + kernel.rows - 1);
37         break;
38     case CONVOLUTION_SAME:  // same
39         r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols, img.rows);
40         break;
41     case CONVOLUTION_VALID:  // valid
42         r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols - kernel.cols + 1, img.rows - kernel.rows + 1);
43         break;
44     default:  // same
45         r = Rect((kernel.cols + 0.5) / 2, (kernel.rows + 0.5) / 2, img.cols, img.rows);
46         break;
47     }
48 
49     imagePad(r).convertTo(convRes, ddepth, 1, 0);
50 }

说明:

不确定矩形框是否正确。