日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

pdf417条码解码(下)——译码

發布時間:2023/12/20 编程问答 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 pdf417条码解码(下)——译码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

解碼須知

  • 符號字符的結構
  • 符號字符的簇
  • 三種譯碼模式

    • 文本

      • 大寫字母型模式
      • 小寫字母型模式
      • 混合型子模式
      • 標點型子模式

      子模式的設置是為了更有效的表示數據,每組子模式選擇了文件中出現頻率較高的一組字符集。在子模式中,每一個字符對應一個基為30的值(0~29),因此一個碼字可以表示一個字符對。
      碼字=30*H+L

      任何模式到文本壓縮模式的鎖定都是到大寫字母型子模式的鎖定。
      在一個子模式轉移符后不接另一個子模式轉移或鎖定。

    • 字節
    • 數字
      分組:將每15個碼字從左到右分為一組(每15個碼字可轉換成44個數字位),其最后一組碼字可小于15個。
      對于每一組碼字:先執行基900到基10的轉換,再去掉前導位1.
  • 轉移和鎖定

    • 模式 鎖定: 碼字用于將當前模式切換為指定的目標模式,該模式在下一個切換前一直有效。
    • 模式 轉移: 碼字用于將文本壓縮模式暫時切換切換為字節壓縮,這種切換僅對切換后的第一個碼字有效,隨后的碼字又返回文本壓縮的當前子模式。

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); %figure; imshow(img);title('原圖'); %邊緣檢測 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; %二值化 值不為0說明為邊緣,設為255. vertical=(by~=0)*255; %figure; imshow(horizontal);title('水平邊緣'); %figure; imshow(vertical);title('豎直邊緣'); %尋找峰值 line(1) = 1; k = 1; for i=3:row-2%由于邊緣的寬度為2個像素,所以不能判斷該行i與鄰行i-1、i+1的大小if 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;%且需要去除鄰近行的干擾,將其設為0horizontal(i-1:i+1,:) = 0; %排除干擾end end k = k+1; line(k) = row; %每層中心 Layers = floor( (line(1:k-1)+line(2:k))/2 );%遍歷豎直邊緣圖vertical每一層中心行,遍歷到豎線時記錄此像素和上一個記錄點的距離,即一個模塊的長度 %記錄每個條空長度 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;%由于邊緣的寬度為2個像素,需要去除鄰近列的干擾,將其設為0vertical(Layers(i),j-1:j+1)=0; %排除干擾endendm = m+1;codes(i,m) = col-last;if len < mlen = m; %各行最大的有效點長度end end %只取有效長度1到len,去除零向量 codes = codes(:,1:len);%計算矩陣code中第一列的平均值,除以8,四舍五入后即為一個模塊的長度aunit auint = sum(codes(:,1))/length(codes(:,1))/8; %code數組點除以aunit,四舍五入后就能得到期望的符號碼字 codes = round(codes/auint); %矩陣code中,前17列和后17列不攜帶碼字,可以除去 codes = codes(:,17:len-17);%遍歷矩陣code,每從(i,j)處取8個數,使用find由8位數字查對應簇(i-1)%3+1的碼字表得到碼字 [r,c] = size(codes); l = ceil(c/8); decodes = zeros(1,r*l); load symcodes.mat -ASCII; for i = 1:rfor 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; %2->數字型、3->字節型、11->文本模式大寫型、12->文本模式小寫型、13->文本模式混合型、14->文本模式標點型 premode = [0,0]; %用于轉移模式時記錄模式值,第一個值表示當前是否為轉移模式,第二個值表示要返回的模式值 tcbyte = zeros(1,2); %用于記錄文本模式時的高低位數據,第一個值表示高位數據,第二個值表示低位數據 valueindex = [0,0]; %用于記錄字節模式和數字模式的緩存序列,其中第一個值表示序列是否有效及何種模式0->無效、1->數字模式、2->字節模式,第二個值表示序列起始位置 str = ''; %用來存放譯碼結果for i=2:codelenif 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); %用來存儲15個碼字if (k+14)<lencurvalues = caches(k:k+14);else %不足15個碼字curvalues(k+15-len:15) = caches(k:len);endlongnum=0;for j=1:15%使用sym以便存儲更多位longnum = longnum+curvalues(j)*sym(9^(15-j))*(100^(15-j)); endtempstr = char(longnum); %轉為字符串str = strcat(str, tempstr(2:end)); %去除第一位1%disp(['數字模式',str]);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 %ll=201,鎖定為小寫字母模式mode = 12;elseif tc_uc(tcbyte(j)+1)==202 %ml=202,鎖定為混合模式mode = 13;elseif tc_uc(tcbyte(j)+1)==204 %ps=204,轉移為標點模式premode(1) = 1;premode(2) = mode;mode = 14;else str = strcat(str,char(tc_uc(tcbyte(j)+1)));%disp(['大寫字母模式',str]);endelseif mode==12 %小寫字母模式if premode(1)==1mode = premode(2);premode(1) = 0;endif tc_lc(tcbyte(j)+1)==205 %as=205,轉移為大寫字母模式premode(1) = 1;premode(2) = mode;mode = 11;elseif tc_lc(tcbyte(j)+1)==202 %ml=202,鎖定為混合模式mode = 13;elseif tc_lc(tcbyte(j)+1)==204 %ps=204,轉移為標點模式premode(1) = 1;premode(2) = mode;mode = 14;elsestr = strcat(str,char(tc_lc(tcbyte(j)+1)));%disp(['小寫字母模式',str]);endelseif mode==13 %混合型if premode(1)==1mode = premode(2);premode(1) = 0;endif tc_mi(tcbyte(j)+1)==200 %al=200,鎖定為大寫字母模式mode = 11;elseif tc_mi(tcbyte(j)+1)==201 %ll=201,鎖定為小寫字母模式mode = 12;elseif tc_mi(tcbyte(j)+1)==203 %pl=203,鎖定為標點模式mode = 14;elseif tc_mi(tcbyte(j)+1)==204 %ps=204,轉移為標點模式premode(1) = 1;premode(2) = mode;mode = 14;elsestr = strcat(str,char(tc_mi(tcbyte(j)+1)));%disp(['混合型',str]);endelseif mode==14 %標點if premode(1)==1mode = premode(2);premode(1) = 0;endif tc_do(tcbyte(j)+1)==200 %al=200,鎖定為大寫字母模式mode = 11;elsestr = strcat(str,char(tc_do(tcbyte(j)+1)));%disp(['標點',str]);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 %disp(['解碼后的數據為:',str])

測試結果

  • 原圖

  • sobel算子邊緣提取

    • 水平方向邊緣

    • 豎直方向邊緣

  • 找出每層中心

    • 邊界

    • 共12層,每層中心如下

  • 獲取符號碼字codes
    截取出的數據塊的符號碼字,層數為12,列數為8*3=24
  • 查表找出codes對應碼字,12層,3個數據塊,一共36個
  • 最終譯碼結果
  • 轉自:https://blog.csdn.net/qazwyc/article/details/57575585

總結

以上是生活随笔為你收集整理的pdf417条码解码(下)——译码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。