佈局算法篇 - 設計稿生成代碼 Imgcook 3.0 系列

文/ 阿里淘系 F(x) Team - 琻中 、民超前端

背景介紹

佈局還原是 D2C 整個鏈路偏核心的部分。在佈局部分,imgcook 使用一套佈局算法將設計稿圖層轉換爲合理的佈局結構,從而生成更加「開發友好」的、擁有層級關係的樹狀結構(例如 頁端的DOM結構 或是 Native 開發的 XML 描述體)。算法

在佈局部分以前,插件會將整個視覺稿結構化,獲得一份記錄了每一個元素的絕對位置、大小、樣式的扁平化 JSON。經過這份扁平的 JSON 咱們能精準還原整張視覺稿。可是,在平常開發中,組件與組件之間的關係並不是扁平的絕對定位,而是更加複雜的關係:例如包含與被包含、同一模塊的反覆使用、同一模塊的不一樣邏輯狀態等等(以下圖)。所以,佈局算法須要進一步升級,擁有支持這些複雜佈局的能力。數組

(「雙十一猜你喜歡」 中的循環體)

(「雙十一筆筆返「 中的多態)

問題分析

從如下「UI 信息架構圖」來看,一個頁面自上而下被細分爲 6 層。從設計稿中,咱們只能獲得_元件_級別的信息。爲了使 imgcook 生成的頁面結構更加符合前端開發者的編碼邏輯,佈局算法須要具有將一些元件組合起來,造成組件、區塊或模塊的能力。markdown

(UI 信息架構圖)

所以,咱們使用瞭如下幾個方案來結構化 schema 的生成:網絡

  • 頁面分割(把頁面分割成不一樣的子模塊)
  • 成組(決定子模塊內組件的包含與被包含關係)
  • 循環(決定子模塊內相同組件平鋪堆疊的邏輯關係)
  • 多態(決定子模塊內同一組件的不一樣狀態的邏輯關係)

以此爲框架,imgcook 致力於推進佈局向智能化的方向發展,使最終生成的代碼更加符合開發者預期,對開發者更加友好。數據結構

技術方案

在下面幾章節中,我將着重介紹「頁面分割」、「循環」與「多態」的能力。在 imgcook 的發展歷程中,咱們會漸漸使用更加智能化(能力分級更高的階段)代替以往純手寫純干預的過程,從而讓整個還原鏈路具有更大的拓展性與泛化能力。可是,鑑於智能化模型在極端的狀況不能 100% 精準,咱們仍是會保留低分級階段的能力以確保主鏈路的「魯棒性」。多線程

(佈局還原階段的智能化能力分層)

頁面分割

首先是頁面分割,當使用 imgcook 對整個頁面進行還原時,咱們會對頁面進行切割,把一整個頁面切分紅幾個模塊來維護。架構

L1 階段人工輔助生成:設計稿模塊協議

在設計稿中,用戶能夠經過設計稿協議手動將頁面分割成指定模塊,以此來增強對頁面分割的干預。在對應模塊的中加入 #module:Name# 的協議,便可將對應的部分轉換成模塊(以下圖)框架

(標註部分)

最終生成(見左邊組件樹,模塊被識別)

L2 階段規則自動生成:結構化數據分割算法

爲了減小人工干預,提升自動識別分割的能力,咱們經過規則匹配相鄰的元素,以此來判斷這些元素是否屬於同一個子模塊。算法會查詢全部相鄰行,並將大型塊狀結構則合併。具體的效果以下圖所示:編輯器


L3 階段智能輔助生成:CV 邊緣檢測

不過,基於規則的頁面分割缺少泛化能力(只有文字與圖片的的邊緣才能被識別爲同一模塊)。在實際的應用過程當中沒法取得很是好的效果。所以咱們推出了第二版,經過計算機視覺來智能地分割模塊。咱們使用 CV 對設計稿進行像素級別的對比,來加強識別的泛化度。


然而,從上圖能夠看出:目前基於 CV 的邊緣檢測雖然比規則具備更強的識別與泛化能力。可是:

  • 像素級別的分割可能會過分分割,將本來不該該被拆開的部分拆成兩個模塊(例如:標題欄和內容部分);
  • 另外,基於像素級的檢測對服務端性能的要求很是嚴苛。據實驗數據,在 8 核多線程環境下,一張頁面設計稿須要 2 秒才能完成檢測。這對於整個還原鏈路來講,耗時仍是很是高的。所以,接下來咱們計劃經過將圖片降維、池化等方式減小像素數量,從而下降運算的成本,以提升識別的效率。

循環識別

循環佈局是界面設計特別經常使用的一種佈局模式。好比(卡片)列表、導航tab、輪播組件都用到了循環的結構。在寫碼的過程當中,合理使用循環可使代碼結構更加合理,又能極大地提升代碼效率。例如如下案例,咱們只需實現一個子組件,並將子組件垂直循環就能獲得一個完整的列表組件(以下圖):


生成一個循環佈局主要經歷了三個階段:
  • 識別階段
  • 標註階段
  • 生成階段

在識別階段,咱們經過算法、模型等方法將循環體從整個 schema 中提取出來;在標註階段,咱們會篩查循環體中的循環元素,並給他們標上序號和循環惟一表示;最後,邏輯庫會將全部篩查出循環體綁定上循環變量並批量生成。

在本章節中,咱們着重介紹循環的第一個階段 —— 識別階段。

識別方案


循環的識別部分位於整個還原鏈路的最後部分(以下圖所示)。在佈局算法進行到最後階段時,元素與元素之間的嵌套層級關係已經趨於穩定,這時候的 schema 即可用於循環的識別計算。

L1 階段人工輔助生成:設計稿循環協議

做爲基礎標註能力,imgcook 提供節點打標的方法,能夠強制將某些元素識別成循環。只須要在設計稿軟件中將循環元素前加上連續的 #loop# 標籤,便可在還原時被識別爲循環子元素(以下圖)。在以下標註下生成代碼,便可獲得一個 「5循環節點」。



L2 階段規則自動生成:循環檢測算法

在識別循環以前,首先須要瞭解爲何會有循環佈局?前端的循環佈局很大程度上由其對應的服務端抽象數據結構有關。在電商行業(尤爲是手淘)中,大多數商品都以列表或者feeds流的形式展現,對應到抽象數據結構中就是 ArrayList。所以,類似的數據結構在同一個組件中對應的前端樣式也是以循環呈現。


瞭解了以上背景,不難推出,循環佈局通常都具備如下特性:
  • 循環的元素通常都在同一父節點下。
  • 循環的元素通常具備類似的形狀、樣式屬性。

拿營銷域下很是常見的卡片式商品舉例(以下圖),每一張商品卡片都具備相似的佈局:正方形頭圖,大字號標題,描述性文字,清晰可辨的行動點。


所以,咱們推出了初版的循環識別算法:首先遍歷全部的父級元素,對全部父元素的直屬子節點進行初步的篩選。初步篩選以後,咱們獲得了一組內部可能存在循環結構的父元素的集合。接下來,咱們會掃描每個可能存在循環結構的父元素的子元素,並計算它們之間的差別。若是該父元素下的子元素幾乎沒有佈局與樣式上的差別,那它極有可能就是循環佈局。最後,咱們將全部循環元素打上標記,並交由業務邏輯庫作統一的出碼處理。

L3 階段智能輔助生成:循環識別模型算法

L1和L2階段均是基於規則的一種人爲定義的節點遍歷算法,基於規則的方法必然不能處理不符合規則的狀況。爲此D2C把目光移到當前如火如荼的人工智能領域,利用深度學習中的特徵提取能力,但願從海量的數據中找出佈局特徵,實現端到端的佈局識別能力,下降甚至沒有人爲定義的規則。

經調研,生成對抗網絡做爲一種新穎的數據生成模型在AI界脫穎而出,在智能佈局識別算法中本文引入了當前CV界火熱的生成對抗網絡,期待生成對抗網絡可以找出佈局規律特徵,將同一佈局裏全部元素進行風格轉換。下面詳細介紹本文的工做原理與實踐經驗。

條件生成對抗網絡

大名鼎鼎的谷歌科學家Goodfellow在2014年提出了重量級的深度學習模型:生成對抗網絡(Generative Adversarial Networks,GAN),GAN做爲一種優秀的圖像生成算法成爲當前無監督學習中最具前景方法之一。GAN中有兩個組件:生成器G(Generative Model)和判別器D(Discriminative Model),生成器負責生成符合真實數據分佈的合成數據,判別器負責判別數據的真假,兩者互相博弈,互相提高各自的能力。因爲深度卷積神經網絡能夠擬合任意函數,故常被應用於生成器和判別器設計中。GAN的原理框架以下:


上圖中,隨機噪聲z做爲生成器G的輸入,生成器輸出合成數據G(z);判別器判別輸入數據是否爲真,輸入數據爲真實數據x時輸出爲D(x),輸入數據爲生成器生成的合成數據時輸出爲D(G(z))。GAN的損失函數數學建模以下:

由上式可知GAN一方面要加強判別器的判別能力,另外一方面要加強生成器生成逼真數據能力,在GAN的訓練過程當中二者不斷進行對抗進而提高各自的能力,最終二者處於一種動態均衡:生成器可以生成逼真的合成數據;判別器沒法將生成器生成的合成數據和真實數據區分開來,即對輸入數據判別爲真的機率基本爲50%。

條件生成對抗網絡(Conditional Generative Adversarial Networks,CGAN)技術是GAN技術的一個進化版本,可以根據輸入條件生成符合真實數據分佈的合成數據,其在原有GAN基礎上加入了監督信息。具體爲:傳統GAN從隨機向量z(噪聲)中學習到圖像y:G:z->y;與傳統GAN不一樣的是CGAN直接從條件圖像中學習到一種映射,即s:G(y,z)->s,式中y爲條件圖,s爲生成器生成的合成圖。

模型訓練與實踐

數據集製做: 首先進行數據集製做,對同一組的佈局進行風格轉換,對應的標籤是一種大白塊風格。生成後的一張訓練數據展現以下:

模型訓練: 接着利用算法pix2pix對模型進行訓練,訓練過程當中的生成器和判別器loss變化以下圖,可知兩個網絡loss均已收斂,訓練完成。


效果展現: 隨機從測試集中選取圖片進行測試,測試結果證實了模型有效。




(識別效果)

由上圖可看出模型將圖片裏的每組用一塊白色區域代替,佈局分組成功。

表達方案

當循環在佈局算法識別以後,在 schema 的 smart.repeat 字段下,就會被標註循環體信息。信息描述了具體哪些元素是在一個循環體中的,每一個元素分別對應循環體的第幾位,等等。

最後在邏輯庫中,imgcook 會用 Array.map 的形式將一個數組映射到組件中。在以下的例子中,一個商品列表被循環生成:


多態識別

除循環佈局之外,多態(multi-status)也是前端編碼中很是重要的一環。一個元素在不一樣的狀態下可能會有不一樣的展現狀態與行動狀態。例如,在以下物品卡片的案例中,針對是否有貨,右下角的「購買」按鈕有 3 種不一樣的狀態:「暫時無貨」,「馬上預定」 和 「馬上下單」。它們有類似的外觀,位置和佈局,可是,它們也有部分差別:

  • 展現差別(顏色、長短、背景圖)
  • 邏輯點差別(點擊後執行的邏輯代碼不一樣)

這樣的前端模式被稱之爲多態,而 imgcook 也在逐漸強化本身識別多態的能力


在 2020 年,imgcook 支持了多態識別的 I1 和 I2 部分能力,可以

識別方案

L1 階段人工輔助生成:設計稿多態協議

除了算法識別以外,咱們還提供了人工標註的方法,以便在算法未能精準識別時,手動干預生成多態。在 imgcook 的菜單中選擇「生成元素多狀態」(或者使用快捷鍵 Ctrl + Shift + M)便可將多個元素綁定爲某一個元素的多種狀態,從而在佈局算法中被識別爲多態元素。


L2 階段規則自動生成:多態檢測規則算法

多態識別算法採用了和循環識別相似的邏輯。首先,它位全還原鏈路的最後一層,它可以將同一個元素的不一樣狀態提取出來,並進行統一的樣式修正與狀態的還原和綁定。


  • 首先找到同一個容器的不一樣狀態,並分析它的子元素
  • 找到佈局位置相近的子元素,分別檢測他們是否有多種狀態
  • 若子元素存在樣式差別則,且經過類似度計算得出他們類似但不相同,則標記爲多態
  • 最終,將擁有多態的子元素抽離,併合並不一樣狀態的樣式佈局

算法的可視化部分能夠參考如下動圖:


這樣,咱們就能從視覺稿中提取出一個元素具備的多種狀態,並將它們統一合併在一塊兒。對於前端而言,只須要傳入對應狀態的參數便可控制展現狀態,從而實現研發提效。

L3 階段智能輔助生成:多態識別模型算法

目前,咱們正在推動多態從 I2 到 I3 發展,使用模型的方法來識別設計稿中可能存在的多態。


imgcook 設計了經過 [YOLO](https://en.wikipedia.org/wiki/Object_detection) 提取設計稿中的類似元素,而且分析它們之間的語義相關性來判斷這些組件是否構成多態。它的主要流程以下:
  • 將整個設計稿做爲圖像信息輸入;
  • 經過 YOLO 目標檢測輸出可能存在多態的元素簇;
  • 對各元素簇內的元素進行語義類似度計算。

表達方案

當多態在佈局算法識別以後,在 schema 的 smart.layerProtocol.multiStatus 字段下,就會被標註多態信息。信息描述了具體哪些元素是在一個多態簇中的,每一個元素分別對應多態的的第幾個狀態。

最後在邏輯庫中,imgcook 會用 condition 字段將每一個狀態的展現條件映射到抽象的邏輯數據中。綁定了 "condition" 字段以後,就能夠經過切換不一樣的數據來預覽不一樣狀態下模塊的樣式/邏輯(以下圖)。


佈局可維護性度量

在不斷優化佈局算法的同時,咱們須要一套體系來衡量算法對整個還原鏈路的優化程度:咱們的算法與模型優化對生成的代碼到底有多大幫助?這些優化的是否合理?是否真正作到了研發提效?因而咱們推出了 2 種佈局可維護性度量方案,來評估佈局還原的準確度:

  • UI 還原度量:度量通過佈局算法後視覺效果上是否 100% 還原。
  • 佈局可維護性度量:根據用戶最後保存的 schema 度量生成的佈局結構的合理性。

UI 還原準確度

UI 還原度量將設計稿原圖片與佈局還原後的 schema 通過 DSL 出碼後渲染的視圖作 CV 對比,以視覺類似度與 DOM 結構複雜程度做爲判斷標準計算的還原度量。


目前 62,807 次的 UI 佈局還原平均分值是 92.1%, 其中 Sketch 設計稿還原平均準確度是 92.45%, PSD 設計稿還原平均準確度是 88.21%。準確度低的主要緣由在於缺少自動判斷非 box 類元素的寬高的能力,例如沒法判斷藝術字的合理寬高而生成錯誤的 box size,須要手動調整。

可是,UI 還原度量只能衡量渲染出來的 UI 和視覺稿的一致程度,不能確保代碼結構的合理性,所以咱們還須要另外一種能夠度量佈局結構的可維護性的方式:

佈局可維護性

在佈局可維護性度量中,咱們將佈局還原生成的 schema 與用戶在編輯器內修改後最後保存的 schema 進行差別對比,經過計算用戶改動量來推測還原效果以及可用率。

schema 變動會有 4 種可能:節點變更、位置變更、樣式變更、屬性變更。其中,後兩種爲通常能力,對佈局影響不大;而前兩種,爲佈局算法的核心能力。因此,在計算可用度時,前者的權重高於後者。以後,只要將變更部分的比例整合,便可計算出總體可用率。

咱們定義了計算佈局還原可維護度的公式:



由此能夠得出每棵子樹的變更率,以及整體變更率。這種可用度度量方式能夠更顯式地反映用戶在使用 Imgcook 時遇到的問題,例如節點名稱、樣式、DOM 結構的改變。
(可佈局變更查看面板)

除了字段綁定、節點屬性、樣式的變化,在最後保存時還刪除了大量循環節點,但這些循環節點並非由人工刪除,而是在佈局還原階段識別了循環以後,在後面的業務邏輯生成階段自動刪除。

2020 年雙 11 大促會場中,帶循環體的模塊佔新增模塊 67.31%,在佈局還原階段循環被識別的模塊佔比 43%,業務邏輯生成階段根據佈局識別結果自動刪除多餘的循環體並生成循環結構代碼。



F(X)Team 開通 微博 啦!
除文章外還有更多的團隊內容等你解鎖🔓
相關文章
相關標籤/搜索