您的位置:首页 > 编程语言 > MATLAB

使用matlab识别条形码(目前还无法自动定位图片中条形码位置,需人工确定条形码所在范围区间)

2016-06-16 19:08 671 查看
close all

I = imread('C:\Users\Administrator\Desktop\001.bmp');

A=size(I);

if length(A)==3

J=rgb2gray(I);

else

J=I;

end

figure(1)

imshow(J);

title('灰度化图像 ');

[e1,e2]=size(J);

Im=imcrop(J,[820,980,800,400]);     缺点:人工确定条形码所在范围区间

figure(2)

subplot(1,2,1),imshow(Im)

title('中心区域 ');

subplot(1,2,2),imhist(Im)

title('中心区域直方图');

[xa,ya]=size(Im);                    

b=double(Im);                   

zd=double(max(Im)) ;                 

zx=double(min(Im)) ;               

T=double((zd+zx))/2;                  

count=double(0);                      

while 1                 

    count=count+1; 

    S0=0.0; n0=0.0;                   

    S1=0.0; n1=0.0;                 

    for i=1:xa

        for j=1:ya

            if double(Im(i,j))>=T

                S1=S1+double(Im(i,j)); 

                n1=n1+1;                

            else 

                S0=S0+double(Im(i,j));  

                n0=n0+1;               

            end 

        end 

    end  

    T0=S0/n0; 

    T1=S1/n1; 

    if abs(T-((T0+T1)/2))<0.1    

        break;

    else

       T=(T0+T1)/2;                 

   end 

end 

count

T

K=find(Im<T);

Im(K)=0;

K=find(Im>=T);

Im(K)=255;

figure(3)

imshow(Im)

title(' 图像二值化 ');

%B=medfilt2(Im,[50,10]);

%figure(4)

%imshow(B)

%title('中值滤波后图像');

%[y0,x0]=size(Im);

%BW = edge(Im,'log'); 

%figure(5);imshow(BW);title('边缘检测图像')

%function code = barcode(pic) %条形码识别

check_left = [13,25,19,61,35,49,47,59,55,11;... %左边数据编码,奇

              39,51,27,33,29,57, 5,17, 9,23]; %左边数据编码,偶

check_right = [114,102,108,66,92,78,80,68,72,116]; %右边数据编码

first_num = [31,20,18,17,12,6,3,10,9,5];    %第一位数据编码

%bar = imread('C:\Users\Administrator\Desktop\001.bmp');  %读输入条形码图片

%B=size(bar);

%if length(B)==3

%bar_Gray=rgb2gray(bar);

%else

%bar_Gray=bar;

%end

bar_Gray=Im;

%bar_Gray = rgb2gray(bar);   %将RGB图片转换灰度图

[a_hist x] = imhist(bar_Gray);

hist_max = [];

if a_hist(1)>a_hist(2)

    hist_max = [hist_max 1];

end

x = max(x);

for i=2:x

    if a_hist(i)>a_hist(i-1) && a_hist(i)>a_hist(i+1)

        hist_max = [hist_max i];

    end

end

if a_hist(x)<a_hist(x+1)

    hist_max = [hist_max x+1];

end

[m,n] = size(hist_max);

k = 0;

max_1 = 0;

max_2 = 0;

for i=1:n

    if k<a_hist(hist_max(i))

        k = a_hist(hist_max(i));

        max_1 = hist_max(i);

    end 

end

temp = a_hist(max_1);

a_hist(max_1) = 0;

k = 0;

for i=1:n

    if k<a_hist(hist_max(i))

        k = a_hist(hist_max(i));

        max_2 = hist_max(i);

    end

end

a_hist(max_1) = temp;

if max_1>max_2

    k = max_1;

    max_1 = max_2;

    max_2 = k;

end

T = max_1;

k = a_hist(max_1);

for i=max_1:max_2

    if k>a_hist(i)

        k = a_hist(i);

        T = i;

    end

end

[m,n] = size(bar_Gray); %求灰度图的大小

for i=1:m        %对图像进行二值化处理

    for j=1:n

        if bar_Gray(i,j)>T    %选择适当的阈值进行二值化处理

            bar_10(i,j) = 1;

        else

            bar_10(i,j) = 0;

        end

    end

end

%imshow(bar_10);

l = 0;      %检测59根条形码

for i=1:m

    k = 1;

    l = l+1;

    for j=1:n-1

        if bar_10(i,j)~=bar_10(i,j+1)   %比较同一行相邻两点的颜色是否一致

            %bar_x(l,k) = i;

            bar_y(l,k) = j; %记录转折点的纵坐标

            k = k+1;    %准备记录下一个数据点

        end

        if k>61 %点数大于60,该行应该删掉

            l = l-1;

            break

        end

    end

    if k<61 %点数小于60,该行应该删掉

        l = l-1;

    end

end

[m,n] = size(bar_y);

if m<=1 %查看条形码是否有效

    code = '0';

    fprintf(1,'GameOver!\n');

    return

end

for i=1:m            %计算每根条形码的宽度

    for j=1:n-1

        bar_num(i,j) = bar_y(i,j+1) - bar_y(i,j);

        if bar_num(i,j)<0

            bar_num(i,j) = 0;

        end

    end

end

bar_sum = sum(bar_num)/m;   %求每根条形码宽度的平均值

k = 0;

for i=1:59   %计算59根条形码的总宽度

    k = k + bar_sum(i);

end

k = k/95;   %计算单位条形码的宽度

for i=1:59  %计算每根条形码所占位数

    bar_int(i) = round(bar_sum(i)/k);

end

k = 1;

for i=1:59  %将条形码转换成二进制数

    if rem(i,2)

        for j=1:bar_int(i)  %黑色条用1表示

            bar_01(k) = 1;

            k = k+1;

        end

    else

        for j=1:bar_int(i)  %白色条用0表示

            bar_01(k) = 0;

            k = k+1;

        end

    end

end

if ((bar_01(1)&&~bar_01(2)&&bar_01(3))...   %判断起始符是否正确

        &&(~bar_01(46)&&bar_01(47)&&~bar_01(48)&&bar_01(49)&&~bar_01(50))...    %判断中间分隔符是否正确

        &&(bar_01(95)&&~bar_01(94)&&bar_01(93)))    %判断终止符是否正确

    l = 1;

    for i=1:6   %将左侧42位二进制数转换为十进制数

        bar_left(l) = 0;

        for k=1:7

            bar_left(l) = bar_left(l)+bar_01(7*(i-1)+k+3)*(2^(7-k));

        end

        l = l+1;

    end

    l = 1;

    for i=1:6   %将右侧42位二进制数转换为十进制数

        bar_right(l) = 0;

        for k=1:7

            bar_right(l) = bar_right(l)+bar_01(7*(i+6)+k+1)*(2^(7-k));

            k = k-1;

        end

        l = l+1;

    end

end

num_bar = '';

num_first = 0;

first = 2;

for i=1:6   %从左边数据编码表中查出条形码编码数字

    for j=0:1

        for k=0:9

            if bar_left(i)==check_left(j+1,k+1)

                num_bar = strcat(num_bar , num2str(k));

                switch first    %记录左边数据的奇偶顺序

                    case 2

                        first = j;

                        break;

                    case 1

                        num_first = num_first + j*(2^(6-i));

                        break;

                    case 0

                        num_first = num_first + ~j*(2^(6-i));

                        break;

                    otherwise

                        break;

                end

            end

        end

    end

end

for i=1:6   %从右边数据编码表中查出条形码编码数字

    for j=0:9

        if bar_right(i)==check_right(j+1)

            num_bar = strcat(num_bar , num2str(j));

        end

    end

end

for i=0:9   %从第一位数据编码表中查出第一位数字

    if num_first==first_num(i+1)

        num_bar = strcat(num2str(i) , num_bar);

        break;

    end

end

if numel(num_bar)~=13

    fprintf(1,'Please Turn It Around!\n');

    return

end

check_code = 0;

for i=1:12  %计算校验码

    if rem(i,2)

        check_code = check_code + str2double(num_bar(i));

    else

        check_code = check_code + str2double(num_bar(i))*3;

    end

end

check_code = rem(check_code,10);

if check_code>0

    check_code = 10 - check_code;

end

if check_code==str2double(num_bar(13)) %判断校验码是否正确

    code = num_bar

else

    fprintf(1,'Please Turn It Around!\n');

    return

end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: