QR Code快速響應矩陣 二維碼編碼全過程詳解(四)
承接上文,我們已經完成了糾錯碼字的生成,那麼接下來:
4.構造最終資訊:
我們選擇的版本和糾錯等級是Version4,L,因此它只有一個塊,因此它的最終序列構造變得簡單起來,只需將80個數據碼字與20個糾錯碼字直接相連就好了。但是筆者還是在這裡講一下要分塊的情況該怎麼得到最終序列。
比如,如果我們選的是Version5,Q,那麼就有四個塊,前兩個塊的資料碼字數是15個,後兩個塊的資料碼字有16個,糾錯碼字是每塊18個,其序列如圖所示:
圖中筆者順帶將剩餘位一同講清楚了,那麼接下來就是佈置矩陣了,就是把編碼得到的碼字和功能圖形,全部寫入矩陣中,得到二維碼;
那麼筆者先將我們前面所得的的碼字擺出來:
開玩笑啦,一共有80個數據碼字和20個糾錯碼字,全擺出來就是800個二進位制位,本文瞬間就成了千字文,所以筆者就將所有完整的碼字擺在本文的末尾,方便大家閱讀。
5.佈置矩陣:
我們選的版本是Version4,大小是33*33的矩陣,如圖所示:
我們先把尋像圖形、分隔符、定點陣圖形以及校正圖形給放入矩陣,並把格式資訊和版本資訊空出標紅(由於版本資訊只有Version7以上的版本才有,因此此處只空格式資訊的位置)
如圖所示;
另外校正圖形的數量以及位置也是隨版本改變而改變,需要查閱相關表格的請到本文章末尾檢視。
然後我們就佈置資料碼字和糾錯碼字到矩陣中,結果如圖:
怎麼樣,是不是有點像二維碼了呢?
可能又有小夥伴已經不太清楚,讀碼的順序了,附圖一張,細節處供參考,
然後對於碼字的寫入矩陣就基本完成了,下一步就是我們的掩碼了。
6.掩碼:
上圖就是最常見的8種掩碼的條件和掩碼圖形,圖中的黑色編為1,其中條件頭上的三塊構成三個數就是掩碼的型別,是要寫入格式資訊的,但是值得注意的是,這張圖是從解碼的角度來講掩碼的,所以色塊得到的3位數還需要去一次掩碼,而格式資訊的掩碼是統一的為:101010000010010,去掩碼後才是寫入格式資訊的資料。
選擇一個好的掩碼,可以讓黑白色塊分別的更均勻,從提高機器識別的準確度,因此對於掩碼的挑選,我們也有專門的演算法來挑選出相對較優的掩碼。
下面我們講怎麼判斷掩碼優劣。
將掩碼與需要掩模的碼字區進行XOR運算後,我們對掩模的結果進行懲罰值計算,然後挑選出懲罰值最小的結果作為掩模方案。
懲罰值記分規則參考:
記分項1:行/列中連續5塊色塊顏色相同記分3分,如果下一塊還是一樣就再加一分;如圖所示:(只例舉了一部分)
記分項2:遇到2*2同色塊,懲罰值為3,遇到2*3或3*2的同色塊,懲罰值為6,遇到3*3的同色塊懲罰值為12,遇到更大的m*n的同色塊,懲罰值為:3*(m-1)*(n-1);
如圖所示:
記分項3:在行或列出現 深淺深深深淺深 這種與位置探測圖形類似的,懲罰值為40;如圖所示:
記分項4:整個二維碼中,深色塊的佔比與50%相減得到得絕對值,每多差5%就多記分10分,假如現在黑色塊是佔61%,那麼懲罰值為20分。
最後,將所有被記得懲罰值相加,得到的懲罰值就是判斷這個二維碼掩模結果的優劣,我們要選擇懲罰值最低的掩碼。
(至於這些懲罰值怎麼才能快速算出來,就看各位自己的演算法嘍)
筆者經過計算後,選擇的掩碼是000這個掩碼,也就是條件為:
i*j%2+i*j%3=0;
7.版本和格式資訊:
格式資訊:
前面我們在矩陣中標紅留出的位置就是用來存格式資訊的,如圖紅色區域:
格式資訊有15位,其中前5位是格式資訊資料位,後面10位是用BCH(15,5)編碼計算得到的糾錯位;
前面5位是資料位,前兩位是糾錯等級,後三位是掩碼型別;
糾錯等級:
L對應01;
M對應00;
Q對應11;
H對應10;
而掩碼的三位就是前面提到過的三個色塊對應的二進位制,比如我們選的掩碼就是的資料位是101;
其他7種:
000 (i+j)%2=0;
001 i%2=0;
010 j%3=0;
011 (i+j)%3=0;
100 (i/2+j/3)%2=0;
110 (i*j%2+i*j%3)%2=0;
111 (i*j%3+i*j%2)%2=0;
而我們的糾錯等級為L,那麼我們得到格式資訊的5位資料位就是:01101;
那麼我們來求它的糾錯位,
01000對應一個多項式:x^3+ x^2+1;並將其先乘以x^10變成x^13+ x^12+x^10;
把它與多項式G(x)=x^10+ x^8+ x^5+ x^4+ x^2+ x^1+1相除得等式:
x^13+ x^12+x^10=( x^10+ x^8+ x^5+ x^4+ x^2+ x^1+1)( x^3+ x^2 + x^1)+ x^9+ x^8+ x^3+ x;
這個等式是怎麼得到的呢?
看圖;
所以將上面除法得到的多項式餘數得出我們的10位糾錯位:
1100001010;
(1表示x^9,x^8,x^3,x這些項存在,0表示其他不存在)
好,那麼整個格式資訊就是:
0110 1110 0001 010
再將它與1010 1000 0010 010作XOR運算得出格式資訊應填入的資訊:
1100 0110 0011 000
然後把這些數填到矩陣圖中的紅色區域,從14填到0,由於格式資訊十分重要,所以有兩個地方儲存,我們對應都給填好。
版本資訊:我們選的這個版本是沒有版本資訊的,如果有版本資訊的話,那麼它的位置也是和格式資訊的位置一樣,是提前預留的,相對位置如圖藍色位置:
也就是18個位,他的佈置如下圖:
它也是由6個數據位和12個糾錯位組成的,也在兩個地方重複儲存,與格式資訊的儲存十分相似。它的前六位就是版本號的二進位制數,如版本7,那麼就是000111,而糾錯位的計算簡直和格式資訊那裡一樣,唯一不同就是,生成多項式G(x)=x^12+ x^11+ x^10+ x^9+ x^8+ x^5+ x^2+1;所以具體的計算請參考前面的多項式除法,這裡不再贅述。
好的,直到現在,我們已經把要編的這個碼已經全部做完了,也就是說,我們這個二維碼已經可以生成了,下面這張圖就是我們處心積慮編出來的二維碼:
這是在Excel裡一個33*33表格裡的示意圖,另外筆者自己使用自己最熟悉的一門語言C++來實現了這二維碼,但是由於C++裡無法直接得到漢字的unicode碼值或者UTF-8碼值,所以,暫時還是隻支援手動輸入unicode碼值,但是筆者做了一些想瞞天過海的事情,於是乎得到了下面這張圖:
形式很簡陋,但是還是可以掃出來的。還有說好的把很多表格都附在文章結尾,每次都忘記了,下篇文章就把前面需要用到的資料的表格儘量附上,另外,歡迎和筆者一起討論,筆者也只是個大二的學生,這趁著國慶假期,研究了幾天QR Code,稍微懂了一點,寫文章的目的其實也很簡單,就想看下自己懂了多少。