博客轉載自: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倍。