当前位置: 首页 > java >正文

相似图像处理程序

工作中遇到很多相似的照片,但是我们想要保留一份。所以写了如下这个python程序来实现这个功能。

1 导入必要的包

import os
import shutil
from datetime import datetime
from collections import defaultdict
from pathlib import Path
from PIL import Image
import imagehash
from tqdm import tqdm

2 核心代码

 path = r"E:\...\图片获取\xxx"        # 要扫描的文件夹
THRESHOLD = 12    # 汉明距离 ≤ THRESHOLD 视为相似
MOVE_FOLDER = True                    
IMG_EXTS = {'.jpg', '.jpeg', '.png', '.bmp', '.tif', '.tiff', '.webp'}
def all_images(root):for p in Path(root).rglob('*'):if p.suffix.lower() in IMG_EXTS:yield str(p)def hash_image(path):try:with Image.open(path) as img:return imagehash.phash(img)except Exception as e:print(f"[WARN] 无法读取 {path}: {e}")return Nonedef group_by_similarity(paths, threshold):hashes = {}for p in tqdm(paths, desc="计算哈希"):h = hash_image(p)if h is not None:hashes[p] = h# 将 ndarray 转成真正的 intitems = [(int.from_bytes(h.hash.astype('uint8').tobytes(), 'big'), p)for p, h in hashes.items()]items.sort(key=lambda t: t[0])groups = []used = set()n = len(items)for i in range(n):if i in used:continuegrp = [items[i][1]]for j in range(i + 1, n):if j in used:continueham = bin(items[i][0] ^ items[j][0]).count('1')if ham <= threshold:grp.append(items[j][1])used.add(j)groups.append(grp)return groupsdef pick_best(group):best = max(group, key=lambda p: os.path.getsize(p))return best, [p for p in group if p != best]def move_duplicates(dup_list):if not dup_list:returndesktop = Path.home() / 'Desktop'recycle = desktop / f"duplicates_{datetime.now():%Y%m%d_%H%M%S}"recycle.mkdir(exist_ok=True)for p in dup_list:try:shutil.move(str(p), recycle / Path(p).name)except Exception as e:print(f"[ERROR] 移动失败 {p}: {e}")def main():paths = list(all_images(path))if not paths:print("未找到任何图片。")returngroups = group_by_similarity(paths, THRESHOLD)to_move = []for g in groups:keep, dups = pick_best(g)to_move.extend(dups)if dups:print(f"保留: {keep}")for d in dups:print(f"  移动: {d}")if to_move:print(f"\n共 {len(to_move)} 张相似图片将被移动。")if MOVE_FOLDER:move_duplicates(to_move)print("已移动到桌面的 duplicates_* 文件夹。")else:for d in to_move:os.remove(d)print("已直接删除。")else:print("未发现相似图片。")
if __name__ == "__main__":main()
http://www.xdnf.cn/news/18417.html

相关文章:

  • 北京-15k测试-入职甲方金融-上班第二天
  • 哈尔滨云前沿服务器租用类型
  • 高效获取应用程序图标的方法
  • CSS 3D动画,围绕旋转动画Demo
  • 面试可能问到的问题思考-Redis
  • 机器学习7
  • 网络与信息安全有哪些岗位:(5)安全开发工程师
  • Ubuntu22.04配置网络上网
  • Ubuntu Server 安装 gvm 管理 Go 语言开发环境
  • 自然语言处理NLP L4: 高级语言模型——四种泛化平滑方式
  • 【TrOCR】用Transformer和torch库实现TrOCR模型
  • Matplotlib+HTML+JS:打造可交互的动态数据仪表盘
  • 智慧工厂的 “隐形大脑”:边缘计算网关凭什么重构设备连接新逻辑?
  • 详细说明http协议特别是conten-length和chunk编码,并且用linux的命令行演示整个过程
  • Go语言变量声明与初始化详解
  • 一个状态机如何启动/停止另一个状态机
  • 【机器学习 / 深度学习】基础教程
  • StarRocks不能启动 ,StarRocksFe节点不能启动问题 处理
  • 生信分析自学攻略 | R语言函数与参数介绍
  • Notepad++换行符替换
  • 造成云手机闪退的原因有哪些?
  • HarmonyOS 实战:6 种实现实时数据更新的方案全解析(含完整 Demo)
  • java18学习笔记-Simple Web Server
  • 【LeetCode 415】—字符串相加算法详解
  • 【数据可视化-96】使用 Pyecharts 绘制主题河流图(ThemeRiver):步骤与数据组织形式
  • 深度学习-168-MCP技术之VSCode中安装插件Cline客户端应用MCP Server工具
  • 计算机网络-1——第一阶段
  • 在.NET 8 中使用中介模式优雅处理多版本 API 请求
  • 【51单片机】【protues仿真】基于51单片机16键电子琴系统
  • 高可用操作步骤