【图像处理】所谓的“快速积分图”,其实并不快

前段时间我开始学习特征提取方面的东西,看到相关的Paper提到了积分图的概念,就自己编码实现了一下

Porikli F. Integral histogram: A fast way to extract histograms in cartesian spaces[C]//Computer Vision and Pattern Recognition, 2005. CVPR 2005. IEEE Computer Society Conference on. IEEE, 2005, 1: 829-836.
Download

这篇Paper中罗里吧嗦给出了一种积分图的快速算法(请原谅我的肤浅,只看懂了灰度特征的积分图),示意图如下:
【图像处理】所谓的“快速积分图”,其实并不快_第1张图片

H(x1,x2,b)=H(x11,x2,b)+H(x1,x21,b)H(x11,x21,b)+Q(f(x1,x2))(1)

他这个公式太高深,咱们就肤浅一点,假如只看灰度特征,意思就是

=++(2)

为了加深理解,请看下图(图是我盗的^_^):
【图像处理】所谓的“快速积分图”,其实并不快_第2张图片

Integral(i,j)=Integral(i,j1)+Integral(i1,j)Integral(i1,j1)+Image(i,j)(3)

如果要求从 (i,j) (i+m,j+n) 两个像素构成的矩形区域的直方图,只需再以上积分图的基础上(此处有误,待修改)

Hist(m,n)(i,j)=Integral(i+m,j+n)Integral(i,j)(4)

即可,非常方便,适用于大量的需要求取局部直方图的场合
但是,仔细看看那个求积分图的过程发现,其实不用分成4部分来进行,只需要2部分就可以了,那就是

=+(5)

这是什么意思呢,请看下图(借的图^_^):
【图像处理】所谓的“快速积分图”,其实并不快_第3张图片

Integral(i,j)=Integral(i,j1)+ColumnSum(j)(6)

(⊙v⊙)嗯,看着还不错哦,貌似一下子简化了很多恩。

(这个概念当初上课时老师提过积分图的概念,也提过原始的算法,更给我们说了这种很简单的算法,还说这个算法他早都发现了,只是没发表论文,不然也会是一片惊天地泣鬼神的作品,,,,这几天当我刚发现这个问题的时候,心里已经万马奔腾了,不错,他在装,,,,)

为什么会是这样呢,,,
想想看,一副 M×N 的图片,从左至右,从上到下的计算积分图,每个像素需要做: 2 ,即复杂度 O(3×M×N)

再看看那个所谓的改进的快速算法,每个像素需要做: 2 ,即复杂度 O(2×M×N)

有问题么??????
有,你把ColumnSum的计算复杂度给吃啦?
这样,把ColumnSum也按照积分图的思想做成累积的形式,,,那么计算ColumnSum的复杂度为 O(M×N) ,为什么是这样?因为你计算ColumnSum是个累计列和的向量啊,长度为 N ,图像总共 M 行,没一行时ColumnSum总得更新吧,,,,
那么那个所谓的改进的快速算法复杂度时多少?
答: O(3×M×N)

那么下面编程实现,并测试一下:

/** * @brief Compute the integral map (The Original Method) * @param pImg * @param width * @param height * @param integmap */
void integralMap(unsigned char *pImg, int width, int height, int *integmap)
{
    int index,sum;
    unsigned char *pCur,*pEnd;
    int *piCur;
    memset(integmap,0,sizeof(int)*width*height);
    //第一行
    for(sum=0,pCur=pImg,pEnd=pImg+width,piCur=integmap;pCur<pEnd;pCur++,piCur++)
    {
        sum+=*pCur;
        *piCur=sum;
    }
    //第一列
    for(sum=0,pCur=pImg,pEnd=pImg+width*height,piCur=integmap;pCur<pEnd;pCur+=width,piCur+=width)
    {
        sum+=*pCur;
        *piCur=sum;
    }
    for(sum=0,index=0,pCur=pImg+width+1,pEnd=pImg+width*height,piCur=integmap+width+1;pCur<pEnd;)
    {
        *piCur=*pCur+*(piCur-1)+*(piCur-width)-*(piCur-width-1);
        index++;
        if(index == width-1)
        {
            piCur+=2;
            pCur+=2;
            index=0;
        }
        else
        {
            pCur++;
            piCur++;
        }
    }
    return;
}
/** * @brief Compute the integral map (The So-Fast Method) * @param pImg * @param width * @param height * @param integmap */
void integralMapFast(unsigned char *pImg, int width, int height, int *integmap)
{
    unsigned char *pCur,*pEnd;
    int *piCur;
    int *colsum,*pc;
    int i,sum;
    colsum = (int*)malloc(sizeof(int)*width);
    memset(colsum,0,sizeof(int)*width);
    memset(integmap,0,sizeof(int)*width*height);
    //第一行
    for(sum=0,pCur=pImg,pEnd=pImg+width,piCur=integmap,pc=colsum;pCur<pEnd;pCur++,piCur++,pc++)
    {
        *pc=*pCur;
        sum+=*pCur;
        *piCur=sum;
    }
    for(i=0,pCur=pImg+width,pEnd=pImg+width*height,piCur=integmap+width,pc=colsum;pCur<pEnd;pCur++,piCur++,pc++)
    {
        if(!i)
        {
            *pc+=*pCur;
            *piCur=*pc;
        }
        else
        {
            *pc+=*pCur;
            *piCur=*pc+*(piCur-1);
        }
        i++;
        if(i==width)
        {
            i=0;
            pc=colsum;
        }
    }
    free(colsum);
    return;
}

下面是测试结果(我用到Ubuntu,可以精确到微秒):
【图像处理】所谓的“快速积分图”,其实并不快_第4张图片
可以看出来,那个所谓的改进的快速算法并不快,反而还要慢,,因为需要为ColumnSum分配空间,还要对其寻址,,,,这都是额外的系统开销,慢是必然的,,,

好了,就酱紫,, ,如果我的算法和理解方法有误,还望不吝指正,我是新手

你可能感兴趣的:(图像处理,积分图)