当前位置:首页 > Software > Python > 正文内容

Smart Image Organizer Assistant 图片数据集重命名、清理,去重错误文件 Python实现

chanra1n6个月前 (05-01)Python1182

功能主要围绕处理目录中的图片文件:识别、检查、删除非图片文件以及重命名操作。这个程序是一个很好的例子,展示了如何使用Python的os库和Pillow(PIL的升级版本)库来执行文件系统的操作。
首先,介绍一下Python的os库。这个库提供了一系列的功能,用来与操作系统进行交互,比如文件的创建、删除、遍历目录等操作。而Pillow库是Python中一个非常强大的处理图片的库,它支持打开、修改、保存多种格式的图片文件。

1. 批量获取子文件夹

我们的第一个函数 get_subfolders 的工作是获取给定根目录下的所有子文件夹路径。程序通过列表推导式,结合os.listdir() 和 os.path.join() 方法来完成这项工作。这个函数可以帮助我们完成初步的目录结构解析。

2. 删除非图片文件

delete_non_image_files 函数通过遍历给定子目录下的所有文件,并检查文件的扩展名是否属于指定的图片格式集合,如果不是,则使用 os.remove() 方法将它们删除。它使用了Python集合,这是一个高效的数据结构,用于检查元素是否存在于集合中。

3. 检查并记录问题图片

check_pic 函数尝试打开一个图片文件,如果文件不存在、有问题或者是一个"解压缩炸弹",它们会引发异常。在这种情况下,该函数会将问题文件的路径记录到一个文本文件中,并尝试删除这个图片文件。这个功能提高了数据清洗的效率。

4. 图片文件重命名

重命名部分是通过 rename_image_files_in_subfolder 函数来完成的。它首先会遍历给定子目录下的所有文件,并为图片文件生成新的文件名,新文件名包括子文件夹的名称和一个独一无二的索引。在重命名之前,它会调用 check_pic 来确保图片文件没有问题。如果需要,它也会相应地处理文件名冲突。

5. 递归处理所有文件夹

最后,我们有 rename_image_files_in_subfolders 函数,它递归地处理给定路径下的所有文件夹,对每个子文件夹调用 rename_image_files_in_subfolder 方法。
我想强调一下最后的测试部分。当程序作为主模块运行时,会进行实际的操作,删除所有子文件夹中的非图片文件,并递归地重命名所有的图片文件。这确保了脚本在执行时不会有未预期的行为。


程序源码:

import os
from PIL import Image

# 获取指定目录下的所有子文件夹
def get_subfolders(path):
    subfolders = [os.path.join(path, o) for o in os.listdir(path)
                  if os.path.isdir(os.path.join(path, o))]
    return subfolders

# 删除指定目录下的所有子文件夹中不是图片文件的文件
def delete_non_image_files(subfolder):
    allowed_exts = {'.jpg', '.jpeg', '.png', '.bmp', '.jpe'}
    for file_name in os.listdir(subfolder):
        file_path = os.path.join(subfolder, file_name)
        if os.path.isfile(file_path):
            file_ext = os.path.splitext(file_name)[1].lower()
            if file_ext not in allowed_exts:
                os.remove(file_path)  # 如果不是图片格式,就删除这个文件

# 检查图片是否有问题并记录问题图片
def check_pic(path_pic, files_to_delete):
    try:
        img = Image.open(path_pic, 'r')
        img.load()
        return True
    except (FileNotFoundError, OSError, Image.DecompressionBombError):
        f = open('False.txt', 'a+')
        f.write(str(path_pic) + '\n')
        f.close()
        try:
            os.remove(path_pic)
        except PermissionError:
            print('File In Use:'+path_pic)
            files_to_delete.append(path_pic)
        except (FileNotFoundError, OSError) as e:
            print(f"删除文件 {path_pic} 失败: {e}")
        return False

# 重命名指定目录下的所有子文件夹中的图片文件
def rename_image_files_in_subfolder(subfolder, subfolder_name):
    try:
        unique_index = 0
        files_to_delete = []  # 保存需要删除的文件
        for index, file_name in enumerate(os.listdir(subfolder)):
            file_path = os.path.join(subfolder, file_name)
            if os.path.isfile(file_path):
                file_ext = os.path.splitext(file_name)[1].lower()
                if file_ext in ['.jpg', '.jpeg', '.png', '.bmp', '.jpe']:
                    # 在重命名之前检查图片是否有问题
                    if check_pic(file_path, files_to_delete):
                        # 如果图片没问题,进行重命名
                        new_file_name = f"{subfolder_name}_{index+1}{file_ext}"
                        new_file_path = os.path.join(subfolder, new_file_name)
                        while os.path.exists(new_file_path):
                            unique_index += 1
                            new_file_name = f"{subfolder_name}_{index+1}_{unique_index}{file_ext}"
                            new_file_path = os.path.join(subfolder, new_file_name)
                        os.rename(file_path, new_file_path)
    except PermissionError:
        print(f"Error: failed to rename files in subfolder {subfolder}.")

# 递归处理所有文件夹
def rename_image_files_in_subfolders(path):
    for root, dirs, files in os.walk(path):
        for subfolder in dirs:
            subfolder_path = os.path.join(root, subfolder)
            rename_image_files_in_subfolder(subfolder_path, subfolder)

# 测试
if __name__ == '__main__':
    for root, dirs, files in os.walk("."):
        for subfolder in dirs:
            subfolder_path = os.path.join(root, subfolder)
            delete_non_image_files(subfolder_path)
            rename_image_files_in_subfolders(subfolder_path)

新版本:

import os
from PIL import Image, ImageFile

# 允许加载截断的图像文件
ImageFile.LOAD_TRUNCATED_IMAGES = True

# 定义允许的图片文件扩展名
ALLOWED_EXTS = {'.jpg', '.jpeg', '.png', '.bmp', '.jpe'}
MIN_DIMENSION = 224

def clean_and_rename_images(root_path):
    files_to_delete = []  # 保存因权限问题暂时无法删除的文件

    # 遍历目录
    for root, dirs, files in os.walk(root_path):
        for file_name in files:
            file_path = os.path.join(root, file_name)
            file_ext = os.path.splitext(file_name)[1].lower()
            if file_ext in ALLOWED_EXTS:
                # 如果文件是图片,检查图片是否有问题
                if not check_pic(file_path, files_to_delete):
                    continue  # 如果图片有问题,跳过重命名
            else:
                # 如果文件不是图片,尝试删除
                try:
                    os.remove(file_path)
                except (PermissionError, FileNotFoundError, OSError) as e:
                    print(f"删除文件 {file_path} 失败: {e}")

    # 重命名图片文件
    for subfolder in get_subfolders(root_path):
        rename_image_files_in_subfolder(subfolder, os.path.basename(subfolder), files_to_delete)

    # 尝试删除权限问题下未能删除的文件
    for file_path in files_to_delete:
        try:
            os.remove(file_path)
        except (FileNotFoundError, OSError) as e:
            print(f"删除文件 {file_path} 失败: {e}")

# 获取指定目录下的所有子文件夹
def get_subfolders(path):
    return [os.path.join(path, o) for o in os.listdir(path) if os.path.isdir(os.path.join(path, o))]

# 检查图片是否有问题并记录问题图片
def check_pic(path_pic, files_to_delete):
    try:
        with Image.open(path_pic) as img:
            img.verify()  # 只用于验证图片,不加载图片数据
        with Image.open(path_pic) as img:
            img.load()  # 加载图片数据,确保没有问题
            if img.width < MIN_DIMENSION or img.height < MIN_DIMENSION:
                raise ValueError(f"Image dimensions are too small: {img.size}")
        return True
    except (FileNotFoundError, OSError, ValueError) as e:
        with open('False.txt', 'a+') as f:
            f.write(str(path_pic) + '\n')
        try:
            os.remove(path_pic)
        except PermissionError:
            files_to_delete.append(path_pic)
        return False

# 重命名指定目录下的所有图片文件
def rename_image_files_in_subfolder(subfolder, subfolder_name, files_to_delete):
    unique_index = 0
    for file_name in os.listdir(subfolder):
        file_path = os.path.join(subfolder, file_name)
        file_ext = os.path.splitext(file_name)[1].lower()
        if file_ext in ALLOWED_EXTS:
            # 构建目标文件名,并确保它是唯一的
            new_file_name = f"{subfolder_name}_{unique_index + 1}{file_ext}"
            new_file_path = os.path.join(subfolder, new_file_name)
            while os.path.exists(new_file_path):  # 如果目标文件名存在,递增序号直到找到唯一的文件名
                unique_index += 1
                new_file_name = f"{subfolder_name}_{unique_index + 1}{file_ext}"
                new_file_path = os.path.join(subfolder, new_file_name)
            os.rename(file_path, new_file_path)
            unique_index += 1

if __name__ == '__main__':
    clean_and_rename_images(".")  # 从当前目录开始处理


扫描二维码推送至手机访问。

版权声明:本文由我的FPGA发布,如需转载请注明出处。

本文链接:https://myfpga.cn/index.php/post/421.html

分享给朋友:

“Smart Image Organizer Assistant 图片数据集重命名、清理,去重错误文件 Python实现” 的相关文章

0.Python环境的搭建

0.Python环境的搭建

   请打开网页  https://www.python.org/downloads/windows/    Windows环境下的Python        这里我选择...

1.Python基本的使用

1.Python基本的使用

我们打开python或者通过运行python也可以,请复制如下代码,然后按下Enter键,看看会发生什么?print('\n'.join([''.join([('MyFpga'[(x-y) % len('MyFpga'...

Python关于turtle的函数名

Python关于turtle的函数名

turtle.forward(distance)                   向当前画笔方向移动distance像素长度turtle.backward(distance)              向当前画笔相反方向移动distance像素长度turtle.right(degree)    ...

搜索字符串

搜索字符串

常用搜索字符串中子串的方法str.count(substring)      返回str中substring子串出现的无覆盖的次数str.find(s1)                    返回s1在这个字符串的最低下标,如果字符串中不存在s1,则返回-1str.rfind(s1)       ...

列表实例

列表实例

随机生成100个小写字母存入一个列表中,统计26个字母的出现次数。import random def getRandomLetter():     code_a=ord('a')     code_z=ord('z')     x=random.randint(code_a,code_z)...