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