需求:两个文件夹里面只有图片,文件格式为.png,且单个文件夹中不存在相似图片,对比检测两个文件夹的相似图片个数。

对比两个图片是否相似代码,利用哈希均值来计算图片的相似度:

import cv2
import numpy as np

# Hash值对比
def cmpHash(hash1, hash2,shape=(10,10)):
    n = 0
    # hash长度不同则返回-1代表传参出错
    if len(hash1)!=len(hash2):
        return -1
    # 遍历判断
    for i in range(len(hash1)):
        # 相等则n计数+1,n最终为相似度
        if hash1[i] == hash2[i]:
            n = n + 1
    return n/(shape[0]*shape[1])
# 均值哈希算法
def aHash(img,shape=(10,10)):
    # 缩放为10*10
    img = cv2.resize(img, shape)
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # s为像素和初值为0,hash_str为hash值初值为''
    s = 0
    hash_str = ''
    # 遍历累加求像素和
    for i in range(shape[0]):
        for j in range(shape[1]):
            s = s + gray[i, j]
    # 求平均灰度
    avg = s / 100
    # 灰度大于平均值为1相反为0生成图片的hash值
    for i in range(shape[0]):
        for j in range(shape[1]):
            if gray[i, j] > avg:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str
def main(img1,img2):
    hash1 = aHash(img1)
    hash2 = aHash(img2)
    n = cmpHash(hash1, hash2)
    print('均值哈希算法相似度:', n)
    if n >= 0.8:
        return 1
    else:
        return 0


if __name__=="__main__":
    main('test0.png','test0_f.png')#测试当前目录下的两个图片相似度

主程序主要用于系统操作,利用循环遍历两个文件夹的照片的绝对路径信息:

import os
import test
import cv2

def photo_circle(path1,path2):
    dir_list1=[]
    dir_list2=[] #分别形成两个空列表
    for img_name_1 in os.listdir(path1):                       #遍历文件夹下面的文件和目录     listdir() 返回path 目录下的文件和目录列表
        img_dir1 = path1+'./'+img_name_1                        #拼接好每个照片的绝对路径
        dir_list1.append(img_dir1)                            #生成一个列表
    for img_name_2 in os.listdir(path2):                       #遍历文件夹下面的文件和目录     listdir() 返回path 目录下的文件和目录列表
        img_dir2 = path2+'./'+img_name_2                        #拼接好每个照片的绝对路径
        dir_list2.append(img_dir2)

    print('第一个文件夹共:',len(dir_list1),'张')
    print('第一个文件夹共:',len(dir_list2),'张')#分别返回两个文件夹各有多少张照片

    i=0
    j=0

    for No_1, img_message in enumerate(dir_list1):  # 将照片的地址组合为索引序列  enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
        img = cv2.imread(img_message)  # 获取照片的信息

        for No_2,other_img_message in enumerate(dir_list2):
            other_img = cv2.imread(other_img_message) # 获取另外一张照片的地址

            try:
                diff = test.main(img,other_img)  # 比较两张照片    ImageChops.difference计算“两个图像之间逐像素差异的绝对值”,这将导致返回差异图像.
                if diff:  # 两张照片如果一样则进行下程序的执行
                    i = i + 1
                    print('现有', i, '相同')

            except:# 如果两张照片不一样,执行以下程序
                print('正常', j)
                continue
        print('最终结果,共有--->', i,'<---张图片相似')

if __name__ == '__main__':
    path1 = r'D:\downloads_b\pictures\file1'
    path2 = r'D:\downloads_b\pictures\file2'#输入要比较的两个文件夹的绝对地址
    photo_circle(path1,path2)

只需调用photo_circle(path1,path2)函数即可对比,参数类型为string,分别是两个文件夹的绝对路径。

验证环节:

文件夹1

文件夹2

python两张图片叠加后颜色融合过渡_python两张图片叠加后颜色融合过渡

python两张图片叠加后颜色融合过渡_绝对路径_02

肉眼观察可得:有3个相似图片,程序运行结果应该为3。开始验证:

python两张图片叠加后颜色融合过渡_绝对路径_03

结果正确!

最终将两个代码整合一下,如下:

import os
import cv2
import numpy as np

def cmpHash(hash1, hash2,shape=(10,10)):
    n = 0
    # hash长度不同则返回-1代表传参出错
    if len(hash1)!=len(hash2):
        return -1
    # 遍历判断
    for i in range(len(hash1)):
        # 相等则n计数+1,n最终为相似度
        if hash1[i] == hash2[i]:
            n = n + 1
    return n/(shape[0]*shape[1])
# 均值哈希算法
def aHash(img,shape=(10,10)):
    # 缩放为10*10
    img = cv2.resize(img, shape)
    # 转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # s为像素和初值为0,hash_str为hash值初值为''
    s = 0
    hash_str = ''
    # 遍历累加求像素和
    for i in range(shape[0]):
        for j in range(shape[1]):
            s = s + gray[i, j]
    # 求平均灰度
    avg = s / 100
    # 灰度大于平均值为1相反为0生成图片的hash值
    for i in range(shape[0]):
        for j in range(shape[1]):
            if gray[i, j] > avg:
                hash_str = hash_str + '1'
            else:
                hash_str = hash_str + '0'
    return hash_str
def picture_com(img1,img2):
    hash1 = aHash(img1)
    hash2 = aHash(img2)
    n = cmpHash(hash1, hash2)
    print('均值哈希算法相似度:', n)
    if n >= 0.8:
        return 1
    else:
        return 0


def photo_circle(path1,path2):
    dir_list1=[]
    dir_list2=[] #分别形成两个空列表
    for img_name_1 in os.listdir(path1):                       #遍历文件夹下面的文件和目录     listdir() 返回path 目录下的文件和目录列表
        img_dir1 = path1+'./'+img_name_1                        #拼接好每个照片的绝对路径
        dir_list1.append(img_dir1)                            #生成一个列表
    for img_name_2 in os.listdir(path2):                       #遍历文件夹下面的文件和目录     listdir() 返回path 目录下的文件和目录列表
        img_dir2 = path2+'./'+img_name_2                        #拼接好每个照片的绝对路径
        dir_list2.append(img_dir2)

    print('第一个文件夹共:',len(dir_list1),'张')
    print('第二个文件夹共:',len(dir_list2),'张')#分别返回两个文件夹各有多少张照片

    i=0

    for No_1, img_message in enumerate(dir_list1):  # 将照片的地址组合为索引序列  enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
        img = cv2.imread(img_message)  # 获取照片的信息

        for No_2,other_img_message in enumerate(dir_list2):
            other_img = cv2.imread(other_img_message) # 获取另外一张照片的地址

            try:
                diff = picture_com(img,other_img)  # 比较两张照片    ImageChops.difference计算“两个图像之间逐像素差异的绝对值”,这将导致返回差异图像.
                if diff:  # 两张照片如果一样则进行下程序的执行
                    i = i + 1
                    print('现有', i, '相同')

            except:
                print('warning!')
                continue
    print('最终结果,共有--->', i,'<---张图片相似')
    return i
if __name__ == '__main__':
    path1 = r'D:\downloads_b\pictures\file1'
    path2 = r'D:\downloads_b\pictures\file2'#输入要比较的两个文件夹的绝对地址
    photo_circle(path1,path2)