前端代码是怎样智能生成的-图像分离篇

简介: 作为阿里经济体前端委员会四大技术方向之一,前端智能化项目经历了 2019 双十一的阶段性考验,交出了不错的答卷,天猫淘宝双十一会场新增模块 79.34% 的线上代码由前端智能化项目自动生成。在此期间研发小组经历了许多困难与思考,本次 《前端代码是怎样智能生成的》 系列分享,将与大家分享前端智能化项目中技术与思考的点点滴滴。

概述

一直以来,如何从“视觉稿”精确的还原出对应的 UI 侧代码一直是端侧开发同学工作里消耗比较大的部分,一方面这部分的工作比较确定缺少技术深度,另一方面视觉设计师也需要投入大量的走查时间,有大量无谓的沟通和消耗。

很多人会比较好奇,为什么我们尝试使用图片做为输入源,一方面基于 Sketch 或者 Photoshop 等插件相对容易拿到确定性的信息,图片在某些方面容易丢失一些特征;另外基于图片的分析其实挑战更大。我们做这个选择有以下原因:

  1. 首先图片作为最终的产出物,更直观和确定性,另外这个链路里对上游不会有约束性。
  2. 视觉稿跟开发代码不一样的地方在于布局的不同,比如 listview ,grdview 这类布局类别在设计稿中是不存在的
  3. 基于图片的应用场景会更普适,类似场景。例如自动化测试能力的支持,基于竞品直接截图来套用我们自己的数据源找体感,这类场景是其他的方案做不到的。
  4. 设计稿有图层堆叠的问题,从图片出发可以更好地合并图层。

图像分离是 D2C 图像处理层的重要组成部分,具体内容包括了版面分析,复杂背景处理,布局识别和属性提取。本篇会从版面分析和复杂背景内容提取两个部分加以介绍。版面分析会将图像分割成若干个区块,并对不同的内容做分割和合并。复杂背景处理会在版面分析的基础上提取一些叠加的元素。

所在分层

本文讲述前端智能化 D2C 里技术分层中的 图层处理 能力层,主要负责识别图像的元素类别和提取样式,同时也为后续的布局算法层赋能。

image.png

版面分析

版面分析主要处理 UI 图像的前景提取和背景分析,通过前后景分离算法,将 UI 视觉稿剪裁为 GUI 元素:

1. 背景分析:通过机器视觉算法,分析背景颜色,背景渐变方向,以及背景的连通区域。
2. 前景分析:通过深度学习算法,对GUI碎片进行整理,合并,识别。

背景分析

背景分析的关键在于找到背景的连通区域和闭合区间,具体的步骤如下:

  • 第一步:判断背景区块,通过 sobel,Lapacian,canny 等边缘检测的方法计算出梯度变化方向,从而得到纯色背景和渐变色背景区域。基于拉普拉斯算子的背景区域提取离散拉普拉斯算子的模板如下:

image.png

此外,我们通过统计背景运动趋势的方式来判定它是否存在渐变色背景。如果存在,我们将通过第二步进行精细化处理。

  • 第二步:基于漫水填充算法,选取漫水的种子节点,滤除渐变色背景区域噪声。
def fill_color_diffuse_water_from_img(task_out_dir, image, x, y, thres_up = (10, 10, 10), thres_down = (10, 10, 10), fill_color = (255,255,255)):
    """
    漫水填充:会改变图像
    """
    # 获取图片的高和宽
    h, w = image.shape[:2]

    # 创建一个h+2,w+2的遮罩层,
    # 这里需要注意,OpenCV的默认规定,
    # 遮罩层的shape必须是h+2,w+2并且必须是单通道8位,具体原因我也不是很清楚。
    mask = np.zeros([h + 2, w + 2], np.uint8)

    # 这里执行漫水填充,参数代表:
    # copyImg:要填充的图片
    # mask:遮罩层
    # (x, y):开始填充的位置(开始的种子点)
    # (255, 255, 255):填充的值,这里填充成白色
    # (100,100,100):开始的种子点与整个图像的像素值的最大的负差值
    # (50,50,50):开始的种子点与整个图像的像素值的最大的正差值
    # cv.FLOODFILL_FIXED_RANGE:处理图像的方法,一般处理彩色图象用这个方法
    cv2.floodFill(image, mask, (x, y), fill_color, thres_down, thres_up, cv2.FLOODFILL_FIXED_RANGE)
    cv2.imwrite(task_out_dir + "/ui/tmp2.png", image)
    # mask是非常重要的一个区域,这块区域内会显示哪些区域被填充了颜色
    # 对于UI自动化,mask可以设置成shape,大小以1最大的宽和高为准
    return image, mask

处理过后的效果如下:

image.png
image.png
(原图与处理效果图)

  • 第三步:通过版面切割,提取 GUI 元素。

image.png
(背景分析后提取的内容模块)

这个时候我们已经成功将图片分层并提取了模块,后续细节可以在前景分析和复杂背景提取中获得。

前景分析

前景分析的关键在于组件完整性切割与识别。我们通过连通域分析,防止组件碎片化,再通过机器学习识别组件类型,再通过组件类型进行碎片化合并,反复执行上述动作,直到无特征属性碎片。我们通过瀑布流中提取一个完整 item 为例:

image.png
(标红部分是处理难点)

闲鱼页面中瀑布流卡片识别是实现布局分析的一个重要步骤,需求是当卡片完整出现在截屏图像中时(允许图标遮挡)需要识别出来,卡片被背景部分遮挡时不应该识别出来。上图的瀑布流卡片样式,由于其布局紧凑且样式繁多,导致容易产生漏检或误检。

基于边缘梯度或连通域的传统图像处理方法能根据图像本身的灰度或者形状特征提取出瀑布流卡片的轮廓,优点是定位精度高、运算速度快。缺点是容易受到干扰,召回率不高。

基于目标检测或者特征点检测的深度学习方法采用有监督的方式学习卡片的样式特征,优点是不易受到干扰,召回率很高。缺点是因为涉及回归过程,定位精度比传统图像处理方法要低,并且需要大量的人工标注,运算速度也比传统图像处理方法要慢。

受集成学习的启发,通过融合传统图像处理方法和深度学习方法,结合两者各自的优点,最终能得到具有较高精确率、召回率和定位精度的识别结果。

传统图像处理算法流程如下图所示:
1》. 输入的瀑布流卡片图像转换成灰度图后使用对比度受限的自适应直方图均衡化 (CLAHE) 进行增强
2》. 使用 Canny 算子进行边缘检测得到二值化图像
3》. 对二值化图像进行形态学膨胀处理,连接断开的边缘
4》. 提取连续边缘的外层轮廓,并基于轮廓包含区域的面积大小丢弃面积较小的轮廓,输出候选轮廓
5》. 使用 Douglas-Peucker 算法进行矩形逼近,保留最像矩形的外轮廓,输出新的候选轮廓
6》. 最后对第 4 步的候选轮廓进行水平和垂直方向投影得到平滑的轮廓作为输出

image.png
(传统图像处理算法流程)

算法流程中 1》-3》可以归为边缘检测部分。

受各种因素影响,图像会出现降质,需要对其进行增强来提高边缘检测的效果。使用全图单一的直方图进行均衡化显然不是最好的选择,因为截取的瀑布流图像不同区域对比度可能差别很大,增强后的图像可能会产生伪影。在单一直方图均衡化的基础上,学者基于分块处理的思想提出了自适应的直方图均衡化算法 (AHE) ,但是AHE在增强边缘的同时有时候也会将噪声放大。后来学者在AHE的基础上提出了 CLAHE ,利用一个对比度阈值来去除噪声的干扰,如下图所示直方图,CLAHE 不是将直方图中超过阈值的部分丢弃,而是将其均匀分布于其他 bin 中。

image.png
(直方图均衡)

Canny 算子是一种经典的边缘检测算子,它能得到精确的边缘位置。Canny 检测的一般步骤为:1) 用高斯滤波进行降噪 2) 用一阶偏导的有限差分计算梯度的幅值和方向 3)对梯度幅值进行非极大值抑制 4) 用双阈值检测和连接边缘。实验过程中,需要多次尝试选择较好的双阈值参数。

检测出来的边缘在某些局部地方会断开,可以采用特定形状和尺寸的结构元素对二值化图像进行形态学膨胀处理来连接断开的边缘。边缘检测的结果如下图所示,其中 c) 中 CLAHE 设定对比度阈值为 10.0 ,区域大小为 (10,10),d) 中 Canny 检测设置双阈值为 (20,80),e) 中形态学膨胀结构元素使用大小为 (3,3) 的十字线。

image.png
(传统图像处理结果图)

算法流程中 4》-6》可以归为轮廓提取部分。二值图像形态学膨胀处理后,首先提取连续边缘的外层轮廓。如下图所示,对于只有 0 和 1 的二值图像,假设 S1 为像素值为 0 的一堆背景点,S2 为像素值为 1 的一堆前景点,外层轮廓 B1 为一堆前景点最外围的点,内层轮廓 B2 为一堆前景点最内部的点。通过对二值图像进行行扫描给不同轮廓边界赋予不同的整数值,从而确定轮廓的类型以及之间的层次关系。提取出外层轮廓后通过计算轮廓包含的面积大小丢弃面积较小的外层轮廓,输出第一步候选轮廓。

image.png
(提取轮廓)

闲鱼页面瀑布流卡片轮廓近似于矩形,在四个角由弧形曲线连接。对于提取的候选轮廓使用 Douglas-Peucker 算法进行矩形逼近,保留形状接近矩形的外轮廓。 Douglas-Peucker 算法通过将一组点表示的曲线或多边形拟合成另一组更少的点,使得两组点之间的距离满足特定的精度。之后输出第二步候选轮廓。

通过对第二步候选轮廓所处位置对应的第一步候选轮廓进行水平和垂直方向投影,去除毛刺影响,输出矩形轮廓。轮廓提取的结果如下图所示,其中 c) 中轮廓包含面积设置的阈值为 10000 ,d) 中 Douglas-Peucker 算法设置的精度为 0.01 * 轮廓长度。本文所有提取的轮廓均包含输入框。

image.png
(不同方法识别结果)

我们再介绍下机器学习如何处理:

传统算法中提出采用传统图像处理方法提取轮廓特征,这样会带来一个问题:当图像不清晰或者有遮挡的情况下无法提取出轮廓,即召回率不是很高。

基于卷积神经网络的目标检测算法能通过输入大量样本数据,学习到更具有代表性和区别性的特征。目前目标检测算法主要分成两个派系:以 R-CNN 家族为代表的两阶段流和以 YOLO 、SSD 为代表的一阶段流。一阶段流直接对预测的目标进行分类和回归,优点是速度快,缺点是 mAP 整体上没有两阶段流高。两阶段流在对预测的目标进行分类和回归前需要先生成候选的目标区域,这样训练时更容易收敛,因此优点是 mAP 高,缺点是速度上不如一阶段流。不管是一阶段流还是两阶段流,通用的目标检测推理过程如图所示。输入一张图像到特征提取网络(可选择 VGG 、Inception 、Resnet 等成熟的 CNN 网络)得到图像特征,然后将特定区域特征分别送入分类器和回归器进行类别分类和位置回归,最后将框的类别和位置进行输出。

image.png
(目标检测网络流程示意)

Faster R-CNN 对 R-CNN 家族最大的贡献是将生成候选目标区域的过程整合到整个网络中,使得综合性能有了较大提高,尤其是在检测速度上。Faster R-CNN 的基本结构如图所示。主要分为 4 个部分:1) conv layers。作为一种特征提取网络,使用一组基础的 conv + relu + pooling 层提取图像的特征,该特征被共享用于后续RPN网络和全连接层。2) Region Proposal Network。该网络用于生成候选目标框,通过 softmax 判断候选框是属于前景还是背景,并且通过候选框回归修正候选框位置。3) RoI pooling。收集输入的特征图和候选区域,将这些候选区域映射到固定大小并送入后续全连接层。4) classifer。计算候选框的具体类别,并且再次回归修正候选框的位置。

image.png
(目标检测网络基本结构示意)

使用 Faster R-CNN 进行瀑布流卡片的识别,得到下图的结果。

image.png
(目标检测结果)

传统算法与机器学习的融合

描述的传统图像方法能够获得高定位精度的卡片位置,但受卡片本身模式的影响,召回率不高)中右边卡片没有检测到。基于目标检测的深度学习方法具有较高的泛化能力,能获得较高的召回率,但是回归过程无法得到高定位精度的卡片位置)中卡片都能检测出来,但有两个卡片的边缘几乎粘连在了一起。

将两种方法得到的结果融合在一起,能同时获得高精确率、高召回率、高定位精度的检测结果。融合过程如下:

  1. 输入一张图像,并行运行传统图像处理方法和深度学习方法,分别得到提取的卡片框 trbox 和 dlbox 。定位精度以 trbox 为标杆,精确率和召回率以 dlbox 为标杆
  2. 筛选 trbox 。规则为当 trbox 与 dlbox 的 IOU 大于某个阈值时(比如 0.8 )保留此trbox,否则丢弃,得到 trbox1
  3. 筛选 dlbox 。规则为当 dlbox 与 trbox1 的 IOU 大于某个阈值时(比如0.8)丢弃此 dlbox ,否则保留,得到 dlbox1
  4. 修正 dlbox1 位置。规则为dlbox1的每条边移动到距离其最近的一条直线上,约束条件为移动的距离不能超过给定的阈值(比如 20 个像素),并且移动的边不能跨越 trbox1 的边,得到修正的 dlbox2
  5. 输出 trbox1 + dlbox2 为最终融合的卡片框
结果

先介绍几个基本指标:
True Positive(TP): 被模型预测为正的正例数
True Negative(TN): 被模型预测为负的负例数
False Positive(FP): 被模型预测为正的负例数
False Negative(FN): 被模型预测为负的正例数
精确率 (Precision) = TP/(TP+FP) :反映了被模型预测的正例中真正的正样本所占比重
召回率 (Recall) = TP/(TP+FN) : 反映了被模型正确预测的正例占总的正样本比重
定位精度 (IOU) = 两个框的交集大小/两个框的并集大小

image.png
(不同方式得到的检测结果)

上图分别显示了不同方法识别的卡片, d) 相对于 b) 的优势是提高了召回率,d) 相对于 c) 的优势是提高了定位精度。图一图二图三显示了一些其他实例图像的识别,每行图像是一类实例图,第一列是原始图像,第二列是传统图像处理识别的卡片,第三列是深度学习识别的卡片,第四列是融合的卡片。

图一图二能够准确识别卡片轮廓:

image.png
image.png
(前景识别结果示例I)

图三融合卡片的下边缘并没有完全贴合,这是因为融合步骤中修正 dlbox1 位置时,采用传统图像处理方法寻找临域范围内最近的直线,受到图像样式的影响,找到的直线并不是期望的卡片下边缘。

image.png
(前景识别结果示例II)

实验过程中随机截取了 50 张闲鱼瀑布流卡片图像,共有卡片 96 个(不包含输入框),对每张图像分别采用传统图像处理方法、深度学习方法、融合方法得到卡片的识别结果,其中传统图像处理方法共识别出 65 个卡片,深度学习方法共识别出 97 个,融合后共识别出 98 个。精确率、召回率、定位精度如下表所示。融合后识别结果结合了传统图像处理方法定位精度高、深度学习方法召回率高的优点。

不同方法结果

image.png

前景算法小结

通过对闲鱼页面瀑布流卡片识别过程中的描述,我们简单介绍了前景处理的探索,通过机器视觉算法和机器学习算法协同完成前景元素的提取和识别。

结束语

本篇我们通过对前景提取和背景分析的介绍,提出了一种通过传统图像处理和深度学习相融合的方法,来得到高精确率、高召回率和高定位精度的识别结果。但方法本身还存在一些瑕疵,比如融合过程对组件元素进行修正时也会受到图像样式的干扰,后续这部分可以进一步进行优化。

复杂背景内容提取

复杂背景内容提取指的是从复杂的背景中提取出特定的内容,例如在图片中提取特定的文字,在图片中提取特定的叠加图层等等。

这是一个业界难题,基于传统的图像处理的方法存在准确率和召回率的问题,没法解决语义的问题。而主流的机器学习的方法,例如目标检测无法获取像素级别的位置信息,而语义分割的方法则只能提取像素而无法获取半透明叠加前的像素信息。

本文考虑到这些痛点,本文采用了目标检测网络来实现内容召回,GAN 网络实现复杂背景中特定前景内容的提取和复原。

复杂背景的处理流程分为如下几个步骤:

image.png

内容召回:

内容召回我们采用目标检测网络来实现,例如 Faster-rcnn 或者 Mask-rcnn 等,如下图所示:

image.png

区域判断:

根据拉普拉斯算子计算周边梯度,判断所处区域是否是复杂区域。

简单背景:

由于目标检测模型本身的局限性,会导致没法达到像素级别的精确性,因此需要对位置做修正。如果是简单背景就可以基于梯度的思想做位置修正,具体计算方式如下:

image.png
(简单背景位置修正公式)

复杂背景:

背景是复杂背景时,左图是原图,右图是提取的文字区块:

image.pngimage.png
(原图和文字区域)

此时提取出的框不是完全正确,那么此时根据梯度等机器视觉算法已经不能对位置做正确的修正了。本文提出了基于 GAN 网络的方式来解决复杂背景内容提取问题,网络的主要结构如下图所示:

image.png
(GAN网络流程图)

为什么选择 GAN 网络?

1)基于 srGAN 网络,该网络加入了特征图的损失函数,这样可以很好保留高频信息,能更好的保留边缘。特征图的损失函数如下图所示:

image.png
(特征图损失函数)

该公式将原图和生成图特征值差的平方做为损失函数。
2)由于有对抗损失的存在,可以很好的降低误检率。
3)最重要的一点是在有透明度的场景下,语义分割网络只能“提取”元素,无法“还原”元素。而GAN网络不仅可以在提取元素的同时还原出未叠加时的像素情况。

网络训练流程图:

image.png
(srGAN网络训练流程)

针对业务场景对 GAN 网络做的改进:

由于我们不是超分辨率场景,因此不用 pixelShuffler 模块做上采样。
由于场景比较复杂,可以引入 denseNet 和加深网络来提高准确率。
内容损失函数对于压制误判的噪点效果不理想,因此加大了误判的惩罚,具体如下图所示:

image.png

预测获取的结果图 I :

image.png
image.png
(复杂背景的文字内容提取)

预测获取的结果图 II :

image.png
image.png
(原图和相应的处理结果)

结束语

本篇我们通过复杂背景内容提取的介绍,提出了一种机器学习为主,图像处理为辅去精确获取特定前景内容的方法,得到了高精确率、高召回率和高定位精度的识别结果。

下图分别是传统算法,语义分割方法和本文融合方法的各个指标的情况。

image.png
(不同算法的识别结果)

业务场景落地

本篇我们提出的方法已经应用在如下场景:

  1. imgcook 图片链路中应用,对于通用场景的准确率能达到 73% ,特定的卡片场景能达到 92% 以上。
  2. 淘宝自动化测试图像内容理解,例如应用在99大促和双11模块识别中。整体的准确率和召回率都能达到 97% 以上。

未来展望

未来我们打算从图片链路出发,做到如下几点:

  1. 丰富和完善布局信息,能够精确地识别 listview,gridview,waterfull 等布局信息。
  2. 进一步提高通用场景的准确率和召回率。针对小目标,我们后续会引入特征金字塔(fpn),Cascade等一系列技术来提高我们的准确率和召回率。
  3. 增加适配的特定场景。现有的场景只覆盖了闲鱼和部分淘宝的页面适配,我们希望后续能够支持更多的页面,进一步提高图像的泛化能力。
  4. 引入图片样本制造机,降低特定场景的接入门槛。
相关文章
|
12天前
|
前端开发 小程序 Java
uniapp上传图片 前端以及java后端代码实现
uniapp上传图片 前端以及java后端代码实现
28 0
|
15天前
|
缓存 前端开发
前端代码整洁与规范之CSS篇
【4月更文挑战第2天】 前端代码整洁与规范之CSS篇
35 4
|
29天前
|
JSON 前端开发 Java
layui上传图片,前端直接拷代码,后端……
layui上传图片,前端直接拷代码,后端……
24 0
|
1月前
|
缓存 前端开发 JavaScript
揭秘前端性能优化:从代码到用户体验的全面升级
揭秘前端性能优化:从代码到用户体验的全面升级
19 0
|
2月前
|
前端开发 JavaScript 安全
从前端性能优化角度谈JavaScript代码压缩与混淆
本文从前端性能优化的角度出发,探讨了JavaScript代码压缩与混淆的重要性及实现方式,通过分析不同压缩混淆工具的特点和效果,为开发者提供了实用的指导和建议。
|
4天前
|
前端开发 JavaScript 算法
比较流行的前端代码书写规范都有哪些
【4月更文挑战第13天】前端代码规范增进代码可读性和团队协作,包括缩进(用2空格)、命名(变量 camelCase,常量 MY_CONSTANT,类 PascalCase)、注释、语句与表达式、错误处理、代码复用。文件命名规范涉及扩展名、目录结构、简洁文件名、入口文件和配置文件命名。遵循这些规范能提高代码一致性,但需按项目需求调整。不断学习新规范以适应前端技术发展。
9 1
|
6天前
|
监控 前端开发 JavaScript
如何使用浏览器调试前端代码?
【4月更文挑战第11天】前端开发中,浏览器调试是关键技能,能提升代码质量。本文介绍了如何使用浏览器的调试工具:1) 打开调试窗口(F12或右键检查);2) Elements标签页检查DOM结构和样式;3) Console调试JavaScript,查看日志和错误信息;4) Sources设置断点调试JS文件;5) 利用Network、Performance和Memory等标签页优化性能。熟悉调试工具、利用日志和错误信息能有效定位问题,提高开发效率。
16 7
|
1月前
|
机器学习/深度学习 人工智能 前端开发
前沿技术探索:构建更智能的前端开发体验
【2月更文挑战第11天】 本文深入探讨了利用人工智能(AI)和机器学习(ML)技术革新前端开发过程的最新趋势。通过分析当前的开发挑战,文章提出了一种结合AI辅助设计、代码自动生成和智能测试的全新前端开发框架。这不仅能显著提升开发效率,还能优化用户体验,为企业创造更大的商业价值。文章的核心在于展示如何通过技术创新,将复杂的前端开发任务简化,从而使开发者能够更加专注于创意和策略的实现。
41 3
|
1月前
|
前端开发 开发者
React Hooks:提升前端开发效率和代码可维护性
传统的 React 类组件在处理状态管理和生命周期函数时存在一些限制,而引入的 React Hooks 技术可以帮助前端开发者更高效地管理组件状态和逻辑,提升代码的可读性和可维护性。本文将介绍 React Hooks 的基本用法及其在实际项目中的应用场景。
|
2月前
|
开发框架 前端开发 JavaScript
如何提高前端代码的可维护性
【2月更文挑战第3天】在现代软件开发中,前端已经变得越来越重要。一个好的前端代码可以帮助团队更快速、高效地开发出高质量的产品。但是,随着项目规模的扩大,前端代码也变得越来越复杂和难以维护。本文将介绍一些提高前端代码可维护性的方法。