UI2Code智慧生成Flutter程式碼——版面分析篇

閒魚技術發表於2019-02-27

背景

《UI2CODE--整體設計》篇中,我們提到UI2Code工程的第一步是版面分析,如果是白色的簡單背景,我們可以像切西瓜一樣,將圖片資訊切割為GUI元素。但是在實際生產過程中,UI的複雜度會高很多。本篇我們將圍繞版面分析這塊內容分享我們的探索過程。

架構設計

版面分析主要處理UI影像的前景提取和背景分析:

UI2Code智慧生成Flutter程式碼——版面分析篇

透過前後景分離演算法,將UI視覺稿剪裁為GUI元素。本文將重點為大家講解以下兩部分的思路和難點。

  1. 背景分析:透過機器視覺演算法,分析背景顏色,背景漸變方向,以及背景的連通區域。

  2. 前景分析:透過深度學習演算法,對GUI碎片進行整理,合併,識別。

背景分析

背景分析的關鍵在於找到背景的連通區域和閉合區間;

我們從一個實際的應用場景來分析整個背景提取的過程:

UI2Code智慧生成Flutter程式碼——版面分析篇

我們期望將上一張圖片,透過UI2CODE,來提取GUI元素。

判斷背景區塊,透過sobel,lapacian,canny等邊緣檢測方法計算出梯度變化方向,從而得到純色背景和漸變色背景區域。

基於拉普拉斯運算元的背景區域提取UI2Code智慧生成Flutter程式碼——版面分析篇

離散拉普拉斯運算元的模板:

UI2Code智慧生成Flutter程式碼——版面分析篇

擴充套件模板:

UI2Code智慧生成Flutter程式碼——版面分析篇

當該區域點與模板點乘,得到的數值越小越是平坦的區域,即接近背景區域。如果是漸變色區域,則統計它的運動趨勢。(左->右,右->左,上->下, 下->上)

提取效果如下:

UI2Code智慧生成Flutter程式碼——版面分析篇

我們發現上圖雖然能大致提取背景輪廓,但是對於有漸變色的背景還是比較粗糙。

因此我們透過統計背景運動趨勢的方式來判定它是否存在漸變色背景。如果存在,我們將透過第二步進行精細化處理。

基於漫水填充演算法,選取漫水的種子節點,濾除漸變色背景區域噪聲。

  1. def fill_color_diffuse_water_from_img(task_out_dir, image, x, y, thres_up = (10, 10, 10), thres_down = (10, 10, 10), fill_color = (255,255,255)):

  2. """

  3. 漫水填充:會改變影像

  4. """

  5. # 獲取圖片的高和寬

  6. h, w = image.shape[:2]

  7. # 建立一個h+2,w+2的遮罩層,

  8. # 這裡需要注意,OpenCV的預設規定,

  9. # 遮罩層的shape必須是h+2,w+2並且必須是單通道8位,具體原因我也不是很清楚。

  10. mask = np.zeros([h + 2, w + 2], np.uint8)

  11. # 這裡執行漫水填充,引數代表:

  12. # copyImg:要填充的圖片

  13. # mask:遮罩層

  14. # (x, y):開始填充的位置(開始的種子點)

  15. # (255, 255, 255):填充的值,這裡填充成白色

  16. # (100,100,100):開始的種子點與整個影像的畫素值的最大的負差值

  17. # (50,50,50):開始的種子點與整個影像的畫素值的最大的正差值

  18. # cv.FLOODFILL_FIXED_RANGE:處理影像的方法,一般處理彩色圖象用這個方法

  19. cv2.floodFill(image, mask, (x, y), fill_color, thres_down, thres_up, cv2.FLOODFILL_FIXED_RANGE)

  20. cv2.imwrite(task_out_dir + "/ui/tmp2.png", image)

  21. # mask是非常重要的一個區域,這塊區域內會顯示哪些區域被填充了顏色

  22. # 對於UI自動化,mask可以設定成shape,大小以1最大的寬和高為準

  23. return image, mask

處理過後的效果如下:

UI2Code智慧生成Flutter程式碼——版面分析篇

透過版面切割提取GUI元素(切割方法之前有提到過)。

UI2Code智慧生成Flutter程式碼——版面分析篇

這個時候我們已經成功提取了80%的GUI元素,但是疊加圖層部分元素還無法解析。

透過霍夫直線、霍夫圖和輪廓查詢的方式找到對稱的輪廓區域。對提取的輪廓區域做第二步到第四步到遞迴處理。

UI2Code智慧生成Flutter程式碼——版面分析篇

複雜背景的提取是後續前景分析的基礎。當提煉出背景區域後,我們就可以透過連通域分析前景區域,並利用元件識別的方式分析前景類別,再透過語義分析等方式對前景做拆分和合並。

背景分析總結

對比較簡單的漸變色背景,透過上述四步基本都能夠解決。基於霍夫直線和霍夫圓的思想,去查詢特定的輪廓區域,並分析這些輪廓區域做細化分析。再透過漫水填充的方式消除漸變色背景。

UI2Code智慧生成Flutter程式碼——版面分析篇

對於複雜背景的處理,可以基於目標檢測的方法,找到一些特定含義的內容。再利用馬爾科夫隨機場(mrf)細化邊緣特徵。

前景分析

前景分析的關鍵在於元件完整性切割與識別;我們透過連通域分析,防止元件碎片化,再透過機器學習識別元件型別,再透過元件型別進行碎片化合並,反覆執行上述動作,直到無特徵屬性碎片。

但是有些情況會比較複雜,我們透過瀑布流中提取一個完整item為例:

概述

閒魚頁面中瀑布流卡片識別是實現佈局分析的一個重要步驟,需求是當卡片完整出現在截圖影像中時(允許圖示遮擋)需要識別出來,卡片被背景部分遮擋時不應該識別出來。下圖所示的瀑布流卡片樣式,由於其佈局緊湊且樣式繁多,導致容易產生漏檢或誤檢。

UI2Code智慧生成Flutter程式碼——版面分析篇

瀑布流卡片樣式 a)紅框顯示卡片部分被圖示遮擋 b)紅框顯示卡片內圖片顏色和卡片外背景顏色接近

基於邊緣梯度或連通域的傳統影像處理方法能根據影像本身的灰度或者形狀特徵提取出瀑布流卡片的輪廓,優點是定位精度高、運算速度快。缺點是容易受到干擾,召回率不高。

基於目標檢測或者特徵點檢測的深度學習方法採用有監督的方式學習卡片的樣式特徵,優點是不易受到干擾,召回率很高。缺點是因為涉及迴歸過程,定位精度比傳統影像處理方法要低,並且需要大量的人工標註,運算速度也比傳統影像處理方法要慢。

整合學習的啟發,透過融合傳統影像處理方法和深度學習方法,結合兩者各自的優點,最終能得到具有較高精確率、召回率和定位精度的識別結果。

傳統影像處理

演算法流程

整個演算法流程如下圖所示:
1》. 輸入的瀑布流卡片影像轉換成灰度圖後使用對比度受限的自適應直方圖均衡化(CLAHE)進行增強
2》. 使用Canny運算元進行邊緣檢測得到二值化影像
3》. 對二值化影像進行形態學膨脹處理,連線斷開的邊緣
4》. 提取連續邊緣的外層輪廓,並基於輪廓包含區域的面積大小丟棄面積較小的輪廓,輸出候選輪廓
5》. 使用Douglas-Peucker演算法進行矩形逼近,保留最像矩形的外輪廓,輸出新的候選輪廓
6》. 最後對第4步的候選輪廓進行水平和垂直方向投影得到平滑的輪廓作為輸出

UI2Code智慧生成Flutter程式碼——版面分析篇

卡片輪廓提取流程

邊緣檢測

演算法流程中1》-3》可以歸為邊緣檢測部分。

受各種因素影響,影像會出現降質,需要對其進行增強來提高邊緣檢測的效果。使用全圖單一的直方圖進行均衡化顯然不是最好的選擇,因為擷取的瀑布流影像不同區域對比度可能差別很大,增強後的影像可能會產生偽影。在單一直方圖均衡化的基礎上,學者基於分塊處理的思想提出了自適應的直方圖均衡化演算法(AHE),但是AHE在增強邊緣的同時有時候也會將噪聲放大。後來學者在AHE的基礎上提出了CLAHE,利用一個對比度閾值來去除噪聲的干擾,如下圖所示直方圖,CLAHE不是將直方圖中超過閾值的部分丟棄,而是將其均勻分佈於其他bin中。

UI2Code智慧生成Flutter程式碼——版面分析篇

CLAHE對比度限制示意圖

Canny運算元是一種經典的邊緣檢測運算元,它能得到精確的邊緣位置。Canny檢測的一般步驟為:1)用高斯濾波進行降噪 2)用一階偏導的有限差分計算梯度的幅值和方向 3)對梯度幅值進行非極大值抑制 4)用雙閾值檢測和連線邊緣。實驗過程中,需要多次嘗試選擇較好的雙閾值引數

檢測出來的邊緣在某些區域性地方會斷開,可以採用特定形狀和尺寸的結構元素對二值化影像進行形態學膨脹處理來連線斷開的邊緣。邊緣檢測的結果如下圖所示,其中c)中CLAHE設定對比度閾值為10.0,區域大小為(10,10),d)中Canny檢測設定雙閾值為(20,80),e)中形態學膨脹結構元素使用大小為(3,3)的十字線。

UI2Code智慧生成Flutter程式碼——版面分析篇

邊緣檢測結果 a)原始影像 b)灰度化影像 c)CLAHE增強影像 d)Canny檢測影像 e)形態學膨脹影像

輪廓提取

演算法流程中4》-6》可以歸為輪廓提取部分。

二值影像形態學膨脹處理後,首先提取連續邊緣的外層輪廓。如下圖所示,對於只有0和1的二值影像,假設S1為畫素值為0的一堆背景點,S2為畫素值為1的一堆前景點,外層輪廓B1為一堆前景點最外圍的點,內層輪廓B2為一堆前景點最內部的點。透過對二值影像進行行掃描給不同輪廓邊界賦予不同的整數值,從而確定輪廓的型別以及之間的層次關係。提取出外層輪廓後透過計算輪廓包含的面積大小丟棄面積較小的外層輪廓,輸出第一步候選輪廓。

UI2Code智慧生成Flutter程式碼——版面分析篇

內外輪廓示意圖

閒魚頁面瀑布流卡片輪廓近似於矩形,在四個角由弧形曲線連線。對於提取的候選輪廓使用Douglas-Peucker演算法進行矩形逼近,保留形狀接近矩形的外輪廓。Douglas-Peucker演算法透過將一組點表示的曲線或多邊形擬合成另一組更少的點,使得兩組點之間的距離滿足特定的精度。之後輸出第二步候選輪廓。
透過對第二步候選輪廓所處位置對應的第一步候選輪廓進行水平和垂直方向投影,去除毛刺影響,輸出矩形輪廓。輪廓提取的結果如下圖所示,其中c)中輪廓包含面積設定的閾值為10000,d)中Douglas-Peucker演算法設定的精度為0.01*輪廓長度。本文所有提取的輪廓均包含輸入框。

UI2Code智慧生成Flutter程式碼——版面分析篇

輪廓提取結果 a)原始影像 b)形態學膨脹影像 c)紅色線段為第一步候選輪廓 d)紅色線段為第二步候選輪廓 e)紅色線段為最終輸出矩形輪廓

深度學習演算法

目標檢測演算法

傳統演算法中提出採用傳統影像處理方法提取輪廓特徵,這樣會帶來一個問題:當影像不清晰或者有遮擋的情況下無法提取出輪廓,即召回率不是很高。
基於卷積神經網路目標檢測演算法能透過輸入大量樣本資料,學習到更具有代表性和區別性的特徵。目前目標檢測演算法主要分成兩個派系:以R-CNN家族為代表的兩階段流和以YOLOSSD為代表的一階段流。一階段流直接對預測的目標進行分類和迴歸,優點是速度快,缺點是mAP整體上沒有兩階段流高。兩階段流在對預測的目標進行分類和迴歸前需要先生成候選的目標區域,這樣訓練時更容易收斂,因此優點是mAP高,缺點是速度上不如一階段流。不管是一階段流還是兩階段流,通用的目標檢測推理過程如圖所示。輸入一張影像到特徵提取網路(可選擇VGG、Inception、Resnet等成熟的CNN網路)得到影像特徵,然後將特定區域特徵分別送入分類器和迴歸器進行類別分類和位置迴歸,最後將框的類別和位置進行輸出。

UI2Code智慧生成Flutter程式碼——版面分析篇

目標檢測推理過程

Faster R-CNN

Faster R-CNN對R-CNN家族最大的貢獻是將生成候選目標區域的過程整合到整個網路中,使得綜合效能有了較大提高,尤其是在檢測速度上。Faster R-CNN的基本結構如圖所示。主要分為4個部分:1)conv layers。作為一種特徵提取網路,使用一組基礎的conv+relu+pooling層提取影像的特徵,該特徵被共享用於後續RPN網路和全連線層。2)Region Proposal Network。該網路用於生成候選目標框,透過softmax判斷候選框是屬於前景還是背景,並且透過候選框迴歸修正候選框位置。3)RoI pooling。收集輸入的特徵圖和候選區域,將這些候選區域對映到固定大小並送入後續全連線層。4)classifer。計算候選框的具體類別,並且再次迴歸修正候選框的位置。

UI2Code智慧生成Flutter程式碼——版面分析篇

Faster R-CNN基本結構

使用Faster R-CNN進行瀑布流卡片的識別,得到下圖的結果。

UI2Code智慧生成Flutter程式碼——版面分析篇

Faster R-CNN識別結果 a)原始影像 b)紅框顯示識別的卡片

傳統演算法與機器學習的融合

融合流程

描述的傳統影像方法能夠獲得高定位精度的卡片位置,但受卡片本身模式的影響,召回率不高)中右邊卡片沒有檢測到。上文中描述的基於目標檢測深度學習方法具有較高的泛化能力,能獲得較高的召回率,但是迴歸過程無法得到高定位精度的卡片位置)中卡片都能檢測出來,但有兩個卡片的邊緣幾乎粘連在了一起。

將兩種方法得到的結果融合在一起,能同時獲得高精確率、高召回率、高定位精度的檢測結果。融合過程如下:

  1. 輸入一張影像,並行執行傳統影像處理方法和深度學習方法,分別得到提取的卡片框trbox和dlbox。定位精度以trbox為標杆,精確率和召回率以dlbox為標杆

  2. 篩選trbox。規則為當trbox與dlbox的IOU大於某個閾值時(比如0.8)保留此trbox,否則丟棄,得到trbox1

  3. 篩選dlbox。規則為當dlbox與trbox1的IOU大於某個閾值時(比如0.8)丟棄此dlbox,否則保留,得到dlbox1

  4. 修正dlbox1位置。規則為dlbox1的每條邊移動到距離其最近的一條直線上,約束條件為移動的距離不能超過給定的閾值(比如20個畫素),並且移動的邊不能跨越trbox1的邊,得到修正的dlbox2

  5. 輸出trbox1+dlbox2為最終融合的卡片框

指標結果

先介紹幾個基本指標:
True Positive(TP):被模型預測為正的正例數
True Negative(TN):被模型預測為負的負例數
False Positive(FP):被模型預測為正的負例數
False Negative(FN):被模型預測為負的正例數
精確率(Precision) = TP/(TP+FP):反映了被模型預測的正例中真正的正樣本所佔比重
召回率(Recall) = TP/(TP+FN):反映了被模型正確預測的正例佔總的正樣本比重
定位精度(IOU) = 兩個框的交集大小/兩個框的並集大小

UI2Code智慧生成Flutter程式碼——版面分析篇

融合結果 a)原始影像 b)紅框顯示傳統影像處理識別的卡片 c)紅框顯示深度學習識別的卡片 d)紅框顯示融合b)和c)後的卡片

上圖分別顯示了不同方法識別的卡片,d)相對於b)的優勢是提高了召回率,d)相對於c)的優勢是提高了定位精度。

圖一圖二圖三顯示了一些其他例項影像的識別,每行影像是一類例項圖,第一列是原始影像,第二列是傳統影像處理識別的卡片,第三列是深度學習識別的卡片,第四列是融合的卡片。

圖一圖二能夠準確識別卡片輪廓:

UI2Code智慧生成Flutter程式碼——版面分析篇圖一

UI2Code智慧生成Flutter程式碼——版面分析篇圖二

圖三融合卡片的下邊緣並沒有完全貼合,這是因為融合步驟中修正dlbox1位置時,採用傳統影像處理方法尋找臨域範圍內最近的直線,受到影像樣式的影響,找到的直線並不是期望的卡片下邊緣。

UI2Code智慧生成Flutter程式碼——版面分析篇

圖三

實驗過程中隨機擷取了50張閒魚瀑布流卡片影像,共有卡片96個(不包含輸入框),對每張影像分別採用傳統影像處理方法、深度學習方法、融合方法得到卡片的識別結果,其中傳統影像處理方法共識別出65個卡片,深度學習方法共識別出97個,融合後共識別出98個。精確率、召回率、定位精度如下表所示。融合後識別結果結合了傳統影像處理方法定位精度高、深度學習方法召回率高的優點。

UI2Code智慧生成Flutter程式碼——版面分析篇

前景演算法小結

透過對閒魚頁面瀑布流卡片識別過程中的描述,我們簡單介紹了前景處理的探索,透過機器視覺演算法和機器學習演算法協同完成前景元素的提取和識別。

結束語

本篇我們透過對前景提取和背景分析的介紹,提出了一種透過傳統影像處理深度學習相融合的方法,來得到高精確率、高召回率和高定位精度的識別結果。但方法本身還存在一些瑕疵,比如融合過程對元件元素進行修正時也會受到影像樣式的干擾,後續這部分可以進一步進行最佳化。歡迎繼續關注本公眾號後續即將更新的系列文章。

相關文章