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

相似图像处理程序

工作中遇到很多相似的照片,但是我们想要保留一份。所以写了如下这个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.dtcms.com/a/342874.html

相关文章:

  • mac的m3芯使用git
  • 1.2 亿篇论文数据集,多学科学术语料库,涵盖医学、化学、生物学、人文、物理、工程、数学、生态、经济与计算机科学,用于 NLP、知识图谱与大模型训
  • 意象驱动的深层语义:感知认知统一对自然语言处理与知识图谱的影响
  • 数据结构——二叉树(Binary Tree)
  • 自然语言处理NLP L4: 高级语言模型——四种泛化平滑方式
  • Spring全家桶之全局异常处理
  • Spring Boot生态中ORM对数据治理的支持有哪些?
  • Ubuntu22.04配置网络上网
  • linux-ubuntu里docker的容器portainer容器建立后如何打开?
  • Maven无法修改镜像,镜像在IDEA里不生效
  • 室外和室内 PoE 延长器有什么区别?
  • [CSP-J2020] 直播获奖
  • 集成学习:从原理到实战,一文掌握 Bagging、Boosting 与 Stacking
  • 集成学习:如何让多个 “弱模型” 变成 “强模型”?
  • demo 汽车之家(渲染-筛选-排序-模块抽离数据)
  • Linux之Ansible自动化运维(二)
  • Linux内核源码详解--缺页异常(Page Fault)处理的核心函数handle_pte_fault
  • Maven(三)
  • Class A 包含字段 x Class B 也包含字段 x,如果判断List<A> lista 和 List<B> listb 有相同的 x?
  • 基于websocket聊天室的基本点
  • SQL中的游标
  • html ajax前端页面
  • 51单片机-驱动直流电机模块教程
  • 单片机\物联网\51单片机\嵌入式开发\软硬件结合的基于STM32的电梯管理系统的设计/基于STM32的电梯运行系统的设计
  • 【华为OD-C卷-020 -关联端口组合并 100分(python、java、c++、js、c)】
  • 解决 uniapp 修改index.html文件不生效的问题
  • PCB文件怎么快速判断是通孔还是盲孔呢?
  • Git 2.15.0 64位安装步骤Windows详细教程从下载到验证(附安装包下载)
  • 14、外部中断
  • 【科普向-第三篇】汽车电子MCU操作系统详解:CP AUTOSAR与FreeRTOS