积分图的快速实现

在积分图中,每个点的值是位于其左上角所有像素值得和,所以,如果原图的宽和高是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之内):






 
 
 

猜你喜欢

转载自blog.csdn.net/myzhouwang/article/details/79905882