ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenCV笔记19 Fourier Tranformation

2022-02-06 15:58:50  阅读:211  来源: 互联网

标签:19 DFT 变换 channels OpenCV 数组 图像 Fourier 傅里叶


一、简介

图像处理可分为两个部分,空间域(时域)和频域。空间域是直接对图像的像素处理,可以划分为灰度变换和滤波两种方式,灰度变化就是对单一像素的灰度值进行调整,而滤波是对整张图像而言的。下面要介绍频域,这里做个记录,看了一篇表好的博文深入浅出的讲解傅里叶变换(真正的通俗易懂)_l494926429的博客-CSDN博客_傅里叶变换对傅里叶变换有一个基础的认识。可以说,傅立叶变换将原来难以处理的时域信号转换成了易于分析的频域信号(信号的频谱),可以利用一些工具对这些频域信号进行处理、加工。最后还可以利用傅立叶反变换将这些频域信号转换成时域信号。

简单的说傅里叶变化就是静一幅图像分解为两个部分:sinwt 和coswt ,这两个部分对应的都是频域,也就是说把一份图像从空间域转化到频域,在频域中进行处理,然后在转会到空间域,形成一个闭环。频域中的值就是负数。 因此在显示变换结果的时候是将实数图像和虚数图像加到一起,也可是幅度图像(magnitude image)加相位图像(phase image)的形式。其中幅度图像包含了原图像中所需要的大部分信息,所以在图像处理过程中,通常仅使用幅度图像。傅里叶变换的目的是在频域中进行带通处理,去掉干扰,得到理想的图像,然后在用傅里叶逆变换对图像进行还原,这里的还原不是原图像,而是理想的目标图像。因此我们可以用这个技术来做图像压缩、钢铁划痕检测等项目。

二、一维数学推导傅里叶变化

任何连续周期的信号都可以由一组适当的正弦曲线组合而成(--天才说的)。也就是说任何的函数都可以用无限多个sin 和 cos 的和 来逼近, 虽然不知道傅里叶本人是如何想到的,但是我们后来的入学者还是要知道其所以然:

三、二维推导

四、OpenCV中的傅里叶变换

opencv学习(十五)之图像傅里叶变换dft_烟雨博客-CSDN博客_opencv 傅里叶变换

1、dft(离散傅里叶)

void dft(
InputArray src, //输入的图像,可以是实数,也可以是虚数
OutputArray dst, // 输出的图像,器大小要看第三个参数
int flags=0, // 默认是0 
      DFT_INVERSE: 用一维或二维逆变换取代默认的正向变换
      DFT_SCALE: 缩放比例标识符,根据数据元素个数平均求出其缩放结果,如有N个元素,则输出结果以1/N缩放输出,常与DFT_INVERSE搭配使用
	  DFT_ROWS: 对输入矩阵的每行进行正向或反向的傅里叶变换;此标识符可在处理多种适量的的时候用于减小资源的开销,这些处理常常是三维或高维变换等复杂操作
	  DFT_COMPLEX_OUTPUT: 对一维或二维的实数数组进行正向变换,这样的结果虽然是复数阵列,但拥有复数的共轭对称性,可以以一个和原数组尺寸大小相同的实数数组进行填充,这是最快的选择也是函数默认的方法。你可能想要得到一个全尺寸的复数数组(像简单光谱分析等等),通过设置标志位可以使函数生成一个全尺寸的复数输出数组
      DFT_REAL_OUTPUT: 对一维二维复数数组进行逆向变换,这样的结果通常是一个尺寸相同的复数矩阵,但是如果输入矩阵有复数的共轭对称性(比如是一个带有DFT_COMPLEX_OUTPUT标识符的正变换结果),便会输出实数矩阵。
int nonzeroRows=0,默认是0,当这个参数不为0,函数会假设只有输入数组(没有设置DFT_INVERSE)的第一行或第一个输出数组(设置了DFT_INVERSE)包含非零值。这样的话函数就可以对其他的行进行更高效的处理节省一些时间,这项技术尤其是在采用DFT计算矩阵卷积时非常有效。
);

2、getOptimalDFTSize()获取dft变换的最佳宽度、高度

int getOptimalDFTSize(
int vecsize // 输入向量尺寸大小 , DFT变换在一个向量尺寸上不是一个单调函数,当计算两个数组卷积或对一个数组进行光学分析,它常常会用0扩充一些数组来得到稍微大点的数组以达到比原来数组计算更快的目的。一个尺寸是2阶指数(2,4,8,16,32…)的数组计算速度最快,一个数组尺寸是2、3、5的倍数(例如:300 = 5*5*3*2*2)同样有很高的处理效率。
getOptimalDFTSize()函数返回大于或等于vecsize的最小数值N,这样尺寸为N的向量进行DFT变换能得到更高的处理效率。在当前N通过p,q,r等一些整数得出N = 2^p*3^q*5^r.
这个函数不能直接用于DCT(离散余弦变换)最优尺寸的估计,可以通过getOptimalDFTSize((vecsize+1)/2)*2得到。
)

 

#if  1  //   getOptimalDFTSize 的使用

Mat  image_make_border(Mat &src) 
{
	cout << "src.rows: " << src.rows << endl;
	cout << "src.cols: " << src.cols << endl;

	int  w = getOptimalDFTSize(src.cols);  // 获得DFT变换的最优宽度
	int  h = getOptimalDFTSize(src.rows);  // 获得DFT变换的最优高度

	cout << "getOptimalDFTSize. rows:      ----------- " << w << endl; 
	cout << "getOptimalDFTSize .cols:      ----------- " << h << endl; 

	Mat  p;
	//  常量扩充图像的边界  上 下 左  右   
	copyMakeBorder(src, p, 0, h - src.rows, 0, w - src.cols, BORDER_CONSTANT, Scalar::all(0));

	p.convertTo(p,CV_32FC1);

	return p;

}
int main(int argc, char** argv)
{

	Mat src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\602.png", IMREAD_GRAYSCALE);
	imshow("输入图像", src);

	//判断图像是否加载成功
	if (src.empty())
	{
		cout << "图像加载失败!" << endl;
		return -1;
	}
	else
		cout << "图像加载成功!" << endl << endl;


	Mat  p = image_make_border(src);

	imshow("结果: ", p / 255);


	waitKey(0);
	return 0;
}



#endif

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

void magnitude(
InputArray x, // 浮点型数据的x 坐标向量,也就是我们长说的实部
 InputArray y, //  y 的坐标,必须和x 尺寸相同
OutputArray magnitude  // 输出的是一个与x 类型和尺寸相同的输出数组
);

 4 、merge函数用来合并通道

merge(
const Mat* mv,  // 图像矩阵数组
 size_t count,  // 需要合并的矩阵的个数
 OutputArray dst  // 
)

5、split 

split(
	const cv::Mat& mtx, //输入图像
	vector<Mat>& mv // 输出的多通道序列(n个单通道序列)
)

#if  1 //   图像合并与分裂
int main()
{
	Mat src = imread("C:\\Users\\19473\\Desktop\\opencv_images\\601.png");
	imshow("src", src);

	//申请一个三通道的 vector
	vector<Mat> rgbChannels(3);
	split(src, rgbChannels);

	//  显示不同的通道
	Mat blank_ch, fin_img;
	blank_ch = Mat::zeros(Size(src.cols, src.rows), CV_8UC1);

	// Showing Red Channel
	// G and B channels are kept as zero matrix for visual perception
	vector<Mat> channels_r;
	channels_r.push_back(blank_ch);
	channels_r.push_back(blank_ch);
	channels_r.push_back(rgbChannels[2]);

	/// Merge the three channels
	merge(channels_r, fin_img);
	imshow("R", fin_img);


	// Showing Green Channel
	vector<Mat> channels_g;
	channels_g.push_back(blank_ch);
	channels_g.push_back(rgbChannels[1]);
	channels_g.push_back(blank_ch);
	merge(channels_g, fin_img);
	imshow("G", fin_img);


	// Showing Blue Channel
	vector<Mat> channels_b;
	channels_b.push_back(rgbChannels[0]);
	channels_b.push_back(blank_ch);
	channels_b.push_back(blank_ch);
	merge(channels_b, fin_img);
	imshow("B", fin_img);

	waitKey(0);
	return 0;
}
#endif

标签:19,DFT,变换,channels,OpenCV,数组,图像,Fourier,傅里叶
来源: https://blog.csdn.net/weixin_39354845/article/details/122796241

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有