版权声明:本文为博主原创文章,欢迎转载,转载请贴上博客地址 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;
}