在积分图中,每个点的值是位于其左上角所有像素值得和,所以,如果原图的宽和高是W和H,那么积分图的宽和高就是W+1和H+1,且第一行和第一列的值都为0,例子如下图:
积分图的计算也很简单,按照如下公式进行计算:
I(x,y) = I(x, y-1) + srcRowSum(x-1, y-1);
其中,I表示积分图,srcRowSum表示在原图上的行和。示意图如下:
图比较粗糙,希望能看懂,看不懂的看如下代码:
void TongIntergal(u08 *src, f32 *integralImg, s32 width, s32 height)
{
f32 *inteImg = integralImg;
s32 integralH = height + 1;
s32 integralW = width + 1;
u08 *srcExt = (u08 *)malloc(integralH * integralW * sizeof(u08));
u08 *srcExtTem = srcExt;
s32 srcExtIdx = 0;
S32 srcIdx = 0;
for (s32 i = 0; i < height; i ++)
{
memcpy(&srcExtTem[srcExtIdx], &src[srcIdx], width * sizeof(u08));
srcExtIdx += integralW;
srcIdx += width;
}
memset(integralImg, 0, sizeof(f32) * integralW);// set the first row to 0;
s32 idx = 0; for (s32 h = 0; h < integralH; h++)// set the first col to 0;
{
inteImg[idx] = 0.f;
idx += integralW;
}
s32 currentRowIdx = integralW + 1;
s32 upLeftIdx = 0;
s32 upIdx = 0;
for (s32 h = 1; h < integralH; h++)
{
s32 currentPixIdx = currentRowIdx;
s32 rowSum = 0;
upIdx = currentPixIdx - integralW;
upLeftIdx = upIdx - 1;
for (s32 w = 1; w < integralW; w++)
{
rowSum += srcExtTem[upLeftIdx];
inteImg[currentPixIdx] = rowSum + inteImg[upIdx];
currentPixIdx++;
upLeftIdx ++;
upIdx ++;
}
currentRowIdx += integralW;
}
}
void TongIntergalShow(f32 *inteImg, u08 *showImg, s32 width, s32 height)
{
s32 memSize = width * height;
f32 maxValue = 0.f;
for (s32 i = 0; i < memSize; i++)
{
maxValue = maxValue > inteImg[i] ? maxValue : inteImg[i];
}
f32 coe = 255.0f / maxValue;
for (s32 i = 0; i < memSize; i++)
{
showImg[i] = (u08)(inteImg[i] * coe);
}
}
main函数如下:
#include "head.h"
#include "tongmatch.h"
#include "test.h"
void main()
{
Mat frame = imread("C:\\Users\\Administrator\\Desktop\\image\\inputvideo\\6.jpg");
// convert to grey
Mat frameGray(frame.size(), CV_32FC1);
cvtColor(frame, frameGray, CV_BGR2GRAY);
f32 *integralData = (f32*)malloc((frameGray.rows + 1)* (frameGray.cols + 1) * sizeof(f32));
// get the run time
double t = (double)getTickCount();
s32 testTime = 100;
for (s32 i = 0; i < testTime; i++)
{
// get the integral image
TongIntergal(frameGray.data, integralData, frame.cols, frame.rows);
}
t = 1000*((double)getTickCount() - t)/getTickFrequency();
cout << "Time is "<< t / testTime << " milliseconds."<< endl;
// to show
Mat ShowImg(Size(frame.cols + 1, frame.rows + 1), CV_8UC1);
TongIntergalShow(integralData, ShowImg.data, frame.cols + 1, frame.rows + 1);
// display
imwrite("C:\\Users\\Administrator\\Desktop\\image\\inputvideo\\11.jpg",ShowImg);
namedWindow("Extracted frame", 0);
imshow("Extracted frame",frameGray);
namedWindow("积分图", 0);
imshow("积分图",ShowImg);
setMouseCallback("积分图", on_mouseShowGray, &ShowImg);
setMouseCallback("Extracted frame", on_mouseShowRgb, &frame);
while (1)
{
imshow("积分图", ShowImg);
imshow("Extracted frame",frameGray);
waitKey(40);
}
}
结果如下,分别是原图,积分图,以及积分图某点的邻域内的值(范围设定在255之内):