Opencv笔记(13)积分图
积分图时一种允许子区域快速求和的数据结构,这种求和在很多方面都很有用,值得一提的是haar小波的计算,它用于人脸识别和类似的算法。Opencv支持积分图的三种变体,分别是总和、平方求和以及倾斜求和。每种情况的结果图像在图像的每个方向上都加1之后,与原始图像的大小相同。
通过积分图,你可以对图像的任意直立或“倾斜”的矩形区域求和、平均以及标准差。即使目标区域大小不确定,也可以高效进行快速模糊、近似梯度、求均值以及标准差,即使对可变大小的窗口,也可以执行快速块相关。

如果要计算中间区域的像素和,我们可以这样计算398-9-10+1=380。使用四个量就可以对任意矩形区域计算并且将计算复杂度控制为O(1)。
cv::integral()标准求和积分
void integral( InputArray src, OutputArray sum, int sdepth = -1 );
第一个参数和第二个参数是输入图像和输出图像,如果输入图像的大小时W×H,输出图像的大小就是(W+1)×(H+1)。第三个参数sdepth指明求和图像(结果图像)需要的深度。sdepth可以是CV:S32, CV::F32或CV::F64.
cv::integral()平方求和积分
void integral( InputArray src, OutputArray sum, OutputArray sqsum, int sdepth = -1, int sqdepth = -1 );
sqsum参数告诉函数除了标准求和还要计算平方和。与之前一样,sdepth指明目标图像的深度。sdepth可以是CV:S32, CV::F32或CV::F64.
cv::integral()倾斜求和积分
void integral( InputArray src, OutputArray sum, OutputArray sqsum, OutputArray tilted, int sdepth = -1, int sqdepth = -1 );
附加参数titled作为一个附加的项由函数计算而来,其他参数全部相同。
积分图应用(1)——均值滤波
通过利用积分图实现任意窗口大小的均值滤波,代码实现如下:
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int getBlockSum(Mat& sum, int row1,int col1,int row2, int col2) {
int br = sum.at<int>(col2 + 1, row2 + 1);
int tl = sum.at<int>(col1, row1);
int tr = sum.at<int>(col2 + 1, row1);
int bl = sum.at<int>(col1, row2 + 1);
return br + tl - tr - bl;
}
void blur_demo(Mat &src, Mat& dst, int ksize) {
int h = src.rows;
int w = src.cols;
int radius = ksize / 2;
Mat sum;
integral(src, sum, CV_32S);
int row1, col1, row2, col2;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
row1 = i - radius < 0 ? 0 : i - radius;
col1 = j - radius < 0 ? 0 : j - radius;
row2 = i + radius < w ? i + radius : w - 1;
col2 = j + radius < h ? j + radius : h - 1;
dst.at<uchar>(j, i) = (uchar)(getBlockSum(sum, row1, col1, row2, col2)/ ksize/ ksize);
}
}
} int main() {
Mat src = imread("D:/Backup/桌面/1.bmp", 0);
clock_t start, end;
start = clock();
int ksize = 5;
cout << "ksize = " << ksize << endl;
// 均值滤波
Mat dst1;
blur(src, dst1,Size(ksize, ksize),Point(-1,-1), BORDER_CONSTANT);
end = clock();
cout << "blur花费"<< end - start << endl;
// 积分图
start = clock();
Mat dst2 = Mat::zeros(src.size(), CV_8UC1);
blur_demo(src, dst2, ksize);
end = clock();
cout << "积分图花费" << end - start << endl;
return 0;
}
积分图应用(2)——动态阈值分割dyn_threshold
原理: 动态阈值分割是指在图像分割的过程中,不用人为的去设置阈值,而是根据图像中存在的特征,进行分割。一般是将原图像与处理后的图像作差,然后去计算差值图像中的亮色区域或者暗色区域。其本质相当于对图像灰度直方图的平滑,进而求取图像中的波谷或者波峰。
pixel = (pixel > (mean - c)) ? object : background
其中默认情况下参数C取值为0。object表示前景像素,background表示背景像素。
特点: 动态阈值分割具有抗干扰性强,稳定性强的特点,对光照变化不敏感。
- 使用均值滤波+二值化实现动态阈值
int ksize = 7;
Mat mean, sub, dst1;
blur(src, mean, Size(ksize, ksize));
subtract(mean, src, sub);
threshold(sub, dst1, 10, 255, THRESH_BINARY_INV);
- 使用积分图实现动态阈值
/*实现步骤
1. 彩色图像转灰度图像
2. 获取灰度图像的像素数据,预计算积分图
3. 根据输入的参数窗口半径大小从积分图中获取像素总和,求得平均值
4. 循环每个像素,根据局部均值实现中心像素的二值化赋值
5. 输出二值图像*/
void dyn_threshold(Mat &src, Mat& dst, int ksize, int c) {
int h = src.rows;
int w = src.cols;
int radius = ksize / 2;
Mat sum;
integral(src, sum, CV_32S);
int row1, col1, row2, col2;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
row1 = i - radius < 0 ? 0 : i - radius;
col1 = j - radius < 0 ? 0 : j - radius;
row2 = i + radius < w ? i + radius : w - 1;
col2 = j + radius < h ? j + radius : h - 1;
dst.at<uchar>(j, i) = src.at<uchar>(j, i) - (uchar)(getBlockSum(sum, row1, col1, row2, col2) / ksize / ksize) + c>0 ? 255 : 0;
}
}
}
结果:运行时间差不多



积分图应用(3)——var_threshold
var_threshold的分割,非常适用于具有较为复杂背景的标识内容进行分割,它能够对获取指定蒙板大小且具有相同灰度的目标进行分割。
算子的函数签名如下:
var_threshold(Image : Region : MaskWidth, MaskHeight, StdDevScale, AbsThreshold, LightDark : )
其中,MaskWidth、 MaskHeight 定义的过滤器蒙板大小决定了要分割的对象的最大尺寸,但是,如果选择的蒙版太大,则可能会合并非常接近的对象。
StdDevScale 局部标准差用作图像中噪声的度量,它可以通过StdDevScale进行缩放,以反映所需的灵敏度,值越高,表示仅选择与其周围环境截然不同的像素。
AbsThreshold则为目标区域的绝对灰度值,在图像的均匀区域中,标准偏差较低;因此,单个灰度值的影响很大,为了降低在均匀区域中的灵敏度,可以调整AbsThreshold。因此,可以忽略同质环境中的微小灰度值变化。
请注意,对于 StdDevScale 的负值,AbsThreshold 也应选择负值。
lightDark: dark 暗 light 光亮 equal 等于 not_equal 不等于
令g(x,y)为点(x,y)处的灰度值,m(x,y) 为均值,d(x,y) 为方差(实际是标准差),则点(x,y)处的阈值v(x,y)定义为:

当LightDark = ‘light’:时,满足下述条件的点被选中到输出区域

当LightDark = ‘dark’:时,满足下述条件的点被选中到输出区域

当LightDark = ‘equal’:时,满足下述条件的点被选中到输出区域

当LightDark = ‘not_equal’:时,满足下述条件的点被选中到输出区域

代码实现:
void var_threshold(Mat& src, Mat& dst, int StdDevScale, int AbsThreshold, int ksize) {
int h = src.rows;
int w = src.cols;
int radius = ksize / 2;
Mat mean, sub, sum, qsum;
blur(src, mean, Size(ksize, ksize));
subtract(mean, src, sub);
integral(sub, sum, qsum, CV_32S, CV_32S);
int row1, col1, row2, col2;
for (int i = 0; i < w; i++) {
for (int j = 0; j < h; j++) {
row1 = i - radius < 0 ? 0 : i - radius;
col1 = j - radius < 0 ? 0 : j - radius;
row2 = i + radius < w ? i + radius : w - 1;
col2 = j + radius < h ? j + radius : h - 1;
int varthreshold = max(StdDevScale * (int)sqrt(getBlockSum(qsum, row1, col1, row2, col2)) / ksize, AbsThreshold);
dst.at<uchar>(j, i) = src.at<uchar>(j, i) - mean.at<uchar>(j, i) - varthreshold>0?255:0;
}
}
}
参考文献:
Opencv笔记(13)积分图的更多相关文章
- 颜色空间转换 cvtColor()[OpenCV 笔记13]
void cvtColor(InputArray src, OutputArray dst, ) src: 输入图像 dst: 输出图像 code: 颜色空间转换标识符 OpenCV2的CV_前缀宏命 ...
- OpenCv关于灰度积分图的SSE代码学习和改进。
最近一直沉迷于SSE方面的优化,实在找不到想学习的参考资料了,就拿个笔记本放在腿上翻翻OpenCv的源代码,无意中看到了OpenCv中关于积分图的代码,仔细研习了一番,觉得OpenCv对SSE的灵活运 ...
- SSE图像算法优化系列六:OpenCv关于灰度积分图的SSE代码学习和改进。
最近一直沉迷于SSE方面的优化,实在找不到想学习的参考资料了,就拿个笔记本放在腿上翻翻OpenCv的源代码,无意中看到了OpenCv中关于积分图的代码,仔细研习了一番,觉得OpenCv对SSE的灵活运 ...
- Opencv中integral计算积分图
Paul Viola和Michael Jones在2001年首次将积分图应用在图像特征提取上,在他们的论文"Rapid Object Detection using a Boosted Ca ...
- OpenCV笔记大集锦(转载)
整理了我所了解的有关OpenCV的学习笔记.原理分析.使用例程等相关的博文.排序不分先后,随机整理的.如果有好的资源,也欢迎介绍和分享. 1:OpenCV学习笔记 作者:CSDN数量:55篇博文网址: ...
- opencv笔记3:trackbar简单使用
time:2015年 10月 03日 星期六 13:54:17 CST # opencv笔记3:trackbar简单使用 当需要测试某变量的一系列取值取值会产生什么结果时,适合用trackbar.看起 ...
- 机器学习实战 - 读书笔记(13) - 利用PCA来简化数据
前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第13章 - 利用PCA来简化数据. 这里介绍,机器学习中的降维技术,可简化样品数据. ...
- opencv笔记6:角点检测
time:2015年10月09日 星期五 23时11分58秒 # opencv笔记6:角点检测 update:从角点检测,学习图像的特征,这是后续图像跟踪.图像匹配的基础. 角点检测是什么鬼?前面一篇 ...
- opencv笔记5:频域和空域的一点理解
time:2015年10月06日 星期二 12时14分51秒 # opencv笔记5:频域和空域的一点理解 空间域和频率域 傅立叶变换是f(t)乘以正弦项的展开,正弦项的频率由u(其实是miu)的值决 ...
- opencv笔记4:模板运算和常见滤波操作
time:2015年10月04日 星期日 00时00分27秒 # opencv笔记4:模板运算和常见滤波操作 这一篇主要是学习模板运算,了解各种模板运算的运算过程和分类,理论方面主要参考<图像工 ...
随机推荐
- Pytorch-卷积神经网络CNN之lenet5的Pytorch代码实现
先说一个小知识,助于理解代码中各个层之间维度是怎么变换的. 卷积函数:一般只用来改变输入数据的维度,例如3维到16维. Conv2d() Conv2d(in_channels:int,out_chan ...
- i-MES生产制造管理系统-老化时间管控
在生产过程中,产品的可靠性是影响其性能和寿命的关键因素,因此提高产品的可靠性是十分必要的,而老化测试是提高产品可靠性的重要手段之一,老化的时间随着产品不同而变化,因此老化时间管控变得尤为重要! 在ME ...
- FPGA技术助手,notepad++ 两个插件
DS的时间很珍贵的 ,尤其是过了32岁以后,一身的病,扛不住996的制度.为了增加速度,只能想办法怎么在fpga工作上面降低时间.你有心思点来点去的GUI的界面.还不如用一个脚本完全做完.notepa ...
- 力扣445(java&python)-两数相加Ⅱ(中等)
题目: 给你两个 非空 链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储一位数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会以零开头. 示 ...
- HarmonyOS NEXT应用开发实战—组件堆叠
介绍 本示例介绍运用Stack组件以构建多层次堆叠的视觉效果.通过绑定Scroll组件的onScroll滚动事件回调函数,精准捕获滚动动作的发生.当滚动时,实时地调节组件的透明度.高度等属性,从而成功 ...
- 飞天大数据产品价值解读— SaaS模式云数据仓库MaxCompute
飞天大数据产品价值解读 - SaaS模式云数据仓库 MaxCompute摘要:企业在数字化转型过程中面临数据技术平台建设和运营的诸多挑战,随着现代化数据仓库向多功能.服务化方向发展演进,技术侧的变革为 ...
- 网易游戏基于 Flink 的流式 ETL 建设
简介: 网易游戏流式 ETL 建设实践及调优经验分享- 网易游戏资深开发工程师林小铂为大家带来网易游戏基于 Flink 的流式 ETL 建设的介绍.内容包括: 专用 ETL EntryX 通用 ETL ...
- [Linux] IP 地址配置, 网络地址配置文件
# 查看与配置网络状态命令 $ ifconfig # 临时设置 eth0 网卡的 IP 地址与子网掩码,netmask 可以省略 $ ifconfig eth0 192.168.0.100 netma ...
- CF1872G
题意:一个正整数序列,\(a[i] < 10^9\),求 \(l\),\(r\),最大化 \[\sum_{i = 1}^{l - 1} a[i] + \prod_{i = l}^r a[i] + ...
- 【GUI界面软件】抖音评论采集:自动采集10000多条,含二级评论、展开评论!
目录 一.背景说明 1.1 效果演示 1.2 演示视频 1.3 软件说明 二.代码讲解 2.1 爬虫采集模块 2.2 软件界面模块 2.3 日志模块 三.获取源码及软件 一.背景说明 1.1 效果演示 ...