需求:两个文件夹里面只有图片,文件格式为.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 |
![]() | ![]() |
肉眼观察可得:有3个相似图片,程序运行结果应该为3。开始验证:
结果正确!
最终将两个代码整合一下,如下:
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)