设计稿生成代码核心技术揭秘:获取图片中前端组件的位置信息

简介: 快来学习前端智能化!

作者 | 缺月

image.png
为了让大家更好地学习 Pipcook 和机器学习,我们准备了实战系列教程,会分别从前端组件识别、图片风格迁移、AI 作诗以及博客自动分类,这几个具体示例来讲解如何在我们日常开发中使用 Pipcook,如果需要了解 Pipcook 1.0,请阅读文章 AI ❤️ JavaScript, Pipcook 1.0

开源地址:https://github.com/alibaba/pipcook

背景

您是否在前端业务中遇到过这样的场景:手中有一些图片,您想有一种自动的方式来识别这些图片这个图片里都包含哪些组件,这些组件都在图片的什么位置,属于哪种类型的组件,这种类型的任务一般在深度学习领域称为目标检测。

目标检测与识别是指从一幅场景(图片)中找出目标,包括检测(where) 和识别(what) 两个过程

这种检测是非常有用的,例如,在图片生成代码的研究里,前端代码主要就是由 div, img, span 组成的,我们可以识别图片里的形状,位图,和文本的位置,然后直接生成相应的描述代码即可。

这篇教程将会教你如何训练出一个模型来做这样一个检测任务。

场景示例

举个例子,如下图所示,这个图片包含着多个组件,包括按钮,开关,输入框等,我们想要识别出他们的位置和类型:
image.png
对于训练好的模型来说,在输入这张图片之后,模型会输出如下的预测结果:

{
  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

    • 1.jpg
    • 1.xml
    • 2.jpg
    • 2.xml
    • ...
  • test

    • 1.jpg
    • 1.xml
    • 2.jpg
    • 2.xml
    • ...

我们需要按照一定比例把我们的数据集分成训练集 (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 为例,详细的介绍一下
image.png
您可以先从上面的 labelimg 官网上安装软件,然后按照以下步骤操作:

  • 按照官网的说明进行构建和启动。
  • 在菜单/文件中单击“更改默认保存的注释文件夹”
  • 点击“打开目录”
  • 点击“创建RectBox”
  • 单击并释放鼠标左键以选择一个区域来标注矩形框
  • 您可以使用鼠标右键拖动矩形框来复制或移动它

训练

在制作好上面的数据集之后,根据之前的章节中的介绍组织文件结构,之后,就可以启动 pipeline 进行训练了,赶快开始吧。

总结

读者到这里已经学会如识别一张图片中的多个前端组件了,可以适用于一些更加通用的场景了。那么在一篇,我们会介绍一个更有趣的例子,就是如何使用 Pipcook 实现图片风格迁移,比如将图片中的橘子都替换称苹果,或者将写实的照片风格替换为油画风格等。


🎉Pipcook 1.0 系列专题 🎉

AI (爱) JavaScript , Pipcook 1.0 正式发布

Pipcook 团队有话说

使用Pipcook对图片中的前端组件进行分类,饼图、折线图还是柱状图?

👉设计稿生成代码核心技术揭秘:获取图片中前端组件的位置信息

未完待续...

❤️欢迎大家关注 Alibaba F2E 微信公众号前端智能化技术分享周(6.29-7.3)❤️


image.png
关注「Alibaba F2E」
把握阿里巴巴前端新动向

相关文章
|
6天前
|
缓存 监控 前端开发
【Flutter 前端技术开发专栏】Flutter 应用的启动优化策略
【4月更文挑战第30天】本文探讨了Flutter应用启动优化策略,包括理解启动过程、资源加载优化、减少初始化工作、界面布局简化、异步初始化、预加载关键数据、性能监控分析以及案例和未来优化方向。通过这些方法,可以缩短启动时间,提升用户体验。使用Flutter DevTools等工具可助于识别和解决性能瓶颈,实现持续优化。
【Flutter 前端技术开发专栏】Flutter 应用的启动优化策略
|
5天前
|
缓存 移动开发 前端开发
【专栏:HTML与CSS前端技术趋势篇】HTML与CSS在PWA(Progressive Web Apps)中的应用
【4月更文挑战第30天】PWA(Progressive Web Apps)结合现代Web技术,提供接近原生应用的体验。HTML在PWA中构建页面结构和内容,响应式设计、语义化标签、Manifest文件和离线页面的创建都离不开HTML。CSS则用于定制主题样式、实现动画效果、响应式布局和管理字体图标。两者协同工作,保证PWA在不同设备和网络环境下的快速、可靠和一致性体验。随着前端技术进步,HTML与CSS在PWA中的应用将更广泛。
|
5天前
|
前端开发 JavaScript 开发者
【专栏:HTML与CSS前端技术趋势篇】前端框架(React/Vue/Angular)与HTML/CSS的结合使用
【4月更文挑战第30天】前端框架React、Vue和Angular助力UI开发,通过组件化、状态管理和虚拟DOM提升效率。这些框架与HTML/CSS结合,使用模板语法、样式管理及组件化思想。未来趋势包括框架简化、Web组件标准采用和CSS在框架中角色的演变。开发者需紧跟技术发展,掌握新工具,提升开发效能。
|
5天前
|
前端开发 JavaScript UED
【专栏:HTML 与 CSS 前端技术趋势篇】Web 性能优化:CSS 与 HTML 的未来趋势
【4月更文挑战第30天】本文探讨了CSS和HTML在Web性能优化中的关键作用,包括样式表压缩、选择器优化、DOM操作减少等策略。随着未来趋势发展,CSS模块系统、自定义属性和响应式设计将得到强化,HTML新特性也将支持复杂组件构建。同时,应对浏览器兼容性、代码复杂度和性能功能平衡的挑战是优化过程中的重要任务。通过案例分析和持续创新,我们可以提升Web应用性能,创造更好的用户体验。
|
5天前
|
移动开发 前端开发 UED
【专栏:HTML与CSS前端技术趋势篇】渐进式增强与优雅降级在前端开发中的实践
【4月更文挑战第30天】前端开发中的渐进式增强和优雅降级是确保跨浏览器、跨设备良好用户体验的关键策略。渐进式增强是从基础功能开始,逐步增加高级特性,保证所有用户能访问基本内容;而优雅降级则是从完整版本出发,向下兼容,确保低版本浏览器仍能使用基本功能。实践中,遵循HTML5/CSS3规范,使用流式布局和响应式设计,检测浏览器特性,并提供备选方案,都是实现这两种策略的有效方法。选择合适策略优化网站,提升用户体验。
|
5天前
|
前端开发 开发者 UED
【专栏:HTML与CSS前端技术趋势篇】网页设计中的CSS Grid与Flexbox之争
【4月更文挑战第30天】本文对比了CSS Grid和Flexbox两种布局工具。Flexbox擅长一维布局,简单易用,适合导航栏和列表;CSS Grid则适用于二维布局,能创建复杂结构,适用于整个页面布局。两者各有优势,在响应式设计中都占有一席之地。随着Web标准发展,它们的结合使用将成为趋势,开发者需掌握两者以应对多样化需求。
|
5天前
|
前端开发 JavaScript 搜索推荐
【专栏:HTML 与 CSS 前端技术趋势篇】HTML 与 CSS 在 Web 组件化中的应用
【4月更文挑战第30天】本文探讨了HTML和CSS在Web组件化中的应用及其在前端趋势中的重要性。组件化提高了代码复用、维护性和扩展性。HTML提供组件结构,语义化标签增进可读性,支持用户交互;CSS实现样式封装、布局控制和主题定制。案例展示了导航栏、卡片和模态框组件的创建。响应式设计、动态样式、CSS预处理器和Web组件标准等趋势影响HTML/CSS在组件化中的应用。面对兼容性、代码复杂度和性能优化挑战,需采取相应策略。未来,持续发掘HTML和CSS潜力,推动组件化开发创新,提升Web应用体验。
|
6天前
|
前端开发 JavaScript 安全
【TypeScript技术专栏】TypeScript在微前端架构中的应用
【4月更文挑战第30天】微前端架构通过拆分应用提升开发效率和降低维护成本,TypeScript作为静态类型语言,以其类型安全、代码智能提示和重构支持强化这一架构。在实践中,TypeScript定义公共接口确保跨微前端通信一致性,用于编写微前端以保证代码质量,且能无缝集成到构建流程中。在微前端架构中,TypeScript是保障正确性和可维护性的有力工具。
|
6天前
|
缓存 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 前端路由实现原理
【4月更文挑战第30天】本文探讨了JavaScript前端路由在SPA中的重要性,阐述了其基本原理和实现方式,包括Hash路由和History路由。前端路由通过监听URL变化、匹配规则来动态切换内容,提升用户体验和交互性。同时,文章也提到了面临的SEO和页面缓存挑战,并通过电商应用案例分析实际应用。理解并掌握前端路由能助开发者打造更流畅的单页应用。
|
6天前
|
Dart 前端开发 测试技术
【Flutter前端技术开发专栏】Flutter开发中的代码质量与重构实践
【4月更文挑战第30天】随着Flutter在跨平台开发的普及,保证代码质量成为开发者关注的重点。优质代码能确保应用性能与稳定性,提高开发效率。关键策略包括遵循最佳实践,编写可读性强的代码,实施代码审查和自动化测试。重构实践在项目扩展时尤为重要,适时重构能优化结构,降低维护成本。开发者应重视代码质量和重构,以促进项目成功。
【Flutter前端技术开发专栏】Flutter开发中的代码质量与重构实践