近期在整理相册的时候,发现相册中有许多重复图片,人工一张张筛查删除太枯燥,便写下这个脚本,用于删除文件夹下重复的图片。

第一部分:判断两张图片是否相同

要查找重复的图片,必然绕不开判断两张图片是否相同。判断两张图片简单呀!图片可以看成数组,比较两个数组是否相等不就行了。但是这样做太过简单粗暴,因为两个数组的每个元素都要一一比较,效率很低。为了尽量避免两个庞大的数组比较:

  • 先进行两张图片的大小(byte)比较,若大小不相同,则两张图片不相同;
  • 在两张图片的大小相同的前提下,进行两张图片的尺寸(长和宽)比较,若尺寸不相同,则两张不相同;
  • 在两张图片的尺寸相同的前提下,进行两张图片的内容(即数组元素)比较,若内容不相同,则图片不相同;

这样,当图片大小或图片尺寸不相同的时候,便认为两张图片不同,可以省去比较数组元素的部分,效率up~

  1. 1 import shutil
  2. 2 import numpy as np
  3. 3 from PIL import Image
  4. 4 import os
  5. 5
  6. 6
  7. 7 def 比较图片大小(dir_image1, dir_image2):
  8. 8 with open(dir_image1, "rb") as f1:
  9. 9 size1 = len(f1.read())
  10. 10 with open(dir_image2, "rb") as f2:
  11. 11 size2 = len(f2.read())
  12. 12 if(size1 == size2):
  13. 13 result = "大小相同"
  14. 14 else:
  15. 15 result = "大小不同"
  16. 16 return result
  17. 17
  18. 18
  19. 19 def 比较图片尺寸(dir_image1, dir_image2):
  20. 20 image1 = Image.open(dir_image1)
  21. 21 image2 = Image.open(dir_image2)
  22. 22 if(image1.size == image2.size):
  23. 23 result = "尺寸相同"
  24. 24 else:
  25. 25 result = "尺寸不同"
  26. 26 return result
  27. 27
  28. 28
  29. 29 def 比较图片内容(dir_image1, dir_image2):
  30. 30 image1 = np.array(Image.open(dir_image1))
  31. 31 image2 = np.array(Image.open(dir_image2))
  32. 32 if(np.array_equal(image1, image2)):
  33. 33 result = "内容相同"
  34. 34 else:
  35. 35 result = "内容不同"
  36. 36 return result
  37. 37
  38. 38
  39. 39 def 比较两张图片是否相同(dir_image1, dir_image2):
  40. 40 # 比较两张图片是否相同
  41. 41 # 第一步:比较大小是否相同
  42. 42 # 第二步:比较长和宽是否相同
  43. 43 # 第三步:比较每个像素是否相同
  44. 44 # 如果前一步不相同,则两张图片必不相同
  45. 45 result = "两张图不同"
  46. 46 大小 = 比较图片大小(dir_image1, dir_image2)
  47. 47 if(大小 == "大小相同"):
  48. 48 尺寸 = 比较图片尺寸(dir_image1, dir_image2)
  49. 49 if(尺寸 == "尺寸相同"):
  50. 50 内容 = 比较图片内容(dir_image1, dir_image2)
  51. 51 if(内容 == "内容相同"):
  52. 52 result = "两张图相同"
  53. 53 return result

第二部分:判断文件夹内是否有重复图片

若要判断文件夹内是否有和图片A相同的图片,则需要遍历文件夹内所有图片,挨个判断两个图片是否相同。若文件夹有1000张图片,那么第1张图片需要与剩下的999张图片作比较,第2张图片需要与剩下的998张图片作比较,第3张需要与剩下的997张图片作比较,以此类推。在此程序中的做法是,先对所有图片按图片大小(byte)排序,然后再执行遍历比较。这样做的结果是:重复图片很大概率会连着出现(因为重复图片大小相同)

  1. if __name__ == '__main__':
  2.  
  3. load_path = 'E:\\测试图片集(未去重)' # 要去重的文件夹
  4. save_path = 'E:\\测试图片集(重复照片)' # 空文件夹,用于存储检测到的重复的照片
  5. os.makedirs(save_path, exist_ok=True)
  6.  
  7. # 获取图片列表 file_map,字典{文件路径filename : 文件大小image_size}
  8. file_map = {}
  9. image_size = 0
  10. # 遍历filePath下的文件、文件夹(包括子目录)
  11. for parent, dirnames, filenames in os.walk(load_path):
  12. # for dirname in dirnames:
  13. # print('parent is %s, dirname is %s' % (parent, dirname))
  14. for filename in filenames:
  15. # print('parent is %s, filename is %s' % (parent, filename))
  16. # print('the full name of the file is %s' % os.path.join(parent, filename))
  17. image_size = os.path.getsize(os.path.join(parent, filename))
  18. file_map.setdefault(os.path.join(parent, filename), image_size)
  19.  
  20. # 获取的图片列表按 文件大小image_size 排序
  21. file_map = sorted(file_map.items(), key=lambda d: d[1], reverse=False)
  22. file_list = []
  23. for filename, image_size in file_map:
  24. file_list.append(filename)
  25.  
  26. # 取出重复的图片
  27. file_repeat = []
  28. for currIndex, filename in enumerate(file_list):
  29. dir_image1 = file_list[currIndex]
  30. dir_image2 = file_list[currIndex + 1]
  31. result = 比较两张图片是否相同(dir_image1, dir_image2)
  32. if(result == "两张图相同"):
  33. file_repeat.append(file_list[currIndex + 1])
  34. print("\n相同的图片:", file_list[currIndex], file_list[currIndex + 1])
  35. else:
  36. print('\n不同的图片:', file_list[currIndex], file_list[currIndex + 1])
  37. currIndex += 1
  38. if currIndex >= len(file_list)-1:
  39. break
  40.  
  41. # 将重复的图片移动到新的文件夹,实现对原文件夹降重
  42. for image in file_repeat:
  43. shutil.move(image, save_path)
  44. print("正在移除重复照片:", image)

第三部分:程序运行结果

若文件夹下有10张图片A、5张图片B、1张图片C,程序运行结束后,该文件夹下剩余1张图片A、1张图片B、1张图片C;其他的图片移动到 save_path 指定的文件夹下。

第四部分:注意

程序代码可以直接复制使用,需要修改 load_path 和 save_path 参数;

保证 load_path 文件夹都为图片格式(.jpg .png .jpeg)的文件类型,不可以有其他格式的文件(例如.mp4);请先用资源管理器处理文件夹,大佬直接修改代码读取文件夹下指定类型的文件;

Python脚本:删除文件夹下的重复图片,实现图片去重的更多相关文章

  1. java删除文件夹下所有文件

    package org.sw; import java.io.File; /** * * @author mengzw * @since 3.0 2014-2-26 */ public class D ...

  2. Linux下的命令,删除文件夹下的所有文件,而不删除文件夹本身

    Linux下的命令,删除文件夹下的所有文件,而不删除文件夹本身 rm -rf *

  3. python删除某一文件夹下的重复文件

    #2022-10-28 import hashlib import os import time def getmd5(filename): """ 获取文件 md5 码 ...

  4. [代码应用]javaSE程序递归删除文件夹下的.bak文件程序源代码

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39158939 本文作者:sushengmiyan ------------------ ...

  5. Python获取指定文件夹下的文件名

    本文采用os.walk()和os.listdir()两种方法,获取指定文件夹下的文件名. 一.os.walk() 模块os中的walk()函数可以遍历文件夹下所有的文件. os.walk(top, t ...

  6. Python遍历一个文件夹下有几个Excel文件及每个Excel文件有几个Sheet

    一. 解决问题: 工作中常会遇到合并Excel文件的需求,Excel文件数量不确定,里面的Sheet 数量是可变的,Sheet Name是可变的,所以,需要用到遍历一个文件夹下有几个Excel文件,判 ...

  7. Python扫描指定文件夹下(包含子文件夹)的文件

    扫描指定文件夹下的文件.或者匹配指定后缀和前缀的函数. 假设要扫描指定文件夹下的文件,包含子文件夹,调用scan_files("/export/home/test/") 假设要扫描 ...

  8. Nodejs下如何判断文件夹的存在以及删除文件夹下所有的文件

    代码如下: var folder_exists = fs.existsSync('./cache'); if(folder_exists == true) { var dirList = fs.rea ...

  9. JAVA中删除文件夹下及其子文件夹下的某类文件

    ##定时删除拜访图片 ##cron表达式 秒 分 时 天 月 ? ##每月1日整点执行 CRON1=0 0 0 1 * ? scheduled.enable1=false ##图片路径 filePat ...

随机推荐

  1. NOIP模拟测试5「星际旅行·砍树·超级树」

    星际旅行 0分 瞬间爆炸. 考试的时候觉得这个题怎么这么难, 打个dp,可以被儿子贡献,可以被父亲贡献,还有自环,叶子节点连边可以贡献,非叶子也可以贡献,自环可以跑一回,自环可以跑两回, 关键是同一子 ...

  2. 学习JDK源码(二):Integer

    最近没有好好保持学习的好习惯,该打. 天天忙,感觉都不知道在干嘛.真的厌倦了普通的Java代码,还是想学点新技术. 用了这么久的Java,最常用的数据类型肯定是Int了,而他的包装类Integer用的 ...

  3. 与KubernetesAPI服务器交互

    在介绍过的Downward API提供了一种简单的方式,将pod和容器的元数据传递给在它们内部运行的进程.但这种方式其实仅仅可以暴露一个pod自身的元数据,而且只可以暴露部分元数据.某些情况下,应用需 ...

  4. Jenkins+SonarQube实现C#代码质量检查

    环境准备 SonarQube 项目创建 jenkins Windows构建节点配置 安装与SonarQube服务端相同版本jdk 安装sonar-scanner 并配置环境变量 安装Visual St ...

  5. CentOS-yum安装Redis(单点)

    源文件安装(推荐安装) 在CentOS系统中,首先安装EPEL仓库,然后更新yum源: $ yum install epel-release -y $ yum update -y 然后安装Redis数 ...

  6. 其他:压力测试Jmeter工具使用

    下载路径: http://yd01.siweidaoxiang.com:8070/jmeter_52z.com.zip 配置汉化中文: 找到jmeter的安装目录:打开 \bin\jmeter.pro ...

  7. Nginx:Nginx配置url重定向

    符号含义: 正则表达式匹配: ~ 为区分大小写匹配 ~* 为不区分大小写匹配 !~和!~*分别为区分大小写不匹配及不区分大小写不匹配 文件及目录匹配: -f和!-f用来判断是否存在文件 -d和!-d用 ...

  8. hadoop学习(三)HDFS常用命令以及java操作HDFS

    一.HDFS的常用命令 1.查看根目录下的信息:./hadoop dfs -ls 2.查看根目录下的in目录中的内容:./hadoop dfs -ls in或者./hadoop dfs -ls ./i ...

  9. java设计模式(9):模板方法模式(TemplateMethod)

    一,定义:模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 二,类图: 三,通过小例子讲解: 这个模式一般用在 ...

  10. Quartz和Spring Task定时任务的简单应用和比较

    看了两个项目,一个用的是Quartz写的定时器,一个是使用spring的task写的,网上看了2篇文章,写的比较清楚,这里做一下留存 链接一.菠萝大象:http://www.blogjava.net/ ...