积分图像(Integral image)

简介: 积分图算法由Crow在1984年首次提出,是为了在多尺度透视投影中提高渲染速度。积分图算法是一种快速计算图像区域和以及图像区域平方和的算法。它的核心思想就是对每一个图像建立起自己的积分图查找表,在图像处理的阶段就可以根据预先建立积分图查找表直接查找从而实现对均值卷积的线性时间计算。做到了卷积执行的时间与窗口大小无关。之前介绍的NL-means算法就可以采用积分图算法进行优化加速。

从直观来说,一张图像就是一个矩形,这个矩形中每个像素点的积分值,就是以图像左上角像素点为左上角顶点,以该像素点为右下角顶点的矩形中包含的所有元素之和。如下图所示,点(x,y)处的积分值为矩形区域中所有像素之和(包括该点)。

65303aa9ff8e4a02b89bcf64d63a1318.jpg

实际计算积分图的时候,为了提高计算效率,通常不会对每一个像素点都重新计算矩形区域包含的所有元素值之和,而是利用相邻点的积分值实现快速计算,如下图所示,点(x,y)的积分值可以使用点(x-1,y)与点(x,y-1)的积分值之和,然后减去重叠区域,也就是减去点(x-1,y-1)的积分值,最后再加上点(x,y)的像素值得到点(x,y)的积分值。

f946faeb710542369f0042807ffdaf68.jpg

上述原理用公式表示为:

I(x,y) = I(x-1,y) + I(x,y-1) - I(x-1,y-1) + pixel(x,y)

此外还需要考虑边界问题,也就是第一行和第一列的计算。

对于第一行:

I(0,0) = pixel(0,0),x=0,y=0

I(x,0) = I(x-1,0) + pixel(x,0),x>0,y=0

对于第一列:

I(0,y) = I(0,y-1) + pixel(0,y),x=0,y>0


根据上述原理,基于OpenCV与C++的实现代码如下:

voidIntegral(Matsrc, Mat&integal_out)
{  
Mattmp(src.size(), CV_64FC1, 0.0);
tmp.ptr<double>(0)[0] = (double)src.ptr<uchar>(0)[0];
for(inti=1; i<src.cols; i++)   //第一行    {
tmp.ptr<double>(0)[i] =tmp.ptr<double>(0)[i-1] +src.ptr<uchar>(0)[i];
    }
for(inti=1; i<src.rows; i++)  //第一列    {
tmp.ptr<double>(i)[0] =tmp.ptr<double>(i-1)[0] +src.ptr<uchar>(i)[0];
    }
for(inti=1; i<src.rows; i++)   //第i行    {
for(intj=1; j<src.cols; j++)   //第j列       {
tmp.ptr<double>(i)[j] =tmp.ptr<double>(i)[j-1] +tmp.ptr<double>(i-1)[j] -tmp.ptr<double>(i-1)[j-1] +src.ptr<uchar>(i)[j];
        }
    }
tmp.copyTo(integal_out);
}

参考OpenCV的官方文档:

C++: voidintegral(InputArrayimage, OutputArraysum, intsdepth=-1Parameters: 
imageSourceimageasWXH  , 8-bitorfloating-point (32for64f).
sumIntegralimageas (W+1) X (H+1) ,
32-bitintegerorfloating-point (32for64f).
sdepthDesireddepthoftheintegralandthetiltedintegralimages,
CV_32S, CV_32F, orCV_64F.

发现为了能容纳最后一列和最后一行的情况,最终的积分图就应该是 (W + 1) X (H + 1)大小,如下图所示,假设输入图像大小为2x2,则积分图大小为3x3:

80931244fc6546b1be3be4483246bc6a.png

OpenCV官方提供两种积分图函数integral(),可以直接调用:

//API一voidintegral( InputArraysrc,     //输入图像OutputArraysum,    //和表intsdepth=-1,);  //和表深度//API二voidintegral( InputArraysrc,     //输入图像OutputArraysum,    //和表OutputArraysqsum,  //平方和表intsdepth=-1,    //和表深度,一般为CV_32Sintsqdepth=-1 ); //平方和表深度,一般为CV_32F

OpenCV实现过程:

#include <opencv2/opencv.hpp>usingnamespacestd;
usingnamespacecv;
intmain() {
Matsrc, sum, sqrsum;
src=imread("1.png", 0);
integral(src, sum, sqrsum, CV_32S, CV_32F);
normalize(sum, sum, 0, 255, NORM_MINMAX, CV_8UC1, Mat());
normalize(sqrsum, sqrsum, 0, 255, NORM_MINMAX, CV_8UC1, Mat());
imshow("原图", src);
imshow("和表积分图", sum);
imshow("平方和表积分图", sqrsum);
waitKey(0);
return0;
}

我们还可以对兴趣区域(ROI)内的像素求和或者平方和:

#include <opencv2/opencv.hpp>usingnamespacestd;
usingnamespacecv;
intget_block_sum(Mat&sum, intx1, inty1, intx2, inty2);
intmain() {
Matsrc, sum, sqrsum;
src=imread("1.png", 0);
//获取ROI,便于观察(使用ImageWatch插件)intLR=4;
intLC=4;
intwidth=6;
intheight=6;
Matroi=src(Rect(LR, LC, width, height)).clone();   
//计算积分图integral(src, sum, sqrsum, CV_32S, CV_32F);
//利用积分图计算ROI内的像素值总和intvalue=get_block_sum(sum, LR, LC, LR+height, LC+width);
cout<<value<<endl;
imshow("原图", src);        
waitKey(0);
return0;
}
intget_block_sum(Mat&sum, intx1, inty1, intx2, inty2) {
intBottomRight=sum.at<int>(x2, y2);
intTopLeft=sum.at<int>(x1, y1);
intTopRight=sum.at<int>(x1, x2);
intBottomLeft=sum.at<int>(x2, y1);
intsum_value= (BottomRight+TopLeft-TopRight-BottomLeft);
returnsum_value;
}
相关文章
|
JSON 数据格式 开发者
Postman模仿GET/POST请求进行接口的本地测试
接口是软件开发中常用的概念,是软件生产过程中比较核心的任务。对于接口开发者,调试接口是一件较为繁琐的事情,很多时候需要线上线下来回切换。在这里,我就跟大家介绍一个只需要在本地就可以调试接口的方法。
723 0
|
存储 缓存 C语言
TCM、ITCM、DTCM
TCM、ITCM、DTCM
1675 0
|
算法 C++
OpenCV-白平衡(灰度世界算法)
OpenCV-白平衡(灰度世界算法)
810 0
|
云计算
Matlab中读取txt文件的几种方法
Matlab中读取txt文件的几种方法 matlab读取文本文件的几种函数: 1、load——适合读取纯数据文本; 2、importdata——只读取数据,自动省略数据格式前后的字符,超大文件不适合; 3、textread、textscan——适合读取行列规整的文本,会存到元胞中,可通过he.
33878 0
|
算法 Java 计算机视觉
图像处理之积分图算法
图像处理之积分图算法
293 2
|
9月前
|
人工智能 程序员 测试技术
AI编程:Coze + Cursor实现一个思维导图的浏览器插件
本文是小卷关于AI编程工具学习的第3篇文章,通过开发一个思维导图生成工具,详细介绍了AI编程的完整流程。从需求分析、插件选择(如Coze的TreeMind),到创建测试工作流、发布API,再到整合API和开发浏览器插件,最终实现了用户选中文字后生成思维导图的功能。文章展示了如何利用现有工具高效开发,并总结了AI编程的优势与未来趋势。
979 14
|
数据挖掘 索引 Python
数据分析缺失值处理(Missing Values)——删除法、填充法、插值法
数据分析缺失值处理(Missing Values)——删除法、填充法、插值法
1742 2
|
开发工具 git 开发者
掌握版本控制的艺术:Git 与 GitHub 的高效使用指南
在软件开发中,版本控制对于代码管理和团队协作至关重要。本文详细介绍了 Git 的核心概念与命令,包括初始化、创建仓库、文件跟踪、分支管理和远程仓库操作。同时,探讨了如何利用 GitHub 进行项目组织、代码审查及自动化工作流。通过遵循最佳实践,如频繁提交、清晰的信息记录和合理使用分支,开发者可以提升工作效率和团队协作能力,确保项目的持续成功。
|
机器学习/深度学习 算法 Go
YOLOv5网络结构解析
YOLOv5网络结构解析
|
安全 Java C++
CAS自旋锁到底是什么?为什么能实现线程安全?
本文是博主对多线程学习总结记录,希望对大家有所帮助。
1507 0
CAS自旋锁到底是什么?为什么能实现线程安全?