opencv实现频域平滑图像

本文是参考opencv低通滤波器这篇文章改进得到的,地址:http://blog.csdn.net/huangli19870217/article/details/1285661。

关于高通滤波,其实只要在createfilter()函数的基础上改写滤波器的函数表示就行,这样就可以实现了,有兴趣的可以自己试试。

#include<opencv2\core\core.hpp>
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;
//创建低通滤波器
void createfilter(Mat& lowTemp,float fc)
{
	//参数准备
	int i, j;
	int state = -1;
	double tempD;
	float width, height;
	width = lowTemp.cols;
	height =lowTemp.rows;
	float x, y;
	x = width / 2;
	y = height / 2;

	//D0截止频率
	double D0 = fc * min(lowTemp.rows, lowTemp.cols) / 2.0;

	for (i = 0; i < height; i++)
	{
		float* ptr = lowTemp.ptr<float>(i);
		for (j = 0; j < width; j++)
		{
			if (i > y && j > x)
			{
				state = 3;
			}
			else if (i > y)
			{
				state = 1;
			}
			else if (j > x)
			{
				state = 2;
			}
			else
			{
				state = 0;
			}

			switch (state)
			{
			case 0:
				tempD = (double)(i * i + j * j); tempD = sqrt(tempD); break;
			case 1:
				tempD = (double)((height - i) * (height - i) + j * j); tempD = sqrt(tempD); break;
			case 2:
				tempD = (double)(i * i + (width - j) * (width - j)); tempD = sqrt(tempD); break;
			case 3:
				tempD = (double)((height - i) * (height - i) + (width - j) * (width - j)); tempD = sqrt(tempD); break;
			default:
				break;
			}

			//二维高斯低通滤波器传递函数
			//tempD = exp(-0.5 * pow(tempD / D0, 2));
			//ptr[j*2]= tempD;
			//ptr[2*j+1]= tempD;



			//衰减系数为2的二维指数低通滤波器传递函数
			//tempD = exp(-pow(tempD / D0, 2));
			//ptr[j*2]= tempD;
			//ptr[2*j+1]= tempD;

			//2阶巴特沃思低通滤波器传递函数
			//tempD = 1 / (1 + pow(tempD / D0, 2 * 2));
			//ptr[j*2]= tempD;
			//ptr[2*j+1]= tempD;


			//二维理想低通滤波器传递函数
				if(tempD <= D0)
				{
					ptr[j*2] = 1.0;
			    	ptr[j*2+1] = 1.0;
				}
				else
				{
					ptr[j*2] = 0.0;
			    	ptr[j*2+1] = 0.0;
				}
		}
	}
}

int main(int argc, char ** argv)
{
	//【1】以灰度模式读取原始图像并显示
	Mat srcImg = imread("test1.jpg", 0);
	imshow("原始图像",srcImg);
	//【2】将输入图像延扩到最佳的尺寸,边界用0补充
	int m = getOptimalDFTSize(srcImg.rows);
	int n = getOptimalDFTSize(srcImg.cols);
	//将添加的像素初始化为0.
	Mat padded;
	copyMakeBorder(srcImg, padded, 0, m - srcImg.rows, 0, n - srcImg.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分离成几个单通道数组
	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, CV_MINMAX);

	//【10】创建低通滤波器
	Mat lowTemp = Mat(complexI.size(),complexI.type());
	createfilter(lowTemp, 0.3);
	//将复数转换为幅值
	split(lowTemp, planes); // 将多通道数组complexI分离成几个单通道数组
	magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude  
	Mat magFilter = planes[0];
	//进行对数尺度(logarithmic scale)缩放
	magFilter += Scalar::all(1);
	log(magFilter, magFilter);//求自然对数
	//剪切和重分布幅度图象限
	//若有奇数行或奇数列,进行频谱裁剪      
	magFilter = magFilter(Rect(0, 0, magnitudeImage.cols & -2, magnitudeImage.rows & -2));
	//重新排列傅立叶图像中的象限,使得原点位于图像中心  
	int cx1 = magFilter.cols / 2;
	int cy1 = magFilter.rows / 2;
	Mat q01(magFilter, Rect(0, 0, cx1, cy1));   // ROI区域的左上
	Mat q11(magFilter, Rect(cx, 0, cx1, cy1));  // ROI区域的右上
	Mat q21(magFilter, Rect(0, cy1, cx1, cy1));  // ROI区域的左下
	Mat q31(magFilter, Rect(cx1, cy1, cx1, cy1)); // ROI区域的右下
	//交换象限(左上与右下进行交换)
	Mat tmp1;
	q01.copyTo(tmp1);
	q31.copyTo(q01);
	tmp1.copyTo(q31);
	//交换象限(右上与左下进行交换)
	q11.copyTo(tmp1);
	q21.copyTo(q11);
	tmp1.copyTo(q21);
	//归一化,用0到1之间的浮点值将矩阵变换为可视的图像格式
	normalize(magFilter, magFilter, 0, 1, CV_MINMAX);
	imshow("滤波器频谱图", magFilter);

	//【11】频域滤波
	mulSpectrums(complexI, lowTemp, complexI,0);
	//【12】傅里叶反变换
	idft(complexI, complexI, cv::DFT_SCALE);
	//【13】还原原始图像
	split(complexI, planes);
	Mat dft_filter_img;
	dft_filter_img.create(complexI.size(), CV_8UC1);
	planes[0].convertTo(dft_filter_img, CV_8UC1);
	dft_filter_img = dft_filter_img(cv::Rect(0, 0, srcImg.cols, srcImg.rows));//剪切图像

	imshow("低通滤波结果", dft_filter_img);
	waitKey(0);
	return 0;
}

原始图像:


滤波器频谱图:


滤波结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值