OpenCV学习----深入理解双边滤波器实现
2017-04-09 15:30
459 查看
前沿
和高斯滤波器相似,双边滤波器也是需要先求出系数,然后在图像上移动掩模,处理图像。第一步:求权重系数
第二步:确定掩模大小
第三部:移动处理整个图像
双边滤波器
前面介绍的高斯滤波器仅仅是考虑空间种像素点的距离关系,并没有考虑到像素值之间的相似程度。(比如说:黑色的头发与蓝天边缘之间没有相似度)这样导致的图像就是一团模糊,双边滤波器(Bilateral Filter)在高斯滤波器基础上增加了图像像素之间的相似程度的考虑。因而,能很好地保持图像的边缘信息。双边滤波系数
双边滤波器的系数取决于两部分:域核
其中:i-k 是在 x 轴的间距,j-l 是在 y 轴的间距。
值域核
其中:|| f(i , j) - f(k,l) || 是像素点差值的绝对值。
双边滤波器的系数取决于两部分的成积。
双边滤波系数算法实现
这个和求高斯滤波器的系数相似,最后转化为一维矩阵方便后边处理。void GetDistanceWeight(double* kerd) //域核 { int k = n/2; double nkerd ; for(int i=-k; i<=k; i++) { for(int j=-k;j<=k;j++) nkerd[i+k][i+k] = exp(-1.0*(i*i+j*j)/(2*sigmad*sigmad)); } for(int i=0;i<n;i++) //二维矩阵转化为一维矩阵 { for(int j=0;j<n;j++) kerd[n*i+j] = nkerd[i][j]; } }
值域核算法实现
像素值之间的差值在0-255之间,建立 值域核系数表格,后边直接查表格。
void GetSimilarityWwight(double* kers)//值核 { for(int i=0; i<256; i++) { kers[i] =exp(-1.0*(i*i)/(2*sigmar*sigmar)); //出现“exp”重载函数不明确,则添加 -1.0*..... } }
双边滤波器完整代码
#include "opencv2/opencv.hpp" #include"opencv2/highgui/highgui.hpp" #include <iostream> #include <math.h> using namespace cv; using namespace std; #define n 5 #define sigmad 30 #define sigmar 20 void GetDistanceWeight(double* kerd) //域核 { int k = n/2; double nkerd ; for(int i=-k; i<=k; i++) { for(int j=-k;j<=k;j++) nkerd[i+k][i+k] = exp(-1.0*(i*i+j*j)/(2*sigmad*sigmad)); } for(int i=0;i<n;i++) //二维矩阵转化为一维矩阵 { for(int j=0;j<n;j++) kerd[n*i+j] = nkerd[i][j]; } } void GetSimilarityWwight(double* kers)//值核 { for(int i=0; i<256; i++) { kers[i] =exp(-1.0*(i*i)/(2*sigmar*sigmar)); } } void BilateralFilter(Mat& src, Mat& dst, double* kerd,double* kers) { dst = src.clone(); int row = dst.rows; int col = dst.cols; int channal = dst.channels(); int ncol = col * channal; int k = n/2; double piexl_sum ; int index; double kernal[n*n]; double temp = 0; double weight_sum=0; for (int i = k; i < (row-k) ; i++) //n/2保证边缘的像素点不被处理 { uchar* ptdst = dst.ptr<uchar>(i); uchar* ptsrc = src.ptr<uchar>(i); for (int j = channal*k;j < (ncol-channal*k); j++) //n/2保证边缘的像素点不被处理 { index =0; piexl_sum = weight_sum =0; for (int kx = (i-k);kx <= i+k; kx++) //内层 kx、ky循环求和 { uchar* ptrsrc = src.ptr<uchar>(kx); for (int ky = (j-channal*k);ky <=(j+channal*k); ky = (ky+channal)) { temp = kerd[index++]*kers[(int)abs(ptsrc[j]-ptrsrc[ky])]; piexl_sum += (ptrsrc[ky]*temp); weight_sum += temp; } } piexl_sum /= weight_sum; //归一化 ptdst[j] =saturate_cast<uchar>(piexl_sum); } } } int main() { Mat src,dst,dst1; double kerd[n*n]; double kers[256]; src =imread("D:/456677.jpg"); if(!src.data) { cout<<"Picture loading failed !"<<endl; return -1; } namedWindow("Win1"); imshow("Win1", src); GetDistanceWeight(kerd); GetSimilarityWwight(kers); BilateralFilter(src,dst,kerd,kers); namedWindow("Win2"); imshow("Win2", dst); bilateralFilter(src,dst1,7,50,3); namedWindow("Win3"); imshow("Win3", dst1); waitKey(0); return 0; }
对彩色图像进行处理结果:
对灰度图像进行处理:
快速双边滤波器
参考
http://blog.csdn.net/fightingforcv/article/details/50491461http://blog.csdn.net/abcjennifer/article/details/7616663
相关文章推荐
- [置顶] Servlet深入学习,规范,理解和实现(中)——深入理解Tomcat(一)
- 【深入理解Java虚拟机】------ 学习0304 HotSpot的算法实现
- [置顶] Servlet深入学习,规范,理解和实现(上)
- Servlet深入学习,规范,理解和实现(上)
- 软件行业有希望,近百人学习《GJB5000A深入理解与实现》
- Servlet深入学习,规范,理解和实现(中)——深入理解Tomcat(一)
- JDK学习---深入理解java中的HashMap、HashSet底层实现
- OpenCV学习——物体跟踪的粒子滤波算法实现之粒子集合变换
- Java学习过程中应该深入理解的一些重点
- C#学习笔记二:用实例深入理解装箱、拆箱
- OpenCV学习——物体跟踪的粒子滤波算法实现之计算选定区域直方图
- 深入剖析ExtJS 2.2实现及应用连载(4):如何学习ExtJS
- OpenCV中滤波器学习笔记(一)--CvSepFilter
- Java学习过程应该深入理解的一些重点
- OpenCV学习——物体跟踪的粒子滤波算法实现之命令行参数处理
- OpenCV学习——物体跟踪的粒子滤波算法实现之设定随机数
- 学习《深入理解C++对象模型》小结
- Java学习过程中应该深入理解的一些重点
- 深入理解计算机系统学习笔记(一)之此书简介
- 《深入理解LINUX内存管理》学习笔记 (四)