使用Python,OpenCV进行图像哈希

使用Python,OpenCV进行图像哈希

这篇博客将介绍图像哈希,感知哈希以及这些算法如何用于(快速)确定图像的视觉内容是否相同或相似。并实现了差异散列,一个常见的感知散列算法(1)非常快,而(2)非常准确。以此来判断图片是否发生变化。

1. 效果图

在这里插入图片描述

2. 原理

图像哈希或者感知哈希的步骤是: 基于图像的内容,构建唯一标识输入图像的散列值。
通过利用图像散列算法,可以在恒定的时间内或最差,O(Log n)时间找到近似相同的图像。

  • 为什么传统哈希不起作用

    传统的md5、sha等密码散列算法的本质:更改文件中的单个位会导致不同的哈希。 实质上图像哈希希望只有单个像素变化的,认为图像没有变化,或者图像缩放也认为没有变化;

  • 差异哈希(DHASH)的好处:
    1)输入图像的宽高比更改(由于忽略了纵横比),图像哈希不会改变;
    2)调整亮度或对比度(1)不会改变哈希值或(2)只会稍微改变它,确保散列将靠近;
    3)差异散列非常快且准确;

  • 通常使用 汉明距离 来比较哈希值。两个汉明距离很小的哈希意味着两个散列是相同的,并且两个图像也是相同的/感知相似的。

3. 源代码

# USAGE
# python hash.py --images images

# 导入必要的包
from imutils import paths
import argparse
import time
import sys
import cv2

# 设置图像散列为8,表示构建8*8=64位哈希值
def dhash(image, hashSize=8):
    # 缩放输入图像,增加一列以计算水平梯度差值
    resized = cv2.resize(image, (hashSize + 1, hashSize))

    # 计算相邻水平梯度列像素差值
    diff = resized[:, 1:] > resized[:, :-1]

    # 转换图像差异为hash
    return sum([2 ** i for (i, v) in enumerate(diff.flatten()) if v])


# 构建命令行参数及解析
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--images", required=True,
                help="dataset of images to search through (i.e., the haytack)")
args = vars(ap.parse_args())

# 获取hastach、needle文件图片
print("[INFO] computing hashes for images...")
hashmapsPaths = list(paths.list_images(args["images"]))

# 移除文件名中的\
if sys.platform != "win32":
    hashmapsPaths = [p.replace("\\", "") for p in hashmapsPaths]

# 初始化存放图像名及其hash值的map,并计时
hashmaps = {
    
    }
start = time.time()

# 遍历hashmaps路径
for p in hashmapsPaths:
    # 从磁盘加载图像
    image = cv2.imread(p)

    # 如果图像为None,则跳过
    if image is None:
        continue

    # 转换图像为灰度图,并计算图像hash值
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    imageHash = dhash(image)

    # 更新hashmaps字典
    l = hashmaps.get(imageHash, [])
    l.append(p)
    hashmaps[imageHash] = l

# 展示hash耗时及hashmaps照片数,开始计算needles文件夹的图像hash值
print("[INFO] processed {} images in {:.2f} seconds".format(
    len(hashmaps), time.time() - start))
print("[INFO] computing hashes for needles...")

for k,v in hashmaps.items():
    print("[INFO] {}: {}".format(k,v))

参考

猜你喜欢

转载自blog.csdn.net/qq_40985985/article/details/115294683