积分图计算

积分图及其应用

  Paul Viola提出一种利用积分图快速计算Haar特征的方法(《Rapid object detection using a boosted cascade of simple features》)。Haar特征的计算需要重复计算目标区域的像素值,使用积分图能大大减少计算量,达到实时计算Haar特征的目的。简单来说,就是先构造一张“积分图”(integral image),也叫Summed Area Table,之后任何一个Haar矩形特征都可以通过查表的方法(Look Up Table)和有限次简单运算得到,大大减少了运算次数。所以但凡需要重复计算目标区域内像素值和的场合,积分图都能派上用场。

       积分图是图像中十分常用的方法,最初是在Haar特征的快速计算中学到(参考博文:利用积分图像法快速计算Haar特征),后来发现在均值滤波,二值化等图像处理方法中也十分常见。如使用积分图像实现自适应阈值化:

自适应阈值是一种局部方法。它的原理是根据每个像素的邻域(如5x5)计算阈值,如将每个像素的值与指定的邻域的平均值进行比较,如果某像素的值与它的局部平均值差别很大,就会被当作异常值在阈值化过程中被分离。

如若不采用积分图像,则每个像素比较时,都需要进行5x5次加法运算;而采用积分图像,运算复杂度不随邻域大小而改变,每次只需计算2次加法和2次减法。

       积分图像中,每个点存储的是其左上方所有像素之和。因此,积分图像从左上角至右下角越来越亮。

核心API:

void integral( // 积分图计算
    InputArray src, // 输入图像,灰度图
    OutputArray sum, // 求和,输出的尺寸比原图行列都要加1 , 不想行列变化的,自己实现积分图算法
    OutputArray sqsum, // 求和的平方,输出的尺寸比原图行列都要加1
    OutputArray tilted, // 旋转45°的积分图
    int sdepth = -1, 
    int sqdepth = -1 
);

     注意sum这一项的大小: (W + 1) X (H + 1)而非W X H,为什么呢,我们知道,某个点的积分图反应的是原图中此位置左上角所有像素之和,这里是的累加和是不包括这个点像素本身的,那么这样,对于原图的第一行和第一列的所有像素,其对应位置的积分图就应该是0, 这样考虑到所有的像素,为了能容纳最后一列和最后一行的情况,最终的积分图就应该是 (W + 1) X (H + 1)大小。

代码示例:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char** argv) 
{
	Mat src = imread("D:/cv400/data/lena.jpg", 0);
	if (src.empty())
	{
		cout<<"Load image error..."<<endl;
		return -1;
	}
	imshow("input image", src);

	Mat sumii = Mat::zeros(src.rows + 1, src.cols + 1, CV_32FC1);
	Mat sqsumii = Mat::zeros(src.rows + 1, src.cols + 1, CV_64FC1);
	integral(src, sumii, sqsumii);

	Mat iiResult;
	normalize(sumii, iiResult, 0, 255, NORM_MINMAX, CV_8UC1, Mat());
	imshow("Integral Image", iiResult);

	waitKey(0);
	return 0;
}

运行截图:

如预期,图像从左上角至右下角越来越亮。

猜你喜欢

转载自blog.csdn.net/andylanzhiyong/article/details/84726347
今日推荐