UI2CODE智慧生成Flutter程式碼——整體設計篇

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

0背景

隨著移動網際網路時代的到來,人類的科學技術突飛猛進。然而軟體工程師們依舊需要花費大量精力在重複的還原UI視覺稿的工作。

UI視覺研發擁有明顯的特徵:元件,位置和佈局,符合機器學習處理範疇。能否透過機器視覺和深度學習等手段自動生成UI介面程式碼,來解放重複勞動力,成為我們關注的方向。

0UI 2 Code是什麼

UI2CODE專案是閒魚技術團隊研發的一款透過機器視覺理解+AI人工智慧將UI視覺圖片轉化為端側程式碼的工具。

2018年3月UI2CODE開始啟動技術可行性預研工作,到目前為止,經歷了3次整體方案的重構(或者重寫)。我們參考了大量的利用機器學習生成程式碼的方案,但都無法達到商用指標,UI2CODE的主要思想是將UI研發特徵分而治之,避免雞蛋放在一個籃子裡。我們著重關注以下3個問題的解法:

  1. 視覺稿還原精度:我們的設計師甚至無法容忍1畫素的位置偏差;

  2. 準確率機器學習還處於機率學範疇,但我們需要100%的準確率

  3. 易維護性:工程師們看的懂,改的動是起點,合理的佈局結構才能保障介面流暢執行。

0UI 2 Code執行效果

UI2CODE外掛化執行效果,如下影片:進過幾輪重構,最終我們定義UI2CODE主要解決feeds流的卡片自動生成,當然它也可以對頁面級自動生成。

0架構設計

UI2CODE智慧生成Flutter程式碼——整體設計篇簡化分析下UI2CODE的流程:
UI2CODE智慧生成Flutter程式碼——整體設計篇大體分為4個步驟:
  1. 1.透過機器視覺技術,從視覺稿提取GUI元素

  2. 2.透過深度學習技術,識別GUI元素型別

  3. 3.透過遞迴神經網路技術,生成DSL

  4. 4.透過語法樹模板匹配,生成flutter程式碼

0版面分析

版面分析只做一件事:切圖。

圖片切割效果直接決定UI2CODE輸出結果的準確率。我們拿白色背景的簡單UI來舉例:
UI2CODE智慧生成Flutter程式碼——整體設計篇上圖是一個白色背景的UI,我們將圖片讀入記憶體,進行二值化處理:

  1. def image_to_matrix(filename):

  2.    im = Image.open(filename)

  3.    width, height = im.size

  4.    im = im.convert("L")

  5.    matrix = np.asarray(im)

  6.    return matrix, width, height

得到一個二維矩陣:將白色背景的值轉化為0。UI2CODE智慧生成Flutter程式碼——整體設計篇

像切西瓜一樣,我們只需要5刀,就可以將GUI元素分離,切隔方法多種多樣:(下面是橫切的程式碼片段,實際切割邏輯稍微複雜些,基本是遞迴過程)

  1. def cut_by_col(cut_num, _im_mask):

  2.    zero_start = None

  3.    zero_end = None

  4.    end_range = len(_im_mask)

  5.    for x in range(0, end_range):

  6.        im = _im_mask[x]

  7.        if len(np.where(im==0)[0]) == len(im):

  8.            if zero_start == None:

  9.                zero_start = x

  10.        elif zero_start != None and zero_end == None:

  11.            zero_end = x

  12.        if zero_start != None and zero_end != None:

  13.            start = zero_start

  14.            if start > 0:

  15.                cut_num.append(start)

  16.            zero_start = None

  17.            zero_end = None

  18.        if x == end_range-1 and zero_start != None and zero_end == None and zero_start > 0:

  19.            zero_end = x

  20.            start = zero_start

  21.            if start > 0:

  22.                cut_num.append(start)

  23.            zero_start = None

  24.            zero_end = None

客戶端的UI基本都是縱向流式佈局,我們可以先橫切在縱切。UI2CODE智慧生成Flutter程式碼——整體設計篇

將切割點的x,y軸座標記錄下來,它將是處理元件位置關係的核心。切割完成後,我們獲取到2組資料:6個GUI元素圖片和對應的座標系記錄。後續步驟透過分類神經網路進行元件識別。

在實際生產過程中,版面分析會複雜些,主要是在處理複雜背景方面。UI2CODE智慧生成Flutter程式碼——整體設計篇關注我們的技術公眾號,我們後續會詳細分解。

0元件識別

進行元件識別前我們需要收集一些元件樣本進行訓練,使用Tensorflow提供的CNN模型和SSD模型等進行增量訓練。

UI2CODE對GUI進行了幾十種型別分類:IMAGE, TEXT,SHAPE/BUTTON,ICON,PRICE等等,分別歸類為UI元件,CI元件和BI元件。

  1. UI元件,主要針對flutter原生的元件進行分類。

  2. CI元件,主要針對閒魚自定義UIKIT進行分類。

  3. BI元件,主要針對具備一定業務意義的feed卡片進行分類。

UI2CODE智慧生成Flutter程式碼——整體設計篇

元件的識別需要反覆的透過全域性特徵反饋來糾正,通常會採用SSD+CNN協同工作,比如下圖的紅色“全新“shape,這該圖例中是richtext的部分,同樣的shape樣式可能屬於button或者icon。

UI2CODE智慧生成Flutter程式碼——整體設計篇

0屬性提取

這塊的技術點比較雜,歸納起來需要處理3部分內容:shape輪廓, 字型屬性和元件的寬高。

UI2CODE智慧生成Flutter程式碼——整體設計篇

完成屬性提取,基本上我們完成所有GUI資訊的提取。生成的GUI DSL如下圖:

UI2CODE智慧生成Flutter程式碼——整體設計篇

透過這些資料我們就可以進行佈局分析了。其中文字屬性的提取最為複雜,後續我們會專門介紹。

0佈局分析

前期我們採用4層LSTM網路進行訓練學習,由於樣本量比較小,我們改為規則實現。規則實現也比較簡單,我們在第一步切圖時5刀切割的順序就是row和col。缺點是佈局比較死板,需要結合RNN進行前置反饋。


影片中展示的是透過4層LSTM預測佈局結構的效果,UI的佈局結構就像房屋的框架,建造完成後透過GUI的屬性進行精裝修就完成了一個UI圖層的程式碼還原工作。

09 程式碼生成及外掛化

機器學習本質上來說還屬於機率學範疇,自動生成的程式碼需要非常高的還原度和100%的準確率,機率註定UI2CODE很難達到100%的準確率,所以我們需要提供一個可編輯工具,由開發者透過工具能夠快速理解UI的佈局結構和修改佈局結構。   

我們將UI2CODE生成的DSL TREE進行程式碼模板化匹配,程式碼模板的內容由資深的flutter技術專家來定義,它代表目前我們發現的最優程式碼實現方案。

UI2CODE智慧生成Flutter程式碼——整體設計篇

程式碼模板中會引入一些標籤,由Intellij plugin來檢索flutter工程中是否存在對應的自定義UIKIT,並進行替換,提高程式碼的複用度。

UI2CODE智慧生成Flutter程式碼——整體設計篇

整個外掛化工程需要提供自定義UIKIT的檢索,替換和校驗工作,以及DSL Tree的建立,修改,圖示等工作,總體來說,更像ERP系統,花費一些時間能夠做的更加完美。

UI2CODE智慧生成Flutter程式碼——整體設計篇

10 小結

本篇我們簡單介紹了UI2CODE的設計思路,我們將整個工程結構分為5個部分,其中4塊內容核心處理機器視覺的問題,透過機器學習將它們連結起來。程式碼的線上釋出是非常嚴格的事情,而機器學習屬於機率學解法,很難達到我們要求的精度,所以我們選擇以機器視覺理解為主,機器學習為輔的方式,構建整個UI2CODE工程體系。我們將持續關注AI技術,來打造一個完美的UI2CODE工具。

相關文章