前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >感知哈希算法计算图像相似度

感知哈希算法计算图像相似度

原创
作者头像
软件架构师Michael
发布2022-11-03 14:14:44
1.3K0
发布2022-11-03 14:14:44
举报
文章被收录于专栏:软件工程师Michael

实现图片相似度比较的哈希算法有三种:均值哈希算法,差值哈希算法,感知哈希算法

下文简单介绍感知哈希算法,其他算法等后续文档再述。

感知哈希算法是一个比均值哈希算法更为健壮的一种算法,与均值哈希算法的区别在于感知哈希算法是通过DCT(离散余弦变换)来获取图片的低频信息。

离散余弦变换(DCT)是种图像压缩算法,它将图像从像素域变换到频率域。然后一般图像都存在很多冗余和相关性的,所以转换到频率域之后,只有很少的一部分频率分量的系数才不为0,大部分系数都为0(或者说接近于0)。经过DCT变换后的系数矩阵从左上角到右下角频率越来越高,因此图片的能量主要保留在左上角的低频系数上了。

具体步骤:

(1)缩小尺寸:pHash以小图片开始,但图片大于8x8,32x32是最好的。这样做的目的是简化了DCT的计算,而不是减小频率。

(2)简化色彩:将图片转化成灰度图像,进一步简化计算量。

(3)计算DCT:计算图片的DCT变换,得到32x32的DCT系数矩阵。

(4)缩小DCT:虽然DCT的结果是32x32大小的矩阵,但我们只要保留左上角的8x8的矩阵,这部分呈现了图片中的最低频率。

(5)计算平均值:如同均值哈希一样,计算DCT的均值。

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

分析: 结果并不能告诉我们真实性的低频率,只能粗略地告诉我们相对于平均值频率的相对比例。只要图片的整体结构保持不变,hash结果值就不变。能够避免伽马校正或颜色直方图被调整带来的影响。对于变形程度在25%以内的图片也能精准识别。

代码实例:

代码语言:javascript
复制

# -*- coding: utf-8 -*-
import cv2
import numpy as np
import os
import glob
dir_data=os.path.dirname(os.path.dirname(__file__))
# Hash值对比


def cmpHash(hash1, hash2,shape=(10, 10)):
    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/(shape[0]*shape[1])


 #  感知哈希算法(pHash)


def pHash(img,shape=(10,10)):
    # 缩放32*32
    img = cv2.resize(img, (115, 114))  # , interpolation=cv2.INTER_CUBIC

    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 将灰度图转为浮点型,再进行dct变换
    dct = cv2.dct(np.float32(gray))
    # opencv实现的掩码操作
    dct_roi = dct[0:10, 0:10]

    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


def match_result():
    for jpgfile in glob.glob(dir_data+'\POC\img/*.jpg'):
        file=os.path.basename(jpgfile)
        img1 = cv2.imread('images/template.jpg')
        img1 = cv2.resize(img1,(115,114))
        img2 = cv2.imread(jpgfile)

        hash1 = pHash(img1)
        hash2 = pHash(img2)
        n = cmpHash(hash1, hash2)
        print('{}的相似度是:{}'.format(file, n))
    

if __name__=="__main__":
    match_result()

以上代码运行结果如下:

相似度计算结果
相似度计算结果

【小结】

图像处理属于AI领域的CV分支,主要难点在于算法的选用与模型的优化,需要长期的算法功底的积累,切不可一蹴而就。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档