zoukankan      html  css  js  c++  java
  • opencv之傅里叶变换

    一、离散傅里叶变换

      离散傅里叶变换是高数中的内容了,自己都不大记得具体的原理了,在这里先复习并记录下来,方便以后查阅。英文全称为Discrete Fourier Transform,简称DFT,是指傅里叶变换在时域和频域都呈现离散的形式,将时域的信号采样变换为在离散时间傅里叶变换频域的采样。在形式上做变换的两端的序列是有限长的,实际上这两组序列都应当被认为是离散周期信号的主值序列。即使对有限序列的信号做DTF,也应当对其进行周期延拓成为周期信号在进行变换。通常使用快速傅里叶变换来高效计算DFT。

      对于一张图片进行傅里叶变换就是将它分解为正弦和余弦两部分,以完成从空间域到频域的转换。在转换到频域时以复数的形式存在,因此变换后的结果需要使用实数图像和虚数图像,或者幅度图像加相位图像的形式。但是在实际处理当中仅仅使用了幅度图像(magitude Image),因为幅度图像包含了几乎所有的原图像的几何信息。但是如果想用傅里叶逆变换就需要同时保留幅度图像和相位图像,才能实现对原图像的操作。

      在频域里,对于一幅图像,高频部分代表了图像的、纹理信息;低频部分则代表了图像的轮廓信息。如果图像受到的噪声恰好在某个特定的频率范围内,就可以使用滤波器来恢复原来的图像。因此傅里叶变换在图像处理中可以做到图像增强和去噪、图像分割之边缘检测、图像特征提取和压缩等。

    二、opencv傅里叶变换的处理函数

      ˇdft()函数

    1 void dft(InputArray src, OutputArray dst, int flags = 0, int nonzeroRows = 0);

    ˇ第一个参数:InputArray类型的src,输入矩阵,可以为实数或者虚数。

    ˇ第二个参数:OutputArray类型的dst,运算结果保存在这里,其尺寸和类型取决于第三个参数

    ˇ第三个参数:int类型的flags。转换的标识符,默认值为0,取值可以为:

    1 DFT_INVERSE       -----> 一维或者二维逆变换
    2 DFT_SCALE         -----> 输出结果以1/N进行缩放,通常结合DFT_INVERSE使用
    3 DFT_ROWS        -----> 对输入矩阵的每行进性正向或者逆向变换,用于在处理多种矢量的时候用于减小资源开销,通常用于三维或者高维变换的操作
    4 DFT_COMPLEX_OUTPUT  -----> 进行一维或者二维实数数组的正变换。其结果是复数阵列,拥有复数的共轭对称性也可以写成一个同样尺寸的实数阵列
    5 DFT_REAL_OUTPUT    -----> 进行一维或二维复数数组反变换。其结果是一个同样大小的复矩阵,如果输入的矩阵具有共轭对称性,便会输出实数矩阵

    ˇ第四个参数:默认为0,非0时,函数会假设只有输入矩阵的一个非0行包含非0元素(设置了DFT_INVERSE)或只有输出矩阵的第一个非0行包含非0元素(设置了DFT_INVERSE)。这样的话,函数就可以对其它进行更高效的处理,以节省时间开销,尤其是在计算矩阵卷积时非常有效。

      ˇgetOPtimalDFTSize()返回DFT最优尺寸大小

    1 int getOptimalDFTSize(int vecsize);

    该函数的参数即向量尺寸,图像的rows、cols

      ˇcopyMakeBorder()扩充图像边界

    1 void copyMakeBorder(InputArray src, OutPutArray dst, int top, int bottom, int left, int right, int borderType, const Scalar& value = Scalar());

    ˇ第一个参数:输入的原图像

    ˇ第二个参数:输出结果,需和原图片有一样的尺寸和类型,且size大小为Size(src.cols + left + right, src.rows + top + bottom)

    ˇ第三~六个参数:向四个方向扩充多少像素,例如top = 2;即向上边界扩充两个像素宽度的边界

    ˇ第七个参数:边界类型,常用取值为BORDER_CONSTANT

    ˇ第八个参数:默认值Scalar(),标记BORDER_CONSTANT时,改参数表示边界值

      ˇmagnitude()计算二维矢量的幅值

    1 void magnitude(InputArray x, InputArray y, OutputArray maginute);

    ˇ第一个参数:输入的矢量的浮点型X坐标值,即实部

    ˇ第二个参数:输入的矢量的浮点型Y坐标值,即虚部

    ˇ第三个参数:输出的maginute,与x有相同的尺寸和类型

      ˇlog()计算自然对数

    1 void log(InputArray src, OuyputArray dst);

    ˇ第一个参数:输入的图像

    ˇ第二个参数:得到的对数值

      ˇnormolize()矩阵归一化

    1 void normalize( InputArray src, OutputArry dst, double alpha = 1, double beta = 0, int norm_type = NORM_L2, int dtype = -1, InputArray mask = noArray() );

    ˇ第一个参数:输入的原图像

    ˇ第二个参数:运算结果的存放,与原图像拥有相同大小和类型

    ˇ第三个参数:归一后的最大值,默认为1

    ˇ第四个参数:归一后的最大值,默认为0

    ˇ第五个参数:归一化类型,NORM_L1、NORM_L2、NORM_INF、NORM_MINMUX等

    ˇ第六个参数:默认值-1,此时与src类型相同,若设置大于0折与src尺寸相同

    ˇ第七个参数:可选的操作掩膜,默认noArray()

    三、离散傅里叶变换测试

     1 // DTF.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
     2 //采用傅里叶变换将图片从空间域转换到频域
     3 //
     4 
     5 #include <iostream>
     6 #include <opencv2/core/core.hpp>
     7 #include <opencv2/highgui/highgui.hpp>
     8 #include <opencv2/imgproc/imgproc.hpp>
     9 
    10 using namespace std;
    11 using namespace cv;
    12 
    13 int main(int argc, char** argv)
    14 {
    15     system("color 2f");
    16 
    17     //这里必须是灰度图片
    18     Mat srcImage = imread("1.jpg", 0);
    19     if (!srcImage.data)
    20     {
    21         cout << "载入图片出错" << endl;
    22         return -1;
    23     }
    24     imshow("原图像", srcImage);
    25 
    26     int m = getOptimalDFTSize(srcImage.rows);
    27     int n = getOptimalDFTSize(srcImage.cols);
    28 
    29     Mat padded;
    30     copyMakeBorder(srcImage, padded, 0, m - srcImage.rows, 0, n - srcImage.cols, BORDER_CONSTANT, Scalar::all(0));
    31 
    32     Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
    33     Mat complexI;
    34     merge(planes, 2, complexI);
    35 
    36     dft(complexI, complexI);
    37 
    38     split(complexI, planes);
    39     magnitude(planes[0], planes[1], planes[0]);
    40     Mat magnitudeImage = planes[0];
    41 
    42     magnitudeImage += Scalar::all(1);
    43     log(magnitudeImage, magnitudeImage);
    44 
    45     magnitudeImage = magnitudeImage(Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));
    46     int cx = magnitudeImage.cols / 2;
    47     int cy = magnitudeImage.rows / 2;
    48     Mat q0(magnitudeImage, Rect(0, 0, cx, cy));
    49     Mat q1(magnitudeImage, Rect(cx, 0, cx, cy));
    50     Mat q2(magnitudeImage, Rect(0, cy, cx, cy));
    51     Mat q3(magnitudeImage, Rect(cx, cy, cx, cy));
    52 
    53     Mat tmp;
    54     q0.copyTo(tmp);
    55     q3.copyTo(q0);
    56     tmp.copyTo(q3);
    57 
    58     q1.copyTo(tmp);
    59     q2.copyTo(q1);
    60     tmp.copyTo(q2);
    61 
    62     normalize(magnitudeImage, magnitudeImage, 0, 1, NORM_MINMAX);
    63     imshow("频谱赋值", magnitudeImage);
    64     waitKey();
    65 
    66 
    67     return 0;
    68 }
    View Code

    累了累了休息会

  • 相关阅读:
    python相关的报错处理
    各版本数据库初次登录时,强制修改密码
    机器被感染病毒文件zigw的处理流程
    Let's encrypt申请泛域名证书以及报错处理
    添加/修改保存
    request.getRemoteUser() Spring Security做权限控制后
    hibernate hbm.xml配置映射
    hibernate 注解配置<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/X
    Web.xml配置详解之context-param
    在web.xml中通过contextConfigLocation配置spring
  • 原文地址:https://www.cnblogs.com/shi-win-snoopy/p/12315953.html
Copyright © 2011-2022 走看看