计算积分图

积分图是为了加速计算HAAR特征值,积分图中每个点的值代表“积分”,即计算相应矩形框中所有像素的累积和。该矩形框的左上角为图像原点,右下角为图像每一点的位置。积分图比原图多一行和一列,分别对应原图像最上面和最左面,即最上面对应以最上面的点为矩形框右下角,此时累积和都为0;最左面对应以最左面的点为矩形框右下角,此时累积和也都为0。

 

为了方便计算积分图,每一点的值为以下二者的和:

1.  该点上一行对应位置的积分值

2.  该点所在行从起点到该点的累积和

该点的积分值为上述二者之和

 

//下面函数中的cn为图像的通道数,即channels,sum为求的积分图,src为原图

template<typename T, typename ST, typename QT>

void integral_( const T* src, size_t _srcstep, ST* sum, size_t _sumstep,

                QT* sqsum, size_t _sqsumstep, ST* tilted, size_t _tiltedstep,

                Size size, int cn ){

    int x, y, k;

 

    int srcstep = (int)(_srcstep/sizeof(T)); //src图每一行的元素个数

    int sumstep = (int)(_sumstep/sizeof(ST)); //sum图每一行的元素个数

    int tiltedstep = (int)(_tiltedstep/sizeof(ST));

    int sqsumstep = (int)(_sqsumstep/sizeof(QT));

 

    size.width *= cn; //原图像每一行的所有元素个数

 

    memset( sum, 0, (size.width+cn)*sizeof(sum[0])); //积分图第一行的元素置为0,积分图比原图多一列和多一行,size.width为原图的宽度,因此积分图的宽度为size.width+cn

    sum += sumstep + cn;//积分图第二行的第二个元素,这里从一开始计数

 

    if( sqsum ){

        memset( sqsum, 0, (size.width+cn)*sizeof(sqsum[0]));

        sqsum += sqsumstep + cn;

    }

 

    if( tilted ){

        memset( tilted, 0, (size.width+cn)*sizeof(tilted[0]));

        tilted += tiltedstep + cn;

    }

 

if( sqsum == 0 && tilted == 0 )

{//遍历原图的全部元素,计算相应的积分值

//原图每行累加srcstep - cn,积分图每行累加 sumstep cn,都是为了下一行的初始指针指向原图

//下一行的第一个元素,积分图的下一行的第二个元素。-cn是因为在每次通道循环计算结束后,src++, //sum++,导致每一行计算完毕后,原图指向该行的第二个元素,积分图指向该行的第三个元素

        for( y = 0; y < size.height; y++, src += srcstep - cn, sum += sumstep - cn )

{

            for( k = 0; k < cn; k++, src++, sum++ )

{  //为实现多通道的积分图,即每次先计算一行中的一个通道的所有积分图

//再计算该行下一个通道的所有积分图

                ST s = sum[-cn] = 0;//每一行的第一个元素,即最左边的元素的所有通道的积分值置0

                for( x = 0; x < size.width; x += cn )

{

                    s += src[x];//计算原图从该行起点(s初始值为0)到对应像素点的累积和

                    sum[x] = sum[x - sumstep] + s;//积分值为上一行对应位置的积分值和

//该点所在行从起点到该点累积和之和。前面将积分图最上面一行置为0,

//就是为第一行计算服务的,方便在第一行计算时找到上一行对应位置的积分值。

                }

            }

        }

    }

    else if( tilted == 0 ){

        for( y = 0; y < size.height; y++, src += srcstep - cn,

                        sum += sumstep - cn, sqsum += sqsumstep - cn ){

            for( k = 0; k < cn; k++, src++, sum++, sqsum++ ){

                ST s = sum[-cn] = 0;

                QT sq = sqsum[-cn] = 0;

                for( x = 0; x < size.width; x += cn ){

                    T it = src[x];

                    s += it;

                    sq += (QT)it*it;

                    ST t = sum[x - sumstep] + s;

                    QT tq = sqsum[x - sqsumstep] + sq;

                    sum[x] = t;

                    sqsum[x] = tq;

                }

            }

        }

    }

    else {

        AutoBuffer<ST> _buf(size.width+cn);

        ST* buf = _buf;

        ST s;

        QT sq;

        for( k = 0; k < cn; k++, src++, sum++, tilted++, buf++ ){

            sum[-cn] = tilted[-cn] = 0;

 

            for( x = 0, s = 0, sq = 0; x < size.width; x += cn ){

                T it = src[x];

                buf[x] = tilted[x] = it;

                s += it;

                sq += (QT)it*it;

                sum[x] = s;

                if( sqsum )

                    sqsum[x] = sq;

            }

 

            if( size.width == cn )

                buf[cn] = 0;

 

            if( sqsum ){

                sqsum[-cn] = 0;

                sqsum++;

            }

        }

 

        for( y = 1; y < size.height; y++ ){

            src += srcstep - cn;

            sum += sumstep - cn;

            tilted += tiltedstep - cn;

            buf += -cn;

 

            if( sqsum )

                sqsum += sqsumstep - cn;

 

            for( k = 0; k < cn; k++, src++, sum++, tilted++, buf++ ){

                T it = src[0];

                ST t0 = s = it;

                QT tq0 = sq = (QT)it*it;

 

                sum[-cn] = 0;

                if( sqsum )

                    sqsum[-cn] = 0;

                tilted[-cn] = tilted[-tiltedstep];

 

                sum[0] = sum[-sumstep] + t0;

                if( sqsum )

                    sqsum[0] = sqsum[-sqsumstep] + tq0;

                tilted[0] = tilted[-tiltedstep] + t0 + buf[cn];

 

                for( x = cn; x < size.width - cn; x += cn ) {

                    ST t1 = buf[x];

                    buf[x - cn] = t1 + t0;

                    t0 = it = src[x];

                    tq0 = (QT)it*it;

                    s += t0;

                    sq += tq0;

                    sum[x] = sum[x - sumstep] + s;

                    if( sqsum )

                        sqsum[x] = sqsum[x - sqsumstep] + sq;

                    t1 += buf[x + cn] + t0 + tilted[x - tiltedstep - cn];

                    tilted[x] = t1;

                }

 

                if( size.width > cn ){

                    ST t1 = buf[x];

                    buf[x - cn] = t1 + t0;

                    t0 = it = src[x];

                    tq0 = (QT)it*it;

                    s += t0;

                    sq += tq0;

                    sum[x] = sum[x - sumstep] + s;

                    if( sqsum )

                        sqsum[x] = sqsum[x - sqsumstep] + sq;

                    tilted[x] = t0 + t1 + tilted[x - tiltedstep - cn];

                    buf[x] = t0;

                }

 

                if( sqsum )

                    sqsum++;

            }

        }

    }

}

 

你可能感兴趣的:(计算积分图)