基于OpenCV的条形码区域检测(五)

版权声明:本文为博主原创文章,欢迎转载,转载请贴上博客地址 http://blog.csdn.net/xdg_blog https://blog.csdn.net/xdg_blog/article/details/53367454

基于OpenCV的条形码区域检测(五)

    在上一篇中,将分好区块的图片进行了Sobel,并滤除了纹理的干扰,得到了每个区块的角度信息,以及各个区块中有效像素点总数,但是只有这些还不能够直接判断哪一个区块内存在条形码,还需要做些处理。

    以下代码为遍历每块区块,并计算其有效像素点占像素总数的比例,以便后面排除干扰区块的影响。

///获得直方图中值最高的项,并返回其与相邻项的和
long getMaxWithAdj(long* hist, int &index) {
    long max = 0;
    int maxindex = 0;
    for (int i = 0; i < 8; ++i) {
        if (hist[i] > max) {
            max = hist[i];
            maxindex = i;
        }
    }
    index = maxindex;
    return hist[(maxindex - 1) % 8] + hist[maxindex] + hist[(maxindex + 1) % 8];

    //long *newHist = new long[8];

    //for (int i = 0; i < 8; ++i) {
    //  newHist[i] = hist[(i - 1) % 8] + hist[i] + hist[(i + 1) % 8];
    //}

    //long max = 0;
    //int maxindex = 0;
    //for (int i = 0; i < 8; ++i) {
    //  if (newHist[i] > max) {
    //      max = newHist[i];
    //      maxindex = i;
    //  }
    //}

    //index = maxindex;

    //long val = newHist[maxindex];

    //if (newHist) {
    //  delete newHist;
    //}
    //newHist = NULL;

    //return val;
}

///计算所有区块的分数
void blockSetTravel() {
    ///遍历所有区块
    for (vector<BlockInfo >::iterator pb = g_blockSet.begin(); pb < g_blockSet.end(); ++pb) {
        int maxIndex = 0;
        ///获得最高的项的和
        long max = getMaxWithAdj(pb->angleHist, maxIndex);
        pb->direction = maxIndex;
        if (pb->count > pb->height*pb->width / 20.0) {
            if (pb->count > 0)
                ///该区块的得分
                pb->score = max*1.0 / pb->count*1.0;
            else
                pb->score = 0;
        }
        else {
            pb->score = 0;
        }
    }
}

    以上注释部分代码为使用相邻方向总和来定位最高项的尝试,但是最终发现在测试图片中,效果没有直接取得最高项,并返回其相邻方向的总和的方式明显。可能与测试图片相关,可以根据不同应用场景变更。


    接着就是根据所有区块的方向信息统计并得到大概的整个可能的条形码区域的方向。

///计算所有区块的总体方向,即整个条形码的大概方向范围在PI的哪一个1/8等分中
int getDirection() {
    int direction[8];
    memset(direction, 0, sizeof(int) * 8);
    ///认为非干扰区块的阈值
    const float SCORE_THRESHOLD = 0.65;
    for each(auto var in g_blockSet) {
        if (var.score >= SCORE_THRESHOLD) {
            direction[var.direction]++;
        }
    }

    int max = 0;
    int maxIndex;
    for (int i = 0; i < 8; ++i) {
        if (direction[i] > max) {
            max = direction[i];
            maxIndex = i;
        }
    }

    return maxIndex;
}

    接下来,使用上面得到的方向在相同尺寸的图片上绘制出来,效果如图

这里写图片描述

    可以看出,这就是图片上的条形码的区域

    绘制该区域的代码如下:

///将指定方向的区块根据梯度强度强弱或深或浅绘制
Mat drawBlockSet(Size size, int direction) {
    Mat result(size, CV_8U, Scalar(0, 0, 0));
    for (vector<BlockInfo >::iterator pvar = g_blockSet.begin(); pvar < g_blockSet.end(); ++pvar) {
        if (pvar->score >= 0.65 && pvar->direction == direction) {
            pvar->exist = true;
            rectangle(result, Rect(pvar->leftTop.x, pvar->leftTop.y, pvar->width, pvar->height), Scalar(255 * pvar->score), -1);
        }
        else {
            pvar->exist = false;
        }
    }
    return result;
}

    接下来要做的就是将该区域的精确的角度求出,如果只是需要条形码的位置,那么求出角度便可以满足要求了。但是如果需要正的条形码的图片,还需将原图片裁剪旋转。且见下回分解!

猜你喜欢

转载自blog.csdn.net/xdg_blog/article/details/53367454