在ui自动化测试领域,会遇到这样的情形:发布一张图片或上传一个头像,如何通过自动化测试的方式判定发布后的图片是否正确呢?又或者,我们如何通过自动化测试的方式判定某网页的某个logo是否与预期的一致呢?也许,你会想,要是能够自动比对图片,将差异化的点在图片上圈出来就好了。相信我,只要你想,就会有。
试想一下,上述情形,像不像我们常玩的“一起来找茬”呢?让我们以具体案例展示如何以自动化的方式“找茬”。
如下所示,图1、图2是我们两张相似图片(暂定图1名为img1,图2名为img2)。我们以图1、图2为例,使用自动化的方法找出两张图片中差异之处。
方案设计
对于比较图片差异性,我们经常使用的是图片识别的方法。最基本的方法则是:
“RGB转灰”将图片转换为灰度图,去除颜色信息干扰;
“切割/缩放至相同尺寸”是为了保持一致性、防止失真,避免图片在尺寸变化时产生失真和形变,从而确保图片的质量和准确性,也避免因为图片的尺寸不同,影响判定结果。同时,缩放和切割,也可以减少图片处理过程中的计算量,提高效率;
“获取图片之间的差异性”有很多方法,例如特征提取和匹配,使用特征提取算法来提取图片中的特征点,并使用特征匹配算法来匹配两张图片中的特征点。这种方法可以在一定程度上容忍平移、旋转、缩放等变化。例如局部比较,将图片分成小块,分别比较每个小块之间的相似性。这种方法可以帮助排除局部变化所引起的影响。例如结构化比较,将图片转换为结构化数据(例如直方图、颜色直方图、梯度直方图等),然后比较结构化数据之间的相似性。例如深度学习方法,使用深度学习模型来学习图片的表示,并进行图片的比较和匹配;
“找到图片之间的差异区域”在获取图片之间的差异性之后,常通过阈值化处理和边界检测等方法,圈出对比图片间差异区域。其中,阈值化处理是将差异区域和背景分离开来。而边界检测算法(或者轮廓检测算法),则是圈定差异区域的边界;
“标记差异区域”则相对简单,将检测出的差异区域编辑,通过一定的轮廓形状(如矩形)和颜色(如红色)在原图种标记出来。
简单阐述了设计方案,接下来让我们看看具体实现方法。
具体实现
本文中,我们使用python的OpenCv模块来实现我们的需求。
如下图3、图4所示,是我们将图1、图2灰化处理后的图片。将彩色图片转为灰度图,只需一行代码即可:
gray_img1 = cv2.imread(img1, cv2.IMREAD_GRAYSCALE) gray_img2 = cv2.imread(img2, cv2.IMREAD_GRAYSCALE)
即,通过cv2.IMREAD_GRAYSCALE将原始图片作为灰度图读入。
在本文中,通过将gray_img2灰度图调整为gray_img1灰度图大小,保持两张图片的大小一致。
height1, width1 = gray_img1.shape[:2] height2, width2 = gray_img2.shape[:2] gray_img2 = cv2.resize(gray_img1, (width1, height1))
如下图5所示,为gray_img2和gray_img1通过结构相似性计算得到的差异图。
(score, diff) = structural_similarity(gray_img1, gray_img2 , full=True) diff = (diff * 255).astype("uint8")
图5 gray_img1和gray_img2差异图
获取差异图后,再经过阈值处理和边界检测,获得差异性区域。通过矩形圈出原图中,具有差异的区域。具体如下图6、图7所示:
thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours(cnts) for c in cnts: # images differ (x, y, w, h) = cv2.boundingRect(c) cv2.rectangle(img1, (x, y), (x + w, y + h), (0, 0, 255), 2) cv2.rectangle(img2, (x, y), (x + w, y + h), (0, 0, 255), 2)
结果对比
让我们来看看自动化获取图片差异性的结果与真实差异区域结果的对比,即:让我们来看看以上方法的优良。
如下图8所示,为img2原始图,图9为自动化识别差异区域结果图,图10为人工识别的差异区域结果图。
不难看出,自动化识别的结果正确性为2/3,其中最右侧绿色球形部分没有正确检测出来。除此之外,图9中还有许多虚假差异性区域被检测出来了。那,这是不是说,我们自动化识别的效果不理想呢?更或者,有人会跳出来说:你这结果差太远了,还不如不做!
其实,并非如此。绿色球形部分没被检测出来,是因为本文中使用的图片灰化方法,将彩色图片转为灰度图时,会丢失某些色彩信息,导致在灰化后,相同的结构、灰度相近的颜色不会被检测出来。而其中增加了许多虚假区域的检测结果,是因为本文是直接截取的网站图片,原始大小和边界具有一定差异性(最明显的就是图9中,上下边缘被标记的红色线条区域),导致检测结果有一定误差性。
本文中,只是选择了最基本的实现方法为例,阐述自动化识别在图片中的作用。虽有误差,但正确性依然可圈可点。由此可见,自动化识别在我们ui自动化测试中(例如图片识别、图片对别等)有一席之地,可以帮助我们提升某些场景下(例如发布一张图片或上传一个头像,通过自动化测试的方式判定发布后的图片的正确性)测试效率。
在文章的最后,想问大家:对于本文中出现的两个检测性误差问题,要如何解决呢?
1)彩色图片灰化,丢失色彩信息,导致检测误差;
2)图片截取,原始大小和边界具有一定差异性,导致检测误差;
欢迎大家积极留言互动~
作者:刘晓佳Rachel