以下OpenCV源代码中是否有错误? (#ifdef,不带#else)

问题描述 投票:0回答:1

这是OpenCV(v4.1.2,/ opencv-4.1.2 / modules / imgproc / src / thresh.cpp)Otsu二值化算法实现的一部分下面的代码计算图像直方图h[N](其中N = 256个灰度值),然后进行一些数学运算。我认为历史计算部分存在错误。有两个版本-简单的暴力循环和展开循环版本。并且暴力循环独立于CV_ENABLE_UNROLLED标志运行。

static double
getThreshVal_Otsu_8u( const Mat& _src )
{
    Size size = _src.size();
    int step = (int) _src.step;
    if( _src.isContinuous() )
    {
        size.width *= size.height;
        size.height = 1;
        step = size.width;
    }

#ifdef HAVE_IPP
    unsigned char thresh = 0;
    CV_IPP_RUN_FAST(ipp_getThreshVal_Otsu_8u(_src.ptr(), step, size, thresh), thresh);
#endif

    const int N = 256;
    int i, j, h[N] = {0};
    #if CV_ENABLE_UNROLLED
    int h_unrolled[3][N] = {};
    #endif
    for( i = 0; i < size.height; i++ )
    {
        const uchar* src = _src.ptr() + step*i;
        j = 0;
        #if CV_ENABLE_UNROLLED
        for( ; j <= size.width - 4; j += 4 )
        {
            int v0 = src[j], v1 = src[j+1];
            h[v0]++; h_unrolled[0][v1]++;
            v0 = src[j+2]; v1 = src[j+3];
            h_unrolled[1][v0]++; h_unrolled[2][v1]++;
        }
        #endif
        for( ; j < size.width; j++ ) <-------------------------------- !!!here
            h[src[j]]++;
    }

    double mu = 0, scale = 1./(size.width*size.height);
    for( i = 0; i < N; i++ )
    {
        #if CV_ENABLE_UNROLLED
        h[i] += h_unrolled[0][i] + h_unrolled[1][i] + h_unrolled[2][i];
        #endif
        mu += i*(double)h[i];
    }

    mu *= scale;
    double mu1 = 0, q1 = 0;
    double max_sigma = 0, max_val = 0;

    for( i = 0; i < N; i++ )
    {
        double p_i, q2, mu2, sigma;

        p_i = h[i]*scale;
        mu1 *= q1;
        q1 += p_i;
        q2 = 1. - q1;

        if( std::min(q1,q2) < FLT_EPSILON || std::max(q1,q2) > 1. - FLT_EPSILON )
            continue;

        mu1 = (mu1 + i*p_i)/q1;
        mu2 = (mu - q1*mu1)/q2;
        sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);
        if( sigma > max_sigma )
        {
            max_sigma = sigma;
            max_val = i;
        }
    }

    return max_val;
}

必须有

for( i = 0; i < size.height; i++ )
    {
        const uchar* src = _src.ptr() + step*i;
        j = 0;
        #if CV_ENABLE_UNROLLED
        for( ; j <= size.width - 4; j += 4 )
        {
            int v0 = src[j], v1 = src[j+1];
            h[v0]++; h_unrolled[0][v1]++;
            v0 = src[j+2]; v1 = src[j+3];
            h_unrolled[1][v0]++; h_unrolled[2][v1]++;
        }
        #else
        for( ; j < size.width; j++ ) <-------------------------------- !!!here
            h[src[j]]++;
        #endif
    }
c++ opencv conditional-compilation
1个回答
0
投票

不,这不是错误。请注意,j变量不会在每个循环开始时重置。第一个循环处理4个项目的块(无论它们是什么),直到剩下不到4个为止。此时,j是需要处理的下一项的索引。第二个循环分别处理其余项目。

如果未定义CV_ENABLE_UNROLLED,则j为0(因为第一个循环没有更新它,而第二个循环分别处理每个项目。

© www.soinside.com 2019 - 2024. All rights reserved.