<返回更多

比较图片相似算法

2019-10-16    
加入收藏

概述

一般情况下, 图片相似算法分为三种

其实三个算法差不多. 我们以均值hash算法为例, 算法的步骤如下:

  1. 缩放为n*n的图片
  2. 去色, 获取灰度图
  3. 得到hash指纹
  4. 比较hash指纹的汉明距离, 得到相似值

上面算法的不同, 主要是得到hash指纹的算法不同

均值hash算法

我们举例说明. 原图如下:

比较图片相似算法

 

缩放为8*8的图片

代码:

img = cv2.resize(img, (8, 8), interpolation=cv2.INTER_CUBIC)
复制代码

缩放结果

比较图片相似算法

 

去色

代码

gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
复制代码

结果:

比较图片相似算法

 

计算灰度平均值

 # 计算灰度平均值
 for i in range(8):
 for j in range(8):
 s = s + gray_img[i, j]
 avg = s / 64
复制代码

计算结果为176

计算Hash指纹

计算方法为, 如果该点灰度值大于平均灰度值, 这为1, 否则为0, 代码如下:

 # 如果值大于灰度值, 则为1, 否则为0. 生成hash指纹
 for i in range(8):
 for j in range(8):
 if gray_img[i, j] > avg:
 hash_str = hash_str + '1'
 else:
 hash_str = hash_str + '0'
复制代码

计算汉明距离

汉明距离: 在信息论中,两个等长字符串之间的汉明距离(英语:Hamming distance)是两个字符串对应位置的不同字符的个数。 代码:

def cmp_hash(hash_1, hash_2):
 # 计算汉明距离
 n = 0
 if len(hash_1) != len(hash_2):
 return -1
 for i in range(len(hash_1)):
 if hash_1[i] != hash_2[i]:
 n = n + 1
 return n
复制代码

差异值hash算法

前面缩放, 置灰, 计算汉明距离等和平均值hash算法一样, 区别在于计算hash指纹的算法不同. 该处算法为: 如果前一个像素大于后一个像素的灰度值, 则为1, 否则为0. 完整的算法如下:

# 差值感应hash
def b_hash(img):
 # 缩放到8*8的图片
 img = cv2.resize(img, (9, 8), interpolation=cv2.INTER_CUBIC)
 # 得到灰度图
 gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 hash_str = ''
 # 如果前一个像素比后一个大, 则为1, 否则为0. 生成hash指纹
 for i in range(8):
 for j in range(8):
 if gray_img[i, j] > gray_img[i, j + 1]:
 hash_str = hash_str + '1'
 else:
 hash_str = hash_str + '0'
 return hash_str
复制代码

感知Hash算法

前面两种比较图片相似的算法很好理解. 感应Hash算法的思想与之不同. 我们换一种角度来看待一张图片. 一个图片其实就是二维的信息图谱, 有各种频率的变化, 频率高的地方代表颜色的变换比较大, 例如轮廓部分. 我们可以利用DCT变换(离散余弦变换)得到频域图. 比较低频部分(为什么要比较低频部分?) 是否相似就可以了.

原图还是上面的原图. 我们先进行缩放, 缩放为32*32的部分

比较图片相似算法

 

灰度处理

比较图片相似算法

 

进行DCT变换

比较图片相似算法

 

我们拿到左上角的8*8的区域, 根据平均值hash算法比较这个灰度图的汉明距离

完整的代码如下:

# 感知hash
def p_hash(img):
 # 缩放到32 * 32
 img = cv2.resize(img, (32, 32), interpolation=cv2.INTER_CUBIC)
 cv2.imwrite("bb.jpg", img)
 # 得到灰度图
 gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 gray_img = gray_img.astype(np.float32)
 cv2.imwrite("cc.jpg", gray_img)
 # 进行离散余弦变换, 目的是将低频部分放到左上角
 img = cv2.dct(gray_img)
 cv2.imwrite("dd.jpg", img)
 # 得到左上角8*8 的频率图
 img = img[0:8, 0:8]
 avg = 0
 # 与得到低频图的平均灰度
 hash_str = ''
 for i in range(8):
 for j in range(8):
 avg += img[i, j]
 avg = avg / 64
 # 如果低频图的像素值大于平均灰度, 则为1, 否则为0. 依次生成hash指纹
 for i in range(8):
 for j in range(8):
 if img[i, j] > avg:
 hash_str = hash_str + '1'
 else:
 hash_str = hash_str + '0'
 return hash_str
复制代码

参考文献:K码农-http://kmanong.top/kmn/qxw/form/home?top_cate=28

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>