UI2CODE智能生成代码——组件识别篇
1.背景
在《UI2CODE——整体设计篇》中,我们介绍了UI2CODE工程的整体流程:
在组件识别这个环节,需要有一种处理布局信息的方法,来解析和计算控件间的布局关系(比如识别业务组件(BI组件)和查找重复布局),以此来提高最终代码的可用性。
在这篇文章,我们将介绍一种布局信息的结构化方法:“连线法”,以及一种布局间的计算和比较方法: “引导连线法”。
首先来看我们需要解决的问题:
2.问题一:识别业务组件
目的:代码复用
业务组件是指某些特定的卡片,比如一个商品详情卡片,这些卡片会在不同页面出现,而这些卡片的代码一般是已经存在的。我们在拿到一张图片的时候,需要先识别出这些组件,这样这一区块就能复用已有的组件代码,而不会造成很多冗余的一次性代码。
老解法:利用深度学习模型SSD做物体检测
如果把寻找业务组件这个问题看成从一张大图片上寻找小图片的话,那么最直接的做法就是用一个物体检测模型(比如SSD)来做,这样只要训练模型来识别每个业务组件的图片就可以了。因此我们尝试了用训练SSD模型来解决这个问题。
存在的问题:训练困难,训练结果不可控
经过训练和测试以后,我们发现用物体检测模型来解这个问题的弊端:
- 需要造大量样本。由于图片信息丰富,为了避免过拟合,需要造大量样本来训练。
- 训练困难,增加新的业务组件成本太高。每增加一个新的业务组件,就需要先造这个组件的样本,然后重新调整训练模型。
- 训练结果不可控。对于一些badcase,没有一些直接有效的方式来做调整和控制,只能不断调整样本。
思考:是否可以利用已有的控件信息?
既然前面已经解析出了各个控件的信息(包含类型以及位置等),那么我们是否可以直接利用这些信息来做处理呢?因此我们想要寻找一种新的方式,来处理和解析控件信息,利用这些信息来实现类似“物体检测”功能
3.问题二:重复布局
目的:提升代码可用性
如上图这个case,对于类似“GridView”的这种布局,我们理想的布局方式应该是有8个Item,每个Item包含一个TextView和ImageView(上图左边)。
存在的问题:没有识别出重复布局,最终代码不可用
然而实际情况是,我们没有做重复布局的检测,因此布局的时候变成了4行(上图右边)。
思考:如何比较布局是否重复?
为了解决上面的问题,我们就需要寻找一种方法,从多个控件信息中,找到一些规律,自动找到这些具有相似情况的布局。
4.问题分析
以上就是我们需要解决的两个问题,我们分析这两个问题,会发现他们有一些共同点:
- 都是由多个控件组成大的布局
- 布局间需要进行比较,寻找“相似布局”
- 都是非结构化数据:无法直接比较、计算
5.解决思路
首先我们需要将非结构化数据转换为结构化数据(或者叫特征提取),这个思路可以参考图片分类任务的做法,不管是聚类算法还是AI模型,都是先做特征提取,再进行进一步处理,实际上做的就是非结构化数据转换成结构化数据。
因此,我们的问题解决思路也就分为两步:
- 布局信息结构化:将布局信息处理成结构化的数据
- 布局比较:对布局进行比较、计算,寻找相似布局
6.布局结构化:控件间的关系
为了分析控件间的关系,我们可以先从简单的开始,看一下两个控件之间的关系都包含哪些信息。
两个控件间的关系,包含以下2个方面的信息:
- 控件属性(类型、文本内容、位置、大小)
- 方向、距离、对齐方式(用连线表达)
控件属性:
对于控件属性,可以直接用它自身表示,包含控件类型、内容、位置、大小等
方向和距离:
对于两个控件的方向和距离,我们可以用一条虚拟的“连线”来表示,这条连线连接两个控件的中心点。这样,这条连线的长度和角度就可以表示两个控件的方向和距离。比如上图,我们可以得到:一个TextView在一个ImageView正上方,距离xxx像素。
对齐方式:
但是除了角度和方向,实际上还存在着一个“对齐方式”信息。
比如上图这个case,如果我们还是连接两个控件的中心点的话(图中蓝色虚线),那这左右两边的图就是指不同的布局(因为两个控件的角度和距离都不一样)。
但是由我们人“肉眼”来看,我们会认为这两个布局是一样的,都是左边一个头像,右边上面跟着一个文本。
因此,我们需要连接TextView的“左边中点”(图上红色实线),这样,不同的连接点位置,就可以表达不同的对齐方式。左对齐的TextView连接左边中点,右对齐的TextView连接右边中点,居中的连接中心点。
定义数据结构
有了上面的分析,我们就可以定义一个数据结构。我们用一个Connection对象表达2个控件间的布局关系,它包含:
- 控件1属性(类型、位置大小等)
- 控件2属性(类型、位置大小等)
- 控件1和控件2间的多条连线(角度、距离)
这样,2个Connection之间就可以进行比较、判断是否“匹配”
Connection匹配计算
两个Connection之间是否“匹配”,必须满足:
- 控件信息匹配(类型一致、ImageView面积相似度满足要求等)
- 方向和距离匹配(连线的余弦相似度)
- 其它自定义的匹配要求
7.布局结构化:整个布局的表示
两个控件间的关系可以用一个Connection来表示,那么多个控件组成的大布局,就可以用一组Connection来表示。
我们对每两个控件建立一个Connection,就可以得到一个Connection数组
这样,我们的第一步“布局信息结构化”就完成了。
8.布局间比较:引导连线法
将布局信息转换成Connection数组以后,我们就可以开始利用这些信息来查找相似布局。
首先,我们可以理解这样一个概念,就是:
一个布局,可以看成由一组Connection对象串联起来,得到的一个“路径”
如上图,蓝色圈内的布局可以看成一组Connection串联起来(红色连线)。
那么,寻找相似布局,就是寻找两条相似“路径”的过程
引导连线法
为了寻找相似路径,我们定义了一个“引导连线法”。
所谓“引导连线法”,就是一个 Leader,一个 Follower,Follower 尝试着跟随 Leader 走出一条一样的路径。
步骤如下:
- 计算出所有相互匹配的Connection(如下图所有绿色的连线)
- 定义一个“Leader”叫A,一个 “Follower” 叫B
- 随机选择一条绿色连线作为A的初始路径,与其相匹配的另一条绿色连线作为B的初始路径
- A尝试着继续往前走,找到下一个路径(绿色连线),B尝试着跟随
- 如果B能跟的上(即找到了一条路径,刚好与A想走的路径匹配上),那么A继续往下走,如果B跟不上,那么A换条路径继续尝试。
- 直到A走的路径B怎么也跟不上时,A和B走过的路径所对应的那些控件,就是拥有相似布局的控件。
9.应用效果
有了结构化的方法和“引导连线法”,我们就可以应用到上述两个问题。
业务组件
- 应用方式
- 对业务组件进行结构化处理(图左红色连线)
- 对待处理图片进行结构化处理
- 找到他们之间可以“匹配”的Connection(图右绿色部分)
- 用“引导连线法”找到相似的布局
- 效果
应用这套算法以后,扩展要识别的组件变得非常简单,只要把新组件的的结构化数据预先计算好存储起来,在查找的时候应用”引导连线法“即可。
重复布局
- 应用方式
查找重复布局步骤如下:
计算自身所有控件的Connection
寻找自身Connection中,互相匹配的 Connection
“引导连线”法寻找匹配的布局“pair”
多个“pair”串联组成一个重复布局
继续尝试对重复布局的每个Item做拆分,可得到“GridView”
这样,最终我们就可以找到,图上有8个布局相似的Item。
- 效果
应用这套算法,可以查找出页面上任意的重复布局,无论是简单的还是复杂的,极大得提升了代码的可用性。
10.结语
以上就是我们针对布局信息的处理和计算的整体思路。当然其中还有很多复杂细节需要处理,比如相似布局相似度计算、重复布局多个“pair”组合起来的时候组合条件的判断、重复布局其它额外信息的提取等。但是总体上都是围绕着“布局信息结构化”和“引导连线法展开”,我们也在不断的继续探寻和持续优化各个环节。
本文作者:闲鱼技术-楚丰
本文为云栖社区原创内容,未经允许不得转载。
UI2CODE智能生成代码——组件识别篇的更多相关文章
- UI2Code智能生成Flutter代码--整体设计篇
摘要: UI2CODE项目是闲鱼技术团队研发的一款通过机器视觉理解+AI人工智能将UI视觉图片转化为端侧代码的工具. 背景: 随着移动互联网时代的到来,人类的科学技术突飞猛进.然而软件工程师们依旧需要 ...
- Bootstrap Blazor Table 组件(三)智能生成
原文链接:https://www.cnblogs.com/ysmc/p/16201153.html Bootstrap Blazor 官网地址:https://www.blazor.zone 有了解过 ...
- 根据官方文档使用Visual Studio Code创建代码组件的一些总结
1.安装组件Visual Studio Code Download Visual Studio Code - Mac, Linux, Windows 2.安装Node.js Download | No ...
- 组件化框架设计之apt编译时期自动生成代码&动态类加载(二)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将继续从以下两个内容来介绍组件化框架设计: apt编译时 ...
- SpringBoot入门篇--整合mybatis+generator自动生成代码+druid连接池+PageHelper分页插件
原文链接 我们这一篇博客讲的是如何整合Springboot和Mybatis框架,然后使用generator自动生成mapper,pojo等文件.然后再使用阿里巴巴提供的开源连接池druid,这个连接池 ...
- Home Assistant + 树莓派:强大的智能家居系统 · 设备接入篇
转载:Home Assistant + 树莓派:强大的智能家居系统 · 设备接入篇 目录 HASS 配置框架 主文件设置 Homebridge 设置 鹬蚌相争? 设备追踪设置 更新日志 作者的话 相信 ...
- 基于语义感知SBST的API场景测试智能生成
摘要:面对庞大服务接口群,完备的接口测试覆盖和业务上下文场景测试看护才有可能保障产品服务的质量和可信.如果你想低成本实现产品和服务的测试高覆盖和高质量看护,这篇文章将为你提供你想要的. 本文分享自华为 ...
- 黄聪:如何使用CodeSmith批量生成代码(转:http://www.cnblogs.com/huangcong/archive/2010/06/14/1758201.html)
先看看CodeSmith的工作原理: 简单的说:CodeSmith首先会去数据库获取数据库的结构,如各个表的名称,表的字段,表间的关系等等,之后再根据用户自定义好的模板文件,用数据库结构中的关键字替代 ...
- 如何使用CodeSmith批量生成代码(原创系列教程)
在上一篇我们已经用PowerDesigner创建好了需要的测试数据库,下面就可以开始用它完成批量代码生成的工作啦. 下面我会一步步的解释如何用CodeSmith实现预期的结果的,事先声明一下,在此只做 ...
随机推荐
- nginx日志字段解析
许包含的变量注释如下: $remote_addr, $http_x_forwarded_for 记录客户端IP地址 $remote_user 记录客户端用户名称 $request 记录请求的URL和H ...
- List的深度序列化Demo
今天项目中出现了这个问题...就是使用一个List去进行其他的操作,生成一个新的List.但是却将原来的List的值也给改了...这应该是引用传递的问题,查了资料发现这是浅拷贝造成的.(ps:使用ad ...
- php中 重载的方法
php中 重载(一)这个文章,谢谢.作为初学者,大牛勿喷: 基本是两个方法 __call,当调用对一个不可访问的对象方法时,会自动执行该魔术方法!(对象调用) 典型的两种处理方式: 1,给出友好的提示 ...
- poj 2001 Shortest Prefixes(字典树trie 动态分配内存)
Shortest Prefixes Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 15610 Accepted: 673 ...
- LintCode_14 二分查找
题目 给定一个排序的整数数组(升序)和一个要查找的整数target,用O(logn)的时间查找到target第一次出现的下标(从0开始),如果target不存在于数组中,返回-1. 样例 在数组 [1 ...
- GitHub的注册与使用
1. 注册账号: 地址: https://github.com/输入账号.邮箱.密码,然后点击注册按钮. 2. 初始设置 注册完成后,选择Free免费账号完成设置 3.验证账号 新建一个仓库 发现邮箱 ...
- Android——内存管理基础
内存收集概念 内存垃圾收集器(garbage collector) 概念:自定内存管理. 功能:分配内存.保证所有被引用的对象还在内存中.可以释放在运行的代码中不再引用的对象的内存. 垃圾收集器避免了 ...
- 从Docker容器内部,如何连接到本机的本地主机?
原文 从Docker容器内部,如何连接到本机的本地主机? 编辑:如果您使用的是Docker-for-mac或Docker-for-Windows 18.03+,只需使用主机连接到您的mysql服务即可 ...
- Leetcode687.Longest Univalue Path最长同值路径
给定一个二叉树,找到最长的路径,这个路径中的每个节点具有相同值. 这条路径可以经过也可以不经过根节点. 注意:两个节点之间的路径长度由它们之间的边数表示. 示例 1: 输入: 5 / \ 4 5 / ...
- DTcms设置 IIS6.0设置url重写导致editor上传全部失效
1.修改iis的重写规则为htm 2.修改后台后缀为htm 解决