博客转载自:https://blog.csdn.net/sunflower_boy/article/details/50783179
//Img_scanner.c 文件内 int zbar_scan_image (zbar_image_scanner_t *iscn, zbar_image_t *img)
经过Zbar example的分析后发现图像扫描的工作都是由zbar_scan_image完成的,zbar_scan_image主要根据设定的扫描密度(density)控制像素点读取(Z字形),scanner.c文件内的zbar_scan_y()来完成滤波,阈值,确定边缘,转化成宽度流。
//先判断有没有设定y密度 if(ydensity > 0)
{
while(y < h) //y从0以ydensity递增到h
{
while(x < w) //x先从0递增到w,再递减回0 { x += 1; zbar_scan_y(); } x = w - 1; y = y+ ydensity //y从0以ydensity递增到h if(y >= h) break; while(x >=0)// x开始递减 { x -= 1; zbar_scan_y(); } x = 0 + 1; y = y + ydensity; } //接着判断x方向扫描密度(xdensity),同理Z字形扫描
}
逐点扫描判断边界,实际的条形码波形不是理论中的方波,而是高斯退化的波,其边界处是凹凸交界的位置。求边界的原理是二阶导数为0或者异号的位置可能为边界即Scanner.c中247行的注释/* 2nd zero-crossing is 1st local min/max - could be edge */
通过第138行dprintf(1, ” thr=%d t=%ld x=%d last=%d.%d (%d)”, thresh, t, scn->x, scn->last_edge >> ZBAR_FIXED, 可以看出关于ZBAR_FIXED是小数位数,ROUND换算下就是0.5。 函数一开头使用EWMA对原始数据滤波,抑制突变。再用y0数组存储邻近点的数据,用来求一阶导数和二阶导数, scn->y0[(x - 1) & 3]很巧妙的限制住了数组索引不越界,循环使用。 紧接着开始求一阶导,二阶导. register int是设置变量常驻cpu,加快执行速度.
但第234行的判断不知何意
if((abs(y1_1) < abs(y1_2)) && ((y1_1 >= 0) == (y1_2 >= 0))) y1_1 = y1_2; //如果y11与y12同向且y11小于y12,则y11=y12
函数
static inline unsigned calc_thresh (zbar_scanner_t *scn) dx = x - lastedge; t = thresh*dx; t /= scn->width; t /=8;
这一段程序主要是为了使thresh逐渐回归到thresh_min,如果dx在8width范围内,则thresh=thresh(1-dx/8w);即如果dx=width,则thresh=7/8thresh。如果dx超出8w范围,则直接置为thresh_min。thresh在每次确定新的边界时更新为此处的y11的0.44倍。