OpenCV 笔记(32):图像处理的傅里叶变换——初探

在图像处理中,图像可以用不同域来表示和分析。

下面是几种最常用的域:

  • 空间域是指由图像像素组成的空间。
  • 时域是指图像随时间变化的域。对于动态图像,例如视频,时域表示图像帧随时间的变化。时域处理是指对图像序列进行操作,例如运动分析、视频压缩等。
  • 频域是将图像从空间域变换到频率域得到的表示。在频域中,图像被表示为一个二维复数矩阵,其中每个元素代表图像中某一特定频率分量的幅度和相位。

图像的空间域、时域和频域是三种不同的表示图像信息的视角,这三者之间可以相互转换。

1. 频域

图像的频域 是通过傅里叶变换将图像从空间域转换到频率域而得到的。在频域中,图像的每个像素点都被表示为一个复数,其幅度表示该频率分量的能量,相位表示该频率分量的初始相位。

在空间域中,图像由像素值矩阵表示,每个像素值代表图像在该位置的颜色或亮度。在频率域中,图像由频谱图表示,频谱图上的每个点代表图像中特定频率的成分。图像的频率域与空间域具有互补关系,图像的任何信息都可以在空间域和频率域中找到。

频率域滤波的基本原理是将图像变换到频率域,然后利用滤波器对图像的频谱分量进行处理,最后将滤波后的频谱分量变换回空间域得到滤波后的图像。

在频率域中,图像的每个像素点都对应着一个频率分量。低频分量对应于图像中的平滑区域和整体形状,而高频分量对应于图像中的细节和边缘。

空间域和频率域的滤波器可以分为四类: 低通、高通、带阻、带通滤波器。

  • 低通滤波器 允许低频分量通过,抑制高频分量。低频分量通常对应于图像中的平滑区域和整体亮度变化,可以用于平滑图像,去除噪声和模糊细节。
  • 高通滤波器 允许高频分量通过,抑制低频分量。高频分量对应于图像中的边缘和细节,可以用于锐化图像,增强图像的边缘和细节。
  • 带通滤波器 只允许特定频率范围内的信号通过,抑制其他频率范围内的信号。可以用于提取图像中的特定特征,例如纹理或边缘。
  • 带阻滤波器 抑制特定频率范围内的信号,允许其他频率范围内的信号通过。可以用于去除图像中的特定噪声,例如摩尔纹。

2. 图像锐化的原理

在该系列的第三十一篇文章中介绍过图像锐化。锐化的目的是为了突出图像的边缘信息 ,加强图像的轮廓特征,以便于人眼的观察和机器的识别。

在空间域,可以用空间微分来实现锐化。微分算子的响应强度与图像在该点的突变程度有关,图像微分增强了边缘和其他突变(如噪声)而消弱了灰度变化缓慢的区域。

在频率域,由于图像中的边缘、线条等细节部分与图像频谱中的高频分量相对应,在频率域中使用高通滤波器能够使图像的边缘或线条变得清晰,从而使图像得到锐化。高通滤波器衰减傅立叶变换中的低频分量,让高频分量顺利通过,使低频分量受到抑制,就可以增强高频的成分。使图像的边沿或线条变得清晰,从而实现图像的锐化。

3. 傅里叶变换

空间域、时域和频域之间可以通过傅立叶变换(Fourier Transform)进行转换。傅立叶变换是一种数学工具,可以将信号从一个域变换到另一个域。

  • 空间域到频域的傅立叶变换 :将图像从空间域 (x,y) 变换到频域 (u,v) ,可以得到图像的频谱。图像的频谱可以反映图像的频率成分,例如图像中边缘、纹理等信息的分布。

  • 频域到空间域的傅立叶逆变换:将图像从频域变换回空间域,可以得到原始图像。

先上基础的公式作为直观地感受,后续文章会做介绍。

一维连续傅里叶变换:

<math xmlns="http://www.w3.org/1998/Math/MathML"> F ( μ ) = ∫ − ∞ ∞ f ( t ) e − j 2 π μ t   d t F(\mu)=\int_{-\infty}^{\infty}f(t)e^{-j2\pi\mu t}\,dt </math>F(μ)=∫−∞∞f(t)e−j2πμtdt

一维连续傅里叶逆变换:

<math xmlns="http://www.w3.org/1998/Math/MathML"> f ( t ) = ∫ − ∞ ∞ F ( μ ) e j 2 π μ t   d μ f(t)= \int_{-\infty}^{\infty}F(\mu)e^{j2\pi\mu t}\,d\mu </math>f(t)=∫−∞∞F(μ)ej2πμtdμ

一维离散傅里叶变换:

<math xmlns="http://www.w3.org/1998/Math/MathML"> F m = ∑ n = 0 M − 1 f n e − j 2 π m n / M m = 0 , 1 , 2 , . . . , M − 1 F_m = \sum_{n=0}^{M-1}f_n e^{-j2\pi mn/M} \quad m = 0,1,2,...,M-1 </math>Fm=∑n=0M−1fne−j2πmn/Mm=0,1,2,...,M−1

一维离散傅里叶逆变换:

<math xmlns="http://www.w3.org/1998/Math/MathML"> f n = 1 M ∑ m = 0 M − 1 F m e j 2 π m n / M n = 0 , 1 , 2 , . . . , M − 1 f_n = \frac{1}{M}\sum_{m=0}^{M-1}F_m e^{j2\pi mn/M} \quad n = 0,1,2,...,M-1 </math>fn=M1∑m=0M−1Fmej2πmn/Mn=0,1,2,...,M−1

二维连续傅里叶变换:

<math xmlns="http://www.w3.org/1998/Math/MathML"> F ( μ , ν ) = ∫ − ∞ ∞ ∫ − ∞ ∞ f ( t , z ) e − j 2 π ( μ t + ν z )   d t d z F(\mu,\nu)=\int_{-\infty}^{\infty}\int_{-\infty}^{\infty}f(t,z)e^{-j2\pi(\mu t+\nu z)}\,dtdz </math>F(μ,ν)=∫−∞∞∫−∞∞f(t,z)e−j2π(μt+νz)dtdz

二维连续傅里叶逆变换:

<math xmlns="http://www.w3.org/1998/Math/MathML"> f ( t , z ) = ∫ − ∞ ∞ ∫ − ∞ ∞ F ( μ , ν ) e j 2 π ( μ t + ν z )   d μ d ν f(t,z)=\int_{-\infty}^{\infty}\int_{-\infty}^{\infty}F(\mu,\nu)e^{j2\pi(\mu t+\nu z)}\,d\mu d\nu </math>f(t,z)=∫−∞∞∫−∞∞F(μ,ν)ej2π(μt+νz)dμdν

二维离散傅里叶变换:

<math xmlns="http://www.w3.org/1998/Math/MathML"> F ( μ , ν ) = ∑ x = 0 M − 1 ∑ y = 0 N − 1 f ( x , y ) e − j 2 π ( μ x / M + ν y / N ) F(\mu,\nu) = \sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y) e^{-j2\pi(\mu x/M + \nu y/N)} </math>F(μ,ν)=∑x=0M−1∑y=0N−1f(x,y)e−j2π(μx/M+νy/N)

二维离散傅里叶逆变换:

<math xmlns="http://www.w3.org/1998/Math/MathML"> f ( x , y ) = 1 M N ∑ μ = 0 M − 1 ∑ ν = 0 N − 1 F ( μ , ν ) e j 2 π ( μ x / M + ν y / N ) f(x,y) = \frac{1}{MN}\sum_{\mu=0}^{M-1} \sum_{\nu=0}^{N-1}F(\mu,\nu)e^{j2\pi(\mu x/M + \nu y/N)} </math>f(x,y)=MN1∑μ=0M−1∑ν=0N−1F(μ,ν)ej2π(μx/M+νy/N)

图像傅里叶变换的计算通常使用离散傅里叶变换(Discrete Fourier Transform,DFT)来实现。DFT 是傅里叶变换的离散化版本,它可以将图像离散化成有限大小的矩阵,然后使用矩阵乘法来计算图像的傅里叶变换。

对于二维离散傅里叶变换,f(x,y) 表示大小为 M*N 的数字图像。 <math xmlns="http://www.w3.org/1998/Math/MathML"> F ( μ , ν ) F(\mu,\nu) </math>F(μ,ν) 表示 f(x,y) 的傅里叶变换。

在式中 f(x,y) 所在坐标系被称为空间域, 由 x = 0,1,2,···,M-1 和 y = 0,1,2,···,N-1 所定义的 M x N 矩阵常被称为空间域矩阵。 <math xmlns="http://www.w3.org/1998/Math/MathML"> F ( μ , ν ) F(\mu,\nu) </math>F(μ,ν) 所在坐标系被称为频域,由 u = 0,1,2,···,M-1 和 v = 0,1,2,···,N-1 定义的 M x N 矩阵常称为频域矩阵。

下面的例子,展示了灰度图像经过傅里叶变换后生成频谱图的过程。

为了便于频域和频谱分析,在傅里叶变换后进行频谱中心化,即对调频谱的四个象限。频谱中心化后,中间最亮的点是低频率,属于直流分量,越往外频率越高。

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>

using namespace cv;
using namespace std;

void myDFT(Mat src, Mat& dst)
{
    // 扩充边界
    int m = getOptimalDFTSize(src.rows);
    int n = getOptimalDFTSize(src.cols);
    copyMakeBorder(src, src, 0, m - src.rows, 0, n - src.cols, BORDER_CONSTANT, Scalar::all(0));

    // 创建一个双通道矩阵 planes,用来储存复数的实部与虚部
    Mat planes[] = {Mat_<float>(src), Mat::zeros(src.size(), CV_32F) };

    Mat complexI;
    // 增加一个通道,将两个 planes 合并,为了存储复数
    merge(planes, 2, complexI);

    // 进行离散傅立叶变换
    dft(complexI, complexI);

    split(complexI, planes); // 将双通道分为两个单通道,一个表示实部,一个表示虚部
    magnitude(planes[0], planes[1], dst); //计算复数的幅值,保存在频谱图 dst

    // M = log(1 + M)
    dst += Scalar(1);   //  取对数前将所有的像素都加1,防止 log0
    log(dst, dst);      // 取对数

    normalize(dst, dst, 0, 1, NORM_MINMAX); //归一化

    imshow("dft", dst); // 二维离散傅里叶

    // 剪切和重分布幅度图像限,如果有奇数行或奇数列,进行频谱裁剪
    dst = dst(Rect(0, 0, dst.cols & -2, dst.rows & -2));

    // 重新排列傅里叶图像中的象限,将频谱中心移至图像中心
    int cx = dst.cols / 2;
    int cy = dst.rows / 2;
    Mat q0(dst, Rect(0, 0, cx, cy));   // 左上区域
    Mat q1(dst, Rect(cx, 0, cx, cy));  // 右上区域
    Mat q2(dst, Rect(0, cy, cx, cy));  // 左下区域
    Mat q3(dst, Rect(cx, cy, cx, cy)); // 右下区域

    /*
    origin:
       q0 | q1
       q2 | q3
    new:
       q3 | q2
       q1 | q0
     */
    // 交换象限
    Mat tmp;
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);// q0 与 q3 进行交换

    q1.copyTo(tmp);
    q2.copyTo(q1);
    tmp.copyTo(q2);// q1 与 q2 进行交换
}

int main()
{
    Mat src = imread(".../girl.jpg");

    Mat gray, dst;
    imshow("src", src);

    cvtColor(src, gray, COLOR_BGR2GRAY);
    imshow("gray", gray);

    myDFT(gray, dst); // 傅里叶变换
    imshow("dst", dst); // 零频率分量移至频谱中心
    waitKey(0);
    return 0;
}

4. 总结

"万物皆可傅里叶",本文是傅里叶变换在该系列的一个开篇,后续还会继续介绍其在图像处理中的应用。

在图像处理领域,傅里叶变换可以将图像从空间域变换到频域,从而揭示图像的频率成分。傅里叶变换在图像处理中有着广泛的应用,例如:图像增强、图像分割、特征提取、图像压缩等。

相关推荐
ctrey_10 小时前
2024-11-1 学习人工智能的Day20 openCV(2)
人工智能·opencv·学习
绕灵儿11 小时前
OpenCV通过指针裁剪图像
人工智能·opencv·计算机视觉
决战春招16 小时前
人工智能之人脸识别(人脸采集人脸识别)
人工智能·opencv·学习·计算机视觉
千秋1000018 小时前
OpenCV—calcHist()函数
人工智能·opencv·计算机视觉
爱写代码的小朋友18 小时前
使用 Python 和 OpenCV 实现实时人脸识别
开发语言·python·opencv
小负不负21 小时前
使用kalibr_calibration标定相机(realsense)和imu(h7min)
数码相机·opencv·计算机视觉
凤枭香21 小时前
python opencv灰度变换
图像处理·人工智能·python·opencv
maxruan1 天前
cv::Mat初始化、赋值初始化与访问方式
人工智能·opencv·计算机视觉
jndingxin1 天前
OpenCV视觉分析之目标跟踪(11)计算两个图像之间的最佳变换矩阵函数findTransformECC的使用
opencv·目标跟踪·矩阵
joker_man11 天前
使用Python和OpenCV实现火焰检测
开发语言·python·opencv