天天看點

設計稿生成代碼核心技術揭秘:擷取圖檔中前端元件的位置資訊

作者 | 缺月
設計稿生成代碼核心技術揭秘:擷取圖檔中前端元件的位置資訊

為了讓大家更好地學習 Pipcook 和機器學習,我們準備了實戰系列教程,會分别從前端元件識别、圖檔風格遷移、AI 作詩以及部落格自動分類,這幾個具體示例來講解如何在我們日常開發中使用 Pipcook,如果需要了解 Pipcook 1.0,請閱讀文章

AI ❤️ JavaScript, Pipcook 1.0

開源位址: https://github.com/alibaba/pipcook

背景

您是否在前端業務中遇到過這樣的場景:手中有一些圖檔,您想有一種自動的方式來識别這些圖檔這個圖檔裡都包含哪些元件,這些元件都在圖檔的什麼位置,屬于哪種類型的元件,這種類型的任務一般在深度學習領域稱為目标檢測。

目标檢測與識别是指從一幅場景(圖檔)中找出目标,包括檢測(where) 和識别(what) 兩個過程

這種檢測是非常有用的,例如,在圖檔生成代碼的研究裡,前端代碼主要就是由 div, img, span 組成的,我們可以識别圖檔裡的形狀,位圖,和文本的位置,然後直接生成相應的描述代碼即可。

這篇教程将會教你如何訓練出一個模型來做這樣一個檢測任務。

場景示例

舉個例子,如下圖所示,這個圖檔包含着多個元件,包括按鈕,開關,輸入框等,我們想要識别出他們的位置和類型:

設計稿生成代碼核心技術揭秘:擷取圖檔中前端元件的位置資訊

對于訓練好的模型來說,在輸入這張圖檔之後,模型會輸出如下的預測結果:

{
  boxes: [
    [83, 31, 146, 71],  // xmin, ymin, xmax, ymax
    [210, 48, 256, 78],
    [403, 30, 653, 72],
    [717, 41, 966, 83]
  ],
  classes: [
    0, 1, 2, 2  // class index
  ],
  scores: [
    0.95, 0.93, 0.96, 0.99 // scores
  ]
}           

同時,我們會在訓練的時候生成 labelmap,labelmap 是一個序号和實際類型的一個映射關系,這個的生成主要是由于現實世界我們的分類名是文本的,但是在進入模型之前,我們需要将文本轉成數字。下面就是一個 labelmap:

{
  "button": 0,
  "switch": 1,
  "input": 2
}           

我們對上面的預測結果做一個解釋:

  • boxes:這個字段描述的是識别出來的每一個元件的位置,按照左上角和右下角的順序展示,如 [83, 31, 146, 71],說明這個元件左上角坐标為 (83, 13), 右下角坐标為 (146, 71)
  • classes: 這個字段描述的是每一個元件的類别,結合 labelmap,我們可以看出識别出來的元件分别為按鈕,開關,輸入框和輸入框
  • scores: 識别出來的每一個組建的置信度,置信度是模型對于自己識别出來的結果有多大的資訊,一般我們會設定一個門檻值,我們隻取置信度大于這個門檻值的結果

資料準備

當我們想要做這樣一個目标檢測的任務時,我們需要按照一定規範制作,收集和存儲我們的資料集,當今業界主要有兩種目标檢測的資料集格式,分别是 Coco 資料集 和 Pascal Voc 資料集, 我們也分别提供了相應的資料收集插件來收集這兩種格式的資料,下面我們以 Pascal voc 格式舉例,檔案目錄為:

  • train
    • 1.jpg
    • 1.xml
    • 2.jpg
    • 2.xml
    • ...
  • validation
  • test

我們需要按照一定比例把我們的資料集分成訓練集 (train),驗證集 (validation) 和測試集 (test),其中,訓練集主要用來訓練模型,驗證集和測試集用來評估模型。驗證集主要用來在訓練過程中評估模型,以友善檢視模型過拟合和收斂情況,測試集是在全部訓練結束之後用來對模型進行一個總體的評估的。

對于每一張圖檔,Pascal Voc 都指定有一個 xml 注解檔案來記錄這個圖檔裡有哪些元件和每個元件的位置,一個典型的 xml 檔案内容為:

<?xml version="1.0" encoding="UTF-8"?>
<annotation>
   <folder>less_selected</folder>
   <filename>0a3b6b38-fb11-451c-8a0d-b5503bc351e6.jpg</filename>
   <size>
      <width>987</width>
      <height>103</height>
   </size>
   <segmented>0</segmented>
   <object>
      <name>buttons</name>
      <pose>Unspecified</pose>
      <truncated>0</truncated>
      <difficult>0</difficult>
      <bndbox>
         <xmin>83</xmin>
         <ymin>31.90625</ymin>
         <xmax>146</xmax>
         <ymax>71.40625</ymax>
      </bndbox>
   </object>
   <object>
      <name>switch</name>
      <pose>Unspecified</pose>
      <truncated>0</truncated>
      <difficult>0</difficult>
      <bndbox>
         <xmin>210.453125</xmin>
         <ymin>48.65625</ymin>
         <xmax>256.453125</xmax>
         <ymax>78.65625</ymax>
      </bndbox>
   </object>
   <object>
      <name>input</name>
      <pose>Unspecified</pose>
      <truncated>0</truncated>
      <difficult>0</difficult>
      <bndbox>
         <xmin>403.515625</xmin>
         <ymin>30.90625</ymin>
         <xmax>653.015625</xmax>
         <ymax>72.40625</ymax>
      </bndbox>
   </object>
   <object>
      <name>input</name>
      <pose>Unspecified</pose>
      <truncated>0</truncated>
      <difficult>0</difficult>
      <bndbox>
         <xmin>717.46875</xmin>
         <ymin>41.828125</ymin>
         <xmax>966.96875</xmax>
         <ymax>83.328125</ymax>
      </bndbox>
   </object>
</annotation>           

這個 xml 注解檔案主要由以下幾個部分組成:

  • folder / filename: 這兩個字段主要定義了注解對應的圖檔位置和名稱
  • size: 圖檔的寬高
  • object:
    • name: 元件的類别名
    • bndbox: 元件的位置

我們已經準備好了一個這樣的資料集,您可以下載下傳下來檢視一下:下載下傳位址

開始訓練

在準備好資料集之後,我們就可以開始訓練了,使用 Pipcook 可以很友善的進行目标檢測的訓練,您隻需搭建下面這樣的 pipeline,

{
  "plugins": {
    "dataCollect": {
      "package": "@pipcook/plugins-object-detection-pascalvoc-data-collect",
      "params": {
        "url": "http://ai-sample.oss-cn-hangzhou.aliyuncs.com/pipcook/datasets/component-recognition-detection/component-recognition-detection.zip"
      }
    },
    "dataAccess": {
      "package": "@pipcook/plugins-coco-data-access"
    },
    "modelDefine": {
      "package": "@pipcook/plugins-detectron-fasterrcnn-model-define"
    },
    "modelTrain": {
      "package": "@pipcook/plugins-detectron-model-train",
      "params": {
        "steps": 100000
      }
    },
    "modelEvaluate": {
      "package": "@pipcook/plugins-detectron-model-evaluate"
    }
  }
}           

通過上面的插件,我們可以看到分别使用了:

  1. @pipcook/plugins-object-detection-pascalvoc-data-collect 這個插件用于下載下傳 Pascal Voc 格式的資料集,主要,我們需要提供 url 參數,我們提供了上面我們準備好的資料集位址
  2. @pipcook/plugins-coco-data-access 我們現在已經下載下傳好了資料集,我們需要将資料集接入成後續模型需要的格式,由于我們模型采用的 detectron2 架構需要 coco 資料集格式,是以我們采用此插件
  3. @pipcook/plugins-detectron-fasterrcnn-model-define 我們基于 detectron2 架構建構了 faster rcnn 模型,這個模型在目标檢測的精準度方面有着非常不錯的表現
  4. @pipcook/plugins-detectron-model-train 這個插件用于啟動所有基于 detectron2 建構的模型的訓練,我們設定了 iteration 為 100000,如果您的資料集非常複雜,則需要調高疊代次數
  5. @pipcook/plugins-detectron-model-evaluate 我們使用此插件來進行模型訓練效果的評估,隻有提供了 test 測試集,此插件才會有效,最終給出的是各個類别的 average precision

由于目标監測模型,尤其是 rcnn 家族的模型非常大,需要在有 nvidia gpu 并且 cuda 10.2 環境預備好的機器上進行訓練:

pipcook run object-detection.json --verbose --tuna           

模型在訓練的過程中會實時列印出每個疊代的 loss,請注意檢視日志确定模型收斂情況:

[06/28 10:26:57 d2.data.build]: Distribution of instances among all 14 categories:
|   category   | #instances   |  category   | #instances   |  category  | #instances   |
|:------------:|:-------------|:-----------:|:-------------|:----------:|:-------------|
|     tags     | 3114         |    input    | 2756         |  buttons   | 3075         |
| imagesUpload | 316          |    links    | 3055         |   select   | 2861         |
|    radio     | 317          |  textarea   | 292          | datePicker | 316          |
|     rate     | 292          | rangePicker | 315          |   switch   | 303          |
|  timePicker  | 293          |  checkbox   | 293          |            |              |
|    total     | 17598        |             |              |            |              |

[06/28 10:28:32 d2.utils.events]:  iter: 0  total_loss: 4.649  loss_cls: 2.798  loss_box_reg: 0.056  loss_rpn_cls: 0.711  loss_rpn_loc: 1.084  data_time: 0.1073  lr: 0.000000  
[06/28 10:29:32 d2.utils.events]:  iter: 0  total_loss: 4.249  loss_cls: 2.198  loss_box_reg: 0.056  loss_rpn_cls: 0.711  loss_rpn_loc: 1.084  data_time: 0.1073  lr: 0.000000  
...
[06/28 12:28:32 d2.utils.events]:  iter: 100000  total_loss: 0.032 loss_cls: 0.122  loss_box_reg: 0.056  loss_rpn_cls: 0.711  loss_rpn_loc: 1.084  data_time: 0.1073  lr: 0.000000             

訓練完成後,會在目前目錄生成 output,這是一個全新的 npm 包,那麼我們首先安裝依賴:

cd output
BOA_TUNA=1 npm install           

安裝好環境之後,我們就可以開始預測了:

const predict = require('./output');
(async () => {
  const v1 = await predict('./test.jpg');
  console.log(v1); 
  // {
  //   boxes: [
  //     [83, 31, 146, 71],  // xmin, ymin, xmax, ymax
  //     [210, 48, 256, 78],
  //     [403, 30, 653, 72],
  //     [717, 41, 966, 83]
  //   ],
  //   classes: [
  //     0, 1, 2, 2  // class index
  //   ],
  //   scores: [
  //     0.95, 0.93, 0.96, 0.99 // scores
  //   ]
  // }
})();           

注意,給出的結果包含三個部分:

  • boxes: 此屬性是一個數組,每個元素是另一個包含四個元素的數組,分别是 xmin, xmax, ymin, ymax
  • scores:此屬性是一個數組,每個元素是對應的預測結果的置信度
  • classes:此屬性是一個數組,每個元素是對應的預測出來的類别

制作自己的資料集

看完上面的描述,你是否已經迫不及待想要用目标檢測解決自己的問題了呢,要想制作自己的資料集,主要有以下幾步

收集圖檔

這一步比較好了解,要想有自己的訓練資料,您需要先想辦法收集到足夠的訓練圖檔,這一步,您不需要讓您自己的圖檔有相應的标注,隻需要原始的圖檔進行标注就好

标注

現在市面上有很多的标注工具,您可以使用這些标注工具在您原始的圖檔上标注出有哪些元件,每個元件的位置和類型是什麼,下面我們拿 labelimg 為例,詳細的介紹一下

設計稿生成代碼核心技術揭秘:擷取圖檔中前端元件的位置資訊

您可以先從上面的 labelimg 官網上安裝軟體,然後按照以下步驟操作:

  • 按照官網的說明進行建構和啟動。
  • 在菜單/檔案中單擊“更改預設儲存的注釋檔案夾”
  • 點選“打開目錄”
  • 點選“建立RectBox”
  • 單擊并釋放滑鼠左鍵以選擇一個區域來标注矩形框
  • 您可以使用滑鼠右鍵拖動矩形框來複制或移動它

訓練

在制作好上面的資料集之後,根據之前的章節中的介紹組織檔案結構,之後,就可以啟動 pipeline 進行訓練了,趕快開始吧。

總結

讀者到這裡已經學會如識别一張圖檔中的多個前端元件了,可以适用于一些更加通用的場景了。那麼在一篇,我們會介紹一個更有趣的例子,就是如何使用 Pipcook 實作圖檔風格遷移,比如将圖檔中的橘子都替換稱蘋果,或者将寫實的照片風格替換為油畫風格等。

🎉Pipcook 1.0 系列專題 🎉

AI (愛) JavaScript , Pipcook 1.0 正式釋出 Pipcook 團隊有話說 使用Pipcook對圖檔中的前端元件進行分類,餅圖、折線圖還是柱狀圖?

👉設計稿生成代碼核心技術揭秘:擷取圖檔中前端元件的位置資訊

未完待續...

❤️歡迎大家關注 Alibaba F2E 微信公衆号前端智能化技術分享周(6.29-7.3)❤️

設計稿生成代碼核心技術揭秘:擷取圖檔中前端元件的位置資訊

關注「Alibaba F2E」

把握阿裡巴巴前端新動向

繼續閱讀