通过投票选出最大差异图片-GO语言实现

作者: 胖艺 | 来源:发表于2018-08-14 23:03 被阅读53次

在UI自动化中,除了通过元素定位来确定结果外,图片的识别慢慢地得到了应用。今天我们讨论一种场景:在多张图片中,例如5张,其中有4张基本一致,有一张和其他四张明显不同。例如我们在百度搜索,如下图1-4所示:

1 2 3 4

如何区别出下图5是另外一张不同的图呢?

5

本文描述的就是在这个场景下通过让图片自己投票选出最大差异的图片并采用go语言实现了这一方法。

首先比较两个图片是否一致,有两个比较直接的方法:一是获取两张图片的余弦值,一是获得两张图片的指纹信息之后进行比较。

这里我们使用 github.com/Comdex/imgo提供的方法:

获取两张图片的余弦值:

func CosineSimilarity(src1string, src2string) (cossimifloat64, errerror)

获得一张图片的指纹信息:

func GetFingerprint(srcstring) (fpstring, 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

统计投票过程和使用指纹一致:

统计投票

对百度收索的图片,进行一次投票的结果:

投票结果

符合我们的预期;

在携程图片的场景下的投票结果:

投票结果

不符合我们的预期。

可见,对于不同的场景,需要对图片对比的基础算法、参数的选择对结果有很大影响。另一个问题是,示例的图片本身不够丰富。也许加入更多的图片,会有不同的效果。

希望对你有帮助。

多谢。

相关文章

  • 通过投票选出最大差异图片-GO语言实现

    在UI自动化中,除了通过元素定位来确定结果外,图片的识别慢慢地得到了应用。今天我们讨论一种场景:在多张图片中,例如...

  • 2020-12-17水稻、小麦GO富集分析

    RNAseq常规做法是先筛选出差异表达基因,然后针对筛选出来的差异基因做GO富集分析。 1.水稻、小麦GO信息提取...

  • go语言并发操作

    go语言实现并发 通过go 实现并发操作 执行上述代码,会间隔执行say方法 通过channel实现并发数据间的通...

  • 使用Tesseract实现图片文字识别

    在Ubuntu Linux下通过go语言实现图片中文识别 1、安装tesseract ocr包 如果是在Cento...

  • Go语言实现TCP通信

    章节 go 优势 go 实现 TCP 通信 1 go 语言优势 1.1 go 语言优势 2 go 实现TCP通信 ...

  • go接口与反射

    go语言的interface是个很松散的概念,类型不必明确声明实现了接口,go语言通过内部维护一个实现此接口方法的...

  • go语言并发goroutine(七)

    1.goroutine基础 goroutine 是go语言实现的核心,实质就是线程,goroutine 是通过go...

  • go 面向对象编程

    尽管GO语言没有封装,继承,多态这些概念,但同样通过别的方式实现这些特性封装:通过方法实现继承:通过匿名字段实现多...

  • Golang笔记: 接口(interface)

    Go语言不是一种“传统”的面向对象编程语言,它里面没有类和继承的关系。但是Go语言通过灵活的接口概念,可以实现很多...

  • 并发routine

    在Go语言中,语言本身就已经实现和支持了并发, 我们只需要通过go关键字来开启goroutine即可。 gouro...

网友评论

    本文标题:通过投票选出最大差异图片-GO语言实现

    本文链接:https://www.haomeiwen.com/subject/mombbftx.html