在過去的 2017 年,支付寶的線下場景不斷擴大,收錢碼、口碑、共享單車、充電寶、停車繳費等產品讓咱們的生活愈來愈便利。二維碼由於成本低、兼容性好成爲了線上線上最主要的鏈接工具,也所以面臨更多新的挑戰。由於二維碼是一種點陣式信息編碼方式,任何視覺上的缺損、彎曲以及光線做用都會極大的影響識別成功率,若是識別困難也就意味着用戶可能選擇放棄,影響支付體驗也影響用戶心智。面試
iOS開發交流技術羣:563513413,無論你是大牛仍是小白都歡迎入駐 ,分享BAT,阿里面試題、面試經驗,討論技術, 你們一塊兒交流學習成長!算法
用戶掃碼體驗的最關鍵的主要有如下幾個因素:app
本文將從以上三個方面,分享支付寶掃碼技術團隊是如何爲用戶打造一個又準又快又穩的極致掃碼體驗。框架
咱們對用戶反饋進行了大量統計分析,發現絕大部分識別失敗都是由於二維碼並不標準,而且很遺憾的是在使用咱們早期的掃碼版本進行識別率測試時發現識別率只有 60%;機器學習
** 策略 1:優化樁點查找算法長寬比耐受
以往的掃碼算法,檢查長寬比例時容許差別 40%,可是因爲使用前向偏差,判斷結果跟長寬的前後順序相關,這會致使有些長寬比失調的碼,橫着掃不出來,可是旋轉 90 度豎着卻能掃出來了 (^OMG^)。函數
優化策略工具
在咱們對比測試集中,識別率提升了 1% 左右。學習
在一張圖片中,要找到二維碼,關鍵在找二維碼特徵定位點:測試
三個角的回字型圖案,這就是二維碼特徵定位點。中間區域的黑白色塊比例是 1:1:3:1:1優化
以往的掃碼算法,樁點識別是經過狀態機 查找 11311 模式後 取中間位置肯定 x 位置 (此時掃描線在第一行 11311 比例處) 在 x 位置縱向搜索 11311 模式, 肯定 y 位置再以 (x,y) 位置橫向搜索 11311 比例,修正 x 位置。這種模式在樁點污損的狀況下,識別能力較差只要在任何一次 11311 模式搜索中遇到干擾點,哪怕是一個像素的椒鹽噪聲也能使樁點查找失敗。(支付寶藍的樁點,會在藍色區域產生大量噪點,致使識別率低下)
爲此,咱們新增了一種樁點識別方式。在狀態機達到 151 模式的時候,開始嘗試確認樁點。(此時掃描線在第一行 151 比例處)。
優化效果
在枚舉全部可能樁點組合 O(N^3) 以前,對全部可疑樁點進行一次對角線檢查過濾。因爲樁點對角線也應該知足 11311 模式 ,用這個規則作一次過濾可疑有效減小運算量,也就有效下降了識別成功和失敗的耗時。
在以往的掃碼算法中在拿到三個樁點後,基於夾角,長度誤差,單位長度查三個數值,用簡單公式計算獲得閾值,判斷是否爲可能的二維碼,誤判機率較大。
爲此,咱們引入機器學習中的邏輯迴歸算法模型。基於支付寶丰富的二維碼數據集,訓練出邏輯迴歸模型,做爲二維碼分類器,明顯下降了誤判機率,也將明顯下降無二維碼時識別失敗的耗時。
因爲輸入的相機幀分辨率高,像素點多,運算量大,以往的掃碼算法在水平跟垂直方向跳行採樣進行計算。但在實際運算中,因爲跳過了太多列,錯過了 11311 模式中某些 1 位置的點,致使樁點查找失敗。
咱們經過將跳行計算行數修改成可配置項,經過線上 AB 灰度測試獲得最合適的跳行策略,總體配置此跳行策略後,識別率獲得明顯提高。
上述優化在測試集的表現
綜上優化,掃碼核心識別能力,在 7744 張圖片測試集上提升了 6.95 個百分點。
除此上述通用掃碼優化以外,咱們還對特殊場景掃碼能力進行提升。
線下場景複雜多變。飲料瓶身上變形的二維碼、超市小票捲起邊角彎曲的二維碼、路邊小販凹凸不平甚至摺疊的二維碼…這些畸變的二維碼容易增長識別難度,甚至致使識別失敗。以往的掃碼算法抗畸變策略中,先用透視變換關係創建映射關係。優勢是:適應性好,知足大多數應用場景。 不足也明顯:對 Version 1 的碼,由於映射關係退化爲仿射變換,效果較差,手機必須和碼平面平行才能方便識別。當物料表面不是平面的時候,效果較差。
優化策略
用新的策略,發票碼這個場景的二維碼識別能力提高明顯。
注意:因爲採用了加強算法,請對準二維碼稍做等待。
商戶或者供應商生成二維碼後,一般會在二維碼的中間部分貼上 Logo,這部分有可能會使二維碼 Decode 時出錯。
優化策略:
對於採樣後拿到的 BitMatrix,對於中間部分一塊矩形區域內的點,採用某些策略來改變中間點的值,使它可以經過容錯邊界的檢查。目前採用兩種策略,第一種是反轉,第二種是每個點隨機取值。目前所取的矩形區域是長、寬的四分之一。
經過此項優化後,掃碼的容錯能力也獲得明顯提高。
GPU 計算二值化,下降識別單幀耗時
所謂圖像二值化就是將圖像上的像素點的灰度值設置爲 0 或 255,也就是將整個圖像呈現出明顯的只有黑和白的視覺效果。下圖左邊爲原圖,右邊是二值化處理過的圖。
在掃碼算法解碼前,有二值化計算,圖像的二值化計算能使圖像中數據量大爲減小,並弱化圖像模糊、顏色對比度不強、光線過強 / 太弱、圖像污損等狀況下其餘信息的干擾,更利於檢測識別。
傳統算法是在 CPU 上進行二值化運算,很是消耗 CPU 資源,但其實 GPU 更擅長大規模並行計算,因此咱們選擇使用 GPU 來作二值化計算。在安卓平臺上使用 RenderScript,iOS 平臺上使用 Metal,都是很底層的框架。
優化結果
1.iOS: 統一電池、角度、光線等環境變量, 在 iPhone6 上測試掃碼核心 5 種攝像頭二值化算法。表現以下:
能夠看出,在圖像二值化方面 Metal 有至關高的優點,相比原來的單純 CPU 處理快了接近 150%, 同時下降了近 50 個百分點的 CPU 資源。
2.Android 機型衆多,咱們抽取了線上數據,能夠看到 GPU 在二值化處理中顯著下降了單幀耗時 30% 以上。
線下物料千奇百怪,掃碼算法爲了解決一些不理想的場景,如二維碼有遮擋、污損、模糊或角度很很差的特殊狀況,須要使用一些比較耗時但比較強大的算法,但普通狀況不須要這些算法。因此,咱們對識碼算法定了優先級,經過時間推移、跳幀觸發等方式調度:
優先級: 暫定高中低三個優先級。
特殊場景算法:
爲碼核心的一種特定能力,如: