OpenCV4.3 Java 编程入门:离散傅里叶变换

1 时域,频域,空间域

首先,需要知道什么是 定义域

定义域(domain of definition)指自变量 x 的取值范围,是函数三要素(定义域、值域、映射法则)之一,映射法则的作用对象。

即,对于函数: y = f ( x ) y = f(x) y=f(x),自变量 x 的取值范围就是定义域!

知道定义域的概念之后,时域,频域,空间域,也就好理解了:

  • 时域:以时间范围为定义域,自变量 x 表示时间;
  • 频域:以频率范围为定义域,自变量 x 表示频率;
  • 空间域:以空间范围为定义域,自变量 x 表示空间;

当然,自变量的个数与定义域的维度有关,比如二维空间,自变量就是 (x,y),三维空间,自变量就是 (x,y,z)。
在这里插入图片描述

时间、空间、频率是人类认识世界的三个维度!当需要认识和理解物体的“粒子”特性时,就从时间和空间的维度着手,而当需要认识和理解物体的“波”的特性时,则需要从频率维度着手。
在这里插入图片描述
微观粒子具有波粒二象性,信息/信号同样也具有“波粒二象性”!

因此,我们在认识和理解“信息/信号”时,既需要认识它“粒子性”的一面,又要认识它“波动性”的一面。
在这里插入图片描述
在哲学上,分析一个事物的发展变化,会从事物发展过程中 直接 (时间 when、地点 where、人物 who、事件 what) 寻找其中的发展规律,来总结历史,预测未来,这其实就是“时域分析”。还有一种办法,就是从影响事物发展的各种因素出发,去分析这些相互独立要素对事物发展变化的影响(比如,气候对皇朝更迭的影响),这就是“频域分析”。

信息/信号一般情况下,只能在时域或空间域采集,比如声音信号的录制,图像信号的拍摄,等等。如果要对采集到的信号进行频域分析,则需要先将信号从时域,或空间域,转换到频域,然后再进行频域分析。傅里叶变换就是一种将信号从时域/空间域转换成频率的技术。

人类的大脑,能够直接获取信号的频域信息,比如听音的时候,能够直接分辨声音的频率,音感好的人,可以从和音中分辨出多个单音。另外,人的眼睛能识别不同的颜色,而颜色本质上就是不同波长/频率的可见光波,也就是说,人的眼睛能识别可见光的频率特征。

可见,大脑是多么的精妙啊,它真的是进化而来吗?

2 傅里叶变换

在这里插入图片描述

简而言之,傅里叶变换是搭建在 时域/空间域频域 之间的桥梁!

任何的信号,都有两种形态,就是时域形态和频域形态,当信号的时域特征明显时,就在时域对其进行分析,当信号的频域特征明显时,就在频域对其分析。而两种形态之间的转换,就需要通过傅里叶变换来完成。
在这里插入图片描述

从纯数学角度讲,傅里叶变换是一种复杂的积分变换。傅里叶变换就是任意一个周期(甚至非周期)函数都可以分解成无数个不同频率的正弦(余弦)函数之和,严格讲这不是傅里叶变换的全部,只是一种特例,或者是利用傅里叶变换理论得到的一种用离散型级数表达的傅里叶变换形式,也称傅里叶级数。

事物的发展变化可以用时变函数描述,可以用微积分的方法回顾历史展望未来,这一过程其实就是解算微分方程的过程,这也叫时域分析。经过傅里叶变换后,就把时域分析变为了频域分析。
在这里插入图片描述

傅里叶变换有很深的哲学内涵,比如在认识自我时,我经历了什么,做了什么,拥有着什么,这些都是时域信息;而我的性格,如勇气、品德、智力,等等,都是频域信息。我们可以努力去调整频域中各个频率值的系数,因为它们会影响我们人生的轨迹!

3 图像处理:频域增强

在进行图像处理时,除了可以在空间域进行外,也可以在频域中进行。图像的频域处理有着客观的物理意义,例如,图像采集时因受到电干扰而产生噪声,这些电磁干扰往往有着特定的频率,因此可以采用频域滤波的方法来消除噪声。

在频域里,对于一幅图像,高频部分代表了图像的细节、文理信息;低频部分代表了图像的轮廓信息。如果对一幅精细的图像使用低通滤波,那么滤波后的结果就只剩下轮廓了。这与信号处理的基本思想是相通的。傅里叶变换在图像处理中可以做到图像增强与图像去噪、图像分割之边缘检测、图像特征提取、图像压缩等。

卷积理论是频域技术的基础,卷积定理指出,函数卷积的傅立叶变换是函数傅立叶变换的乘积。具体分为时域卷积定理和频域卷积定理,时域卷积定理即时域内的卷积对应频域内的乘积;频域卷积定理即频域内的卷积对应时域内的乘积,两者具有对偶关系。
在这里插入图片描述
因为空间域至少是二维的,所以需要 2D傅里叶变换。
在这里插入图片描述

设函数 f ( x , y ) f(x, y) f(x,y) 与线性位移不变算子 h ( x , y ) h(x, y) h(x,y) 的卷积结果是 g ( x , y ) g(x, y) g(x,y),即 g ( x , y ) = h ( x , y ) ∗ f ( x , y ) g(x, y) = h(x, y) * f(x, y) g(x,y)=h(x,y)f(x,y),那么根据卷积定理在频域有 G ( u , v ) = H ( u , v ) F ( u , v ) G(u, v)=H(u, v)F(u, v) G(u,v)=H(u,v)F(u,v),其中 G ( u , v ) , H ( u , v ) , F ( u , v ) G(u, v),H(u,v),F(u, v) G(u,v)H(u,v)F(u,v) 分别是 g ( x , y ) , h ( x , y ) , f ( x , y ) g(x, y),h(x, y),f(x, y) g(x,y)h(x,y)f(x,y) 的傅里叶变换。用线性系统理论的话来说, H ( u , v ) H(u, v) H(u,v) 是转移函数。

在具体的增强应用中, f ( x , y ) f(x, y) f(x,y) 是已知的(所以 F ( u , v ) F(u, v) F(u,v) 可利用变换得到),需要确定的是 H ( u , v ) H(u, v) H(u,v),这样具有所需特性的 g ( x , y ) g(x, y) g(x,y) 就可得到: g ( x , y ) = F − 1 [ H ( u , v ) F ( u , v ) ] g(x, y)=F^{-1}[H(u, v)F(u, v)] g(x,y)=F1[H(u,v)F(u,v)]

因此,在频域进行图像处理的主要步骤:

  1. 计算目标图像的傅里叶变换;
  2. 将其与一个转移函数(需要设计)相乘;
  3. 再将结果傅里叶反变换以得到处理后的图像;

在这里插入图片描述
如上图,(a) 所示是一个 2-D 图像函数,这个函数在原点为中心的一个正方形内为正值常数,而在其他地方为 0 ;(b) 所示是它的灰度图显示;© 所示是这个 2-D 图像傅里叶变换后的频谱幅度的灰度图显示。

4 傅里叶变换定理

f ( x , y ) f(x, y) f(x,y) F ( u , v ) F(u, v) F(u,v) 构成一对变换,即
在这里插入图片描述
则有以下一些定理成立。

1、平移定理

傅里叶变换的平移定理可写成(a,b,c和d均为标量):
在这里插入图片描述
表明将 f ( x , y ) f(x, y) f(x,y) 在空间平移相当于把其变换在频域与一个指数项相乘,而将 f ( x , y ) f(x, y) f(x,y) 在空间与一个指数项相乘相当于把其变换在频域平移。另外,对 f ( x , y ) f(x, y) f(x,y) 的平移不影响其傅里叶变换的幅值。

2、 旋转定理

傅里叶变换的旋转定理反映了傅里叶变换的旋转性质。

首先借助极坐标变换 x = r c o s θ , y = r s i n θ , u = w c o s ϕ , v = w s i n ϕ x=rcosθ,y=rsinθ,u=wcosϕ,v=wsinϕ x=rcosθy=rsinθu=wcosϕv=wsinϕ,将 f ( x , y ) f(x, y) f(x,y) F ( u , v ) F(u, v) F(u,v) 转换为 f ( r , θ ) f(r, θ) f(r,θ) F ( w , ϕ ) F(w, ϕ) F(w,ϕ)。直接将它们代入傅里叶变换对得到( θ 0 θ_0 θ0为旋转角度):
在这里插入图片描述
上式表明,对 f ( x , y ) f(x, y) f(x,y) 旋转 θ 0 θ_0 θ0 对应于将其傅里叶变换 F ( u , v ) F(u, v) F(u,v) 也旋转 θ 0 θ_0 θ0。类似地,对 F ( u , v ) F(u, v) F(u,v) 旋转 θ 0 θ_0 θ0 也对应于将其傅里叶反变换 f ( x , y ) f(x, y) f(x,y) 旋转 θ 0 θ_0 θ0
在这里插入图片描述
将图像在图像空间旋转一定的角度,其傅里叶变换则在频谱空间旋转相应的角度。

3、尺度定理

傅里叶变换的尺度定理也称相似定理,它给出傅里叶变换在尺度(放缩)变化时的性质,可用下两式表示(其中 a 和 b 均为标量):
在这里插入图片描述

上两式表明,对 f ( x , y ) f(x, y) f(x,y) 在幅度方面的尺度变化导致对其傅里叶变换 F ( u , v ) F(u, v) F(u,v) 在幅度方面的对应尺度变化,而对 f ( x , y ) f(x, y) f(x,y) 在空间尺度方面的放缩则导致对其傅里叶变换 F ( u , v ) F(u, v) F(u,v) 在频域尺度方面的相反放缩。对 $f(x, y)¥ 的收缩(对应a>1,b>1)不仅导致 F ( u , v ) F(u, v) F(u,v) 的膨胀,而且会使 F ( u , v ) F(u, v) F(u,v) 的幅度减小。

在这里插入图片描述
4、卷积定理

卷积定理指出:两个函数在空间的卷积与它们的傅里叶变换在频域的乘积构成一对变换,而两个函数在空间的乘积与它们的傅里叶变换在频域的卷积构成一对变换。
在这里插入图片描述

5、相关定理

相关定理指出:两个函数在空间的相关与它们的傅里叶变换(其中一个为其复共轭)在频域的乘积构成一对变换,而两个函数(其中一个为其复共轭)在空间的乘积与它们的傅里叶变换在频域的相关构成一对变换。即
在这里插入图片描述

如果f(x)和g(x)是同一个函数,称为自相关;如果f(x)和g(x)不是同一个函数,称为互相关。

5 傅里叶变换特性

在这里插入图片描述
上式中, e x p [ ‒ j 2 π ( u x + v y ) / N ] / N exp[‒j2π(ux+vy)/N]/N exp[j2π(ux+vy)/N]/N e x p [ j 2 π ( u x + v y ) / N ] / N exp[j2π(ux+vy)/N]/N exp[j2π(ux+vy)/N]/N 分别是正反傅里叶变换的核。傅里叶变换有许多特性都是由其核所决定的。下面介绍两个常用的特性:可分离性和对称性。
2-D傅里叶变换的可分离性指其变换核中 x x x u u u y y y v v v 可以分离,这可表示成(以正变换核为例,但反变换核也类似):
在这里插入图片描述
2-D傅里叶变换的对称性指傅里叶变换核分离后的两部分具有相同的形式。所以,2-D傅里叶变换的正反变换核都具有可分离性和对称性,傅里叶变换是一种可分离和对称变换。

具有可分离变换核的2-D变换可分成两个步骤计算,每个步骤用一个1-D变换。以2-D傅里叶变换为例:
在这里插入图片描述

首先沿f(x, y)的每一列进行1-D变换得到,然后沿G(x, v)的每一行进行1-D变换得到,这样,为计算一个2-D傅里叶变换,只需要计算两次1-D傅里叶变换。在这里插入图片描述

6 dft() 函数

	/*
     * @param src 输入图像矩阵,可为实数或者虚数;
     * @param dst 输出图像矩阵,其尺寸和类型取决于 flags 参数;
     * @param flags 转换标识, 
     */
    public static void dft(Mat src, Mat dst, int flags);

该函数对一维或二维浮点数组执行正向或反向离散傅里叶变换。
在这里插入图片描述
示例代码:

import org.bytedeco.javacpp.Loader;
import org.junit.Test;
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import java.util.List;
import java.util.*;
public class DftTest{
    static {
        Loader.load(org.bytedeco.opencv.opencv_java.class);
    }

    @Test
    public void dftTest(){
        Mat I = Imgcodecs.imread("images/dog.PNG", Imgcodecs.IMREAD_GRAYSCALE);

        Mat padded = new Mat();                     // 将输入图像扩展到最佳大小

        // 获取图像的傅里叶最优尺寸大小,主要是为了提高运算速度。
        int m = Core.getOptimalDFTSize( I.rows() );
        int n = Core.getOptimalDFTSize( I.cols() );

        // 在边框上添加零值,将图像扩充为最优尺寸;
        Core.copyMakeBorder(I, padded, 0, m - I.rows(), 0, n - I.cols(), Core.BORDER_CONSTANT, Scalar.all(0));

        /*
        * 傅里叶变换的结果复数。这意味着对于每个像素值,结果是两个值。此外,频域范围比空间范围大得多。
        * 因此,通常至少以浮点格式存储这些数据,并用另一个通道将其展开,以保存复数值。
        * */
        List<Mat> planes = new ArrayList<>();
        padded.convertTo(padded, CvType.CV_32F);
        planes.add(padded);
        planes.add(Mat.zeros(padded.size(), CvType.CV_32F));
        Mat complexI = new Mat();
        Core.merge(planes, complexI);

        // 执行傅里叶变换
        Core.dft(complexI, complexI); // 输入与输出在相同的 Mat 对象


        // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
        Core.split(complexI, planes);                               // planes.get(0) = Re(DFT(I)
        // planes.get(1) = Im(DFT(I))

        // 计算二维矢量的幅值:幅值 = sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)
        Core.magnitude(planes.get(0), planes.get(1), planes.get(0));
        Mat magI = planes.get(0);
        Mat matOfOnes = Mat.ones(magI.size(), magI.type());
        Core.add(matOfOnes, magI, magI);
        Core.log(magI, magI); // 通过对数转换实现尺度缩放

        // 在扩充边界时,在图像中添加了额外的像素,需要将这部分像素剔除。
        magI = magI.submat(new Rect(0, 0, magI.cols() & -2, magI.rows() & -2));// 如果频谱的行数或列数为奇数,则裁剪频谱
        // 重新排列傅里叶图像的象限,使原点位于图像中心
        int cx = magI.cols()/2;
        int cy = magI.rows()/2;
        Mat q0 = new Mat(magI, new Rect(0, 0, cx, cy));    // Top-Left - Create a ROI per quadrant
        Mat q1 = new Mat(magI, new Rect(cx, 0, cx, cy));      // Top-Right
        Mat q2 = new Mat(magI, new Rect(0, cy, cx, cy));      // Bottom-Left
        Mat q3 = new Mat(magI, new Rect(cx, cy, cx, cy));         // Bottom-Right
        Mat tmp = new Mat();               // 交换象限:左上与右下互换
        q0.copyTo(tmp);
        q3.copyTo(q0);
        tmp.copyTo(q3);
        q1.copyTo(tmp);                    // 交换象限:左上与右下互换
        q2.copyTo(q1);
        tmp.copyTo(q2);
        magI.convertTo(magI, CvType.CV_8UC1);
        Core.normalize(magI, magI, 0, 255, Core.NORM_MINMAX, CvType.CV_8UC1); // 归一化

        HighGui.imshow("Input Image"       , I   );   
        HighGui.imshow("Spectrum Magnitude", magI);
        HighGui.waitKey();
        System.exit(0);
    }
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值