
一、项目介绍
以图搜图的关键技术叫做“感知哈希算法”(Perceptual hash algorithm),即用一个特征向量(“指纹”(fingerprint)字符串)来描叙一张图片,然后比较不同图像的指纹,差异越小,说明图像越相似。
例如在购物电商系统中,通过以图搜图上传一张iphone14搜索出相类似的商品如下图所示:
借助OpenCV中的按位异或函数cv2.bitwise_xor(),可以计算出哈希值的距离。在进行按位异或运算时,如果两个数的运算数相同则返回0,否则返回1。例如:
cv2.bitwise_xor('1011', '1010') 可以得到的结果为:’0001‘
cv2.bitwise_xor('1111', '0010') 可以得到的结果为:’1101‘
本文以一个小型以图搜图项目,介绍感知哈希的计算流程以及代码实现。
二、计算流程
基于感知哈希算法的计算流程:
-
OpenCV修改尺寸
cv2.resize(src, size)
-
OpenCV色彩空间转换
cv2.cvtColor(img, cv2.COLOR_BRG2GRAY)
-
Numpy计算像素均值
m = np.mean()
-
构造感知哈希位信息
#如果像素点的像素值大于均值,得到1,否则为0
r = img > m
r.astype(int)
-
转换一维数据哈希值
函数flatten()
注意:flatten()可以将原始的二维数据转换为一维数组,数据发生变化,不会对原来的数据造成影响。
-
cv2.bitwise_xor计算距离
cv2.bitwise_xor(src1, src2) #异或运算(相同为0, 不同为1),
np.sum() #逐位进行求和
-
遍历所有图像,计算图像内所有图像哈希值
glob.glob('images/*.png')
-
结果显示
cv2.imread()
plt.subplot(nrows, ncols, index) #行数、列数、窗口序号
plt.imshow()
三、代码实现
import glob
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 1、提取感知哈希值
def getHash(I):
size = (8, 8)
I = cv2.resize(I, size)
I = cv2.cvtColor(I, cv2.COLOR_BGR2GRAY)
m = np.mean(I)
r = (I>m).astype(int)
x = r.flatten()
return x
# 2、计算汉明距离
def hamming(h1, h2):
r = cv2.bitwise_xor(h1, h2)
h = np.sum(r)
return h
# 3、计算检索图像的感知哈希值
o = cv2.imread('sun1.png')
h = getHash(o)
# print('图像的感知哈希值:', h)
images = []
# EXTS = 'jpg', 'jpeg', 'gif', 'png', 'bmp'
images.extend(glob.glob('images/*.png'))
# print(images)
seq = []
for f in images:
I = cv2.imread(f)
seq.append((f, getHash(I)))
# print(seq)
# 4、计算检索图像与图像库内所有图像的距离,将最小距离对应的图像作为检索结果
distance = []
for x in seq:
distance.append((hamming(h, x[1]), x[0]))
# print(distance)
s = sorted(distance)
# print(s)
r = []
for i in range(9):
r.append(cv2.imread(str(s[i][1])))
# r2 = cv2.imread(str(s[1][1]))
# r3 = cv2.imread(str(s[2][1]))
plt.figure('result')
plt.subplot(331)
plt.imshow(cv2.cvtColor(o, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.subplot(332)
plt.imshow(cv2.cvtColor(r[0], cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.subplot(333)
plt.imshow(cv2.cvtColor(r[1], cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.subplot(334)
plt.imshow(cv2.cvtColor(r[2], cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.subplot(335)
plt.imshow(cv2.cvtColor(r[3], cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.subplot(336)
plt.imshow(cv2.cvtColor(r[4], cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.subplot(337)
plt.imshow(cv2.cvtColor(r[5], cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.subplot(338)
plt.imshow(cv2.cvtColor(r[6], cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.subplot(339)
plt.imshow(cv2.cvtColor(r[7], cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()
运行上述代码,输出上图中的第一幅图像,通过感知哈希算法可以在我们的图像检索库中得到最相似的8张图像,进行结果的展示。
作者简介


