调试基本完成,主要错误原因是matlab无法实现宏定义,预先计算出的宏值和带入公式中计算的结果不一致,四舍五入和C中结果不一样,所以图中有的蓝线和黄线差±1个像素,中间还有两处错误,没找到原因。
%zbar_scan_test.m
%在有些位置
function zbar_scan_test ()
clc;
ZBAR_FIXED = 5;
ROUND = bitshift(1, (ZBAR_FIXED - 1));
ZBAR_SCANNER_THRESH_MIN = 4;
ZBAR_SCANNER_THRESH_INIT_WEIGHT = 0.44;
THRESH_INIT = (((ZBAR_SCANNER_THRESH_INIT_WEIGHT ...
* (bitshift(1,ZBAR_FIXED + 1)) + 1) / 2));
ZBAR_SCANNER_THRESH_FADE = 8;
ZBAR_SCANNER_EWMA_WEIGHT = 0.78;
EWMA_WEIGHT = int32(((ZBAR_SCANNER_EWMA_WEIGHT ...
* bitshift(1, (ZBAR_FIXED + 1)) + 1) / 2));
scn = struct('y1_min_thresh',ZBAR_SCANNER_THRESH_MIN, ...
'x',1, ...
'y1_sign',0, ...
'y1_thresh',ZBAR_SCANNER_THRESH_MIN, ...
'cur_edge',0, ...
'last_edge',0, ...
'width',0);
Img = imread('pic/barcode.bmp');
data = double(Img(50,:));
len = length(data);
y = data(1);
y0 = zeros(1,len);
y0(1:4) = data(1:4);
edge = zeros(1,len);
load('edgeX.mat','edgeX');
edgeY = zeros(1,length(edgeX));
for i=1:length(edgeX)
edgeY(i) = 100;
end
figure(1);
subplot(211);
plot(data);
hold on;
plot(y0);
stem(edgeX,edgeY);
hold off;
subplot(212);
stem(edge);
for x = 4:len
scn.x = x - 1;
y = data(x);
y01 = y0(x-1);
% update weighted moving average
y00 = y01 + bitshift(int32((y-y01) * EWMA_WEIGHT), -ZBAR_FIXED,'int32');
y0(x) = y00;
y02 = y0(x-2);
y03 = y0(x-3);
% 1st differential @ x-1
y11 = y01 - y02;
y12 = y02 - y03;
if ((abs(y11) <abs(y12)) && ...
(y11 >= 0) == (y12 >= 0))
y11 = y12;
end
% 2nd differentials @ x-1 & x-2
y21 = y00 - (y01*2) + y02;
y22 = y01 - (y02*2) + y03;
X = sprintf('scan: x=%d y=%d y0=%d y1=%d y2=%d',...
scn.x,y,y01,y11,y21);disp(X);
% 2nd zero-crossing is 1st local min/max - could be edge
y2_rev = ((y21>0)&&(y22<0)) || ((y21<0)&&(y22>0));
if ((~y21) || ...
y2_rev) && ...
(calc_thresh <= abs(y11))
%check for 1st sign change
y1_rev = ((scn.y1_sign>0)&&(y11<0)) || ((scn.y1_sign<0)&&(y11>0));
if y1_rev
%intensity change reversal - finalize previous edge
process_edge;
end
if y1_rev || (abs(scn.y1_sign) < abs(y11))
scn.y1_sign = y11;
% adaptive thresholding
% start at multiple of new min/max
scn.y1_thresh = bitshift(int32(abs(y11)*THRESH_INIT+ROUND),...
-ZBAR_FIXED,'int32');
X = sprintf('thr=%d',scn.y1_thresh);disp(X);
if(scn.y1_thresh < scn.y1_min_thresh)
scn.y1_thresh = scn.y1_min_thresh;
end
% update current edge
d = y21 - y22;
scn.cur_edge = bitshift(1,ZBAR_FIXED);
if ~d
scn.cur_edge = bitshift(scn.cur_edge,-1);
else if y21
% interpolate zero crossing
scn.cur_edge = scn.cur_edge - ...
(bitshift(y21,ZBAR_FIXED)+1) / d;
end
end
scn.cur_edge = scn.cur_edge + bitshift(scn.x,ZBAR_FIXED);
edge(bitshift(int32(scn.cur_edge),-ZBAR_FIXED)) = 50;
end
end
end
figure(1);
subplot(211);
plot(data);
hold on;
plot(y0);
stem(edgeX,edgeY);
hold off;
subplot(212);
stem(edge);
hold on;
stem(edgeX,edgeY);
hold off;
% nested functions clac_thresh
function thresh = calc_thresh
% threshold 1st to improve noise rejection
thresh = scn.y1_thresh;
if(thresh <= scn.y1_min_thresh || ~scn.width)
thresh = scn.y1_min_thresh;
return;
end
% slowly return threshold to min
dx = bitshift(scn.x,ZBAR_FIXED) - scn.last_edge;
t = thresh * dx;
t = t / scn.width;
t = t / ZBAR_SCANNER_THRESH_FADE;
X = sprintf(' thr=%d t=%ld x=%d last=%d.%d (%d)', ...
thresh,t,scn.x, ...
bitshift(scn.last_edge,-ZBAR_FIXED), ...
bitand(scn.last_edge,(bitshift(1,ZBAR_FIXED)-1)), ...
dx);disp(X);
if thresh > t
thresh = thresh - t;
if thresh > scn.y1_min_thresh;
return
end
end
scn.y1_thresh = scn.y1_min_thresh;
thresh = scn.y1_min_thresh;
return;
end %end calc_thresh()
function process_edge
if ~scn.y1_sign
scn.cur_edge = bitshift(1,ZBAR_FIXED)+ROUND;
scn.last_edge = scn.cur_edge;
else if ~scn.last_edge
scn.last_edge = scn.cur_edge;
end
end
scn.width = scn.cur_edge - scn.last_edge;
X = sprintf('sgn=%d cur=%d.%d w=%d ', ...
scn.y1_sign,bitshift(scn.cur_edge,-ZBAR_FIXED), ...
bitand(scn.cur_edge,bitshift(1,ZBAR_FIXED)-1), ...
scn.width);
if sign(y11) > 0
X = [X ,'SPACE'];
else X = [X, 'BAR'];
end
disp(X);
scn.last_edge = scn.cur_edge;
end
end