可靠性研究:图片相似性检测

可靠性做久后,我常常感到无力,因为很多东西不在控制范围内。

比如说安装,声明是售后安装,但很多人是自己安装,或者装修时找水电工等人安装。即使是售后人员去安装,也会有很多不按要求来的。

首先要做的是设计保证,减少对安装人员的要求。但即使设计上做得再多,也很难做到免安装,依然要管控安装的质量。于是有了拍照上传确认,对安装中重要的点进行拍照。

这就涉及到图像的质量的检测。最好是在上传的时候就进行判断,比如照片是否重复利用,照片数量是否全,是否模糊,是否违反安装红线等等。也可以事后抽一些图稽查。很多时候,稽查是靠人工的,但工作量很大,我们可以考虑用程序去实现。

本文讲相似相同图片的识别,后续讲模糊检测,AI审图进行红线管控等。

以下面这个例子为例:

图1 一组相似图片

这两张图片一眼看上去,感觉左边的图是右边的图的局部截取放大图。仔细再看,可以发现并不是,细节上还是有差异,不是同一张图的截取。这种情况人工稽查可能会误判。

售后系统上存在大量此类图片,为了减少人工稽查工作量,我们使用程序来帮助识别。

图像相似检测有很多种方法,这里我们采用感知哈希方法来进行比较。它的总体思想是为图片生成一个指纹,两张图片的指纹越相似,说明两张图片就越相似。

整体步骤可以描述为以下几步:

第1步:缩小尺寸。由于图片的原始尺寸可能不同,我们把图片都缩放到32*32去比较,总共1024个像素。这样可以把图片的尺寸差异去除,只保留结构,另外32*32这个尺寸也是为了减少后续DCT变换的计算量。

图片缩放时,比较有影响的是采用哪种插值方法。我暂时还没有去详细研究哪种插值方法好,但据网络搜索的结果,说是在缩小图像时,用Area插值方法比较好,就先用这个方法,后续可以进一步研究。

第2步:简化色彩。把图片转为灰度图,使得进一步减少计算量。

第3步:计算DCT。把图片进行DCT变换,得到一个32*32的矩阵。DCT变换又称离散余弦变换(DCT,Discrete Cosine Transform)是与傅里叶变换相关的一种变换,它类似于离散傅里叶变换(DFT, Discrete Fourier Transform)。

图像处理二维DCT变换数学公式如下:

二维DCT变换就是将二维图像从空间域转换到频率域。计算出图像由哪些二维余弦波构成,计算出的结果为c(u ,v),其中u为二维波的水平方向频率,v为二维波的垂直方向频率;最终会计算出很多的c(u,v) ; 每一个c称为一个DCT系数,代表的是频率为(u,v)的二维波的振幅(或者能量),所有这些二维波的叠加就是那个原始的图片。

第4步:截取DCT。虽然DCT结果是32*32的矩阵,但我们只取左上角8*8的部分作为后续计算,这部分呈现了图像的低频部分。DCT变换的时候,滤掉了高频的部分,一般图形高频部分的系数是比较小的,在量化的时候可以忽略掉。

  图1右侧图片经过DCT变换后的图像

第5步:计算平均值。计算8*8矩阵,共64个像素的灰度平均值。

第6步:计算hash值。根据8*8的DCT矩阵,设置0或1的值,大于等于DCT均值的设为”1”,小于DCT均值的设为“0”。组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。

第7步:比较图片。汉明距离可以衡量两张图片的差异。汉明距离越小,则代表相似度越高。这里定义相似度的计算公式为:(1-汉明距离/64)*100%

通过上述步骤,我们就得到了开头两张图的相似度:

实现上述过程,可以借助opencv第三方库实现,它里面已经定义有很多函数,例如缩放,转灰度,DCT变换等。当然,如果想加深对图像处理的理解,在学习之初,我建议自己编写程序去实现,把这些库函数自己写一遍。

以下是用python实现的参考代码:

import cv2
import numpy as np

# 感知哈希算法
def pHash(path):
    # 读图片
    img = cv2.imread(path)
    # 缩放32*32,这里使用了AREA插值
    img = cv2.resize(img, (32, 32), interpolation=cv2.INTER_AREA)
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 将灰度图转为浮点型,再进行dct变换    
    dct = cv2.dct(np.float32(gray))
    # 只取左上角8*8计算
    dct_roi = dct[0:8, 0:8]
 
    hash = []
    avreage = np.mean(dct_roi)
    for i in range(dct_roi.shape[0]):
        for j in range(dct_roi.shape[1]):
            if dct_roi[i, j] > avreage:
                hash.append(1)
            else:
                hash.append(0)
    return hash
    
# Hash值对比 
def cmpHash(hash1, hash2):
    n = 0
    # hash长度不同则返回-1代表传参出错
    if len(hash1) != len(hash2):
        return -1
    # 遍历判断
    for i in range(len(hash1)):
        # 不相等则n计数+1,n最终为相似度
        if hash1[i] != hash2[i]:
            n = n + 1
    return n
 
if __name__ == "__main__":
    hash1 = pHash("D:/0/t3.png")
    hash2 = pHash("D:/0/t4.png")
    n = cmpHash(hash1, hash2)
    print('感知哈希算法相似度:%.2f'%(1-float(n/64)))

 但python处理速度实在太慢,不适合在大量图片处理中使用,实际软件开发中,我是用C#编程实现的。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值