天天看點

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

閑魚技術-上葉

背景:

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

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

UI2CODE簡單介紹:

  UI2CODE項目是閑魚技術團隊研發的一款通過機器視覺了解+AI人工智能将UI視覺圖檔轉化為端側代碼的工具。

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

視覺稿還原精度:我們的設計師甚至無法容忍1像素的位置偏差;
準确率:機器學習還處于機率學範疇,但我們需要100%的準确率;
易維護性:工程師們看的懂,改的動是起點,合理的布局結構才能保障界面流暢運作。           

UI2CODE運作效果:

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

架構設計:

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

簡化分析下UI2CODE的流程:

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

大體分為4個步驟:

1.通過機器視覺技術,從視覺稿提取GUI元素
2.通過深度學習技術,識别GUI元素類型
3.通過遞歸神經網絡技術,生成DSL
4.通過文法樹模闆比對,生成flutter代碼
           

版面分析

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

  圖檔切割效果直接決定UI2CODE輸出結果的準确率。我們拿白色背景的簡單UI來舉例:

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

上圖是一個白色背景的UI,我們将圖檔讀入記憶體,進行二值化處理:

def image_to_matrix(filename):
    im = Image.open(filename)
    width, height = im.size
    im = im.convert("L")
    matrix = np.asarray(im)
    return matrix, width, height           

得到一個二維矩陣:将白色背景的值轉化為0.

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

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

def cut_by_col(cut_num, _im_mask):
    zero_start = None
    zero_end = None
    end_range = len(_im_mask)
    for x in range(0, end_range):
        im = _im_mask[x]
        if len(np.where(im==0)[0]) == len(im):
            if zero_start == None:
                zero_start = x
        elif zero_start != None and zero_end == None:
            zero_end = x
        if zero_start != None and zero_end != None:
            start = zero_start
            if start > 0:
                cut_num.append(start)
            zero_start = None
            zero_end = None
        if x == end_range-1 and zero_start != None and zero_end == None and zero_start > 0:
            zero_end = x
            start = zero_start
            if start > 0:
                cut_num.append(start)
            zero_start = None
            zero_end = None
           

用戶端的UI基本都是縱向流式布局,我們可以先橫切在縱切。

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

将切割點的x,y軸坐标記錄下來,它将是處理元件位置關系的核心。切割完成後,我們擷取到2組資料:6個GUI元素圖檔和對應的坐标系記錄。後續步驟通過分類神經網絡進行元件識别。

在實際生産過程中,版面分析會複雜些,主要是在處理複雜背景方面。

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

關注我們的技術公衆号,我們後續會詳細分解。

元件識别:

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

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

UI元件,主要針對flutter原生的元件進行分類。
CI元件,主要針對閑魚自定義UIKIT進行分類。
BI元件,主要針對具備一定業務意義的feed卡片進行分類。           
重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

元件的識别需要反複的通過全局特征回報來糾正,通常會采用SSD+CNN協同工作,比如下圖的紅色“全新“shape,這該圖例中是richtext的部分,同樣的shape樣式可能屬于button或者icon。

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

屬性提取:

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

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

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

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

通過這些資料我們就可以進行布局分析了。

其中文字屬性的提取最為複雜,後續我們會專門介紹。

布局分析:

  前期我們采用4層LSTM網絡進行訓練學習,由于樣本量比較小,我們改為規則實作。規則實作也比較簡單,我們在第一步切圖時5刀切割的順序就是row和col。缺點是布局比較死闆,需要結合RNN進行前置回報。

視訊中展示的是通過4層LSTM預測布局結構的效果,UI的布局結構就像房屋的架構,建造完成後通過GUI的屬性進行精裝修就完成了一個UI圖層的代碼還原工作。

代碼生成及插件化:

  機器學習本質上來說還屬于機率學範疇,自動生成的代碼需要非常高的還原度和100%的準确率,機率注定UI2CODE很難達到100%的準确率,是以我們需要提供一個可編輯工具,由開發者通過工具能夠快速了解UI的布局結構和修改布局結構。

  我們将UI2CODE生成的DSL TREE進行代碼模闆化比對,代碼模闆的内容由資深的flutter技術專家來定義,它代表目前我們發現的最優代碼實作方案。

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

代碼模闆中會引入一些标簽,由Intellij plugin來檢索flutter工程中是否存在對應的自定義UIKIT,并進行替換,提高代碼的複用度.

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

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

重磅系列文章|UI2Code智能生成Flutter代碼--整體設計篇

小結:

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

繼續閱讀