python实现对文件夹的图片分类存放(自动新建文件夹存放图片)

以下是单个文件夹里的所有图片,我们的目的是把这些图片按照“-”前的数字序号进行分类,存到新的文件夹里。
在这里插入图片描述
“-”前面的数字为类别,后面是对应序号。所以我根据“-”符号获取“-”前面类别进行划分,根据每个类别创建对应文件夹,把各个类别里的图片都放入对应文件夹中去。最终效果
在这里插入图片描述
名为1的文件夹中的内容
在这里插入图片描述
分类成功,如果再次运行,因为图片重复,给他继续延续序号,如果中间的序号不连续有断层,例如(1-0001,1-0005)会自动填补断层(1-0002~1-0004)。
在这里插入图片描述

完成步骤或思路:

①拆分图片的标签:

def seplabel(fname):
    # .前面的字符
    filestr = fname.split(".")[0]
    # -前面的字符
    label = int(filestr.split("-")[0])
    return label

②图片类别的个数:

# 把图片中的类别总个数找出来,即要创建多少个文件夹
def labelnum(fname):  # C:/Users/sinyjam/Desktop/xingzuotu/*.jpg
    # 图片数记录
    num = len(imglist)
    labelnumber = []
    maxlabel = 0
    for i in range(0, num):
        imglist2 = os.path.basename(imglist[i])  # 获取路径下图片名称
        a = seplabel(imglist2)
        labelnumber.append(a)
        set(labelnumber)
        # set去除多余元素,最后数量为[1,2,3,4,5]
        num = len(set(labelnumber))
    return num

③图片具体类别(list存储):

# 把图片中的类别保存下来
def labellist(fname):  # C:/Users/sinyjam/Desktop/xingzuotu/*.jpg
    # 图片数记录
    num = len(imglist)
    labelnumber = []
    labelnumberlist = []
    maxlabel = 0
    for i in range(0, num):
        imglist2 = os.path.basename(imglist[i])  # 获取路径下图片名称
        a = seplabel(imglist2)
        labelnumber.append(a)
        set(labelnumber)
        # set去除多余元素,最后数量为举例:[1,2,3,4,5] 5个
    labelnumberlist = set(labelnumber)
    return labelnumberlist

④读取图片类别数目创建对应类别序号文件夹:

# 创建文件夹
def createfilefloder(fname):
    path = 'C:/Users/sinyjam/Desktop/xingzuotu2/'  # 设置创建后文件夹存放的位置
    for i in labellist(fname):  # 这里创建类别个数个文件夹
        # *定义一个变量判断文件是否存在,path指代路径,str(i)指代文件夹的名字*
        isExists = os.path.exists(path + str(i))
        if not isExists:  # 判断如果文件不存在,则创建
            os.makedirs(path + str(i))
            print("%s 目录创建成功" % i)
        else:
            print("%s 目录已经存在" % i)
            continue  # 如果文件不存在,则继续上述操作,直到循环结束

⑤将图片复制并分类到目标文件夹:

# 读取文件并且复制文件到相应的文件夹,
# 这里的fname2不能是全路径到jpg,最后是文件夹/结尾
def readImgAndSave(fname2):
    ls = os.listdir(fname2)
    for i in ls:
        print(i)
        istr = i.split(".")[0]
        label = istr.split("-")[0]
        dst = os.path.join(destination_path, label)
        new_image = os.path.join(dst, i)
        # print(istr)
        # print(label)
        if not os.path.exists(new_image):
            shutil.copy(fname2 + '/' + i, destination_path + '%s' % label + '/')
        else:
            images = os.listdir(dst)
            max_serial = -1
            for im in images:
                _, serial_num = im.split('-')[0], im.split('-')[1]
                theNum = re.compile('0*([1-9][0-9]*)').findall(serial_num)[0]
                max_serial = max(max_serial, int(theNum))
            max_serial += 1
            new_name = label + '-' + str(max_serial).zfill(4) + '.jpg'
            new_file_path = os.path.join(dst, new_name)
            shutil.copy(fname2 + '/' + i, new_file_path)

⑥将图片转为RGB(可选项):

因为神经网络训练的要求,提前做好RGB转换

# 转RGB
def ChangeToRgb(fname):
    for infile in glob.glob(picturepath):
        # file为前面的所有路径,ext为.jpg,拼在一起是一个完整的路径
        file, ext = os.path.splitext(infile)
        Img = Image.open(infile)
        # 看图片类型。是不是我们要的RGB,不是就转换成RGB
        print(Img.mode, file)
        if Img.mode != 'RGB':
            Img = Img.convert('RGB')

代码

接下来将提供两个版本的代码(思路类似,只是第二种稍作优化,删去了一些冗余代码,看起来简洁)

一、上述拆分步骤的完整代码

from PIL import Image
import numpy as np
import pickle, glob
import os  # 导入创建文件夹模块
import shutil
import re

# 拆分标签
def seplabel(fname):
    # .前面的字符
    filestr = fname.split(".")[0]
    # -前面的字符
    label = int(filestr.split("-")[0])
    return label


# 把图片中的类别总个数找出来,即要创建多少个文件夹
def labelnum(fname):  # C:/Users/sinyjam/Desktop/xingzuotu/*.jpg
    # 图片数记录
    num = len(imglist)
    labelnumber = []
    maxlabel = 0
    for i in range(0, num):
        imglist2 = os.path.basename(imglist[i])  # 获取路径下图片名称
        a = seplabel(imglist2)
        labelnumber.append(a)
        set(labelnumber)
        # set去除多余元素,最后数量为[1,2,3,4,5]
        num = len(set(labelnumber))
    return num


# 把图片中的类别保存下来
def labellist(fname):  # C:/Users/sinyjam/Desktop/xingzuotu/*.jpg
    # 图片数记录
    num = len(imglist)
    labelnumber = []
    labelnumberlist = []
    maxlabel = 0
    for i in range(0, num):
        imglist2 = os.path.basename(imglist[i])  # 获取路径下图片名称
        a = seplabel(imglist2)
        labelnumber.append(a)
        set(labelnumber)
        # set去除多余元素,最后数量为举例:[1,2,3,4,5] 5个
    labelnumberlist = set(labelnumber)
    return labelnumberlist


# 创建文件夹
def createfilefloder(fname):
    path = 'C:/Users/sinyjam/Desktop/xingzuotu2/'  # 设置创建后文件夹存放的位置
    for i in labellist(fname):  # 这里创建类别个数个文件夹
        # *定义一个变量判断文件是否存在,path指代路径,str(i)指代文件夹的名字*
        isExists = os.path.exists(path + str(i))
        if not isExists:  # 判断如果文件不存在,则创建
            os.makedirs(path + str(i))
            print("%s 目录创建成功" % i)
        else:
            print("%s 目录已经存在" % i)
            continue  # 如果文件不存在,则继续上述操作,直到循环结束


# 读取文件并且复制文件到相应的文件夹,
# 这里的fname2不能是全路径到jpg,最后是文件夹"/"结尾
# C:/Users/sinyjam/Desktop/xingzuotu
def readImgAndSave(fname2):
    ls = os.listdir(fname2)
    for i in ls:
        print(i)
        istr = i.split(".")[0]
        label = istr.split("-")[0]
        dst = os.path.join(destination_path, label)
        new_image = os.path.join(dst, i)
        # print(istr)
        # print(label)
        if not os.path.exists(new_image):
            shutil.copy(fname2 + '/' + i, destination_path + '%s' % label + '/')
        else:
            images = os.listdir(dst)
            max_serial = -1
            for im in images:
                _, serial_num = im.split('-')[0], im.split('-')[1]
                theNum = re.compile('0*([1-9][0-9]*)').findall(serial_num)[0]
                max_serial = max(max_serial, int(theNum))
            max_serial += 1
            new_name = label + '-' + str(max_serial).zfill(4) + '.jpg'
            new_file_path = os.path.join(dst, new_name)
            shutil.copy(fname2 + '/' + i, new_file_path)

# 转RGB
def ChangeToRgb(fname):
    for infile in glob.glob(source_path):
        # file为前面的所有路径,ext为.jpg,拼在一起是一个完整的路径
        file, ext = os.path.splitext(infile)
        Img = Image.open(infile)
        # 看图片类型。是不是我们要的RGB,不是就转换成RGB
        print(Img.mode, file)
        if Img.mode != 'RGB':
            Img = Img.convert('RGB')


source_path = "C:/Users/sinyjam/Desktop/xingzuotu/*.jpg"
source_pathf = "C:/Users/sinyjam/Desktop/xingzuotu/"
destination_path = "C:/Users/sinyjam/Desktop/xingzuotu2/"
imglist = glob.glob(source_path)
ChangeToRgb(source_path)
# 类别数print(labelnum(imglist))
# 根据类别数创造文件夹
createfilefloder(labelnum(imglist))
# 打印list里有哪些
# print(labellist("C:/Users/sinyjam/Desktop/xingzuotu/*.jpg"))
readImgAndSave(source_pathf)


如果觉得前面的麻烦,也没事,这里优化了代码,只是分文件夹的话,下面的够用了
简化版代码即可:

二、 精简版(25行超浓缩)

import os
import re
from shutil import copyfile
import shutil
source_path = r'C:\Users\sinyjam\Desktop\aaa'
destination_path = r'C:\Users\sinyjam\Desktop\aaa3'
#返回文件名
images = os.listdir(source_path)
print(images)
num = 0
for i in images:
    category, name = i.split('-')[0], i.split('-')[1]
    src = os.path.join(source_path, i)
    dst = os.path.join(destination_path, category)
    new_image = os.path.join(dst, i)
    if not os.path.exists(dst):
        os.mkdir(dst)
        continue
    elif not os.path.exists(new_image):
        shutil.copy(src, new_image)
    else:
        images = os.listdir(dst)
        max_serial = -1
        for im in images:
            _, serial_num = im.split('-')[0].strip(), im.split('-')[1].strip()
            theNum = re.compile('0*([1-9][0-9]*)').findall(serial_num)[0]
            max_serial = max(max_serial, int(theNum))
        max_serial += 1
        new_name = category + '-' + str(max_serial).zfill(4) + '.jpg'
        new_file_path = os.path.join(dst, new_name)
        shutil.copy(src, new_file_path)

——孙LL&Sinysama

<think>好的,我现在需要帮用户解决用Python对指定文件夹内所有图片自动按顺序命名或添加序号的问题。首先,我得理清楚用户的需求。用户提到的是对图片进行编号,可能是重命名,也可能是复制到其他位置并添加序号。根据提供的引用,用户可能有两种需求:直接重命名原文件,或者复制到另一个文件夹并添加序号。需要确认用户的具体需求,但根据问题描述,用户可能希望直接在原文件夹中重命名,或者复制到另一个位置。 接下来,我要看看用户提供的引用内容。引用[1]展示了如何遍历文件夹中的文件并添加序号打印,引用[2]是重命名并复制到目标文件夹,引用[3]是关于视频截取图片并按顺序保存。综合这些,我需要结合这些方法,编写一个适合图片处理的脚本。 首先,用户需要处理的是图片文件,所以需要识别常见的图片扩展名,如.jpg、.png等。然后,确定是按顺序编号,比如从1开始,可能需要在数字前面补零,如0001,0002,这样排序更直观。例如,使用zfill(4)来生成四位数的序号。 接下来,考虑是重命名原文件还是复制到新位置。根据用户的问题,可能两种需求都有,但用户的问题更倾向于重命名或添加序号。可能需要提供两种方案:一种是在原文件夹内直接重命名,另一种是复制到目标文件夹并添加前缀或序号。 然后,需要考虑文件的遍历方式。使用os模块的listdir可能不够,因为可能需要递归子文件夹,但用户的问题可能仅指定一个文件夹内的图片。如果用户需要处理子文件夹中的图片,可能需要os.walk,但根据引用[2],用户可能希望处理所有子文件夹中的文件,并添加文件夹名前缀。但用户的问题并没有提到子文件夹,所以可能需要先确认,但用户的问题明确是“指定文件夹内所有图片”,可能不需要处理子目录,但根据示例引用[2],可能需要处理子目录中的文件,并加上文件夹名称。例如,如果图片在子文件夹a、b、c中,重命名为a-1.jpg,b-1.jpg等。不过用户的问题可能只是单纯地对一个文件夹中的所有图片进行编号,比如image001.jpg, image002.jpg等。 另外,需要确保只处理图片文件,因此需要检查文件扩展名。常见的图片扩展名包括.jpg、.jpeg、.png、.gif、.bmp等。可以通过判断文件名的小写后缀是否在这些列表中。 接下来,代码结构大致如下: 1. 导入os和shutil模块(如果需要复制的话)。 2. 定义目标文件夹和源文件夹路径。 3. 遍历源文件夹中的文件,过滤出图片文件。 4. 对图片文件进行排序,可能需要按名称或按修改时间排序,用户可能希望按当前顺序处理,但需要明确。例如,按文件名排序或者按创建时间排序,用户可能需要指定,但问题中没有说明,所以可能需要按文件名的自然顺序排序。 5. 生成新的文件名,添加序号,如使用str(num).zfill(4)来生成四位数的序号。 6. 重命名或复制文件到目标位置。 需要考虑是否保留原文件名。例如,用户可能希望完全用序号代替原文件名,或者将序号添加到原文件名前。例如,原文件名为photo.jpg,变成001_photo.jpg或者直接001.jpg。需要根据用户需求决定。引用[2]中的例子是使用文件夹名称加序号,如文件夹a中的文件变成a-1.txt,而引用[3]是使用data变量加序号。因此可能需要用户自定义命名规则,但用户的问题只是按顺序命名,可能更倾向于用序号直接命名,如1.jpg, 2.jpg等,或者按某种前缀,如image_001.jpg。 此外,处理文件时需要注意不要覆盖已有的文件。例如,如果直接重命名为1.jpg,而文件夹中已经有这个文件,就会覆盖。因此,可能需要将文件复制到新文件夹,或者在重命名时确保新文件名唯一。或者,用户可能希望在原文件夹中重命名,但需要按顺序编号,确保不会重复。 综上所述,可能的解决方案有两种: 方案一:在原文件夹内重命名图片文件,按顺序编号,如0001.jpg, 0002.png等。但需要注意文件类型不同,扩展名不同,但用户可能希望统一扩展名?或者保留原扩展名。通常保留原扩展名。 方案二:将图片复制到目标文件夹,并按顺序命名,可能加上文件夹名前缀,如引用[2]中的方式。 用户的问题比较笼统,可能需要提供一个通用的方法,让用户可以选择。例如,用户可能想将指定文件夹中的所有图片文件(无论子文件夹)重命名为序列号+原文件名,或者直接序列号+扩展名。 根据引用[1]中的例子,可以遍历文件,过滤出图片,然后按顺序重命名。例如: import os folder_path = 'path/to/folder' target_folder = 'path/to/target' # 如果复制的话 image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'] # 获取所有图片文件 files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f)) and os.path.splitext(f)[1].lower() in image_extensions] # 按文件名排序 files.sort() # 遍历并重命名或复制 for index, file in enumerate(files, start=1): ext = os.path.splitext(file)[1] new_name = f"{index:04d}{ext}" src_path = os.path.join(folder_path, file) dst_path = os.path.join(folder_path, new_name) # 原文件夹重命名 # 或者复制到目标文件夹: # dst_path = os.path.join(target_folder, new_name) os.rename(src_path, dst_path) 但这里有一个问题,如果直接在原文件夹中重命名,当处理后面的文件时,可能会遇到已经存在的文件名,比如如果原来的文件名已经是数字开头的,可能会覆盖。例如,如果有一个文件名为0002.jpg,当处理到第二个文件时,试图重命名为0002.jpg,而如果原文件夹中已有这个文件,就会出错。因此,更安全的方法是将文件复制到目标文件夹,而不是直接重命名原文件。或者,在重命名时使用临时文件名,但这样比较复杂。 因此,更安全的方式是复制到新文件夹,并赋予新的序号名称,这样原文件保持不变,新文件夹中的文件都是按顺序命名的。例如: import os import shutil source_folder = 'path/to/source' target_folder = 'path/to/target' if not os.path.exists(target_folder): os.makedirs(target_folder) image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'] files = [f for f in os.listdir(source_folder) if os.path.isfile(os.path.join(source_folder, f)) and os.path.splitext(f)[1].lower() in image_extensions] files.sort() # 或者按修改时间排序,根据用户需求 for idx, filename in enumerate(files, 1): ext = os.path.splitext(filename)[1] new_name = f"{idx:04d}{ext}" src = os.path.join(source_folder, filename) dst = os.path.join(target_folder, new_name) shutil.copy2(src, dst) # 复制文件,保留元数据 这样,所有图片会被复制到目标文件夹,并按0001.jpg、0002.png等命名。如果用户希望在原文件夹中直接重命名,那么需要确保新文件名不会冲突。例如,可以先将所有文件重命名为临时名称,然后再重命名为目标名称,或者按逆序处理,但这样比较复杂。 另一种方法是先收集所有文件的信息,然后逐个重命名。例如,先获取所有文件列表,生成新名称,然后按顺序处理。例如,先将所有文件改名为temp_前缀,然后再改名为序号,但这需要更多的步骤。 不过,用户可能更希望一个简单的方法,所以可能建议复制到目标文件夹,这样更安全。 另外,用户可能需要处理子文件夹中的图片,比如引用[2]中的例子,遍历所有子文件夹中的文件,并添加文件夹名前缀。例如,文件夹a中的文件变成a_1.jpg,文件夹b中的文件变成b_1.jpg等。用户的问题中提到“指定文件夹内所有图片”,可能包括子文件夹中的图片,但需要明确。如果用户需要包括子文件夹中的图片,则需要使用os.walk。 例如: import os import shutil source_folder = 'path/to/source' target_folder = 'path/to/target' image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'] counter = 1 for root, dirs, files in os.walk(source_folder): for file in files: ext = os.path.splitext(file)[1].lower() if ext in image_extensions: src_path = os.path.join(root, file) # 生成新名称 new_name = f"{counter:04d}{ext}" dst_path = os.path.join(target_folder, new_name) shutil.copy2(src_path, dst_path) counter += 1 这样,所有子文件夹中的图片都会被复制到目标文件夹,并按全局计数器编号。但用户可能需要按每个子文件夹单独编号,如引用[2]中的方式,添加文件夹名作为前缀。例如,文件夹a中的文件变成a_1.jpg,a_2.jpg等。这种情况下,需要处理每个子文件夹内的文件,并添加对应的前缀。 例如: import os import shutil source_folder = 'path/to/source' target_folder = 'path/to/target' image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp'] for root, dirs, files in os.walk(source_folder): # 获取当前文件夹名称 folder_name = os.path.basename(root) # 初始化计数器 counter = 1 for file in files: ext = os.path.splitext(file)[1].lower() if ext in image_extensions: src_path = os.path.join(root, file) new_name = f"{folder_name}_{counter:04d}{ext}" dst_path = os.path.join(target_folder, new_name) shutil.copy2(src_path, dst_path) counter += 1 这样,每个子文件夹中的图片会以文件夹名+序号的方式命名,例如a_0001.jpg,b_0001.jpg等。但用户的问题可能不需要子文件夹的处理,因此需要根据具体情况调整。 回到用户的问题,用户想对“指定文件夹内所有图片自动按顺序命名。假设用户指的是单个文件夹,不包含子文件夹,那么可以使用第一种方法,遍历该文件夹中的文件,过滤出图片,然后按顺序命名。 此外,用户可能需要指定排序方式,比如按文件名排序、按修改时间排序等。例如,如果想按创建时间排序,可以使用os.path.getmtime获取文件修改时间,然后排序。 例如: files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f)) and os.path.splitext(f)[1].lower() in image_extensions] files.sort(key=lambda x: os.path.getmtime(os.path.join(folder_path, x))) 这样,文件会按修改时间排序,然后按顺序编号。 总结,用户需要的步骤大致如下: 1. 指定源文件夹和目标文件夹(如果需要复制)。 2. 遍历源文件夹中的文件,过滤出图片文件。 3. 对文件进行排序(按名称、时间等)。 4. 生成带序号的新文件名。 5. 复制或重命名文件。 在代码实现中,需要注意文件路径的处理,使用os.path.join,并处理扩展名的大小写问题。同时,确保目标文件夹存在,如果不存在则创建。 最后,根据用户提供的引用,特别是引用[2]和引用[3],可能还需要考虑如何整合这些方法。例如,用户可能希望将不同文件夹中的图片合并到一个目标文件夹,并按统一序号命名,或者按原文件夹名称加序号命名。需要根据用户的具体需求调整代码。 根据用户的问题描述,他们可能希望两种方式:直接在原文件夹中添加序号,或者复制到新文件夹并添加序号。因此,在回答中可能需要提供两种情况的代码示例,并说明如何修改以适应不同需求。</think>可以通过Python的`os`和`shutil`模块实现图片文件的批量重命名或复制操作。以下是两种常见场景的解决方案: --- ### **场景一:在原文件夹内直接重命名图片** 若需对指定文件夹内的所有图片按顺序重命名(例如`0001.jpg`, `0002.png`),代码如下: ```python import os folder_path = "图片文件夹路径" # 替换为实际路径 image_exts = {'.jpg', '.jpeg', '.png', '.gif', '.bmp'} # 获取所有图片文件并按文件名排序 files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f)) and os.path.splitext(f)[1].lower() in image_exts] files.sort() # 可选按修改时间排序:key=lambda x: os.path.getmtime(...) # 重命名 for idx, filename in enumerate(files, 1): old_path = os.path.join(folder_path, filename) ext = os.path.splitext(filename)[1] new_name = f"{idx:04d}{ext}" # 生成4位序号 new_path = os.path.join(folder_path, new_name) os.rename(old_path, new_path) ``` --- ### **场景二:复制图片到新文件夹并按序号命名** 若需保留原文件并将带序号的新文件保存到另一个文件夹: ```python import os import shutil source_folder = "源文件夹路径" # 替换为实际路径 target_folder = "目标文件夹路径" # 替换为实际路径 image_exts = {'.jpg', '.jpeg', '.png', '.gif', '.bmp'} # 创建目标文件夹 os.makedirs(target_folder, exist_ok=True) # 遍历并复制文件 files = [f for f in os.listdir(source_folder) if os.path.isfile(os.path.join(source_folder, f)) and os.path.splitext(f)[1].lower() in image_exts] files.sort() # 按需调整排序方式 for idx, filename in enumerate(files, 1): src = os.path.join(source_folder, filename) ext = os.path.splitext(filename)[1] new_name = f"image_{idx:04d}{ext}" # 命名格式如image_0001.jpg dst = os.path.join(target_folder, new_name) shutil.copy2(src, dst) # 复制并保留元数据 ``` --- ### **关键点说明** 1. **文件过滤**:通过扩展名筛选图片文件,避免处理其他类型文件[^1]。 2. **序号补零**:使用`f"{idx:04d}"`生成4位序号(如0001),保证文件名排序一致性[^3]。 3. **排序方式**:默认按文件名排序,可通过`key=os.path.getmtime`改为按修改时间排序。 4. **路径安全**:使用`os.path.join()`处理路径兼容性,避免操作系统差异问题[^2]。 ---
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sinysama

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值