筛查以jpg结尾的图片python_【python工具开发笔记】基于tkinter比较筛选目录下是否存在相同图片...

该博客介绍了一个使用Python实现的工具,用于在目录及其子目录下筛查jpg图片并比较它们的相似度。通过递归获取所有图片路径,利用hash算法和PIL库检查图片的平均哈希值来判断图片是否相同。此外,还提到了如何在Windows和Mac环境下打包成可执行文件,以及使用tkinter创建GUI界面的相关技巧。
摘要由CSDN通过智能技术生成

筛选目录下所有图片,是否有相同的图片存在,存在的话打印出相同的两张图的具体路径。

成品界面如下(MAC和windows版本界面是一样):

首先是先拿到路径下所有的图片,对比图片的相似度,经过百度有可以直接引用一个python的hash算法进行比较,传入图片路径和设定误差值即可。将相同的图片信息存在txt文件中用来保存。

考虑到路径下可能存在多个文件夹嵌套、图片名字相同的情况,传入hash算法的文件名必须是带路径的,否则只能检测当前目录下的图片,并不能遍历到子文件夹中。

大概思路如下:

1. 获取所有文件名(带路径)

com_path = [""]

def get_all(path):

paths = os.listdir(path) # 列出指定路径下的所有目录和文件

for i in paths:

com_path = os.path.join(path,i)

if os.path.isdir(com_path):

get_all(com_path) # 如果该路径是目录,则调用自身方法

elif os.path.isfile(com_path):

if com_path.split(".")[-1] in ['jpg','png','bmp']:

com_path_T = {com_path.split('\\')[-1]:com_path}

compath.update(com_path_T)

用递归遍历获取所有带路径的文件名,将文件名和带路径的文件名存入字典中。开始考虑用列表存,但是在通过append函数循环添加时,参数是list时报错,所有就用的字典存放,后面查询也方便。

2. 通过字符串切片用"."进行分割出后缀,即文件格式得到所有的图片

3. 拿到所有图片并带路径,循环两两比较图片,调用比较函数

hash算法比较图片函数(传入图片路径可直接使用):

def compare_image_with_hash(image_file_name_1, image_file_name_2, max_dif=0):

ImageFile.LOAD_TRUNCATED_IMAGES = True

hash_1 = None

hash_2 = None

image_file1 = open(image_file_name_1,'rb').read()

Has = hashlib.md5(image_file1).hexdigest()

image_file2 = open(image_file_name_2,'rb').read()

Has1 = hashlib.md5(image_file2).hexdigest()

if image_file1 != image_file2:

return False

with open(image_file_name_1, 'rb') as fp:

hash_1 = imagehash.average_hash(Image.open(fp))

with open(image_file_name_2, 'rb') as fp:

hash_2 = imagehash.average_hash(Image.open(fp))#对比图片是否一样

dif = hash_1 - hash_2

if dif < 0:

dif = -dif

if dif <= max_dif:

return True

else:

return False

函数compare_image_with_hash本身比较图片hash值的时候,发现对于一个图只改变了颜色,hash值是不变的,因此需要用image_file2 = open(image_file_name_2,'rb').read()

Has1 = hashlib.md5(image_file2).hexdigest()加以判断。

4. 关于Windows打包,比较简单:

使用Python打包EXE可执行文件时,需要使用Pyinstaller,使用命令pip install PyInstaller进行安装

-c显示命令行窗口与-w相反,默认含有此参数

-w不显示命令行窗口编写GUI程序时使用此参数有用。

-F生成one-file的程序生成结果是一个exe文件,所有的第三方依赖、资源和代码均被打包进该exe内

出现上述问题,一般是因为磁盘不够运行导致的。跟打包的exe没有关系。

5. 关于Mac环境,遇到比较多的问题(打包app暂时没有解决):

首先装py2applet后,输入以下命令即可。打包前需要把第三方库,编辑setup.py手动添加第三方库。

py2applet   --make-setup  xxx.py

python setup.py py2app

6. 线程简单用法

def thread_it(func, *args):

'''将函数放入线程中执行'''

# 创建线程

t = threading.Thread(target=func, args=args)

# 守护线程

t.setDaemon(True)

# 启动线程

t.start()

例如在按键启动线程执行函数:tkinter.Button(Root,text="开始查找",command=lambda :thread_it(getuser(函数名),函数参数)).pack()

7. tkinter基本用法

Root=tkinter.Tk() #创建Tk对象

Root.title("xxxxx") #设置窗口标题

Root.geometry("300x160+500+200") #设置窗口尺寸

XX=tkinter.Label(Root,text="XXXXXXXX") #标签

XX.pack() #指定包管理器放置组件

该方法没有对位置进行设置,可以用label.place(x=20, y=20)进行位置设置。

--------------------------------------源码----------------------------------------------

#coding=utf-8

from tkinter import *

import tkinter as tk

from tkinter import Canvas as C

import tkinter,time,decimal,math,string

import tkinter.messagebox #这个是消息框,对话框的关键

import tkinter.font as tkFont

import os

from PIL import Image

from PIL import ImageFile

import imagehash

import threading

import hashlib

def thread_it(func, *args):

'''将函数放入线程中执行'''

# 创建线程

t = threading.Thread(target=func, args=args)

# 守护线程

t.setDaemon(True)

# 启动线程

t.start()

def clear():

if tkinter.messagebox.askokcancel('提示', '确认结束吗'):

root.quit()

def compare_image_with_hash(image_file_name_1, image_file_name_2, max_dif=0):

ImageFile.LOAD_TRUNCATED_IMAGES = True

hash_1 = None

hash_2 = None

image_file1 = open(image_file_name_1,'rb').read()

Has = hashlib.md5(image_file1).hexdigest()

image_file2 = open(image_file_name_2,'rb').read()

Has1 = hashlib.md5(image_file2).hexdigest()

if image_file1 != image_file2:

return False

with open(image_file_name_1, 'rb') as fp:

hash_1 = imagehash.average_hash(Image.open(fp))

with open(image_file_name_2, 'rb') as fp:

hash_2 = imagehash.average_hash(Image.open(fp))#对比图片是否一样

dif = hash_1 - hash_2

if dif < 0:

dif = -dif

if dif <= max_dif:

return True

else:

return False

com_path = [""]

compath = {} #字典

def get_all(path):

#path =r'D:\Test3'

paths = os.listdir(path) # 列出指定路径下的所有目录和文件

for i in paths:

com_path = os.path.join(path,i)

# print(com_path)

if os.path.isdir(com_path):

get_all(com_path) # 如果该路径是目录,则调用自身方法

elif os.path.isfile(com_path):

#print(com_path.split(".")[-1])

if com_path.split(".")[-1] in ['jpg','png','bmp','tif','gif','pcx','tga','exif','fpx','svg','psd','cdr','pcd','dxf','ufo','eps','ai','raw','WMF','webp','avif'

'JPG','PNG','BMP','TIF','GIF','PCX','TGA','EXIF','FPX','SVG','PSD','CDR','PCD','DXF','UFO','EPS','AI','RAW','WMF','WEBP','AVIF'

]:

com_path_T = {com_path.split('\\')[-1]:com_path}

compath.update(com_path_T)

#print(com_path.split('\\')[-1],"======",com_path)

get_all(path=r'.')

keyList = []

valueList = []

print(len(compath))

for key in compath.keys():

keyList.append(key)

for value in compath.values():

valueList.append(value)

def getuser():

line_new = open("test.txt",'w')

FlagNum = 0

strInfoT = "正在循环对比..."

tkinter.Label(root,text=strInfoT).place(x=50, y=70)

for i in range(0,len(valueList),1):

strInfoNum = "已完成"+str(i+1)+"个..."

tkinter.Label(root,text=strInfoNum).place(x=160, y=70)

for j in range(1,len(valueList),1):

if i!=j and i

if compare_image_with_hash(valueList[i],valueList[j],0) == True:

FlagNum = 1

line_new.write(valueList[i]+"和"+valueList[j]+"相同\n")

line_new.close()

if FlagNum == 1:

tkinter.messagebox.showwarning('警告','图片相同,相同照片以保持至根目录下的test.txt中,请确认!!')

elif FlagNum == 0:

tkinter.messagebox.showwarning('提示','当前路径下没有相同的图片!')

else:

tkinter.messagebox.showwarning('异常','异常情况!')

root = tkinter.Tk() # 创建窗口对象的背景色

root.geometry("280x150+600+200")

root.title("图片筛查工具")

strInfo = "需要循环比较 "+str(len(compath))+" 个文件,请稍等!"

tkinter.Label(root,text=strInfo).place(x=50, y=40)

tkinter.Button(root,text="开始筛查",command=lambda :thread_it(getuser)).place(x=50, y=100) #command绑定获取文本框内容方法

tkinter.Button(root,text="结束筛查",command= clear).place(x=170, y=100) #command绑定获取文本框内容方法

root.mainloop() #进入主循环

原文链接:https://blog.csdn.net/Beyond_1024/article/details/110822276

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值