UI2CODE智慧生成程式碼——元件識別篇

閒魚技術發表於2019-05-14

背景

《UI2CODE——整體設計篇》中,我們介紹了UI2CODE工程的整體流程:

UI2CODE智慧生成程式碼——元件識別篇

在元件識別這個環節,需要有一種處理佈局資訊的方法,來解析和計算控制元件間的佈局關係(比如識別業務元件(BI元件)和查詢重複佈局),以此來提高最終程式碼的可用性。

在這篇文章,我們將介紹一種佈局資訊的結構化方法:“連線法”,以及一種佈局間的計算和比較方法: “引導連線法”

首先來看我們需要解決的問題。

問題一:識別業務元件

01  目的:程式碼複用

業務元件是指某些特定的卡片,比如一個商品詳情卡片,這些卡片會在不同頁面出現,而這些卡片的程式碼一般是已經存在的。我們在拿到一張圖片的時候,需要先識別出這些元件,這樣這一區塊就能複用已有的元件程式碼,而不會造成很多冗餘的一次性程式碼。

UI2CODE智慧生成程式碼——元件識別篇

0老解法:利用SDD模型做物體檢測

如果把尋找業務元件這個問題看成從一張大圖片上尋找小圖片的話,那麼最直接的做法就是用一個物體檢測模型(比如SSD)來做,這樣只要訓練模型來識別每個業務元件的圖片就可以了。因此我們嘗試了用訓練SSD模型來解決這個問題。

0存在的問題:訓練困難,結果不可控

經過訓練和測試以後,我們發現用物體檢測模型來解這個問題的弊端:

  1. 需要造大量樣本。由於圖片資訊豐富,為了避免過擬合,需要造大量樣本來訓練。

  2. 訓練困難,增加新的業務元件成本太高。每增加一個新的業務元件,就需要先造這個元件的樣本,然後重新調整訓練模型。

  3. 訓練結果不可控。對於一些badcase,沒有一些直接有效的方式來做調整和控制,只能不斷調整樣本。

0思考:是否可以利用已有的控制元件資訊

既然前面已經解析出了各個控制元件的資訊(包含型別以及位置等),那麼我們是否可以直接利用這些資訊來做處理呢?因此我們想要尋找一種新的方式,來處理和解析控制元件資訊,利用這些資訊來實現類似“物體檢測”功能。

問題二:重複佈局

0目的:提升程式碼可用性

UI2CODE智慧生成程式碼——元件識別篇

如上圖這個case,對於類似“GridView”的這種佈局,我們理想的佈局方式應該是有8個Item,每個Item包含一個TextView和ImageView(上圖左邊)。

0存在的問題:無法識別重複佈局

然而實際情況是,我們沒有做重複佈局的檢測,因此佈局的時候變成了4行(上圖右邊)。

0思考:如何比較佈局是否重複

為了解決上面的問題,我們就需要尋找一種方法,從多個控制元件資訊中,找到一些規律,自動找到這些具有相似情況的佈局。

問題分析

以上就是我們需要解決的兩個問題,我們分析這兩個問題,會發現他們有一些共同點:

  1. 都是由多個控制元件組成大的佈局

  2. 佈局間需要進行比較,尋找“相似佈局”

  3. 都是非結構化資料:無法直接比較、計算

解決思路

首先我們需要將非結構化資料轉換為結構化資料(或者叫特徵提取),這個思路可以參考圖片分類任務的做法,不管是聚類演算法還是AI模型,都是先做特徵提取,再進行進一步處理,實際上做的就是非結構化資料轉換成結構化資料。

UI2CODE智慧生成程式碼——元件識別篇

因此,我們的問題解決思路也就分為兩步:

1. 佈局資訊結構化:將佈局資訊處理成結構化的資料

2. 佈局比較:對佈局進行比較、計算,尋找相似佈局

佈局資訊結構化

為了分析控制元件間的關係,我們可以先從簡單的開始,看一下兩個控制元件之間的關係都包含哪些資訊。

01 控制元件間的關係

兩個控制元件間的關係,包含以下2個方面的資訊:

1. 控制元件屬性(型別、文字內容、位置、大小)

2. 方向、距離、對齊方式(用連線表達)

控制元件屬性

對於控制元件屬性,可以直接用它自身表示,包含控制元件型別、內容、位置、大小等

方向和距離

UI2CODE智慧生成程式碼——元件識別篇

對於兩個控制元件的方向和距離,我們可以用一條虛擬的“連線”來表示,這條連線連線兩個控制元件的中心點。這樣,這條連線的長度和角度就可以表示兩個控制元件的方向和距離。比如上圖,我們可以得到:一個TextView在一個ImageView正上方,距離xxx畫素。

對齊方式

UI2CODE智慧生成程式碼——元件識別篇

但是除了角度和方向,實際上還存在著一個“對齊方式”資訊。

比如上圖這個case,如果我們還是連線兩個控制元件的中心點的話(圖中藍色虛線),那這左右兩邊的圖就是指不同的佈局(因為兩個控制元件的角度和距離都不一樣)。

但是由我們人“肉眼”來看,我們會認為這兩個佈局是一樣的,都是左邊一個頭像,右邊上面跟著一個文字。

因此,我們需要連線TextView的“左邊中點”(圖上紅色實線),這樣,不同的連線點位置,就可以表達不同的對齊方式。左對齊的TextView連線左邊中點,右對齊的TextView連線右邊中點,居中的連線中心點。

0定義資料結構

有了上面的分析,我們就可以定義一個資料結構。我們用一個Connection物件表達2個控制元件間的佈局關係,它包含:

  1. 控制元件1屬性(型別、位置大小等)

  2. 控制元件2屬性(型別、位置大小等)

  3. 控制元件1和控制元件2間的多條連線(角度、距離)

UI2CODE智慧生成程式碼——元件識別篇

這樣,2個Connection之間就可以進行比較、判斷是否“匹配”

0Connection匹配計算

兩個Connection之間是否“匹配”,必須滿足:

  1. 控制元件資訊匹配(型別一致、ImageView面積相似度滿足要求等)

  2. 方向和距離匹配(連線的餘弦相似度)

  3. 其它自定義的匹配要求

0整個佈局的表示

兩個控制元件間的關係可以用一個Connection來表示,那麼多個控制元件組成的大布局,就可以用一組Connection來表示。

我們對每兩個控制元件建立一個Connection,就可以得到一個Connection陣列

UI2CODE智慧生成程式碼——元件識別篇

這樣,我們的第一步“佈局資訊結構化”就完成了。

佈局間比較

將佈局資訊轉換成Connection陣列以後,我們就可以開始利用這些資訊來查詢相似佈局。

首先,我們可以理解這樣一個概念,就是:

一個佈局,可以看成由一組Connection物件串聯起來,得到的一個“路徑”

UI2CODE智慧生成程式碼——元件識別篇如上圖,藍色圈內的佈局可以看成一組Connection串聯起來(紅色連線)。

那麼,尋找相似佈局,就是尋找兩條相似“路徑”的過程

0引導連線法

為了尋找相似路徑,我們定義了一個“引導連線法”。

所謂“引導連線法”,就是一個 Leader,一個 Follower,Follower 嘗試著跟隨 Leader 走出一條一樣的路徑。

步驟如下:

  1. 計算出所有相互匹配的Connection(如下圖所有綠色的連線)

  2. 定義一個“Leader”叫A,一個 “Follower” 叫B

  3. 隨機選擇一條綠色連線作為A的初始路徑,與其相匹配的另一條綠色連線作為B的初始路徑

  4. A嘗試著繼續往前走,找到下一個路徑(綠色連線),B嘗試著跟隨

  5. 如果B能跟的上(即找到了一條路徑,剛好與A想走的路徑匹配上),那麼A繼續往下走,如果B跟不上,那麼A換條路徑繼續嘗試。

  6. 直到A走的路徑B怎麼也跟不上時,A和B走過的路徑所對應的那些控制元件,就是擁有相似佈局的控制元件。UI2CODE智慧生成程式碼——元件識別篇

應用效果

有了結構化的方法和“引導連線法”,我們就可以應用到上述兩個問題。

0業務元件

應用

  1. 對業務元件進行結構化處理(圖左紅色連線)

  2. 對待處理圖片進行結構化處理

  3. 找到他們之間可以“匹配”的Connection(圖右綠色部分)

  4. 用“引導連線法”找到相似的佈局UI2CODE智慧生成程式碼——元件識別篇

效果

應用這套演算法以後,擴充套件要識別的元件變得非常簡單,只要把新元件的的結構化資料預先計算好儲存起來,在查詢的時候應用”引導連線法“即可。

0重複佈局

應用

查詢重複佈局步驟如下:

1. 計算自身所有控制元件的Connection

2. 尋找自身Connection中,互相匹配的 Connection

UI2CODE智慧生成程式碼——元件識別篇

3. “引導連線”法尋找匹配的佈局“pair”

UI2CODE智慧生成程式碼——元件識別篇

4. 多個“pair”串聯組成一個重複佈局

UI2CODE智慧生成程式碼——元件識別篇

5. 繼續嘗試對重複佈局的每個Item做拆分,可得到“GridView”

UI2CODE智慧生成程式碼——元件識別篇

這樣,最終我們就可以找到,圖上有8個佈局相似的Item。

效果

應用這套演算法,可以查詢出頁面上任意的重複佈局,無論是簡單的還是複雜的,極大得提升了程式碼的可用性。

結語

以上就是我們針對佈局資訊的處理和計算的整體思路。當然其中還有很多複雜細節需要處理,比如相似佈局相似度計算、重複佈局多個“pair”組合起來的時候組合條件的判斷、重複佈局其它額外資訊的提取等。但是總體上都是圍繞著“佈局資訊結構化”和“引導連線法展開”,我們也在不斷的繼續探尋和持續最佳化各個環節。

相關文章