在图像处理中经常会遇到各种滤波(平滑、锐化)的情况,基本方法都是将图像与一个核进行卷积实现。而卷积定理指出,两个函数的卷积的傅里叶变换等于各自的傅里叶变换的乘积,即:

那么,两个函数的卷积可以通过如下方式得到,对两个函数傅里叶变换的乘积做傅里叶反变换,即:

在进行卷积运算时,一般是将核沿着图像从左到右从上到下计算每一个像素处与核卷积后的值,这样的计算量较大,采用傅里叶变换的方法可以提高运算效率。

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>using namespace cv;
using namespace std;//http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#dft[2]
void convolveDFT(Mat A, Mat B, Mat& C)
{// reallocate the output array if neededC.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type());Size dftSize;// calculate the size of DFT transformdftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1);// allocate temporary buffers and initialize them with 0'sMat tempA(dftSize, A.type(), Scalar::all(0));Mat tempB(dftSize, B.type(), Scalar::all(0));// copy A and B to the top-left corners of tempA and tempB, respectivelyMat roiA(tempA, Rect(0,0,A.cols,A.rows));A.copyTo(roiA);Mat roiB(tempB, Rect(0,0,B.cols,B.rows));B.copyTo(roiB);// now transform the padded A & B in-place;// use "nonzeroRows" hint for faster processingdft(tempA, tempA, 0, A.rows);dft(tempB, tempB, 0, B.rows);// multiply the spectrums;// the function handles packed spectrum representations wellmulSpectrums(tempA, tempB, tempA, DFT_COMPLEX_OUTPUT);//mulSpectrums(tempA, tempB, tempA, DFT_REAL_OUTPUT);// transform the product back from the frequency domain.// Even though all the result rows will be non-zero,// you need only the first C.rows of them, and thus you// pass nonzeroRows == C.rowsdft(tempA, tempA, DFT_INVERSE + DFT_SCALE, C.rows);// now copy the result back to C.tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C);// all the temporary buffers will be deallocated automatically
}int main(int argc, char* argv[])
{const char* filename = argc >=2 ? argv[1] : "Lenna.png";Mat I = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);if( I.empty())return -1;Mat kernel = (Mat_<float>(3,3) << 1, 1, 1, 1, 1, 1, 1, 1, 1);cout << kernel;Mat floatI = Mat_<float>(I);// change image type into floatMat filteredI;convolveDFT(floatI, kernel, filteredI);normalize(filteredI, filteredI, 0, 1, CV_MINMAX); // Transform the matrix with float values into a// viewable image form (float between values 0 and 1).imshow("image", I);imshow("filtered", filteredI);waitKey(0);}

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

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

需要注意的是,一般求法中,利用核游走整个图像进行卷积运算,实际上进行的是相关运算,真正意义上的卷积,应该首先把核翻转180度,再在整个图像上进行游走。OpenCV中的filter2D实际上做的也只是相关,而非卷积。"The function does actually compute correlation, not the convolution: ... That is, the kernel is not mirrored around the anchor point. If you need a real convolution, flip the kernel using flip() and set the new anchor to (kernel.cols - anchor.x - 1, kernel.rows - anchor.y - 1)"[3]

参考文献:
[1] http://zh.wikipedia.org/wiki/%E5%8D%B7%E7%A7%AF%E5%AE%9A%E7%90%86
[2] http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#dft
[3] http://docs.opencv.org/modules/imgproc/doc/filtering.html#filter2d

通过傅里叶变换方法求图像卷积-OpenCV实现相关推荐

  1. OpenCV下利用傅里叶变换和逆变换实现图像卷积算法,并附自己对于卷积核/模板核算子的理解

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 学过信号与系统的人都知道,卷积运算一般是转化成频 ...

  2. 【OpenCV 4开发详解】图像卷积

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  3. OpenCV之core 模块. 核心功能(1)Mat - 基本图像容器 OpenCV如何扫描图像、利用查找表和计时 矩阵的掩码操作 使用OpenCV对两幅图像求和(求混合(blending))

    Mat - 基本图像容器 目的 从真实世界中获取数字图像有很多方法,比如数码相机.扫描仪.CT或者磁共振成像.无论哪种方法,我们(人类)看到的是图像,而让数字设备来"看"的时候,则 ...

  4. OpenCV快速傅里叶变换(FFT)用于图像和视讯流的模糊检测

    OpenCV快速傅里叶变换(FFT)用于图像和视频流的模糊检测 翻译自[OpenCV Fast Fourier Transform (FFT) for blur detection in images ...

  5. 【OpenCV 4】图像卷积操作(Blur)

    一.编程环境: OpenCV  4.1.0 IDE Visual Studio 2017 Enterprise (15.9.13) 操作系统 Windows 10 x64 中文专业版 (1903) 二 ...

  6. 【python+opencv】图像卷积及滤波

    目录 1.噪声的分类 2.图像卷积 2.1单次卷积操作 2.2对整幅图像卷积 2.3完整卷积过程 3.opencv中的卷积-filter2D函数 4.卷积中的padding填充(边界填充) 5.pad ...

  7. OpenCV学习笔记(十)——图像卷积(cv.filter2D()、矩阵旋转cv.filp())

    目录 1 图像卷积过程 2 cv.filter2D() 3 cv.filp() 卷积运算在信号处理中十分常见,而图像信息可以看成一种信号.例如,图像的每一行可以看出测量亮度变化的信号,而每一列可以看作 ...

  8. OpenCV 图像卷积:cv.filter2D() 函数详解

    API 照例,我们搬一下官网的 API: C++ void cv::filter2D(InputArray src,OutputArray dst,int ddepth,InputArray kern ...

  9. 【opencv】25.图像卷积cv::filter2D()以及c++代码实例

    自己写图像锐化函数: #include <iostream> #include <opencv2/core.hpp> #include <opencv2/highgui. ...

最新文章

  1. 关于一个无限分类的多选,单选相关的控件
  2. Python基础-安装
  3. 你见过最垃圾的代码长什么样?(来长长见识)
  4. js对象,原型,call,apply浅析
  5. 2021-11-05 虚拟机centos7更改root与home分区大小
  6. 搞工程和搞电子的人摆摊能做什么?
  7. pojBuy Tickets2828线段树或者树状数组(队列中倒序插队)
  8. java cl 規格_Java JavaCL類代碼示例
  9. 视频数据:骨骼数据采集(Skeleton Data)
  10. Centos7设置静态IP后无法上网的解决方法
  11. centos 5.4 nfs服务器搭建
  12. java堆外内存为何比java堆更适合用来进行网络IO操作
  13. Hyper-V虚拟化测试12非计划的故障转移
  14. 数论基本定理及应用(四)
  15. Java简单ztree树
  16. OpenGL中的坐标变换、矩阵变换【转载】
  17. ftp下载,6步掌握ftp下载软件的使用方法
  18. AMiner发布:2022年人工智能全球最具影响力学者榜单AI 2000
  19. SALSA:基于Hi-C辅助组装长读长组装结果
  20. 网易云音乐打卡2.0(一天300首)10级指日可待

热门文章

  1. SESSION 与 COOKIE的区别是
  2. 【李宏毅2020 ML/DL】P74 Generative Adversarial Network | Basic Idea
  3. 对症下药,方能药到病除——如何修复drv?
  4. linux获取打开串口失败的原因,linux – 从串口读取失败
  5. mysql 邻接表_图的邻接表存储结构详解
  6. siamese改进_[CVPR2019]我对Siamese网络的一点思考(SiamMask)
  7. windbg调试句柄泄露
  8. 避免门事件 巧妙清除搜狗浏览器记录
  9. python测试开发工程师前景_测试开发工程师,薪水20k值吗?
  10. Spring.Net配置多数据源