opencv之莫名其妙的条件宏ICV_DEF_FIND_STUMP_THRESHOLD_SQ解释~

来源:互联网 发布:域名国外备案 编辑:程序博客网 时间:2024/05/06 20:08

本博转载自:http://www.itnose.net/detail/6183849.html

曾经有一刻,一直在纠结opencv->haartraining中的条件宏ICV_DEF_FIND_STUMP_THRESHOLD_SQ的使用,该宏的作用是寻找特征值数组中的最佳阈值,使得error最小。

ICV_DEF_FIND_STUMP_THRESHOLD_SQ代码如下:

/* least sum of squares error */#define ICV_DEF_FIND_STUMP_THRESHOLD_SQ( suffix, type )                                  \    ICV_DEF_FIND_STUMP_THRESHOLD( sq_##suffix, type,                                     \        /* calculate error (sum of squares)          */                                  \        /* err = sum( w * (y - left(rigt)Val)^2 )    */                                  \        curlerror = wyyl + curleft * curleft * wl - 2.0F * curleft * wyl;                \        currerror = (*sumwyy) - wyyl + curright * curright * wr - 2.0F * curright * wyr; \    )

其中,ICV_DEF_FIND_STUMP_THRESHOLD定义如下:

#define ICV_DEF_FIND_STUMP_THRESHOLD( suffix, type, error )                              \CV_BOOST_IMPL int icvFindStumpThreshold_##suffix(                                              \        uchar* data, size_t datastep,                                                    \        uchar* wdata, size_t wstep,                                                      \        uchar* ydata, size_t ystep,                                                      \        uchar* idxdata, size_t idxstep, int num,                                         \        float* lerror,                                                                   \        float* rerror,                                                                   \        float* threshold, float* left, float* right,                                     \        float* sumw, float* sumwy, float* sumwyy )                                       \{                                                                                        \    int found = 0;                                                                       \    float wyl  = 0.0F;                                                                   \    float wl   = 0.0F;                                                                   \    float wyyl = 0.0F;                                                                   \    float wyr  = 0.0F;                                                                   \    float wr   = 0.0F;                                                                   \                                                                                         \    float curleft  = 0.0F;                                                               \    float curright = 0.0F;                                                               \    float* prevval = NULL;                                                               \    float* curval  = NULL;                                                               \    float curlerror = 0.0F;                                                              \    float currerror = 0.0F;                                                              \    float wposl;                                                                         \    float wposr;                                                                         \                                                                                         \    int i = 0;                                                                           \    int idx = 0;                                                                         \                                                                                         \    wposl = wposr = 0.0F;                                                                \    if( *sumw == FLT_MAX )                                                               \    {                                                                                    \        /* calculate sums */                                                             \        float *y = NULL;                                                                 \        float *w = NULL;                                                                 \        float wy = 0.0F;                                                                 \                                                                                         \        *sumw   = 0.0F;                                                                  \        *sumwy  = 0.0F;                                                                  \        *sumwyy = 0.0F;                                                                  \        for( i = 0; i < num; i++ )                                                       \        {                                                                                \            idx = (int) ( *((type*) (idxdata + i*idxstep)) );                            \            w = (float*) (wdata + idx * wstep);                                          \            *sumw += *w;                                                                 \            y = (float*) (ydata + idx * ystep);                                          \            wy = (*w) * (*y);                                                            \            *sumwy += wy;                                                                \            *sumwyy += wy * (*y);                                                        \        }                                                                                \    }                                                                                    \                                                                                         \    for( i = 0; i < num; i++ )                                                           \    {                                                                                    \        idx = (int) ( *((type*) (idxdata + i*idxstep)) );                                \        curval = (float*) (data + idx * datastep);                                       \         /* for debug purpose */                                                         \        if( i > 0 ) assert( (*prevval) <= (*curval) );                                   \                                                                                         \        wyr  = *sumwy - wyl;                                                             \        wr   = *sumw  - wl;                                                              \                                                                                         \        if( wl > 0.0 ) curleft = wyl / wl;                                               \        else curleft = 0.0F;                                                             \                                                                                         \        if( wr > 0.0 ) curright = wyr / wr;                                              \        else curright = 0.0F;                                                            \                                                                                         \        error                                                                            \                                                                                         \        if( curlerror + currerror < (*lerror) + (*rerror) )                              \        {                                                                                \            (*lerror) = curlerror;                                                       \            (*rerror) = currerror;                                                       \            *threshold = *curval;                                                        \            if( i > 0 ) {                                                                \                *threshold = 0.5F * (*threshold + *prevval);                             \            }                                                                            \            *left  = curleft;                                                            \            *right = curright;                                                           \            found = 1;                                                                   \        }                                                                                \                                                                                         \        do                                                                               \        {                                                                                \            wl  += *((float*) (wdata + idx * wstep));                                    \            wyl += (*((float*) (wdata + idx * wstep)))                                   \                * (*((float*) (ydata + idx * ystep)));                                   \            wyyl += *((float*) (wdata + idx * wstep))                                    \                * (*((float*) (ydata + idx * ystep)))                                    \                * (*((float*) (ydata + idx * ystep)));                                   \        }                                                                                \        while( (++i) < num &&                                                            \            ( *((float*) (data + (idx =                                                  \                (int) ( *((type*) (idxdata + i*idxstep))) ) * datastep))                 \                == *curval ) );                                                          \        --i;                                                                             \        prevval = curval;                                                                \    } /* for each value */                                                               \                                                                                         \    return found;                                                                        \}

当时觉得很奇怪,内部条件宏ICV_DEF_FIND_STUMP_THRESHOLD括号内明明只有 suffix, type, error 三个参数,怎么调用传递的时候

  ICV_DEF_FIND_STUMP_THRESHOLD( sq_##suffix, type,                                     \        /* calculate error (sum of squares)          */                                  \        /* err = sum( w * (y - left(rigt)Val)^2 )    */                                  \        curlerror = wyyl + curleft * curleft * wl - 2.0F * curleft * wyl;                \        currerror = (*sumwyy) - wyyl + curright * curright * wr - 2.0F * curright * wyr; \

里面却是上面这个样子,前面两个参数,外加两句代码行?

后来弄明白了,我们注意看ICV_DEF_FIND_STUMP_THRESHOLD中的error的相关使用就知道了,在ICV_DEF_FIND_STUMP_THRESHOLD中间,孤零零的一句代码

                                                                                       \        error                                                                            \                                                                                         \

原来error不能说的上是条件宏的一个参数,他就是一个代码段,调用的时候,相当于直接把代码段粘贴到上面的位置!

为啥要这么用呢,原因就是error代表的代码段,复用率十分高,所以索性直接写成这样的形式,C语言,真的是灵活异常哎。。。。

类似的宏还有:

ICV_DEF_FIND_STUMP_THRESHOLD_MISC( 16s, short )ICV_DEF_FIND_STUMP_THRESHOLD_MISC( 32s, int )ICV_DEF_FIND_STUMP_THRESHOLD_MISC( 32f, float )ICV_DEF_FIND_STUMP_THRESHOLD_GINI( 16s, short )ICV_DEF_FIND_STUMP_THRESHOLD_GINI( 32s, int )ICV_DEF_FIND_STUMP_THRESHOLD_GINI( 32f, float )ICV_DEF_FIND_STUMP_THRESHOLD_ENTROPY( 16s, short )ICV_DEF_FIND_STUMP_THRESHOLD_ENTROPY( 32s, int )ICV_DEF_FIND_STUMP_THRESHOLD_ENTROPY( 32f, float )


此外,sq_##suffix起到了连接字符串的功能,如果suffix是16s,那么sq_##suffix实际上就是sq_16s,再然后,直接指向相关函数。

本文转自:http://www.itnose.net/detail/6183849.html

0 0