www.pudn.com > SG_Recognition.rar > SG_Recognition.m
%==================================================
% 单组(一般3行象素为一组)条形码的识别函数
%==================================================
function [ResultCode,ErrorCode] = SG_Recognition(A)
global StartRow;
global EndRow;
global bwA;
global SysDigital;
ErrorCode = 0;
ResultCode = [99,99,99,99,99,99,99,99,99,99,99,99];
SL_A = SG_Vote(A);
ColorFlag = 10; % 条码颜色的标志位,1为白色,0为黑色,10为初始值
k = 1;
% 计算0和1的个数,并存储在TCounter向量中
for i = 1:length(SL_A)
if SL_A(i)==1 & ColorFlag==10 % 起始象素为白色
ColorFlag = 1;
Counter = 1;
StartColorFlag = 1; % 由于起始象素为白色,置起始象素颜色标志位为1
elseif SL_A(i)==0 & ColorFlag==10 % 起始象素为黑色
ColorFlag = 0;
Counter = 1;
StartColorFlag = 0; % 由于起始象素为黑色,置起始象素颜色标志位为0
elseif SL_A(i)==1 & ColorFlag==1 % 当前象素为白色,前一象素也为白色
Counter = Counter+1;
elseif SL_A(i)==0 & ColorFlag==1 % 当前象素为黑色,而前一象素为白色
TCounter(k) = Counter;
k = k+1;
ColorFlag = 0;
Counter = 1;
elseif SL_A(i)==0 & ColorFlag==0 % 当前象素为黑色,前一象素也为黑色
Counter = Counter+1;
elseif SL_A(i)==1 & ColorFlag==0 % 当前象素为白色,而前一象素为黑色
TCounter(k) = Counter;
k = k+1;
ColorFlag = 1;
Counter = 1;
end
end
TCounter(k) = Counter; % 注:将以上循环没有写进TCounter的最后一串同色象素的个数写入TCounter向量末尾
% 计算条形码的起始位和结束位
if StartColorFlag==1
StartPos = 2;
else
StartPos = 1;
end
StartFlag = 0;
while StartFlag==0
if StartPos+2<=length(TCounter)
ErrorCode = 0;
% 当前条宽与后两个条宽比较接近时认为找到了left-guard bar,否则继续搜索
if abs(TCounter(StartPos)-TCounter(StartPos+1))<3 & abs(TCounter(StartPos)-TCounter(StartPos+2))<3
StartFlag = 1;
else
StartPos = StartPos+2;
end
else
ErrorCode = 1; % ErrorCode=1表示找不到条形码的起始位置
return;
end
end
EndPos = StartPos;
EndFlag = 0;
while EndFlag==0
if EndPos+1<=length(TCounter)
ErrorCode = 0;
% 当下一个条宽比当前条宽大得多,并且所确定的码长足够长的时候认为找到了right-guard bar,否则继续搜索
if TCounter(EndPos+1)/TCounter(EndPos)>=6
if EndPos-StartPos+1<=20
StartPos = EndPos+2;
EndPos = StartPos;
else
EndFlag = 1;
end
else
EndPos = EndPos+1;
end
else
ErrorCode = 2; % ErrorCode=2表示找不到条形码的结束位置
return;
end
end
% 识别本组条形码
% 注:以下迭代识别条形码时采用随机抽取扫描条的方法,随机数的产生服从均匀分布
if EndPos-StartPos+1==59 % 如果前面判断的条码宽度符合要求则开始识别
T = TCounter(StartPos:EndPos);
[ResultCode,ErrorFlag] = SG_BarcodeRec(T);
if ErrorFlag==0
if CheckCode(ResultCode)==0 % 校验失败,继续迭代寻找正确的解
SeedNum = rand(1);
SG_StartRow = fix((EndRow-StartRow+1).*SeedNum+StartRow);
SG_A = bwA(SG_StartRow:SG_StartRow+2,:);
ResultCode = SG_Recognition(SG_A);
end
else
ErrorCode = 3;
end
else % 如果前面判断的条码宽度不合要求则迭代寻找符合要求的扫描条(SingleGroup)
SeedNum = rand(1);
SG_StartRow = fix((EndRow-StartRow+1).*SeedNum+StartRow);
SG_A = bwA(SG_StartRow:SG_StartRow+2,:);
ResultCode = SG_Recognition(SG_A);
end
%-----------------------------------------------------------
% 根据校验位对已识别出的条形码进行校验,返回校验结果
% 参数说明: ResultCode 识别的条码向量(1*12)
% CheckResult 识别结果。
% 0为识别失败,1为识别成功
%-----------------------------------------------------------
function [CheckResult] = CheckCode(ResultCode)
global SysDigital;
CodeLen = length(ResultCode);
NumSum = sum(ResultCode(1:2:(CodeLen-1)).*3)+sum(ResultCode(2:2:(CodeLen-1)))+SysDigital;
CheckDigital = 10-mod(NumSum,10);
if ResultCode(CodeLen)==CheckDigital
CheckResult = 1;
else
CheckResult = 0;
end
%----------------------------------------------------------
% 识别本组扫描条的条形码的子函数,返回识别结果的向量
% 参数说明: T 从起始位Left-guard到结束位Right-guard
% 的同色象素个数的向量
% ResultCode 保存识别结果数字的向量
%----------------------------------------------------------
function [ResultCode,ErrorFlag] = SG_BarcodeRec(T)
global SysDigital;
% 条形码的首位表示ISBN或ISSN码,值为9
ErrorFlag = 0;
ParityEncode = SysDigital;
PixelPerDigital = sum(T)/95;
T = round(T./PixelPerDigital);
for i = length(T)
if T(i)==0
T(i) = 1;
end
end
% 识别前6个数字
for i = 1:6
TSub = T(i*4:i*4+3);
OddEvenFlag = SelectParity(ParityEncode,i);
[R,F] = TemplateMatch(TSub,OddEvenFlag);
if F==1
ResultCode(i) = R;
else
ErrorFlag = 1;
end
end
% 识别后6个数字
CodeLength = length(ResultCode);
for i = 1:6
TSub = T((i-1)*4+1+32:(i-1)*4+4+32);
OddEvenFlag = 1;
[R,F] = TemplateMatch(TSub,OddEvenFlag);
if F==1
ResultCode(CodeLength+i) = R;
else
ErrorFlag = 1;
end
end
%-------------------------------------------------------------------
% 决定前6个数字的奇偶模板
% 参数说明: ParityEncode EAN13码的首位数字
% (系统码,决定采用何种奇偶模板)
% DigitalPos 待识别的是第几位数字
% OddEvenFlag 返回值,代表该位应该采用奇模板还是
% 偶模板。1为奇模板,0为偶模板
%-------------------------------------------------------------------
function [OddEvenFlag] = SelectParity(ParityEncode,DigitalPos)
switch ParityEncode
case 0
OddEvenFlag = 1;
case 1
if DigitalPos==1 | DigitalPos==2 | DigitalPos==4
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
case 2
if DigitalPos==1 | DigitalPos==2 | DigitalPos==5
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
case 3
if DigitalPos==1 | DigitalPos==2 | DigitalPos==6
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
case 4
if DigitalPos==1 | DigitalPos==3 | DigitalPos==4
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
case 5
if DigitalPos==1 | DigitalPos==4 | DigitalPos==5
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
case 6
if DigitalPos==1 | DigitalPos==5 | DigitalPos==6
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
case 7
if DigitalPos==1 | DigitalPos==3 | DigitalPos==5
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
case 8
if DigitalPos==1 | DigitalPos==3 | DigitalPos==6
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
case 9
if DigitalPos==1 | DigitalPos==4 | DigitalPos==6
OddEvenFlag = 1;
else
OddEvenFlag = 0;
end
end
%-----------------------------------------------------------
% 单组(一般3行象素一组,扫描条)的投票矩阵
% 每列的3象素值进行投票以决定投票结果的象素向量
% 参数说明: A 参加投票的象素值矩阵。
% VoteA 投票结果的象素向量,扫描条的识别实际上
% 只针对该投票结果的象素向量来进行
%-----------------------------------------------------------
function [VoteA] = SG_Vote(A)
VoteA = sum(A);
for i = 1:length(VoteA)
if VoteA(i)>1
VoteA(i) = 1;
else
VoteA(i) = 0;
end
end