基于OpenCV底层实现均值滤波,中值滤波和高斯滤波
来源:互联网 发布:为什么是三生万物 知乎 编辑:程序博客网 时间:2024/05/17 20:54
起因:自己也看到一些底层的实现代码,感觉代码质量不高,而且各种指针问题,这里自己实现一下,个人认为实现的还是蛮清晰的。
首先,对于均值滤波和中值滤波不再介绍,code can explain.
对于高斯滤波,其实就是加权平均的过程,中间元素由周围元素的加权平均得到,距离越近,权值越高。
其中这里的u,v表示的是到中心点的距离,这点要注意。
可以看到,其具有sigma一个参数,但是对于我们要使用的模板,需要添加一个窗口大小的参数,因此,根据上面的公式可以生成高斯模板。
const float pi = 3.1415;vector<vector<float>> gaussTemplate(float sigma, int size) { int xcore = size / 2, ycore = size / 2; vector<vector<float>> res; float base = 1.0 / 2 / pi / sigma / sigma; for (int x = 0; x < size; x++) { vector<float>v; for (int y = 0; y < size; y++) { float t1 = (pow(x - xcore, 2) + pow(y - ycore, 2)) / 2.0 / sigma / sigma; float temp = base*exp(-t1); v.push_back(temp); } res.push_back(v); } return res;}
如下生成与维基百科中一样的模板:
0.00000067 0.00002292 0.00019117 0.00038772 0.00019117 0.00002292 0.00000067 0.00002292 0.00078633 0.00655972 0.01330386 0.00655972 0.00078633 0.00002292 0.00019117 0.00655972 0.05472210 0.11098272 0.05472210 0.00655972 0.00019117 0.00038772 0.01330386 0.11098272 0.22508571 0.11098272 0.01330386 0.00038772 0.00019117 0.00655972 0.05472210 0.11098272 0.05472210 0.00655972 0.00019117 0.00002292 0.00078633 0.00655972 0.01330386 0.00655972 0.00078633 0.00002292 0.00000067 0.00002292 0.00019117 0.00038772 0.00019117 0.00002292 0.00000067
下面用代码实现均值滤波,中值滤波和不同的高斯滤波,当然你也可以改变模板的大小,这里给原图像加了椒盐噪声,可以看出中值滤波效果最好,从算法的角度上也可得出这一结论。
#include "opencv2/opencv.hpp"#include "opencv2/opencv_modules.hpp"#include "opencv2/highgui/highgui.hpp"#include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<iomanip>using namespace cv;using namespace std;//添加椒盐噪声void salt(Mat& image, int n) { for (int k = 0; k<n; k++) { int i = rand() % image.cols; int j = rand() % image.rows; if (image.channels() == 1) { //判断是一个通道 image.at<uchar>(j, i) = 255; } else { image.at<cv::Vec3b>(j, i)[0] = 255; image.at<cv::Vec3b>(j, i)[1] = 255; image.at<cv::Vec3b>(j, i)[2] = 255; } }}//中值滤波void medeanFilter(Mat& src, int win_size) { int rows = src.rows, cols = src.cols; int start = win_size/2; for (int m = start; m <rows - start; m++) { for (int n = start; n < cols - start; n++) { vector<uchar> model; for (int i = -start + m; i <= start + m; i++) { for (int j = -start + n; j <= start + n; j++) { //cout << int(src.at<uchar>(i, j)) << endl; model.push_back(src.at<uchar>(i, j)); } } sort(model.begin(), model.end()); //采用快速排序进行 src.at<uchar>(m, n) = model[win_size*win_size/2]; } }}//均值滤波void meanFilter(Mat& src, int win_size) { int rows = src.rows, cols = src.cols; int start = win_size / 2; for (int m = start; m <rows - start; m++) { for (int n = start; n < cols - start; n++) { int sum = 0; for (int i = -start + m; i <= start + m; i++) { for (int j = -start + n; j <= start + n; j++) { sum += src.at<uchar>(i, j); } } src.at<uchar>(m, n) = uchar(sum / win_size / win_size); } }}//生成高斯模板const float pi = 3.1415;vector<vector<float>> gaussTemplate(float sigma, int size) { int xcore = size / 2, ycore = size / 2; vector<vector<float>> res; float base = 1.0 / 2 / pi / sigma / sigma; for (int x = 0; x < size; x++) { vector<float>v; for (int y = 0; y < size; y++) { float t1 = (pow(x - xcore, 2) + pow(y - ycore, 2)) / 2.0 / sigma / sigma; float temp = base*exp(-t1); v.push_back(temp); } res.push_back(v); } return res;}//高斯滤波void gaussFilter(Mat& src,int size,float sigma) { vector<vector<float>> gaussTem = gaussTemplate(sigma,size); int rows = src.rows, cols = src.cols; int start = size / 2; for (int m = start; m <rows - start; m++) { for (int n = start; n < cols - start; n++) { float sum = 0; for (int i = -start + m; i <= start + m; i++) { for (int j = -start + n; j <= start + n; j++) { //cout << gaussTem[i - m + start][j - n + start] << endl; sum += src.at<uchar>(i, j)*gaussTem[i-m+start][j-n+start]; //重点理解!!! } } src.at<uchar>(m, n) = uchar(sum); } }}
测试:
int main(){ Mat src = imread("lena.jpg"); cvtColor(src, src,CV_BGR2GRAY); //中值滤波 Mat dst; src.convertTo(dst, CV_8UC1); salt(dst, 3000); namedWindow("origin"); imshow("origin", dst); medeanFilter(dst,3); namedWindow("median filter"); imshow("median filter", dst); //均值滤波 Mat dst1; src.convertTo(dst1, CV_8UC1); salt(dst1, 3000); meanFilter(dst1, 3); namedWindow("mean filter"); imshow("mean filter", dst1); float sigma = 0.84089642; int size = 7; vector<vector<float>> gaussTem = gaussTemplate(1, 3); for (auto num : gaussTem) { for (auto c : num) cout <<setprecision(8)<<std::fixed << c<< setw(11); cout << endl; cout << endl; } Mat dst2; src.convertTo(dst2, CV_8UC1); salt(dst2, 3000); gaussFilter(dst2, 3, 1); namedWindow("gause"); imshow("gause", dst2); Mat dst3; src.convertTo(dst3, CV_8UC1); salt(dst3, 3000); gaussFilter(dst3, 3, 0.6); namedWindow("gause2"); imshow("gause2", dst3); waitKey(); return 0;}
结果如下图所示:
第一行为均值和中值滤波,都是使用3*3模板
第二行为用高斯滤波不同的模板得来。
参考资料:
1. https://zh.wikipedia.org/wiki/%E9%AB%98%E6%96%AF%E6%A8%A1%E7%B3%8A
2. http://blog.csdn.net/hhygcy/article/details/4329056
1 0
- 基于OpenCV底层实现均值滤波,中值滤波和高斯滤波
- opencv----滤波函数:方框滤波、均值滤波、高斯滤波、中值滤波、双边滤波
- opencv实现图像邻域均值滤波、中值滤波、高斯滤波
- opencv实现图像邻域均值滤波、中值滤波、高斯滤波
- opencv实现图像邻域均值滤波、中值滤波、高斯滤波
- OpenCV 高斯、中值、均值、双边滤波
- 图像滤波----高斯滤波/中值滤波/均值滤波
- python3 利用opencv 添加中值滤波,均值滤波,高斯滤波,高斯双边滤波
- MatLab 均值滤波、中值滤波、高斯滤波
- 均值滤波 中值滤波 高斯平滑滤波
- 图像平滑技术之盒滤波、均值滤波、中值滤波、高斯滤波、双边滤波的原理概要及OpenCV代码实现
- 【拜小白opencv】34-图像平滑处理,6种滤波总结的综合示例【盒式滤波、均值滤波、高斯滤波、中值滤波、双边滤波、导向滤波】
- 方框滤波,高斯滤波,中值滤波,双边滤波,opencv实现
- 高斯滤波、均值滤波、中值滤波、最小均方差滤波、Gabor滤波的优缺点是什么?
- 中值和均值滤波
- [学习opencv]高斯、中值、均值、双边滤波
- OpenCV--图像滤波-方框-均值-高斯-中值-双边
- opencv cvEqualizeHist cvSmooth高斯、均值、中值滤波
- 【推箱子】
- SQLite简介
- (提高篇)进制的转换(数组的练习)
- 原来的麻烦
- mybatis学习总结-核心配置文件mybatis-config.xml(二)
- 基于OpenCV底层实现均值滤波,中值滤波和高斯滤波
- new_learning
- Struts2中#,$,%等符号的使用
- 左值右值
- [51nod 1425]减减数
- super关键字
- 第十一周项目1--(2)二叉树构造算法的验证--由后序序列和中序序列构造二叉树
- matlab之判别分析
- mybatis绑定错误