(原+转)使用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 }
说明:
不确定矩形框是否正确。
posted on 2016-05-05 17:31 darkknightzh 阅读(5569) 评论(6) 编辑 收藏 举报