OpenCV离散傅里叶变换

离散傅里叶变换

  • 作用:得到图像中几何结构信息
  • 结论:傅里叶变换后的白色部分(即幅度较大的低频部分),表示的是图像中慢变化的特性,或者说是灰度变化缓慢的特性(低频部分)。
    傅里叶变换后的黑色部分(即幅度低的高频部分),表示图像中快变化的特性,或者说是灰度变化快的特性(高频部分)。

dft()函数

函数原型

void dft(InputArray src, OutputArray dst, int flage=0, int nonzeroRow=0)
  • InputArray 类型的src。输入矩阵,可以为实数或者虚数。
  • OutputArray 类型的dst。函数调用后的运算结果存在这里,其尺寸取决于标识符,也就是第三个参数。
  • int 类型的falgs。转换的标识符,有默认值0,取值可以为表中的结合。

标识符名称 | 意义
-|
DFT_INVERSE | 用一维或二维逆变换代替默认的正向变换。
DFT_SCALE | 缩放比例标识符,输出的结果都会以1/N进行放缩,通常擦很难过会结合DFT_INVERSE一起使用。
DFT_ROWS | 对输入矩阵的每行进行正向或反向的变换,此标识符可以在处理多种矢量的时候用于减小资源的开销,这些处理常常是三维或高位变换等复杂操作
DFT_COMPLEX_OUTPUT | 进行一维或二维复数苏胡祖反变换。这样的结果通常是一个大小相同的复矩阵。如果输入的矩阵有复数的共轭对称性(比如是一个带有DEF_COMPLEX_OUTPUT标识符的正变换结果),便会输出实矩阵。

  • int 类型的nonzeroRows,有默认值0.当此参数设为非零时(最好是取值为想要处理的那一行的值,比如C。rows),函数会假设只有输入矩阵的第一个非零行包含非零元素(没有设置DFT_INVERSE标识符),或只有输出矩阵的一个非零行包含非零元素(设置了DFT_INVERSE标识符)。这样的话,函数就可对其他行进行更高效的处理,以节省时间开销。

返回DFT最优尺寸大小:getOptimalDFTSize()函数

函数原型

int getOptimalDFTSize(int vecsize)
  • int 类型的vecsize,向量尺寸,即图片的rows、cols。

扩充图像边界:copyMakeBorder()函数

函数原型

void copyMakeBorder(InputArray src, OutputArray dst, int top, int bottom, int left, int right, int borderType, const Scalar& value=Scalar())
  • InputArray 类型的src,输入图像,即源图像,填Mat类型的对象即可。
  • OutputArray 类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,需和源图片有一样的尺寸和类型,且size 应该为Size(src.cols+left+right , src.rows+top+bottom)。
  • 接下来的4个参数分别是为int 类型的top、bottom、left、right,分别表示在源图像的四个方向上填充多少像素。
  • 第七个参数,int 类型的 borderType,边界类型,常见取值为BORDER_CONSTANT,可参考borderInterpolate()得到更多细节。
  • 第八个参数,const Scalar& 类型的value,有默认值Scalar(),可以理解为默认值为0。当borderType取值为BORDER_CONSTANT时,这个参数表示边界值。

计算二维矢量的幅值:magnitude()函数

函数原型

void magnitude(InputArray x, InputArray y, OutputArray magnitude)
  • InputArray 类型的x,表示矢量的浮点型X坐标值,也就是实部。
  • InputArray 类型的y,表示矢量的浮点型Y坐标值,也就是虚部。
  • OutputArray 类型的magnitude,输出的幅值,它和第一个参数x有着同样的尺寸和类型。

计算自然对数:log()函数

计算数组元素绝对值的自然对数
函数原型

void log(InputArray src, OutputArray dst)
  • 输入图像
  • 得到的对数值

矩阵归一化:normalize()函数

函数原型

void normalize(InputArray src, OutputArray dst, double alpha=1, double beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray())
  • InputArray 类型的src。输入图像,即源图像,填Mat类的对象即可。
  • OutputArray 类型的dst。函数调用后的运算结果。和源图片有一样的尺寸和类型。
  • double 类型的alpha。归一化后的最大值,默认值1。
  • double 类型的beta。归一化后的最小值,默认值0。
  • int类型的norm_type。归一化类型,有NORM_INF、NORM_L1、NORM_L2和NORM_MINMAX等参数可选,有默认值NORM_12。
  • int 类型的dtype,有默认值-1。当参数去负值时,输出矩阵和src有同样的类型,否则,它和src有同样的通道数,且此时图像深度为CV_MAT_DEPTH (dtype)。
  • InputArray 类型的mask,可选的操作掩膜,有默认值noArray()。

综合示例

#include<core.hpp>
#include<imgproc.hpp>
#include<highgui.hpp>
#include<iostream>
using namespace cv;
using namespace std;


int main()
{
    // 1.以灰度模式读取
    Mat srcImage = imread("..//..//0.jpg",0);
    if (!srcImage.data)
    {
        printf("读入错误");
        return false;
    }
    imshow("原始图像", srcImage);

    // 2.将输入图像延扩到最佳尺寸,边界用0补充
    int m = getOptimalDFTSize(srcImage.rows);
    int n = getOptimalDFTSize(srcImage.cols);
    // 将添加的像素初始化为0。
    Mat padded;
    copyMakeBorder(srcImage, padded, 0, m - srcImage.rows, 0, n - srcImage.cols, BORDER_CONSTANT, Scalar::all(0));

    // 3.为傅里叶变换的结果(实部和虚部)分配空间。
    // 将planes数组组合合并成一个多通道的数组complexI
    Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(),CV_32F) };
    Mat complexI;
    merge(planes, 2, complexI);

    // 4.进行离散傅里叶变换
    dft(complexI, complexI);

    // 5.将复数转换为幅值,即 log(1+sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)
    split(complexI, planes);    //将多通道数组complexI分离成几个单通道数组,[0]=Re,[1]=Im
    magnitude(planes[0], planes[1], planes[0]); //planes[0] = magnitude
    Mat magnitudeImage = planes[0];

    // 6.进行对数尺度(logarithmic scale)缩放
    magnitudeImage += Scalar::all(1);
    log(magnitudeImage, magnitudeImage);    //求自然对数

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

    // 重新排列傅里叶图像中的象限,使得原点位于图像中心
    int cx = magnitudeImage.cols / 2;
    int cy = magnitudeImage.rows / 2;
    Mat q0(magnitudeImage, Rect(0, 0, cx, cy));     //ROI区域的左上
    Mat q1(magnitudeImage, Rect(cx, 0, cx, cy));    //ROI区域的右上
    Mat q2(magnitudeImage, Rect(0, cy, cx, cy));    //ROI区域的左下
    Mat q3(magnitudeImage, Rect(cx, cy, cx, cy));   //ROI区域的右下
    //交换象限(左上与右下进行交换)
    Mat tmp;
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);
    //交换象限(右上与左下进行交换)
    q1.copyTo(tmp);
    q2.copyTo(q1);
    tmp.copyTo(q2);

    // 8.归一化,用0到1之间的浮点值将矩阵变换为可视化的图像格式
    normalize(magnitudeImage, magnitudeImage, 0, 1, NORM_MINMAX);

    // 9.显示效果图
    imshow("频谱幅值", magnitudeImage);
    waitKey();

return 0;
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容