在UI自动化中,除了通过元素定位来确定结果外,图片的识别慢慢地得到了应用。今天我们讨论一种场景:在多张图片中,例如5张,其中有4张基本一致,有一张和其他四张明显不同。例如我们在百度搜索,如下图1-4所示:
1 2 3 4如何区别出下图5是另外一张不同的图呢?
5本文描述的就是在这个场景下通过让图片自己投票选出最大差异的图片并采用go语言实现了这一方法。
首先比较两个图片是否一致,有两个比较直接的方法:一是获取两张图片的余弦值,一是获得两张图片的指纹信息之后进行比较。
这里我们使用 github.com/Comdex/imgo提供的方法:
获取两张图片的余弦值:
func CosineSimilarity(src1string, src2string) (cossimifloat64, errerror)
获得一张图片的指纹信息:
本文这里先采用了图片的指纹信息比对作为基础,之后再介绍使用余弦值做对比基础。
获取一张图片的指纹,就如同信息摘要,需要对图片做一定的简化。在imgo的实现中,将图片简化为了一个8*8的矩阵。为了更精准地比对图片,首先将矩阵大小参数化,之后我们通过参数来构建数据的矩阵:
GetFingerprintByLargeMatrix在获得一张图片的指纹后,我们还需要对比两张图片指纹的异同之处。图片的指纹是一个01序列。通过对比每一位上的01值,可以得到不同处的位置。通过三个指标来表达指纹的差异程度:位置的平均值avg、位置的中位数mid、差异位置的个数dc:
diffFingerPrint将这个方法进一步封装后,我们提供一个获得两张图片的指纹和三个表达指纹差异程度的值,并在这里定义了我们需要构建的矩阵大小为300*300:
GetFingerPrintDiff这样之后,将之前的5张图片,每张图片分别与每张图片两两对比,我们就能获得一个每张图片的指纹与每张图片的指纹差的差异表,差异值是由位置的平均值avg、位置的中位数mid、位置的个数dc构成的三元组(avg,mid,dc),同时我们可以得到位置的平均值avg的数组avgarray,位置的中位数的数组midarray,位置的个数的数组dcarray:
差异表此时,我们已知差异值表,面临的问题是让每个图片自己选出与自己差异最大的那张图片。
首先我们构建一个选出数组中的最大值与其位置的函数:
FindBigestNumAndIndex然后计算这样我们就能找出三个数组:平均值avg的数组avgarray,位置的中位数的数组midarray,位置的个数的数组dcarray中,差异最大的数和其对应图片的位置。然后用三个差异值进行投票,假设三个值的权重都为1,统计投票结果,即可找到与某张图片差异最大的的图片的位置下标,代码如下:
FindTheMostDiffOne运行结果如下,与图片1差异最大的是图片5:
与图片1差异最大的是图片5通过图片两两循环对比后,每个图片就自己选出的与自身差异最大的图片,最后通过统计得票情况,得票最高的图片即为那张不同的图片,代码如下:
统计最终得票对开头的百度搜索图片为例,运行程序,结果如下:
得票结果最终选出图片5是不同的。
回到开头,我们面临的场景是:在多张图片中,例如5张,其中有4张基本一致,有一张和其他四张明显不同。而有时,可能其中4张图片彼此间的也有一些差距,例如页面上有一些动态的活动信息,不同的截图活动信息会不同,例如下面图1-4携程图片和图5:
1 2 3 4 5每个图都有明显的差异,但图1-4相比图5是大同小异。运行程序的结果是:
选1最终图片1被选了出来,并不是我们想要的结果。
此时我们观察差异表,能够发现avg和mid的值明显比dc的值大1-2倍。此时我们可以加大dc的权重作为平衡:
FindTheMostDiffOne运行程序的结果:
选出5针对不同的场景对权重作出调整,对结果的正确性有很大影响。
最后回顾下一下,咱们面临的基本场景是:在多张图片中,例如5张,其中有4张基本一致,有一张和其他四张明显不同。要自动的选出其中明显不同那一张图片。
解决此问题的基本思路是:首先是使用指纹信息得出三个用来表达图片差异的指标;然后通过三个指标和权重计算出差异值;之后每张图片根据差异值选出与自己差异最大的图片;最后统计每张图片都得票数,票高者即为差异最大的图片。
其中,我们采用了指纹信息作为比较图片差异的基础。前文提到另一个比较图片差异的方法是比较图片的余弦值。两张图片的余弦值越大则越相近,越小差异越大,所以我们只需要找到余弦值最小的图片,即是差异最大的图片。最后再统计投票结果,就能找到最大差异的图片。
用更大的矩阵计算余弦值,提高对比的精细度:
CosineSimilarityByLargeMatrix找到最小余弦值的函数(余弦值范围[-1,1]):
FindTheLetstNumAndIndex再封装之后:
FindTheMostDiffOneByCos统计投票过程和使用指纹一致:
统计投票对百度收索的图片,进行一次投票的结果:
投票结果符合我们的预期;
在携程图片的场景下的投票结果:
投票结果不符合我们的预期。
可见,对于不同的场景,需要对图片对比的基础算法、参数的选择对结果有很大影响。另一个问题是,示例的图片本身不够丰富。也许加入更多的图片,会有不同的效果。
希望对你有帮助。
多谢。
网友评论