閑魚技術-上葉

背景:

隨著移動互聯網時代的到來,人類的科學技術突飛猛進。然而軟體工程師們依舊需要花費大量精力在重複的還原UI視覺稿的工作。 UI視覺研發擁有明顯的特徵:組件,位置和佈局,符合機器學習處理範疇。能否通過機器視覺和深度學習等手段自動生成UI界面代碼,來解放重複勞動力,成為我們關注的方向。

UI2CODE簡單介紹:

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

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

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

UI2CODE運行效果:

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


視頻封面

05:21

架構設計:

簡化分析下UI2CODE的流程:

大體分為4個步驟:

1.通過機器視覺技術,從視覺稿提取GUI元素
2.通過深度學習技術,識別GUI元素類型
3.通過遞歸神經網路技術,生成DSL
4.通過語法樹模板匹配,生成flutter代碼

版面分析

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

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

上圖是一個白色背景的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.

像切西瓜一樣,我們只需要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基本都是縱向流式佈局,我們可以先橫切在縱切。

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

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

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

組件識別:

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

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

UI組件,主要針對flutter原生的組件進行分類。
CI組件,主要針對閑魚自定義UIKIT進行分類。
BI組件,主要針對具備一定業務意義的feed卡片進行分類。

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

屬性提取:

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

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

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

佈局分析:

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


視頻封面

00:40

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

代碼生成及插件化:

機器學習本質上來說還屬於概率學範疇,自動生成的代碼需要非常高的還原度和100%的準確率,概率註定UI2CODE很難達到100%的準確率,所以我們需要提供一個可編輯工具,由開發者通過工具能夠快速理解UI的佈局結構和修改佈局結構。 我們將UI2CODE生成的DSL TREE進行代碼模板化匹配,代碼模板的內容由資深的flutter技術專家來定義,它代表目前我們發現的最優代碼實現方案。

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

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

小結:

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

歡迎關注微信公眾號「閑魚技術」查看ui2code以及flutter乾貨合集。


推薦閱讀:
相關文章