图片对比 平均哈希法(aHash)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图片对比 平均哈希法(aHash)相关的知识,希望对你有一定的参考价值。
■环境
Python 3.6.0
Pycharm 2017.1.3
■库、库的版本
PIL version: 1.1.7
Pillow version: 3.4.2
■参考
https://segmentfault.com/a/1190000004467183
https://www.cnblogs.com/tomato0906/articles/5616692.html
■逻辑
平均哈希法(aHash)
1. 打开图片
2. 修改图片大小,12*12(图片越大,精度越高)。
3. 转成灰度图,使用Image的对象的方法convert(‘L‘)。
4. 计算灰度图的所有像素平均值。
5. 获取图片指纹:遍历灰度图的所有像素,比平均值大则记录为1,否则记录为0。
6. 对比两张图片的灰度图所有像素,得到汉明距离。
7. 汉明距离等于0说明两张图片完全一样。
■代码
from PIL import Image
import os
import datetime
def get_img_gray_list(image_gray):
"""
获取灰度图像素集合
:param image_gray: 灰度图
:return: 灰度图像素集合
"""
gray_list = []
for h in range(0, image_gray.size[1]):
for w in range(0, image_gray.size[0]):
gray_list.append(image_gray.getpixel((w, h)))
return gray_list
def get_img_gray_avg(gray_list):
"""
获取灰度图像素平均值
:param gray_list: 灰度图像素集合
:return: 灰度图像素平均值
"""
return sum(gray_list) / len(gray_list)
def get_img_fingerprints(image_gray, image_gray_avg):
"""
获取图片指纹:遍历灰度图的所有像素,比平均值大则记录为1,否则记录为0。
:param image_gray: 灰度图
:param image_gray_avg: 灰度图像素平均值
:return: 图片指纹集合
"""
img_fingerprints = ‘‘
for h in range(1, image_gray.size[1]):
for w in range(1, image_gray.size[0]):
if image_gray.getpixel((w, h)) > image_gray_avg:
img_fingerprints += ‘1‘
else:
img_fingerprints += ‘0‘
return img_fingerprints
def get_img_gray_bit(image, resize=(12, 12)):
"""
获取图片指纹
:param image: 图片
:param resize: Resize的图片大小
:return: 图片指纹
"""
# 修改图片大小
image_resize = image.resize(resize)
# 修改图片成灰度图
image_gray = image_resize.convert("L")
# 获取灰度图像素集合
gray_list = get_img_gray_list(image_gray)
# 获取灰度图像素平均值
image_gray_avg = get_img_gray_avg(gray_list)
# 获取图片指纹
img_fingerprints = get_img_fingerprints(image_gray, image_gray_avg)
return img_fingerprints
def get_mh(img_fingerprints1, img_fingerprints2):
"""
获取汉明距离
:param img_fingerprints1: 比较对象1的指纹
:param img_fingerprints2: 比较对象2的指纹
:return: 汉明距离
"""
hm = 0
for i in range(0, len(img_fingerprints1)):
if img_fingerprints1[i] != img_fingerprints2[i]:
hm += 1
return hm
def is_image_file(file_name):
"""
判断文件是否是图片
:param file_name: 文件名称(包含后缀信息)
:return: 1:图片,0:非图片
"""
ext = (os.path.splitext(file_name)[1]).lower()
if ext == ".jpg" or ext == ".jpeg" or ext == ".bmp" or ext == ".png":
return 1
return 0
def get_all_img_list(root_path):
"""
获取目标文件夹下所有图片路径集合
:param root_path: 目标文件夹
:return: 图片集合
"""
img_list = []
# 获取目标文件夹下所有元组
root = os.walk(root_path)
# 循环元组,获取目标文件夹下所有图片路径集合
for objects in root:
for obj in objects:
if "/" in str(obj):
# 记录文件夹路径
path = str(obj)
elif len(obj) > 0:
# 如果是文件,判断是否是图片。如果是图片则保存进
for file in obj:
if "." in str(file) and is_image_file(file) == 1:
full_path = path + "/" + str(file)
img_list.append(full_path)
return img_list
def compare_img(root_path):
"""
比较图片 (Main)
:param root_path: 目标文件夹
"""
# 获取目标文件夹下所有图片路径集合
img_list = get_all_img_list(root_path)
# 遍历目标文件夹下所有图片进行两两比较
for files1 in img_list:
im1 = Image.open(files1)
im1_size = im1.size
img_fingerprints1 = get_img_gray_bit(im1)
for files2 in img_list:
if files1 != files2:
im2 = Image.open(files2)
im2_size = im2.size
# 如果两张图片大小一样再判断汉明距离
if im1_size == im2_size:
img_fingerprints2 = get_img_gray_bit(im2)
compare_result = get_mh(img_fingerprints1, img_fingerprints2)
# 汉明距离等于0,说明两张图片完全一样
if compare_result == 0:
print("图片相同:" + files1 + "::::::" + files2)
start_time = datetime.datetime.now()
start_time = start_time.strftime(‘%Y-%m-%d %H:%M:%S‘)
print("start time: " + start_time)
compare_img("C:/Users/x230/Desktop/test")
end_time = datetime.datetime.now()
end_time = end_time.strftime(‘%Y-%m-%d %H:%M:%S‘)
print("end time: " + end_time)
d1 = datetime.datetime.strptime(start_time, ‘%Y-%m-%d %H:%M:%S‘)
d2 = datetime.datetime.strptime(end_time, ‘%Y-%m-%d %H:%M:%S‘)
print("耗时: " + str((d2 - d1).seconds))
以上是关于图片对比 平均哈希法(aHash)的主要内容,如果未能解决你的问题,请参考以下文章