■环境		
	Python 3.6.0																																																	
	Pycharm 2017.1.3																																															
																																																		
																																																		
■库、库的版本																																																		
	PIL 1.1.7																																																	
	Pillow 3.4.2																																																	
																																																		
																																																		
■参考																																																		
	https://segmentfault.com/a/1190000004467183																																																	
	https://www.cnblogs.com/tomato0906/articles/5616692.html																																																	
																																																		
																																																		
■逻辑																																																		
	1. 打开图片。																																																	
	2. 修改图片大小,12*12(图片越大,精度越高)。																																																	
	3. 转成灰度图,使用Image的对象的方法convert('L')。																																																	
	4. 计算灰度图的所有像素平均值。																																																	
	5. 获取图片指纹:遍历灰度图的所有像素,比平均值大则记录为1,否则记录为0。																																																	
	6. 对比两张图片的指纹,得到汉明距离。																																																	
	7. 汉明距离等于0说明两张图片完全一样。																																																	
	8. 当两张图片的字节数大小一样时才对比。																																																	
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.replace("\\", "/"))
    return img_list


def compare_img(root_path):
    """
    比较图片 (Main)
    :param root_path: 目标文件夹
    """
    compared_list = []
    # 获取目标文件夹下所有图片路径集合
    img_list = get_all_img_list(root_path)
    # 遍历目标文件夹下所有图片进行两两比较
    for file1 in img_list:
        # 已经发现是相同的图片不再比较
        if file1 in compared_list:
            continue
        im1 = Image.open(file1)
        im1_size = os.path.getsize(file1)
        img_fingerprints1 = get_img_gray_bit(im1)
        for file2 in img_list:
            # 当不是自己时再比较
            if file1 != file2:
                im2 = Image.open(file2)
                im2_size = os.path.getsize(file2)
                # 如果两张图片字节数大小一样再判断汉明距离
                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("图片相同:" + file1 + "::::::" + file2)
                        compared_list.append(file1)
                        compared_list.append(file2)


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))