OpenCV书签 #均值哈希算法的原理与相似图片搜索实验 |
您所在的位置:网站首页 › 哈希相似度算法 › OpenCV书签 #均值哈希算法的原理与相似图片搜索实验 |
1. 介绍
均值哈希算法(Average Hash Algorithm,简称aHash) 是哈希算法的一种,主要用来做相似图片的搜索工作。 2. 原理 均值哈希算法(aHash)首先将原图像缩小成一个固定大小的像素图像,然后将图像转换为灰度图像,通过缩小图像的每个像素与平均灰度值的比较,生成一组哈希值。最后,利用两组图像的哈希值的汉明距离来评估图像的相似度。 魔法: 概括地讲,均值哈希算法一共可细分六步: 缩小图像: 将目标图像缩小为一个固定的大小,通常为8x8像素,总共64个像素。作用是去除各种图像尺寸和图像比例的差异,只保留结构、明暗等基本信息,目的是确保图像的一致性,降低计算的复杂度。图像灰度化: 将缩小的图像转换为灰度图像。灰度平均值: 计算灰度图像的平均灰度值。减少计算量。比较平均值: 遍历灰度图像的每个像素,比较每个像素的灰度值是否大于或小于平均值。对于大于等于平均值的像素,将其表示为1,对于小于平均值的像素,将其表示为0。最后,得到一个64位的二进制值(8x8像素的图像)。生成哈希值: 由于64位二进制值太长,所以按每4个字符为1组,由2进制转成16进制。这样就转为一个长度为16的字符串。这个字符串也就是这个图像可识别的哈希值,也叫图像指纹,即这个图像所包含的特征。哈希值比较: 通过比较两个图像的哈希值的汉明距离(Hamming Distance),就可以评估图像的相似度,距离越小表示图像越相似。3. 实验 第一步:缩小图像 将目标图像缩小为一个固定的大小,通常为8x8像素,总共64个像素。作用是去除各种图像尺寸和图像比例的差异,只保留结构、明暗等基本信息,目的是确保图像的一致性,降低计算的复杂度。 1)读取原图 # 测试图片路径 img_path = 'img_test/apple-01.jpg' # 通过OpenCV加载图像 img = cv2.imread(img_path) # 通道重排,从BGR转换为RGB img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
将缩小的图像转换为灰度图像。也就是说,所有像素点总共只有64种灰度颜色。 # 图像灰度化:将彩色图像转换为灰度图像。 img_gray = cv2.cvtColor(img_resize, cv2.COLOR_BGR2GRAY) print(f"缩放8x8的图像中每个像素的颜色=\n{img_gray}")输出打印: 缩放8x8的图像中每个像素的颜色= [[253 253 253 253 253 253 253 253] [253 253 253 148 253 253 253 253] [253 253 253 215 178 253 253 253] [253 253 119 93 132 176 253 253] [253 253 61 61 53 130 253 253] [253 253 112 67 66 142 253 253] [253 253 252 54 54 253 253 253] [253 253 236 63 146 249 253 253]]计算灰度图像的平均灰度值。减少计算量。 img_average = np.mean(img_gray) print(f"灰度图像中所有像素的平均值={img_average}")输出打印: 灰度图像中所有像素的平均值=209.890625 第四步:比较平均值遍历灰度图像的每个像素,比较每个像素的灰度值是否大于或小于平均值。对于大于等于平均值的像素,将其表示为1;对于小于平均值的像素,将其表示为0。最后,得到一组长64位的二进制字符串(8x8像素的图像)。因为对于机器而言,只认识0和1,所以这组64位的二进制就可以表示这张图像的结构和亮度分布。 # 遍历图像像素:嵌套循环遍历图像的所有像素,对比灰度图像的平均灰度值,转换为二进制的图像哈希值 img_hash_binary = [] for i in range(img_gray.shape[0]): for j in range(img_gray.shape[1]): if img_gray[i,j] >= img_average: img_hash_binary.append(1) else: img_hash_binary.append(0) print(f"对比灰度图像的平均像素值降噪(图像的二进制哈希值)数组={img_hash_binary}") # 将列表中的元素转换为字符串并连接起来,形成一组64位的图像二进制哈希值字符串 img_hash_binary_str = ''.join(map(str, img_hash_binary)) print(f"对比灰度图像的平均像素值降噪(图像的二进制哈希值)={img_hash_binary_str}")代码分解和含义如下: 初始化空列表:创建一个空的列表 img_hash_binary,用于存储图像的哈希值。遍历图像像素:嵌套循环遍历图像的所有像素,其中 img_gray 是输入的灰度图像,img_gray.shape[0] 和 img_gray.shape[1] 分别表示图像的高度和宽度。计算平均值:代码中使用变量 img_average 存储了一个平均值,用于与图像像素的灰度值进行比较。根据亮度值生成哈希值:对于每个像素,代码比较像素的灰度值与平均值 (img_gray[i, j] >= img_average)。如果像素的灰度值大于或等于平均值,就将数字1添加到 img_hash_binary 列表中,表示该像素是亮的。如果像素的灰度值小于平均值,就将数字0添加到 img_hash_binary 列表中,表示该像素是暗的。最终哈希值:完成循环后,img_hash_binary 列表将包含图像的二进制哈希值,其中每个元素代表一个像素的明暗情况。输出打印: 对比灰度图像的平均像素值降噪(图像的二进制形式)数组=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1] 对比灰度图像的平均像素值降噪(图像的二进制形式)=1111111111101111111101111100001111000011110000111110011111100111或者,使用等价的 lambda 表达式。效果一样。 # lambda表达式 img_hash_binary_str = "" for i in range(8): img_hash_binary_str += ''.join(map(lambda i: '0' if i |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |