opencv C++ 傅里叶变换及反变换

本文介绍了一个使用C++与OpenCV实现的傅里叶变换和高通滤波处理过程。通过该方法可以对图像进行频域处理,实现噪声去除等功能。文中详细展示了如何构建填充矩阵、进行离散傅里叶变换(DFT)、应用高通滤波器以及进行逆变换等步骤。

此文为本人测试代码记录。

傅里叶变换 及 高通滤波处理

 

#include <opencv2/opencv.hpp>
#include<iostream>
#include<vector>
#include<string>
#include<Windows.h>
#include "contrib.hpp"
#include <opencv2/imgproc/types_c.h>

using namespace cv;
using namespace std;

void shift_img(Mat &srcimg, Mat &dstimg);

void main()
{
    Mat img, img_std;
    Mat image1 = imread(".../ceshi.bmp");
    if (image1.channels() > 1)
        cvtColor(image1, img_std, COLOR_RGBA2GRAY);
    else
        img_std = image1.clone();


	int M = getOptimalDFTSize(img_std.rows);
	int N = getOptimalDFTSize(img_std.cols);
	Mat padded;
	copyMakeBorder(img_std, padded, 0, M - img_std.rows, 0, N - img_std.cols, BORDER_CONSTANT, Scalar::all(0));

	Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
	Mat complexImg;
	merge(planes, 2, complexImg);

	dft(complexImg, complexImg);

	split(complexImg, planes);
	magnitude(planes[0], planes[1], planes[0]);
	Mat mag = planes[0].clone();
	mag += Scalar::all(1);
	log(mag, mag);

	// crop the spectrum, if it has an odd number of rows or columns
	mag = mag(Rect(0, 0, mag.cols & -2, mag.rows & -2));

	int cx = mag.cols / 2;
	int cy = mag.rows / 2;

    cv::Mat MagI;
    shift_img(mag, MagI);
	normalize(MagI, MagI, 0, 255, NORM_MINMAX);
    convertScaleAbs(MagI, MagI);
  
    imwrite("...\\dft.bmp", MagI);

    int hsize_width = 30;
    int hsize_height = 10;

    cv::Rect rect_center = Rect(cx - hsize_width, cy - hsize_height, 2 * hsize_width, 2 * hsize_height);
    cv::Mat Mask_center = Mat::ones(mag.rows, mag.cols, CV_8UC1);
    cv::Mat mag_mask = planes[0].clone();

    shift_img(mag_mask, mag_mask);
    mag_mask(rect_center).setTo(0);
    shift_img(mag_mask, mag_mask);

    cv::Mat mag_mask_x = planes[1].clone();

    shift_img(mag_mask_x, mag_mask_x);
    mag_mask_x(rect_center).setTo(0);
    shift_img(mag_mask_x, mag_mask_x);


    Mat icomplexImg;

    vector<Mat> merge_img(2);
    merge_img[0] = mag_mask;
    merge_img[1] = mag_mask_x;
    merge(merge_img,icomplexImg);

    Mat iDft[] = { Mat::zeros(padded.size(),CV_32F),Mat::zeros(padded.size(),CV_32F) };
    idft(icomplexImg, icomplexImg, DFT_SCALE | DFT_REAL_OUTPUT); // IDFT进行DFT逆变换
    split(icomplexImg, iDft);
    magnitude(iDft[0], iDft[1], iDft[0]);

    Mat dst(iDft[0], Rect(0, 0, img_std.cols, img_std.rows));

    convertScaleAbs(dst, dst);


    imwrite("...\\iDFT.bmp", dst);


    waitKey(0);
}



void shift_img(&srcimg, Mat &dstimg)
{
    int cx = srcimg.cols / 2;
    int cy = srcimg.rows / 2;
    Mat tmp;
    Mat q0(srcimg, Rect(0, 0, cx, cy));
    Mat q1(srcimg, Rect(cx, 0, cx, cy));
    Mat q2(srcimg, Rect(0, cy, cx, cy));
    Mat q3(srcimg, Rect(cx, cy, cx, cy));

    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);
    q2.copyTo(q1);
    tmp.copyTo(q2);
    dstimg = srcimg.clone();
}

python代码 仿真相对方便

可参考 python 傅里叶变换 频域高通低通滤波

### 使用OpenCV C++实现图像增强的傅里叶变换 为了利用傅里叶变换来增强图像,在C++中使用OpenCV库是一个高效的选择。下面展示了一个具体的例子,该实例展示了如何读入一幅灰度图并对其进行离散傅里叶变换(DFT),接着通过调整频域中的某些成分来进行图像增强操作。 #### 1. 加载图片并转换成灰度模式 ```cpp #include <opencv2/opencv.hpp> using namespace cv; Mat img = imread("path_to_image", IMREAD_GRAYSCALE); // 将路径替换为实际文件位置 if(img.empty()){ printf("Could not open or find the image\n"); return -1; } ``` #### 2. 执行快速傅里叶变换 (FFT) ```cpp // 对输入图像执行DFT, 并将结果存储在一个复数矩阵中. dft(img, dftImg, DFT_COMPLEX_OUTPUT); // 移动零频率分量到中心以便于可视化效果更好 Mat planes[] = { Mat_<float>(img), Mat::zeros(img.size(), CV_32F) }; merge(planes, 2, complexI); dft(complexI, complexI); split(complexI, planes); // 将多通道数组拆分为几个单通道数组 magnitude(planes[0], planes[1], planes[0]);// 计算幅度谱 Mat magI = planes[0]; magI += Scalar::all(1); // 切换到Log尺度 log(magI, magI); // 裁剪和重排振幅范围以获得更好的显示结果 normalize(magI, magI, 0, 1, NORM_MINMAX); // 变换回uint8_t形式用于显示 imshow("Spectrum Magnitude", magI); waitKey(); ``` #### 3. 应用高通滤波器或其他类型的滤波器进行图像增强 这里仅给出概念性的描述,具体实施取决于所选滤波算法以及期望达到的效果。对于简单的高频强调可考虑如下方式: - 创建一个与原始大小相同的掩模; - 设置中心区域外的所有像素值为1(允许这些部分通过),而内部设为0(阻止低频信息传递); - 将此掩模应用于之前得到的复数值表示形式的数据上; - 进行逆向傅里叶变换恢复空间域内的修改后的版本; 注意这只是一个非常基础的方法示意,实践中可能还需要更复杂的处理逻辑才能取得理想的结果[^1].
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值