积分图实现快速均值滤波
写在前面
在实际应用中,效率是不得不考虑的问题。上一篇博客介绍了均值滤波原理,这一篇就写用积分图实现的快速均值滤波吧。
还是贴一下常规与快速的效率对比吧:
下图是常规均值滤波处理一张分辨率为485*528图像的时间(模板15*15):
下图是积分图快速均值滤波处理的时间(模板15*15):
可以说加速后,速度提升很多。而且最重要的是,用积分图的快速均值滤波受模板变化的影响不大!!!为深刻地体现这一特点,我把模板设置为151*151,可想而知,常规方法的计算量是多么的大!这个时候快速均值滤波的优势是多么的明显!请看下图:
下图是常规均值滤波处理一张分辨率为485*528图像的时间(模板151*151):
下图是积分图快速均值滤波处理的时间(模板151*151):
常规方法都达到了1738ms,快速方法还是3ms左右,惊艳有木有!!!
当然再加上sse优化、openmp+x86循环展开,速度到1ms都有可能吧。可惜我不会,以后再学sse优化吧。
积分图原理
积分图法也分为常规方法和改进方法。先介绍最原始的常规方法。
定义
积分图任意一个位置的值等于原图中该位置左上角所有值的和,即对于R*C图像矩阵的积分图可以定义计算:
举个栗子:
1 | 2 | 3 | 2 | 4 |
0 | 5 | 1 | 7 | 2 |
3 | 1 | 5 | 9 | 8 |
5 | 2 | 6 | 2 | 1 |
1 | 0 | 8 | 5 | 4 |
1 | 3 | 6 | 8 | 12 |
1 | 8 | 12 | 21 | 27 |
4 | 12 | 21 | 39 | 53 |
9 | 19 | 34 | 54 | 69 |
10 | 20 | 43 | 68 | 87 |
而且,积分图只需遍历一次图像即可有效地计算出来,因为积分图每一点(x,y)的值是:
所以,一旦积分图计算完毕,对任意矩形区域的和的计算就可以在常数时间内完成。如下图中,阴影矩形区域的和为:
举个栗子:
1 | 2 | 3 | 2 | 4 |
0 | 5 | 1 | 7 | 2 |
3 | 1 | 5 | 9 | 8 |
5 | 2 | 6 | 2 | 1 |
1 | 0 | 8 | 5 | 4 |
1 | 3 | 6 | 8 | 12 |
1 | 8 | 12 | 21 | 27 |
4 | 12 | 21 | 39 | 53 |
9 | 19 | 34 | 54 | 69 |
10 | 20 | 43 | 68 | 87 |
要求中间红色区域的和,只需对积分图进行如下计算:
也就是:5+1+7+1+5+9+2+6+2 = 54+1-8-9.
应用
积分图可用于快速计算Haar特征、二值化、均值滤波等等一切符合积分图法这一思想的算法。
由于均值滤波原理本质上是计算任意点的邻域内的平均值,而平均值由求和除以面积得到。所以无论如何改变模板大小,都可以利用积分图快速计算出每个点邻域内的和。
改进方法
对于积分图法的改进,有一位图像算法优化大佬给出了办法,图文并茂:13行代码实现最快速最高效的积分图像算法。思想就是不需要由三个位置的积分计算,只需由上方的Inegral(i-1,j)加上当前行的累加和即可,这样又减少了一次运算。这种改进办法比上面常规的方法快1.5倍左右!
代码
代码里包含了两种积分图的计算方法(常规和改进),暂时支持灰度图,RGB图就是每个通道分别计算就行。
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <ctime>//
//积分图-常规方法
//由三个由三个位置的积分计算出来
//对于W*H图像:3*(W-1)*(H-1)次加减法
//
void Im_integral(cv::Mat& src,cv::Mat& dst){int nr = src.rows;int nc = src.cols;dst = cv::Mat::zeros(nr + 1, nc + 1, CV_64F);for (int i = 1; i < dst.rows; ++i){for (int j = 1; j < dst.cols; ++j){double top_left = dst.at<double>(i - 1, j - 1);double top_right = dst.at<double>(i - 1, j);double buttom_left = dst.at<double>(i, j - 1);int buttom_right = src.at<uchar>(i-1, j-1);dst.at<double>(i, j) = buttom_right + buttom_left + top_right - top_left;}}
}//
//积分图-优化方法
//由上方negral(i-1,j)加上当前行的和即可
//对于W*H图像:2*(W-1)*(H-1)次加减法
//比常规方法快1.5倍左右
/
void Fast_integral(cv::Mat& src, cv::Mat& dst){int nr = src.rows;int nc = src.cols;int sum_r = 0;dst = cv::Mat::zeros(nr + 1, nc + 1, CV_64F);for (int i = 1; i < dst.rows; ++i){ for (int j = 1, sum_r = 0; j < dst.cols; ++j){//行累加,因为积分图相当于在原图上方加一行,左边加一列,所以积分图的(1,1)对应原图(0,0),(i,j)对应(i-1,j-1)sum_r = src.at<uchar>(i-1 , j-1) + sum_r; dst.at<double>(i, j) = dst.at<double>(i-1, j)+sum_r;}}
}//积分图快速均值滤波
void Fast_MeanFilter(cv::Mat& src, cv::Mat& dst, cv::Size wsize){//图像边界扩充if (wsize.height % 2 == 0 || wsize.width % 2 == 0){fprintf(stderr, "Please enter odd size!");exit(-1);}int hh = (wsize.height - 1) / 2;int hw = (wsize.width - 1) / 2;cv::Mat Newsrc;cv::copyMakeBorder(src, Newsrc, hh, hh, hw, hw, cv::BORDER_REFLECT_101);//以边缘为轴,对称dst = cv::Mat::zeros(src.size(), src.type());//计算积分图cv::Mat inte;Fast_integral(Newsrc, inte);//均值滤波double mean = 0;for (int i = hh+1; i < src.rows + hh + 1;++i){ //积分图图像比原图(边界扩充后的)多一行和一列 for (int j = hw+1; j < src.cols + hw + 1; ++j){double top_left = inte.at<double>(i - hh - 1, j - hw-1);double top_right = inte.at<double>(i-hh-1,j+hw);double buttom_left = inte.at<double>(i + hh, j - hw- 1);double buttom_right = inte.at<double>(i+hh,j+hw);mean = (buttom_right - top_right - buttom_left + top_left) / wsize.area();//一定要进行判断和数据类型转换if (mean < 0)mean = 0;else if (mean>255)mean = 255;dst.at<uchar>(i - hh - 1, j - hw - 1) = static_cast<uchar> (mean);}}}int main(){cv::Mat src = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\Fig0334(a)(hubble-original).tif");if (src.empty()){return -1;}if (src.channels()>1)cvtColor(src, src, CV_RGB2GRAY);cv::Mat dst;double t2 = (double)cv::getTickCount(); //测时间Fast_MeanFilter(src, dst, cv::Size(151,151));//均值滤波t2 = (double)cv::getTickCount() - t2;double time2 = (t2 *1000.) / ((double)cv::getTickFrequency());std::cout << "FASTmy_process=" << time2 << " ms. " << std::endl << std::endl;cv::namedWindow("src");cv::imshow("src", src);cv::namedWindow("dst");cv::imshow("dst", dst);cv::waitKey(0);}
效果
原图 快速积分图均值滤波(11*11) 经典均值滤波(11*11)
可见,效果上是一样的,但是效率大不一样,开篇已经介绍过了。
积分图实现快速均值滤波相关推荐
- 积分图求局部均值,方差,标准差
积分图求局部均值,方差,标准差 局部 即图像在某个窗口内的值,例如求图像3×3窗口内的均值,方差和标准差 积分图 积分图最重要的作用是快速计算像素值累计,如果公式中包含累加,可以考虑使用积分图的方式. ...
- 图像模糊--快速均值滤波
https://blog.csdn.net/zhonghuan1992/article/details/41131183
- 均值滤波原理及C++实现
写在前面 从均值滤波开始,着手实现各种常用的滤波算法.均值滤波是一种线性滤波.图像的空域滤波无非分为两种,线性滤波和非线性滤波.由于我之前对线性.非线性理解不够清晰,这次就好好总结一下吧. 线性滤波: ...
- 【OpenCV】OpenCV中积分图函数与应用
OpenCV中积分图函数与应用 参考资料 opencv 查找integral,目前网上大部分的资料来自于opencv https://docs.opencv.org/master/d7/d1b/gro ...
- OpenCV中积分图介绍与应用
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 一:图像积分图概念 积分图像是Crow在1984年首次提出,是为了 ...
- NR基础篇上——均值滤波、高斯滤波、双边滤波、NLM
人类的世界就是一个信号传输的世界,所以噪声无处不在,图像作为一种信号传输的方式当然也无法幸免.为了尽量减少噪声对图像质量的影响,还原物体的本来状态就提出了一系列降噪的方法,本文就简单介绍几种常见的降噪 ...
- [Python从零到壹] 五十五.图像增强及运算篇之图像平滑(均值滤波、方框滤波、高斯滤波)
又是一年1024,首先,祝大家节日快乐! 欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界 ...
- 均值滤波计算_图像处理基础均值滤波(模糊)
作者:爱干球的RD 图像处理中,有几种常见的基础算法,比如"模糊"."灰度"."浮雕"."黑白"."底片&qu ...
- 图像处理之积分图应用二(快速边缘保留滤波算法)
图像处理之积分图应用二(快速边缘保留滤波算法) 一:基本原理 传统的图像边缘保留滤波算法-如高斯双边模糊.Mean-Shift模糊等计算复杂.效率比较低,虽然有各种手段优化或者快速计算方法,当时算法相 ...
最新文章
- 【读书笔记】iOS-网络-解析响应负载
- java udp乱码_【Java】Java UDP 套接字编程乱码问题
- 《转载》Java异常处理的10个最佳实践
- mysql 查询表总行数字段_mysql中怎么查询表中的字段个数
- 干货!几招教你降低论文重复率!!
- Spring系列(二):Bean注解用法介绍
- 别了,Docker Swarm !你好,K8s !
- VirtualBox 虚拟机复制
- 内存二三事: Xcode 内存图、Instruments 可视化检测循环引用
- opencv引起的、破坏了电脑系统环境变量的处理办法
- 大学计算机专业分流考试,北京林业大学计算机类(入学一年后分流至计算机科学与技术、数字媒体技术、网络工程、计算机科学与技术(物联网))专业2016年在江苏理科高考录取最低分数线...
- apache log分析
- 解读 | 自监督视觉特征学习综述
- 【Pandas分组聚合】进阶:透视表、交叉表(pivot_table() 、crosstab())
- 手机版kali nethunter刷入
- 使用梯度上升法求解 PCA 问题
- 试用artipub一文多发平台
- 卷积神经网络的网络结构——ResNet
- JVM---数据存储和访问(类文件结构)
- xv6源码解析(一)——系统启动