Paul Viola和Michael Jones在2001年首次将积分图应用在图像特征提取上,在他们的论文“Rapid Object Detection using a Boosted Cascade of Simple Features”中,积分图被当作一种新的图像特征表征方式,可以把检测的Haar特征非常高效的计算出来,用于实时人脸检测系统。

积分图是一种能够描述全局信息的矩阵表示方法,其构造方式是积分图像上位置(i,j)处的值ii(i,j)是原图像(i,j)左上角方向所有像素的和。

利用积分图可以可以快速的计算图像上某一区域内的像素和,如下图:

Opencv中integral计算积分图_归一化

要计算区域D内的像素和,只需要获取到积分图上1、2、3/4点各自的像素值,分别表述为ii(1)、ii(2)、ii(3)、ii(4),则区域D的像素和=ii(4)+ii(1)-ii(2)-ii(3)。


传统的计算像素和的方式需要遍历区域D内所有的像素,再执行累加,计算量随着区域D面积的增大而增大,而对积分图方式来说,只需要在计算积分图之后,通过简单几次加减运算就可以得到某一区域内“像素和”这一特征,计算速度非常快,并且这种速度的提升效果随着区域面积的增大和计算次数的增多表现的更为明显。


Opencv中使用integral函数计算积分图。


void integral( InputArray src, OutputArray sum, int sdepth=-1 );


第一个参数src,可以使灰度图或RGB彩色图,单通道和三通道均可作为输入,但每个通道的精度必须是8位int或32位、64位浮点型;

第二个参数sum,积分图,若输入src是灰度图,则积分图也是灰度图,若输入src是RGB三通道图,则积分图sum也是RGB三通道彩色。sum的图像深度是32位整型或32位、64位浮点型,这取决于第三个参数sdepth的定义;

第三个参数sdepth,定义积分图的深度(depth),32位整型或者32位、64位浮点型。注意图像的深度跟图像的通道数是无关的,相关概念可以参看这里:Opencv Mat矩阵中data、size、depth、elemSize、step等属性的理解 ;

所以在使用sum之前,声明即可,可以不事先定义Mat矩阵的大小和数据类型。


#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"

using namespace cv;

int main(int argc,char *argv[])
{
Mat image=imread(argv[1]);
//cvtColor(image,image,CV_RGB2GRAY); //原图像是三通道,积分图也是三通道
Mat imageIntegral;
integral(image,imageIntegral,CV_32F); //计算积分图
normalize(imageIntegral,imageIntegral,0,255,CV_MINMAX); //归一化,方便显示
Mat imageIntegralNorm;
convertScaleAbs(imageIntegral,imageIntegralNorm); //精度转换为8位int整型
imshow("Source Image",image);
imshow("Integral Image",imageIntegralNorm);
waitKey();
}



原图:

Opencv中integral计算积分图_灰度图_02


积分图:

Opencv中integral计算积分图_积分图_03


显示的积分图是经过归一化后的。可以看到从左上角到右下角,图像是越来越亮的,也就是说积分图上像素值是越来越大的。


积分图的图像通道数跟原始图像保存一致,当计算积分图的原始图像是彩色图像时,积分图也是彩色图像,这时候积分图计算的不是灰度,而是颜色:

Opencv中integral计算积分图_积分图_04