眼中有碼,心中無碼

眼中有碼,心中無碼

日常生活中二維碼的使用已經無處不在,付款碼、微信名片、健康碼、乘車碼……一張小小的二維碼侵入到生活中的方方面面。黑白色塊組成的有限區域,如何攜帶信息。不同應用場景下的二維碼會不會重複,會不會像 IPV4 一樣被耗盡?如果您對這些也有疑問,請您帶着問題閱讀本文。

一. 你一定沒見過的二維碼

二維碼有很多種類,目前主流的有 PDF417碼,QR碼,漢信碼,顏色條碼,EZ碼,Aztec碼,QuickMark,Data Matrix 這幾種。我們每天付款、點餐時使用的是 QR碼,又稱 Quick Response Code ,是1994年由日本人發明。

按照實現原理,二維碼可以分爲兩類:

  • 堆疊式/行排式(原理是建立在一維條碼基礎之上,按需要堆積成二行或多行)

  • 矩陣式二維碼(原理是在一個矩形空間通過黑、白像素在矩陣中的不同分佈進行編碼)

小知識:

  1. 二維碼種類有很多,我們平時說的二維碼是 QR碼,只是二維碼的一種
  2. QR碼 是日本人發明的

在這裏插入圖片描述

最右下角的 QR碼使我們最常見到的,本文就以 QR碼切入,分析實現原理。

二. 信息是如何傳遞的?

二維碼在代碼編制上巧妙地利用構成計算機邏輯基礎的“0”、“1”,使用若干個與二進制相對應的幾何形體來表示文字數值信息,這些特定的幾何圖形按一定規律在平面(二維方向上)分佈的、黑白相間的、記錄數據符號信息的圖形。通過掃碼槍、手機 APP等識別到二維碼,還原信息。非常像加密和解密的過程。

整體結構

QR碼從結構上基本上可被分爲定位區、功能區、數據區三部分

在這裏插入圖片描述

1. 定位區

常見的二維碼,不論你是站着掃,趴着掃,跪着掃,左左右右上上下下地都能識別得到,全都是依賴這三個數據模塊:

  1. 定位標誌。在左上,右上,左下有三個大型的 “回” 字的黑白相間同心正方形,爲QR碼識別定位標誌,失去其中一個會影響識別。
  2. 定時標誌。用於定位,二維碼如果尺寸過大,掃描時容易畸變,時序圖案的作用就是防止掃描時畸變的產生;
  3. 校正標誌。Version2 以上需要

2. 功能區

  1. 格式信息。存放格式化數據,表示改二維碼的糾錯級別,分爲L、M、Q、H;
  2. 版本信息:用於 Version 7 以上,需要預留兩塊 3×6 的區域存放部分版本信息;

3. 數據部分

實際保存的二維碼信息,和糾錯碼元(用於修正二維碼損壞帶來的錯誤)

版本分類

QR碼設有 1 到 40 的不同版本(種類),每個版本都具備固有的碼元結構(碼元數)。“碼元結構”是指二維碼中的碼元(碼元是指構成QR碼的方形黑白點)數。從version 1(21碼元×21碼元)開始,在縱向和橫向各自以 4 碼元爲單位遞增,一直到 version 40(177碼元×177碼元)。

在這裏插入圖片描述

三. 碼,是如何生成的?

一個二維碼的生成大致分爲下面幾步:

數據分析

  1. 確定編碼的字符類型,按相應的字符集轉換成符號字符;
  2. 選擇糾錯等級,在規格一定的條件下,糾錯等級越高其真實數據的容量越小

數據編碼

  1. 類似於utf8編碼,給定一個字符串,然後將其編碼成一串二進制數。
  2. 根據選擇的編碼模式和版本信息、糾錯等級,生成原始信息的數據編碼。

糾錯編碼

  1. 根據源數據編碼結果可以計算得到糾錯碼,使用的是Reed-Solomon糾錯算法

構造矩陣

  1. 根據選擇的版本信息和整體結構中提到的3個部分,爲矩陣格子中分別填充0和1

掩碼

可能上面畫出來後,黑白分佈不均勻會導致存在大片的白色或黑色,造成掃描識別的困難。二維碼提供了8Mask掩碼圖案:

在這裏插入圖片描述

我們需要拿着上面生成的圖案和掩碼圖案做一次異或操作,這樣黑白分佈就會均勻。經過掩碼之後的二維碼,就是我們日常見到的分佈均勻的二維碼,至此繪製纔算完成。

四. 舉個例子

假設我們對字符串 “01234567” 生成一個二維碼,需要以下步驟:

1. 模式選擇

QR 碼支持的編碼模式有這些:

在這裏插入圖片描述

由於 “01234567” 都是數字,我們選擇數字模式。數字模式下,需要編碼的數字的個數如果不是3的倍數,會將最後剩下的 1 或 2 位數會被轉成 4 或 7 bits,其它的每 3 位數字會被編成 X 個 bits,(X大小需要基於二維碼的版本,沒有爲什麼一切都在 qr code spec 中有定義)

不同版本的二維碼容量不同,參考:

在這裏插入圖片描述

我們選擇 version 1 ,糾錯級別 H 完全足夠。每個版本下,不同編碼模式下需要被編碼的 bits 個數如下表:

在這裏插入圖片描述

因爲我們得出結論:

  1. “01234567” 選擇數字模式編碼
  2. 二維碼選擇 version 1 H
  3. 每3位數字會被編碼成10個bit,剩下的1或2位數會被轉成4或7bits

2. 編碼

分成 3 組,012 和 345 和 67。其中,012 轉成 0000001100(10位); 345 轉成 0101011001(10位); 67 轉成 1000011(不足3個數,編碼爲 7 個 bits)

3 個二進制串起來: 0000001100 0101011001 1000011

總共是 8 個數字,8 轉成二進制是 0000001000(10位),再加上我們選擇的數字模式的標識符 0001 ,最後得到二進制串爲:

0001 0000001000 0000001100 0101011001 1000011 0000
數字| 8個數字 | 012 | 345 | 67 | 結束符

共45個bit,按 8個bit 一組重新排列,不是8個倍數我們還要在後面加上足夠的0湊齊8個倍數:

00010000 00100000 00001100 01010110 01100001 10000000

共 48個bit,還沒有達到我們最大的 bits 數限制,則需要在編碼最後加上補齊符(Padding Bytes),我們選擇的是 version 1 的 H 級別,容量是 72 bits ,現在只有 48 個 bits,還差24個bits ,需要補齊。Padding Bytes就是重複補充這兩個 bytes 11101100 和 00010001 ,補充完整爲:

00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100

上面的編碼就是數據碼了,叫 Data Codewords,每一個8 bits 叫一個 codeword ,我們還要對這些數據碼加上糾錯信息。

3. 糾錯編碼

有了糾錯編碼,纔可以使得有些二維碼有了殘缺、污損也可以儘量掃碼解析出來;纔可以使得二維碼中心位置可以供某些商家加上對解析不必要的圖標

在這裏插入圖片描述

我們選擇的是級別 H,參考糾錯碼分組定義:

在這裏插入圖片描述

  • 糾錯塊個數(Number of error correction blocks):需要劃分糾錯塊的個數;
  • 糾錯塊碼字數(Error Correction Code Per Blocks):每個塊中的碼字個數,即有多少個字節 Bytes;

(26,9,8)表示在version 1 H 中,總共26個 codewords ,其中 9 個爲原始數據碼,17個爲糾錯碼,其中每個糾錯碼佔 8 個 bits

我們假設計算(計算方法)好的糾錯碼共 17 個 codewords,分別是 E1,E2,E3 …… E17

4. 最終編碼

原始的Data Codewords ,一共包含 9 個codewords:

00010000 00100000 00001100 01010110 01100001 10000000 11101100 00010001 11101100

我們分別命名爲:D1, D2, D3……D9

源碼和糾錯碼,最終形成的數據爲:D1 D2 D3 D3 D3 D3 D3 D3 D3 E1 E2 E3 …… E17

5. 構造矩陣

有了編碼,我們就可以畫圖像了。

首先根據 version 確定矩陣整體大小,我們是version 1 ,因此是 21 * 21 的矩陣。

接下來在左上、左下、右上三個位置填充定位標誌。

填充校驗方塊,確定校正標誌,填充格式信息,填充版本信息

最後填充數據和糾錯碼,從二維碼的右下角開始,沿着紅線填充我們數據編碼的每一個bit1表示黑色,0表示白色,遇到非數據區繞開或跳過。如圖示:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

6. 掩碼

這樣下來,我們的圖就填好了。但是,也許那些點並不均衡,如果出現大面積的空白或黑塊,掃描識別會很困難。所以,我們還要做 Masking 操作。QR 有8個 Mask 可以使用,每種 Mask 的圖示和算法,參考第三part中掩碼小節中的圖。

mask 就是和上面生成的圖做 XOR 操作,且只會和數據區進行 XOR ,不會影響功能區。

在這裏插入圖片描述

我們需要拿着上面生成的圖案和掩碼圖案做一次異或操作,這樣黑白分佈就會均勻很多!具體選擇哪一個掩碼圖案呢?也是有一個灰常複雜的計算方案,大體步驟是分別將原始圖案和每一個掩碼圖案做異或,然後按照一套規則來計算均勻程度,最終選擇最均勻的那個。參考 Data Masking深度探索二維碼原理及其應用

掩碼之後的二維碼就是最終的圖了。

五. 用完了該咋辦?

在這裏插入圖片描述

這是微信後臺下載的本公衆號名片,採用 37 * 37 規格的矩陣 (相信我,爲了數清楚,小眼睛已瞎)。以這個矩陣爲例:

3個定位區大小都是7 * 7,所以在這個矩陣上可用的格子數量是 37 * 37 - 3 * 7 * 7 = 1222 個。考慮到上半篇幅我們提到的掩碼,佔位之類的,假設只有 1000 個格子可用。每個格子或是黑或是白,只有 0 或 1 兩種選擇,1000 個格子組合下來是 2 ^ 1000,表示成 10 進制數字是(不用費工夫算了,計算器算不出來,寫程序搞出來的):

10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

這僅僅是理論值,再去掉全黑全白和其他不能用的情況,仍然是一個超級大的數。37 * 37 只是version 5 ,上半篇幅我們提到了 QR 碼有40個 version 。因此二維碼用完,存在理論上的可能性,不過你我一定是等不到那天了。即便是真到了用完的一天,參考 IPV4 升 IPV6 的方案可以繼續擴大尺寸。

六. 會不會重複?

二維碼作爲信息的載體,只要是信息是一致的那麼生成的二維碼就會重複。現實場景中,每個 APP 或者每個企業在內部環境下是可以保證信息的唯一性,因此我們生成的二維碼是唯一的。微信二維碼的唯一性是在微信系統之內的唯一。二維碼上的黑白點排列並不是隨機無意義的,而是原始二進制代碼,代表某種意義,而不同的人的二維碼要代表的事是不同的,所以不會有重複的。

其他

現在市面上出現了彩色二維碼,或者不規則二維碼。這個和本文講述的生成過程並不衝突。彩色二維碼被攝像頭掃描,採集到圖像後不是直接進行解析的,程序會對二維碼進行裁剪處理,去噪處理,灰度處理等。而所謂灰度處理,就是把圖片處理成灰度圖片,灰度圖像也稱爲“黑白”圖像。最終圖片會轉成只有 “0” 和 “1” 的矩陣。

參考

QR Code 官網

維基百科

Data Masking

深度探索二維碼原理及其應用

關注我

如果您在微信閱讀,請您點擊鏈接 關注我 ,如果您在 PC 上閱讀請掃碼關注我,歡迎與我交流隨時指出錯誤
小眼睛聊技術

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章