生活随笔
收集整理的這篇文章主要介紹了
pdf417条码解码(下)——译码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
解碼須知
- 符號字符的結構
- 符號字符的簇
三種譯碼模式
轉移和鎖定
- 模式 鎖定: 碼字用于將當前模式切換為指定的目標模式,該模式在下一個切換前一直有效。
- 模式 轉移: 碼字用于將文本壓縮模式暫時切換切換為字節壓縮,這種切換僅對切換后的第一個碼字有效,隨后的碼字又返回文本壓縮的當前子模式。
pdf417條碼參考資料及碼字表自取
步驟
碼字提取
功能描述:
提取圖像邊緣,從水平邊緣可以得到層數,從豎直邊緣可以得到條空長度;通過查對應簇的碼字表得到碼字
設計思路:
- 選用邊緣檢測算子sobel,使用其水平方向掩碼和豎直方向掩碼對圖像濾波可分別得到水平邊緣和豎直邊緣。
- 圖像中層與層之間的邊界都會在水平投影圖上形成明顯的峰值,峰值的中點就是層的中心
- 豎直邊緣包含了每個條空的長度信息,即每一層每兩條豎線間的距離,記錄到code中
- 起始符的長是17個模塊,最前面黑色塊長是8個模塊,矩陣code中第一列的像素點數除以8即為一個模塊的長度aunit
- Code數組點除以aunit,四舍五入后就能等得到期望的符號碼字
- Pdf417每一行的簇按0,3,6依次排列,查對應簇的碼字表得到碼字
function str=mydecode(filepath)
img = imread(filepath);
if(
length(
size(img)))==
3img = rgb2gray(img);
end
[row,col] =
size(img);
img = double(img);
topso =
[-1 -2 -1;0 0 0;1 2 1];
lefso =
[-1 0 1;-2 0 2;-1 0 1];
bx =
abs(imfilter(img,topso));
by =
abs(imfilter(img,lefso));
horizontal=(bx~=
0)*
255;
vertical=(by~=
0)*
255;
line(
1) =
1;
k =
1;
for i=
3:row-
2if sum(horizontal(
i,:)) > sum(horizontal(
i-
2,:)) && sum(horizontal(
i,:)) > sum(horizontal(
i-
3,:))...&& sum(horizontal(
i,:)) > sum(horizontal(
i+
2,:)) && sum(horizontal(
i,:)) > sum(horizontal(
i+
3,:))k = k+
1;line(k) =
i;horizontal(
i-
1:
i+
1,:) =
0;
end
end
k = k+
1;
line(k) = row;
Layers =
floor( (line(
1:k-
1)+line(
2:k))/
2 );
codes =
zeros(k-
1, col);
len =
0;
for i=
1:k-
1last =
1;m =
0;
for j=
2:col-
1if vertical(Layers(
i),
j)==
255m = m+
1;codes(
i,m) =
j-last;last =
j;vertical(Layers(
i),
j-
1:
j+
1)=
0;
endendm = m+
1;codes(
i,m) = col-last;
if len < mlen = m;
end
end
codes = codes(:,
1:len);
auint = sum(codes(:,
1))/
length(codes(:,
1))/
8;
codes =
round(codes/auint);
codes = codes(:,
17:len-
17);
[r,c] =
size(codes);
l =
ceil(c/
8);
decodes =
zeros(
1,r*l);
load
symcodes.mat -ASCII;
for i =
1:r
for j =
1:
8:ctemp = sum(codes(
i,
j:
j+
7).*(
10.^(
8-(
1:
8))));decodes((
i-
1)*l+
ceil(
j/
8)) =
find(symcodes(
mod((
i-
1),
3)+
1,:) == temp) -
1;
end
end
文本、數字壓縮模式譯碼
功能描述:根據碼字判斷文本、數字壓縮模式的鎖定和轉移,在對應模式下完成碼字的譯碼。
設計思路:
- 數據區中的第一個碼字是符號長度值。
- 根據碼字判斷文本、數字、壓縮模式的鎖定和轉移,使用mode記錄當前的解碼模式 ,數字型:2,字節型:3, 文本大寫模式:11,文本小寫:12,文本混合:13,文本標點:14
- 使用premode用于轉移模式時記錄模式值,第一個表示當前是否為轉移模式,第二個表示要返回的模式值
- 根據碼字表,建立文本模式下各子模式下的對應字符表,tcbyte記錄文本模式時的高低位數據,第一個值表示高位,第二個表示低位。
- 數字壓縮模式將每15個碼字從左到右分為一組,其最后一組碼字可小于15個。對于每一組碼字,先執行基900到基10的轉換,再去掉前導位。用valueindex記錄字節模式和數字模式的緩存序列,其中第一個值表示序列是否有效及何種模式 ,無效 0,數字模式1, 字節模式 2, 第二個值表示序列起始位置。
tc_uc =
[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,32,201,202,204];
tc_lc =
[97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,32,205,202,204];
tc_mi =
[48,49,50,51,52,53,54,55,56,57,38,13,09,44,58,35,45,46,36,47,43,37,42,61,94,203,32,201,200,204];
tc_do =
[59,60,62,64,91,92,93,95,96,126,33,13,09,44,58,10,45,46,36,47,34,124,42,40,41,63,123,125,39,200];codelen = decodes(
1);
mode =
11;
premode =
[0,0];
tcbyte =
zeros(
1,
2);
valueindex =
[0,0];
str =
'';
for i=
2:codelen
if decodes(
i)>=
900 if decodes(
i)==
900mode =
11;
elseif decodes(
i)==
902mode =
2;
elseif decodes(
i)==
901 || decodes(
i)==
924 || decodes(
i)==
913mode =
3;
endif valueindex(
1)==
1 caches = decodes(valueindex(
2):(
i-
1)); len =
size(caches,
2);
for k=
1:
15:lencurvalues =
zeros(
1,
15);
if (k+
14)<lencurvalues = caches(k:k+
14);
else curvalues(k+
15-len:
15) = caches(k:len);
endlongnum=
0;
for j=
1:
15longnum = longnum+curvalues(
j)*sym(
9^(
15-
j))*(
100^(
15-
j));
endtempstr = char(longnum); str = strcat(str, tempstr(
2:
end));
endendvalueindex =
[0,0];
elseif mode>
10 tcbyte(
1) =
floor(decodes(
i)/
30); tcbyte(
2) =
mod(decodes(
i),
30);
for j=
1:
2if mode==
11 if premode(
1)==
1 mode = premode(
2);premode(
1) =
0;
endif tc_uc(tcbyte(
j)+
1)==
201 mode =
12;
elseif tc_uc(tcbyte(
j)+
1)==
202 mode =
13;
elseif tc_uc(tcbyte(
j)+
1)==
204 premode(
1) =
1;premode(
2) = mode;mode =
14;
else str = strcat(str,char(tc_uc(tcbyte(
j)+
1)));
endelseif mode==
12 if premode(
1)==
1mode = premode(
2);premode(
1) =
0;
endif tc_lc(tcbyte(
j)+
1)==
205 premode(
1) =
1;premode(
2) = mode;mode =
11;
elseif tc_lc(tcbyte(
j)+
1)==
202 mode =
13;
elseif tc_lc(tcbyte(
j)+
1)==
204 premode(
1) =
1;premode(
2) = mode;mode =
14;
elsestr = strcat(str,char(tc_lc(tcbyte(
j)+
1)));
endelseif mode==
13 if premode(
1)==
1mode = premode(
2);premode(
1) =
0;
endif tc_mi(tcbyte(
j)+
1)==
200 mode =
11;
elseif tc_mi(tcbyte(
j)+
1)==
201 mode =
12;
elseif tc_mi(tcbyte(
j)+
1)==
203 mode =
14;
elseif tc_mi(tcbyte(
j)+
1)==
204 premode(
1) =
1;premode(
2) = mode;mode =
14;
elsestr = strcat(str,char(tc_mi(tcbyte(
j)+
1)));
endelseif mode==
14 if premode(
1)==
1mode = premode(
2);premode(
1) =
0;
endif tc_do(tcbyte(
j)+
1)==
200 mode =
11;
elsestr = strcat(str,char(tc_do(tcbyte(
j)+
1)));
endendendelseif mode==
2 if valueindex(
1)==
0valueindex(
1)=
1;valueindex(
2)=
i;
endelseif mode==
3 if valueindex(
1)==
0valueindex(
1)=
2;valueindex(
2)=
i;
endendend
end
測試結果
原圖
sobel算子邊緣提取
找出每層中心
- 獲取符號碼字codes
截取出的數據塊的符號碼字,層數為12,列數為8*3=24
- 查表找出codes對應碼字,12層,3個數據塊,一共36個
- 最終譯碼結果
- 轉自:https://blog.csdn.net/qazwyc/article/details/57575585
總結
以上是生活随笔為你收集整理的pdf417条码解码(下)——译码的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。