写在前面,吐个槽。
离一千米的谱,找个高通滤波程序,c++的,就难找。找到一运行,还有问题。调了一晚上,第二天一看,居然昨晚调对了,但是以为不对把程序删了。
摊手,就逼熊猫摊手。
大佬传送门:OpenCV C++实现频域滤波器汇总 理想低通、理想高通、巴特沃思低通、巴特沃思高通、高斯低通、高斯高通
注:
1)运行环境VS
2)大佬程序是直接复制在编辑器里,会出现不明符号的问题
3)使用的源图像要和main.cpp放在一起
4)滤波后图像被imwrite标准化了,参考imwrite保存的图像都是黑的,这里我只保存gauss_high结果,如何使保存图像不黑乎乎见最下,乘个255
搬运党直取
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
cv::Mat image_make_border(cv::Mat &src)
{
int w = getOptimalDFTSize(src.cols);
int h = getOptimalDFTSize(src.rows);
Mat padded;
copyMakeBorder(src, padded, 0, h - src.rows, 0, w - src.cols, BORDER_CONSTANT, Scalar::all(0));
padded.convertTo(padded, CV_32FC1);
return padded;
}
//频率域滤波
Mat frequency_filter(Mat &scr, Mat &blur)
{
//***********************DFT*******************
Mat plane[] = {
scr, Mat::zeros(scr.size() , CV_32FC1) }; //创建通道,存储dft后的实部与虚部(CV_32F,必须为单通道数)
Mat complexIm;
merge(plane, 2, complexIm);//合并通道 (把两个矩阵合并为一个2通道的Mat类容器)
dft(complexIm, complexIm);//进行傅立叶变换,结果保存在自身
//***************中心化********************
split(complexIm, plane);//分离通道(数组分离)
// plane[0] = plane[0](Rect(0, 0, plane[0].cols & -2, plane[0].rows & -2));//这里为什么&上-2具体查看opencv文档
// //其实是为了把行和列变成偶数 -2的二进制是11111111.......10 最后一位是0
int cx = plane[0].cols / 2; int cy = plane[0].rows / 2;//以下的操作是移动图像 (零频移到中心)
Mat part1_r(plane[0], Rect(0, 0, cx, cy));//元素坐标表示为(cx,cy)
Mat part2_r(plane[0], Rect(cx, 0, cx, cy));
Mat part3_r(plane[0], Rect(0, cy, cx, cy));
Mat part4_r(plane[0], Rect(cx, cy, cx, cy));
Mat temp;
part1_r.copyTo(temp);//左上与右下交换位置(实部)
part4_r.copyTo(part1_r);
temp.copyTo(part4_r);
part2_r.copyTo(temp);//右上与左下交换位置(实部)
part3_r.copyTo(part2_r);
temp.copyTo(part3_r);
Mat part1_i(plane[1], Rect(0, 0, cx, cy));//元素坐标(cx,cy)
Mat part2_i(plane[1], Rect(cx, 0, cx, cy));
Mat part3_i(plane[1], Rect(0, cy, cx, cy));
Mat part4_i(plane[1], Rect(cx, cy, cx, cy));
part1_i.copyTo(temp);//左上与右下交换位置(虚部)
part4_i.copyTo(part1_i);
temp.copyTo(part4_i);
part2_i.copyTo(temp);//右上与左下交换位置(虚部)
part3_i.