【OpenCV图像处理】十七、图像的导向滤波
http://blog.csdn.net/qq_34784753/article/details/70229009?locationNum=12&fps=1
导向图滤波是一种图像滤波技术,通过一张引导图G,对目标图像P(输入图像)进行滤波处理,使得最后的输出图像大体上与目标图像P相似,但是纹理部分与引导图G相似。其典型应用有两个:保边图像平滑,抠图。
导向滤波是由何凯明等人在2010年发表在ECCV的文章“Guided Image Filtering”文中提到的,后来陆续发表了改进算法快速导向滤波的实现。导向滤波不仅能够实现双边滤波的边缘平滑,而且在检测到边缘附近有很好的表现,可以应用在图像增强、HDR压缩、图像抠图以及图像去雾等场景中。
导向滤波的实现原理如下:
对于普通的线性变换滤波器,输入图像是I,输出图像是S,导向函数为T,导向滤波定义在像素点j处的滤波结果可以表示为下式:
其中,i,j是图像像素的下标,滤波器核函数Wij是图像的加权系数,景点的双边滤波器核给定如下:
其中x是像素坐标Ki是一个归一化参数
参数σs和σr代表空间相似度以及颜色范围相似度的灵敏性
假设导向滤波器存在线性模型如下:
其中窗口函数Wk是S以I为中心在像素k位置形成的线性变换,叙述ak和bk满足相同的线性系数,为确定线性系数,定义的输出相应q应满足下式:
其中ni表示噪声,局部线性模型确定输入与输出相应的边缘,就可以最小化q与I之间的差异,同事保持原线性变换。
最小化窗口函数Wk:
其中Ψ是一个正则化参数,根据线性变换得到系数ak和bk:
其中μk与σk是导向图像I的窗口wk的均值和方差,|w|是像素的总个数,
其中μk与σk是导向图像I的窗口wk的均值与方差,|w|为像素的总个数,其中
导向滤波实现步骤如下:
(1.利用boxFilter滤波器完成均值计算,其中均值包括导向均值、原始均值、互相关均值以及自相关均值
(2.根据均值计算相关系数参数,包括自相关与互相关方差。
(3.计算窗口线性变换参数系数a、b。
(4.根据公式计算参数a、b的均值。
(5.利用参数得到导向滤波输出矩阵S。
图像的导向滤波操作相关代码如下:
- //图像的导向滤波操作
- #include <iostream>
- #include <opencv2\core\core.hpp>
- #include <opencv2\highgui\highgui.hpp>
- #include <opencv2\imgproc\imgproc.hpp>
- using namespace cv;
- using namespace std;
- //导向滤波器
- Mat guidedfilter(Mat &srcImage, Mat &srcClone, int r, double eps);
- int main()
- {
- Mat srcImage = imread("2345.jpg");
- if (srcImage.empty())
- {
- cout << "读入图片错误!" << endl;
- system("pause");
- return -1;
- }
- //进行通道分离
- vector<Mat>vSrcImage, vResultImage;
- split(srcImage, vSrcImage);
- Mat resultMat;
- for (int i = 0; i < 3; i++)
- {
- //分通道转换成浮点型数据
- Mat tempImage;
- vSrcImage[i].convertTo(tempImage, CV_64FC1, 1.0 / 255.0);
- Mat p = tempImage.clone();
- //分别进行导向滤波
- Mat resultImage = guidedfilter(tempImage, p, 4, 0.01);
- vResultImage.push_back(resultImage);
- }
- //通道结果合并
- merge(vResultImage, resultMat);
- imshow("原图像", srcImage);
- imshow("导向滤波后图像", resultMat);
- waitKey(0);
- return 0;
- }
- Mat guidedfilter(Mat &srcImage, Mat &srcClone, int r, double eps)
- {
- //转换源图像信息
- srcImage.convertTo(srcImage, CV_64FC1);
- srcClone.convertTo(srcClone, CV_64FC1);
- int NumRows = srcImage.rows;
- int NumCols = srcImage.cols;
- Mat boxResult;
- //下面按照步骤进行导向滤波操作
- /
- //步骤一:计算均值
- boxFilter(Mat::ones(NumRows, NumCols, srcImage.type()),
- boxResult,CV_64FC1,Size(r,r));
- //生成导向均值mean_I
- Mat mean_I;
- boxFilter(srcImage, mean_I, CV_64FC1, Size(r, r));
- //生成原始均值mean_P
- Mat mean_P;
- boxFilter(srcClone, mean_P, CV_64FC1, Size(r, r));
- //生成互相关均值mean_IP
- Mat mean_IP;
- boxFilter(srcImage.mul(srcClone), mean_IP,
- CV_64FC1, Size(r, r));
- Mat cov_IP = mean_IP - mean_I.mul(mean_P);
- //生成自相关均值mean_II
- Mat mean_II;
- //应用盒滤波计算相关均值
- boxFilter(srcImage.mul(srcImage), mean_II, CV_64FC1, Size(r, r));
- //步骤二:计算相关系数
- Mat var_I = mean_II - mean_I.mul(mean_I);
- Mat var_IP = mean_IP - mean_I.mul(mean_P);
- //步骤三:计算参数系数a,b
- //a = cov_Ip ./ (var_I + eps);
- Mat a = cov_IP / (var_I + eps);
- //b = mean_p - a .* mean_I;
- Mat b = mean_P - a.mul(mean_I); //这个地方应该是减号,不应该是等号
- //步骤四:计算系数a,b的均值
- Mat mean_a;
- boxFilter(a, mean_a, CV_64FC1, Size(r, r));
- mean_a = mean_a / boxResult;
- Mat mean_b;
- boxFilter(b, mean_b, CV_64FC1, Size(r, r));
- mean_b = mean_b / boxResult;
- //步骤五:生成输出矩阵
- Mat resultMat = mean_a.mul(srcImage) + mean_b;
- return resultMat;
- }
执行程序后,效果如下所示:
下面简单介绍一下在程序中使用到的几个OpenCV中的相关操作:
1.convertTo( )函数
在使用Opencv中,经常会会出现读取一个图片内容后要把图片内容的像素信息转为浮点并把当前的mat作为矩形进行矩阵计算,那么这里就有一个类型转换问题,在OpenCV中有一个函数可以用于类型的相互转换,也就是convertTo函数
函数的声明如下:
- void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
参数说明:
m – 目标矩阵。如果m在运算前没有合适的尺寸或类型,将被重新分配。
rtype – 目标矩阵的类型。因为目标矩阵的通道数与源矩阵一样,所以rtype也可以看做是目标矩阵的位深度。如果rtype为负值,目标矩阵和源矩阵将使用同样的类型。
alpha – 尺度变换因子(可选)。
beta – 附加到尺度变换后的值上的偏移量(可选)。
函数原理:
函数将源矩阵中的像素值转换为目标类型。最后会使用溢出保护函数saturate_cast<> ,以避免转换过程中可能出现的溢出。函数执行下面的运算:
2.mul()函数
Opencv中mul()函数会计算两个Mat矩阵对应位的乘积,所以要求参与运算的矩阵A的行列和B的行列数一致。计算结果是跟A或B行列数一致的一个Mat矩阵。
其相关声明如下:
- MatExpr mul(InputArray m, double scale=1) const;
以简单的情况为例,对于2*2大小的Mat矩阵A和B:
对A和B执行mul运算:
mul函数说明:
1. mul操作不对参与运算的两个矩阵A、B有数据类型上的要求,但要求A,B类型一致,不然报错;
2. Mat AB=A.mul(B),若声明AB时没有定义AB的数据类型,则默认AB的数据类型跟A和B保存一致;
3. 若AB精度不够,可能产生溢出,溢出的值被置为当前精度下的最大值;
【OpenCV图像处理】十七、图像的导向滤波相关推荐
- 《OpenCv视觉之眼》Python图像处理二十一:Opencv图像处理之图像线性变换和非线性变换的方法及原理
本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...
- OpenCv图像处理之图像视频摄像头读取和保存
OpenCv图像处理之图像视频摄像头读取与保存 使用cv::imread()读取图片 使用cv::imwrite()存储图片 使用cv::VideoCapture::open()读取视频 使用cv:: ...
- OpenCV图像处理(十一)---图像梯度
安培定则:也叫右手螺旋定则,是表示电流和电流激发磁场的磁感线方向间关系的定则.通电直导线中的安培定则(安培定则一):用右手握住通电直导线,让大拇指指向电流的方向,那么四指指向就是磁感线的环绕方向:通电 ...
- OpenCv图像处理之图像归一化
OpenCv图像处理之图像归一化 归一化 中心化 标准化 归一化 图像处理中,图像单通道像素值为0~255之间的uchar类型,通常使用min-max归一化将其转化为0~1区间之间,既不会改变数据的分 ...
- 图像处理(七)导向滤波磨皮
导向滤波磨皮的对应文献为:Guided Image Filtering,这个算法速度极其之快,比其他的保边缘磨皮算法都快,甚至快上好几倍.这个算法最初来自于何明凯的图像去雾算法中,现在已然被应用封装与 ...
- matlab导向滤波磨皮,图像处理(七)导向滤波磨皮
导向滤波磨皮的对应文献为:Guided Image Filtering,这个算法速度极其之快,比其他的保边缘磨皮算法都快,甚至快上好几倍.这个算法最初来自于何明凯的图像去雾算法中,现在已然被应用封装与 ...
- Opencv图像处理(图像的线性灰度变换)
图像增强简介 分段线性法变换原理 代码实现和效果预览 疫情期间,楼主作为大三学生每天除了要应付网课和作业之外还得抽出时间准备研究生考试.虽说少了很多时间学习自己喜欢的知识,但近期由于课程作业关系需要在 ...
- Python OpenCV 图像处理之 图像运算和图像位运算知识补充
Python OpenCV 365 天学习计划,与橡皮擦一起进入图像领域吧.本篇博客是这个系列的第 51 篇. 该系列文章导航参考:https://blog.csdn.net/hihell/categ ...
- OpenCV图像处理--将图像裁剪为圆形
1,需求 为了便于项目前端展示用户头像,需要将头像处理为圆形,非圆形区域设置为透明.其实,前端可以在显示的时候处理,但是前端采用WebGL,暂时搞不定,所以由后端进行图像的一次性加工. 于是,我们尝试 ...
最新文章
- 脑机接口和卷积神经网络的初学者指南(二)
- 如何提升研发人员的非技术才能
- 【加】德鲁·卡宾森 - 质量效应3:天罚(2013年6月26日)
- [转]JavaScript ES6 class指南
- Dev Winform 简洁界面模板制作
- python是什么时候发布的_python发布日期
- QDD pricing determination does not trigger - set breakpoint to resolve it
- 大学只待成追忆,只是工作已半年,2016再见
- java office文件加水印_永中Office与统一操作系统UOS完成适配,开辟高效智能办公新领域...
- 深入理解synchronized关键字
- 采购季:云服务不断进化为企业带来更多选择
- Google发布中文名称“谷歌”
- 怀疑Alexa算法调整,清理一批网站
- mysql查看实例下的表_mysql 实例下具体查看库,和表的大小
- 【老生谈算法】matlab实现遗传算法源码——遗传算法
- 在Linux系统中重现黑客帝国经典画面
- Redis进击(二)搭建Redis主从复制服务集群(一主两从、反客为主)【Windows环境】
- Applet 小应用程序查看器 乱码(小方块)
- Python几种主流框架,知道三种你就是大神,干货建议收藏
- Atitit 旅游强县城 名单列表 旅游资源但其实,北上广深大概只占全国面积的0.33%,加上新一线城市,也只是占了全国面积的3%。在剩下的97%的土地上,有着约300个地级市,3000个