频率域滤波【4】:带阻滤波

//快速傅里叶变换
void fft2Image(InputArray _src, OutputArray _dst)
{
	//得到Mat类型
	Mat src = _src.getMat();
	//判断位深
	CV_Assert(src.type() == CV_32FC1 || src.type() == CV_64FC1);
	CV_Assert(src.channels() == 1 || src.channels() == 2);
	int rows = src.rows;
	int cols = src.cols;
	//为了进行快速的傅里叶变换,我们经行和列的扩充,找到最合适扩充值
	Mat padded;
	int rPadded = getOptimalDFTSize(rows);
	int cPadded = getOptimalDFTSize(cols);
	//进行边缘扩充,扩充值为零
	copyMakeBorder(src, padded, 0, rPadded - rows, 0, cPadded - cols, BORDER_CONSTANT, Scalar::all(0));
	//快速的傅里叶变换(双通道:用于存储实部 和 虚部)
	dft(padded, _dst, DFT_COMPLEX_OUTPUT);
}
//求傅里叶变换的幅度谱 amplitude spectrum
void amplitudeSpectrum(InputArray _srcFFT, OutputArray _dstSpectrum)
{
	//判断傅里叶变换是两个通道
	CV_Assert(_srcFFT.channels() == 2);
	//分离通道
	vector<Mat> FFT2Channel;
	split(_srcFFT, FFT2Channel);
	//计算傅里叶变换的幅度谱 sqrt(pow(R,2)+pow(I,2))
	magnitude(FFT2Channel[0], FFT2Channel[1], _dstSpectrum);
}
//傅里叶谱的灰度级显示
Mat graySpectrum(Mat spectrum)
{
	Mat dst;
	log(spectrum + 1, dst);
	//归一化
	normalize(dst, dst, 0, 1, NORM_MINMAX);
	//为了进行灰度级显示,做类型转换
	dst.convertTo(dst, CV_8UC1, 255, 0);
	return dst;
}
//求相位谱 phase spectrum
Mat phaseSpectrum(Mat _srcFFT)
{
	//相位谱
	Mat phase;
	phase.create(_srcFFT.size(), CV_64FC1);
	//分离通道
	vector<Mat> FFT2Channel;
	split(_srcFFT, FFT2Channel);
	//计算相位谱
	for (int r = 0; r<phase.rows; r++)
	{
		for (int c = 0; c < phase.cols; c++)
		{
			//实部 虚部
			double real = FFT2Channel[0].at<double>(r, c);
			double imaginary = FFT2Channel[1].at<double>(r, c);
			// atan2 的返回值范围 [0,180] [-180,0]
			phase.at<double>(r, c) = atan2(imaginary, real);
		}
	}
	return phase;
}


//带阻
//枚举类型:理想带阻滤波器,,巴特沃斯带阻滤波器,高斯带阻滤波器
enum BRFILTER_TYPE { IBR_FILTER = 0, BBR_FILTER = 1, GBR_FILTER = 2 };
//构建带阻滤波器
Mat createBRFilter(Size _size, Point center, float _radius, float _bandWidth, int type, int n = 2)
{
	Mat _bpFilter(_size, CV_32FC1);
	int rows = _size.height;
	int cols = _size.width;
	CV_Assert(_bandWidth / 2 <= _radius);
	//构造理想带阻滤波器
	if (type == IBR_FILTER)
	{
		for (int r = 0; r < rows; r++)
		{
			for (int c = 0; c < cols; c++)
			{
				float norm2 = pow(abs(float(r - center.y)), 2) + pow(abs(float(c - center.x)), 2);
				if (sqrt(norm2) <= _radius + _bandWidth / 2 && sqrt(norm2) >= _radius - _bandWidth / 2)
					_bpFilter.at<float>(r, c) = 0;
				else
					_bpFilter.at<float>(r, c) = 1;
			}
		}
	}
	//构造巴特沃斯带阻滤波器
	if (type == BBR_FILTER)
	{
		for (int r = 0; r < rows; r++)
		{
			for (int c = 0; c<cols; c++)
			{
				float norm2 = pow(abs(float(r - center.y)), 2) + pow(abs(float(c - center.x)), 2);
				if (norm2 != pow(_radius, 2))
					_bpFilter.at<float>(r, c) = 1.0 / (1.0 + pow(sqrt(norm2)*_bandWidth / (norm2 - pow(_radius, 2)), 2 * n));
				else
					_bpFilter.at<float>(r, c) = 0;
			}
		}
	}
	//构造高斯带阻滤波
	if (type == GBR_FILTER)
	{
		for (int r = 0; r< rows; r++)
		{
			for (int c = 0; c < cols; c++)
			{
				float norm2 = pow(abs(float(r - center.y)), 2) + pow(abs(float(c - center.x)), 2);
				if (norm2 != 0)
					_bpFilter.at<float>(r, c) = 1.0 - exp(-pow((norm2 - pow(_radius, 2)) / (_bandWidth*sqrt(norm2)), 2));
				else
					_bpFilter.at<float>(r, c) = 1;
			}
		}
	}
	return _bpFilter;
}

//带阻滤波器
Mat brFilter(Mat &src, Mat &F, Point maxLoc, int type, int radius,int bandWid)
{
	Mat brFilter;//带阻滤波器
	Mat F_brFilter;//带阻傅里叶变换
	Mat FbrSpectrum;//带阻傅里叶变换的傅里叶谱灰度级
	Mat result;

	/* -- 第四步:构造带阻滤波器 -- */
	brFilter = createBRFilter(F.size(), maxLoc, radius, bandWid, type);


	/*-- 第六步:带阻滤波器和图像快速傅里叶变换点乘 --*/
	F_brFilter.create(F.size(), F.type());
	for (int r = 0; r < F_brFilter.rows; r++)
	{
		for (int c = 0; c < F_brFilter.cols; c++)
		{
			//分别取出当前位置的快速傅里叶变换和理想带阻滤波器的值
			Vec2f F_rc = F.at<Vec2f>(r, c);
			float lpFilter_rc = brFilter.at<float>(r, c);
			//带阻滤波器和图像的快速傅里叶变换对应位置相乘
			F_brFilter.at<Vec2f>(r, c) = F_rc*lpFilter_rc;
		}
	}

	//带阻傅里叶变换的傅里叶谱
	amplitudeSpectrum(F_brFilter, FbrSpectrum);
	//带阻傅里叶谱的灰度级的显示
	FbrSpectrum = graySpectrum(FbrSpectrum);
	/* -- 第七、八步:对带阻傅里叶变换执行傅里叶逆变换,并只取实部 -- */
	dft(F_brFilter, result, DFT_SCALE + DFT_INVERSE + DFT_REAL_OUTPUT);
	/* -- 第九步:同乘以(-1)^(x+y) -- */
	for (int r = 0; r < result.rows; r++)
	{
		for (int c = 0; c < result.cols; c++)
		{
			if ((r + c) % 2)
				result.at<float>(r, c) *= -1;
		}
	}
	//注意将结果转换 CV_8U 类型
	result.convertTo(result, CV_8UC1, 1.0, 0);
	/* -- 第十步:截取左上部分,大小等于输入图像的大小 --*/
	result = result(Rect(0, 0, src.cols, src.rows)).clone();
	return result;
}

void main()
{	/* -- 第一步:读入图像矩阵 -- */
	Mat image = imread("lena.jpg", 0);
	Mat fI;
	image.convertTo(fI, CV_32FC1);
	/* -- 第二步:每一个数乘以(-1)^(r+c) -- */
	for (int r = 0; r < fI.rows; r++)
	{
		for (int c = 0; c < fI.cols; c++)
		{
			if ((r + c) % 2)
				fI.at<float>(r, c) *= -1;
		}
	}
	/* -- 第三、四步:补零和快速傅里叶变换 -- */
	Mat F;//图像的快速傅里叶变换
	fft2Image(fI, F);
	//傅里叶谱
	Mat amplSpec;
	amplitudeSpectrum(F, amplSpec);
	//傅里叶谱的灰度级显示
	Mat spectrum = graySpectrum(amplSpec);
	//找到傅里叶谱的最大值的坐标
	Point maxLoc;
	minMaxLoc(spectrum, NULL, NULL, NULL, &maxLoc);

	Mat result;
	//低通
	//result  = LPFilter(image, F, maxLoc, 0, 25);

	//高通
	//result = ihpFilter(image, F, maxLoc, 0, 25);

	//带阻
	result = brFilter(image, F, maxLoc, 0, 50, 40);

	cout << "";
}

原图:

傅里叶:

带阻:

反变换:

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
float DigFil(invar, setic) float invar; int setic; /******************************************************************************/ /* Filter Solutions Version 2009 Nuhertz Technologies, L.L.C. */ /* www.nuhertz.com */ /* +1 602-279-2448 */ /* 3rd Order Band Pass Butterworth */ /* Bilinear Transformation with Prewarping */ /* Sample Frequency = 5.000 KHz */ /* Standard Form */ /* Arithmetic Precision = 4 Digits */ /* */ /* Center Frequency = 300.0 Rad/Sec */ /* Pass Band Width = 20.00 Rad/Sec */ /* */ /******************************************************************************/ /* */ /* Input Variable Definitions: */ /* Inputs: */ /* invar float The input to the filter */ /* setic int 1 to initialize the filter to zero */ /* */ /* Option Selections: */ /* Standard C; Initializable; Internal States; Not Optimized; */ /* */ /* There is no requirement to ever initialize the filter. */ /* The default initialization is zero when the filter is first called */ /* */ /******************************************************************************/ /* */ /* This software is automatically generated by Filter Solutions */ /* no restrictions from Nuhertz Technologies, L.L.C. regarding the use and */ /* distributions of this software. */ /* */ /******************************************************************************/ { float sumnum=0.0, sumden=0.0; int i=0; static float states[6] = {0.0,0.0,0.0,0.0,0.0,0.0}; static float znum[7] = { -7.968e-09, 0.0, 2.39e-08, 0.0, -2.39e-08, 0.0, 7.968e-09 }; static float zden[6] = { .992, -5.949, 14.88, -19.86, 14.92, -5.981 }; if (setic==1){ for (i=0;i<6;i++) states[i] = [i] = [i]*invar; return 0.0; } else{ sumnum = sumden = 0.0; for (i=0;i<6;i++){ sumden += states[i]*zden[i]; sumnum += states[i]*znum[i]; if (i<5) states[i] = states[i+1]; } states[5] = invar-sumden; sumnum += states[5]*znum[6]; return sumnum; } }
Python带阻滤波是一种数字信号处理技术,用于在频率域上滤除某一频带内的信号。它基于离散傅立叶变换(DFT)和离散傅立叶逆变换(IDFT)进行实现。 Python中可以使用SciPy库来实现带阻滤波。首先,通过DFT将输入信号转换为频谱表示,然后通过对频谱进行操作来去除指定频带内的信号,最后进行IDFT将处理后的频谱转换回时域信号。 实现Python带阻滤波的关键是设置滤波器的频响特性。常用的带阻滤波器包括巴特沃斯滤波器和切比雪夫滤波器。这些滤波器可以通过SciPy库中的相关函数进行设计和实现。 使用Python带阻滤波的步骤如下: 1. 导入所需的库,例如SciPy的fft和ifft函数。 2. 将原始信号通过fft函数进行DFT转换得到频谱表示。 3. 根据滤波器的设计要求,创建一个滤波器函数。可以使用巴特沃斯或切比雪夫等函数来生成滤波器的频响曲线。 4. 将滤波器函数应用到频谱中,将需要去除的频带设置为0。 5. 使用ifft函数将处理后的频谱进行IDFT转换回时域信号。 6. 得到经过带阻滤波处理后的信号。 需要注意的是,滤波器的设计需要根据具体应用需求进行选择。不同的滤波器设计方和参数设置会产生不同的滤波效果。此外,带阻滤波器在去除频带内的信号同时也可能会引入一些失真,因此在应用中需谨慎选择阻带的位置和带宽。 综上所述,Python带阻滤波是一种基于DFT和IDFT的数字信号处理技术,通过滤波器的设计和频谱操作来去除指定频带内的信号。使用合适的滤波器设计方和参数设置,可以实现对信号的有效去除和滤波处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值