【CV\utils】计算机视觉:视频图像(清洗、裁剪、人脸区域抓取等)数据预处理&数据集制作 || 代码合集

【start:2023.06.15】

1. FFmpeg

在以下视频图像数据集的制作流程中,绝大多数都要用到ffmpeg软件

【ref】9份ffmpeg典藏文档文档,比官方都详细

1.1. 下载

【Python】ffmpeg的安装配置和python中使用ffmpy(保姆级图文)

ffmpeg官网

https://ffmpeg.org/download.html
https://www.gyan.dev/ffmpeg/builds/
https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-full.7z

下载ffmpeg-git-full.7z,下载完毕后直接解压即可

1.2. 万能观影

用 ffplay 快速打开视频&图片:

E:\lxq\ffmpeg-6.0-full_build\bin\ffplay.exe

1.3. 拷贝视频

import subprocess

## 拷贝前询问是否覆盖
cmd = f"ffmpeg -i {out_mp4} -c copy {out_mp4_.replace('data/out_put', new_folder_path)}"
subprocess.run(cmd.split())

# 拷贝时默认覆盖
cmd = f"ffmpeg -y -i {out_mp4} -c copy {out_mp4_.replace('data/out_put', new_folder_path)}"
subprocess.run(cmd.split())

1.4. 裁剪视频

# trim video to shorter seconds
# ffmpeg  -ss 00:00:05  -to 00:00:10 -y -i data/examples/bella_porch.mp4 -c copy data/out_put/video_mp4.mp4
cmd = f"ffmpeg  -ss {min_time} -to {max_time} -y -i {video_input} -c copy {video_mp4}"
subprocess.run(cmd.split())

1.5. 横向拼接视频

cmd = f"ffmpeg -y -i {driving_mp4} -i {out_mp4} -filter_complex hstack=inputs=2 {final_mp4}"
subprocess.run(cmd.split())

2. OpenCV

2.1. 安装

2.1.1. 安装cv2库

pip install opencv-python

2.1.1. 安装dlib库

pip install Cmake

pip install boost

pip install dlib-19.19.0-cp38-cp38-win_amd64.whl

手动下载dlib的whl文件:dlib-19.19.0-cp38-cp38-win_amd64.whl
【ref】dlib(提供cp39、cp38、cp37安装包)

下载官方训练好的特征预测器:http://dlib.net/files
比如:68个关键点模型:shape_predictor_68_face_landmarks.dat

2.2. 视频编码

【ref】VideoWriter_fourcc()常见的编码参数

3. 文件提取

把某个文件夹下的所有子文件夹内的所有图片转存到其他文件夹
提取后,可以选择是否重命名,
重命名也可以最后再做,因为不重命名的好处是方便做后面的数据分析,比如:如果发现广告图的名字有一定特征,可以统一清洗

3.1. 图像提取:代码

该代码适用于所有格式文件的提取

import os
from glob import glob
from shutil import copy2

# 指定要遍历的根文件夹
root_folder = r'E:\aigc_230517'
# 保存输出的文件夹
output_folder = r'E:\aigc_230518_2'

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

# 遍历根文件夹及其子文件夹,查找所有特定格式的文件
# png,jpg,jpeg,jfif,webp
image_files = glob(os.path.join(root_folder, '**/*.png'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jpg'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jpeg'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jfif'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.webp'), recursive=True)
print(f"len image_files : {len(image_files)}")

# 初始化计数器变量
counter = 0

# 逐个复制每个图片文件到新路径
for image_file in image_files:

    # 将计数器加 1,以便下次保存时使用下一个序号
    counter += 1
    print(f"进度:{counter} / {len(image_files)}")
    
    # 使用 os.path.splitext() 函数获取文件名和扩展名
    filename, ext = os.path.splitext(image_file)
    filename = filename.split('\\')[-1]
    print(filename, ext)
    
    # 复制文件到新路径,采用原名
    new_path = os.path.join(output_folder , filename+ext)
    # 复制文件到新路径,用序号作为新名称
    # new_path = os.path.join(output_folder , str(counter)+ext)
    copy2(image_file, new_path)

3.2. 视频提取:代码

import os
from glob import glob
from shutil import copy2

# 指定要遍历的根文件夹
root_folder = r'E:\迅雷下载\FaceForensics++\data\downloaded_videos1'
# 保存输出的文件夹
output_folder = r'E:\迅雷下载\FaceForensics++\data\all_video'

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

# 遍历根文件夹及其子文件夹,
image_files = glob(os.path.join(root_folder, '**/*.mp4'), recursive=True)
print(f"len image_files : {len(image_files)}")

# 初始化计数器变量
counter = 0

# 逐个复制每个图片文件到新路径
for image_file in image_files:

    # 将计数器加 1,以便下次保存时使用下一个序号
    counter += 1
    print(f"进度:{counter} / {len(image_files)}")
    
    # 使用 os.path.splitext() 函数获取文件名和扩展名
    filename, ext = os.path.splitext(image_file)
    filename = filename.split('\\')[-1]
    print(filename, ext)
    
    # 复制文件到新路径,采用原名
    new_path = os.path.join(output_folder, filename+ext)
    # 复制文件到新路径,用序号作为新名称
    # new_path = os.path.join(output_folder, str(counter)+ext)
    copy2(image_file, new_path)

3.3. 迁移指定类型文件的父文件夹:代码

import os
from glob import glob
from shutil import copy2
import datetime

'''
迁移指定类型文件的父文件夹
提取整个文件夹及其子文件夹到新的文件夹中,并可以对具体文件进行操作
'''

# 指定要遍历的根文件夹
root_folder = r'E:\AIGC_230630'
# 保存输出的文件夹
output_folder = r'E:\AIGC_230630_jpg'

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

# 遍历根文件夹及其子文件夹,查找所有特定格式的文件
# png,jpg,jpeg,jfif,webp
file_path_box = glob(os.path.join(root_folder, '**/*.png'), recursive=True)
file_path_box += glob(os.path.join(root_folder, '**/*.jpg'), recursive=True)
file_path_box += glob(os.path.join(root_folder, '**/*.jpeg'), recursive=True)
file_path_box += glob(os.path.join(root_folder, '**/*.jfif'), recursive=True)
file_path_box += glob(os.path.join(root_folder, '**/*.webp'), recursive=True)
print(f"len file_path_box : {len(file_path_box)}")

# 初始化计数器变量
counter = 0
if_rename = True
# 逐个复制每个图片文件到新路径
starttime = datetime.datetime.now() # 获得计算机当前时间
for file_path in file_path_box:

    # 将计数器加 1,以便下次保存时使用下一个序号
    counter += 1
    print(f"进度:{counter} / {len(file_path_box)}")
    
    # 使用 os.path.splitext() 函数获取文件名和扩展名
    file_path_without_ext, ext_src = os.path.splitext(file_path)
    # print('file_path_without_ext, ext ',file_path_without_ext, ext)
    file_last_folder_path = os.path.join(*file_path_without_ext.split('\\')[:-1])
    # print(f'file_last_folder_path : {file_last_folder_path}')
    file_name = file_path_without_ext.split('\\')[-1]
    # print('file_name, ext ',file_name, ext)
    
    ext_dist = '.jpg'
     
    if if_rename == True:
        new_file_name_ext = '0'*(6-len(str(counter)))+str(counter) + ext_dist
    else:
        new_file_name_ext = file_name + ext_dist

    ## 创建(拷贝)指定文件的所有父辈文件夹
    #############################
    file_last_folder_path = file_last_folder_path.replace('AIGC_230630', 'AIGC_230630_jpg')
    os.makedirs(file_last_folder_path, exist_ok=True)

    ## 对具体文件进行操作
    #############################
    new_file_path = os.path.join(file_last_folder_path, new_file_name_ext)
    print(f'new_file_path : {new_file_path}')

    if ext_src == '.jpg':
        copy2(file_path, new_file_path)
    else:
        format_to_jpg(file_path, new_file_path)
    
    #############################

    # if counter == 50:
    #     break

endtime = datetime.datetime.now() # 获取过段时间后的时间
print(f'用时:{(endtime - starttime).seconds}秒')    # 计算时间差并以秒的格式输出

4. 图片清洗

爬取计算机视觉的数据集时,用插件可以提取AI生成图片网站上的所有图片,但这样做会爬到很多不需要的图(如二维码、广告图、网站logo),要如何清洗数据?


当从 AI 生成图片网站上爬取计算机视觉数据集时,需要先进行数据清洗以排除不需要的图像。以下是一些可能有用的技术:

  1. 利用正则表达式或字符串匹配来过滤文件名或 URL。例如,您可以使用正则表达式来匹配不需要的图像的名称、路径或 URL。

  2. 使用计算机视觉技术,例如物体检测、语义分割或人脸识别,来检测并排除不需要的图像。例如,您可以使用物体检测来检测广告标志或二维码,并将它们从数据集中移除。

  3. 使用人工审核的方法,手动筛选出需要的图像并删除不需要的图像。虽然这种方法可能比较耗时,但可以确保数据集是正确的。

  4. 结合多种技术进行数据清理。例如,结合正则表达式和计算机视觉技术来自动检测和过滤不需要的图像,然后再进行人工审核。

需要注意的是,即使采取了以上方法进行数据清洗,仍然存在误差的可能性。因此,建议在训练计算机视觉模型之前,对数据集进行进一步的验证和预处理,以确保数据质量。


4.1. 图像案例:去广告思路

filename, ext = os.path.splitext(image_file)
对于filename==纯数字+ext的图片,有一部分是广告,
对于后缀名是".png"的图片,有一部分是广告,计算:

  1. 文件大小/分辨率<0.5
  2. 长和宽<100

则视该图为广告图,需要删除


为什么png图片的分辨率和大小不成正比?

PNG 图片是一种基于无损压缩的位图格式,它使用 DEFLATE 压缩算法来减小文件大小。因此,在 PNG 图片中,分辨率和文件大小不是成正比关系。

PNG 图片的文件大小取决于多个因素,包括图像的尺寸、颜色深度、颜色模式、压缩级别等。以下是一些可能影响 PNG 文件大小的因素:

  1. 图像尺寸:更大的图像尺寸将导致更大的文件大小。

  2. 颜色深度:PNG 支持 8 位和 16 位颜色深度。较高的颜色深度会导致更大的文件大小。

  3. 颜色模式:PNG 支持灰度、索引和 RGB 颜色模式。RGB 模式下的图片通常会比索引或灰度模式下的图片更大。

  4. 压缩级别:PNG 使用 DEFLATE 压缩算法来减小文件大小。使用更高的压缩级别可以减小文件大小,但会增加解压时间。

由于这些因素的影响,PNG 图片的分辨率和文件大小之间不是一定的正比关系。例如,两张具有相同分辨率但采用不同颜色深度和颜色模式的 PNG 图片,它们的文件大小也可能有很大的差异。


在这里插入图片描述在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.2. 图像案例:去重思路

filename, ext = os.path.splitext(image_file)
去除filename[-1]==')'的图片

在这里插入图片描述

4.3. 图像案例:图像数据清洗代码

import os
from glob import glob
from shutil import copy2
from PIL import Image

def is_advertisement_image(filename, counter, size_ratio_threshold=0.5):
    # 加载图片
    with Image.open(filename) as img:
        # 计算图片尺寸和文件大小
        width, height = img.size
        file_size = os.path.getsize(filename)
        # 计算图片大小和分辨率的比率
        size_ratio = file_size / (width * height)
        print(f"图 {counter}, 文件大小、分辨率、比值:{file_size, width , height, size_ratio}")
        # 如果比率小于阈值,则视为广告图
        if size_ratio < size_ratio_threshold:
            return True
        elif width<100 and height<100:
            return True
        else:
            return False


# 指定要遍历的根文件夹
root_folder = r'E:\aigc_230518_2'
output_folder = r'E:\aigc_230518_3'

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

# 遍历根文件夹及其子文件夹,查找所有 PNG 和 JPG 格式图片
image_files = glob(os.path.join(root_folder, '**/*.png'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jpg'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jpeg'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jfif'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.webp'), recursive=True)


# 初始化计数器变量
counter = 0

# 逐个复制每个图片文件到新路径
for image_file in image_files:

    # 将计数器加 1,以便下次保存时使用下一个序号
    counter += 1
    # print(f"图 {counter}")

    # 使用 os.path.splitext() 函数获取文件名和扩展名
    all_filename, ext = os.path.splitext(image_file)
    filename = all_filename.split('\\')[-1]
    # print(f"名 {counter,filename, ext}")

    if ext=='.png' and is_advertisement_image(image_file, counter):
        # 同时满足png格式和小质量,视为广告图
        print(f"***图 {counter} 是广告图")
        continue
    # elif is_advertisement_image(image_file, counter):
    #     print(f"***图 {counter} 是小糊图")
    #     continue
    elif filename[-1]==')':
        print(f"***图 {counter} 是重复图")
        continue
    else:
        print(f"***图 {counter} 是正常图 √")

    # 1/0

    # 复制文件到新路径
    new_path = os.path.join(output_folder, filename+ext)
    # 重命名图片,再复制文件到新路径
    # new_path = os.path.join(output_folder, str(counter)+ext)
    copy2(image_file, new_path)

5. 格式转换

把图片转换成imagenet的格式.jpeg

在图像文件中,通常会使用 “.jpg” 或者 “.jpeg” 文件扩展名来表示 JPEG 格式的图片。实际上,这两个文件扩展名都表示同一种格式。

JPEG(全称为 Joint Photographic Experts Group)是一种广泛使用的有损压缩图像格式,它可以在保证图像质量的前提下减小图像文件的大小。“.jpeg” 扩展名通常用于 UNIX 系统和 Macintosh 上,而 “.jpg” 扩展名则更常见于 Windows 系统。

虽然 “.jpg” 和 “.jpeg” 两个扩展名的名称略有不同,但它们所表示的文件格式是完全相同的,因此这两个术语可以互换使用。在 Python 中,Pillow 库中的 Image 类和相关函数都支持 “.jpg” 和 “.jpeg” 这两种文件扩展名。

5.1. 图像案例:代码

函数版:

from PIL import Image
def format_to_jpg(file_path, new_file_path):
    try:
        with Image.open(file_path) as im:
            im = im.convert("RGB")
            im.save(new_file_path, quality=95)
    except:
        print(f'wrong : {file_path}')

完整版:

from PIL import Image
import os
import datetime

# 定义输入和输出路径以及目标格式
input_folder = r"F:\1\waifu-diffusion_pic"
output_folder = r"F:\1\waifu-diffusion_jpg"

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

file_path_box = os.listdir(input_folder)

target_format = "jpg"
if_rename = True
count = 0
starttime = datetime.datetime.now() # 获得计算机当前时间
# 遍历所有文件并转换格式
for filename in file_path_box:
    count += 1
    # 打开图片并保存为目标格式
    with Image.open(os.path.join(input_folder, filename)) as im:
        im = im.convert("RGB")
        if if_rename == True:
            new_name = '0'*(5-len(str(count)))+str(count)
            new_filename = new_name + "." + target_format
        else:
            new_filename = os.path.splitext(filename)[0] + "." + target_format

        im.save(os.path.join(output_folder, new_filename), quality=95)
    print(f'{count} / {len(file_path_box)}, {filename}, {new_filename}')

    # if count == 50:
    #     break

endtime = datetime.datetime.now() # 获取过段时间后的时间
print((endtime - starttime).seconds)    # 计算时间差并以秒的格式输出

6. 视频时长裁剪

6.1. 视频案例:代码

import os
import subprocess
from glob import glob

##############################
######## 参数
##############################

# 视频文件路径
video_folder = r"E:\迅雷下载\FaceForensics++\data\all_video"
# 输出文件夹路径
output_folder = r"E:\迅雷下载\FaceForensics++\data\tailor"

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

# 裁剪时长(秒)
duration = 6

##############################
######## 运行
##############################

video_files = glob(os.path.join(video_folder, '**/*.mp4'), recursive=True)
print(f"len image_files : {len(video_files)}")

# 初始化计数器变量
counter = 0

for video_input in video_files:

    # 将计数器加 1,以便下次保存时使用下一个序号
    counter += 1
    print(f"video_files 进度:{counter} / {len(video_files)}")

    # 获取视频文件名(不包含扩展名)
    video_name = os.path.splitext(os.path.basename(video_input))[0]

    # 计算总时长(秒)
    cmd_duration = f"ffprobe -v error -select_streams v:0 -show_entries stream=duration -of default=noprint_wrappers=1:nokey=1 {video_input}"
    total_duration = float(subprocess.check_output(cmd_duration, shell=True))

    # 计算裁剪片段数
    num_clips = int(total_duration // duration)

    # 根据裁剪片段数进行循环裁剪
    for i in range(num_clips):

        print(f"clips 进度:{i} / {num_clips}")
        
        start_time = i * duration
        output_file = os.path.join(output_folder, f"{video_name}_{i+1}.mp4")

        # 使用 FFmpeg 进行裁剪操作
        cmd = f"ffmpeg -ss {start_time} -t {duration} -i {video_input} -c copy {output_file}"
        subprocess.call(cmd, shell=True)

7. 人脸区域抓取

7.1. 视频案例:人脸区域抓取代码

仅记录首次出现的人脸检测框的尺寸和位置
然后一直固定这个检测框,进行后续的裁剪工作

哪一帧帧出现了人脸,就从哪一帧开始记录视频
如果face出现次数与总帧数的比例小于drop_rate,则丢弃该视频

可扩大检测框,但无法处理边框触碰边缘的情况
检测框中心定位法可能会遇到奇数误差,而检测框四方定位法不会

import cv2
import dlib

'''
仅记录首次出现的人脸检测框的尺寸和位置
然后一直固定这个检测框,进行后续的裁剪工作

哪一帧帧出现了人脸,就从哪一帧开始记录视频
如果face出现次数与总帧数的比例小于drop_rate,则丢弃该视频

可扩大检测框,但无法处理边框触碰边缘的情况
检测框中心定位法可能会遇到奇数误差,而检测框四方定位法不会
'''

def capture_face(video_path, output_path):
    # 加载人脸检测器模型
    detector = dlib.get_frontal_face_detector()

    # 打开视频文件
    cap = cv2.VideoCapture(video_path)

    # 获取视频帧率和尺寸
    fps = cap.get(cv2.CAP_PROP_FPS)
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

    # 始化计数器变量
    frame_index = 0
    appear_face_times = 0

    # 记录首次出现的人脸框的尺寸以及位置
    face_size = (0, 0)

    # 往两端各延伸一定比例,每个方向两端共延伸双倍比例
    region_scale = 0.5

    # 如果face出现的次数小于drop_rate,则丢弃
    drop_rate = 0.7

    # 逐帧处理视频
    while cap.isOpened():
        ret, frame = cap.read()
        frame_index += 1
        # if frame_index%10 == 0:
        #     print(f"frame_index : {frame_index}")

        if not ret:     #我们可以根据ret做一个判断,if not ret就是没读到数据,就是if true
            break       #没读到数据就直接退出
            
        # 进行人脸检测
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        faces = detector(gray)
        # print(f'faces : {faces}')
        # print(f'len faces : {len(faces)}')
        # print(f'type faces : {type(faces)}')

        # 只裁剪第一次出现的人脸,然后一直固定这个人脸框
        if appear_face_times == 0:
            # 计算最大的人脸框尺寸,只跟踪其中一个
            face_index_you_want_to_trck = 0
            for i in range(len(faces)):
                if i == face_index_you_want_to_trck:
                    face = faces[i]
                    x, y, w, h = face.left(), face.top(), face.width(), face.height()
                    face_size =  (w, h)
                    break

        
        # 等到出现了人脸,知道了检测框尺寸,再创建VideoWriter
        if appear_face_times == 0 and face_size != (0, 0):
            appear_face_times = 1
            # region_size = (1+region_scale)*face_size
            region_size = tuple(map(lambda ii: int((1+2*region_scale) * ii), face_size))
            print(f"face appear in frame : {frame_index}, face_size : {face_size}, region_size : {region_size}")
            # 创建视频编码器
            fourcc = cv2.VideoWriter_fourcc(*'mp4v')
            out = cv2.VideoWriter(output_path, fourcc, fps, region_size)

            # 检测框四方定位法,不会遇到奇数误差
            x1 = x - region_scale*w
            x2 = x1 + region_size[0]
            y1 = y - region_scale*h
            y2 = y1 + region_size[1]
            x1 = int(x1)
            x2 = int(x2)
            y1 = int(y1)
            y2 = int(y2)

            # # 检测框中心定位法,可能会遇到奇数误差
            # center_x = int(x + w/2)
            # center_y = int(y + h/2)
            # x1 = center_x - region_size[0]/2
            # x2 = center_x + region_size[0]/2
            # y1 = center_y - region_size[1]/2
            # y2 = center_y + region_size[1]/2
            # x1 = int(x1)
            # x2 = int(x2)
            # y1 = int(y1)
            # y2 = int(y2)

            print(f"    x y w h : {x},{y},{w},{h}")
            print(f"    y1 y2 x1 x2 : {y1},{y2},{x1},{x2}")


        # 保存人脸区域为视频帧
        # out.write(frame[y:y+h, x:x+w])
        # 注意,这里的参数位置是y前x后,和前面不一样
        if appear_face_times >= 1 and len(faces)> 0:
            appear_face_times += 1
            out.write(frame[y1:y2, x1:x2])
    
    frame_sum = frame_index
    print(f'appear_face_times : {appear_face_times} , frame_sum : {frame_sum}')
    if appear_face_times < drop_rate*frame_index:
        # 脸部出现次数太少,我们丢弃了视频
        region_size = (2,2)
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        out = cv2.VideoWriter(output_path, fourcc, fps, region_size)
        print(f"The faces weren't seen enough. We dropped the video")

    cap.release()        
    if appear_face_times >= 1:
        print(f"capture face success!")
        # 释放资源
        out.release()
    elif appear_face_times == 0:
        print(f'there is no face')

# video_path = r'E:\迅雷下载\FaceForensics++\data\region\test.mp4'
# output_path = r'E:\迅雷下载\FaceForensics++\data\region\output.mp4'

# capture_face(video_path, output_path)

批量调用:

import os
from glob import glob
from shutil import copy2

# 指定要遍历的根文件夹
root_folder = r'E:\迅雷下载\FaceForensics++\data\tailor'
# 保存输出的文件夹
output_folder = r'E:\迅雷下载\FaceForensics++\data\region'

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

# 遍历根文件夹及其子文件夹,查找所有特定格式的文件
# png,jpg,jpeg,jfif,webp
# mp4
image_files = glob(os.path.join(root_folder, '**/*.mp4'), recursive=True)
print(f"len image_files : {len(image_files)}")

# 初始化计数器变量
counter = 0

# 逐个复制每个图片文件到新路径
for image_file in image_files:

    # 将计数器加 1,以便下次保存时使用下一个序号
    counter += 1
    print(f"进度:{counter} / {len(image_files)}")
    
    # 使用 os.path.splitext() 函数获取文件名和扩展名
    filename, ext = os.path.splitext(image_file)
    filename = filename.split('\\')[-1]
    print(filename, ext)
    
    # 复制文件到新路径,采用原名
    new_path = os.path.join(output_folder , filename+ext)
    # 复制文件到新路径,用序号作为新名称
    # new_path = os.path.join(output_folder , str(counter)+ext)
    # copy2(image_file, new_path)
    capture_face(image_file, new_path)

8. 文件改名

为了充分利用文件名的信息,该步骤一般放在最后一步前

8.1. 图像案例:代码

import os
from glob import glob
from shutil import copy2

# 指定要遍历的根文件夹
root_folder = r'E:\lxq\Awesome-Backbones-main\aigc_dataset\ai_jpeg'
output_folder = r'E:\lxq\Awesome-Backbones-main\aigc_dataset\ai_rename'
if not os.path.exists(output_folder):
    print('create new folder')
    os.makedirs(output_folder)
print(f'\noutput_folder : {output_folder}')

# 遍历根文件夹及其子文件夹,查找所有 PNG 和 JPG 格式图片
# png,jpg,jpeg,jfif,webp
image_files = glob(os.path.join(root_folder, '**/*.png'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jpg'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jpeg'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.jfif'), recursive=True)
image_files += glob(os.path.join(root_folder, '**/*.webp'), recursive=True)

# 初始化计数器变量
counter = 0

# 逐个复制每个图片文件到新路径
for image_file in image_files:
    # 将计数器加 1,以便下次保存时使用下一个序号
    counter += 1
    print(counter)

    # 使用 os.path.splitext() 函数获取文件名和扩展名
    filename, ext = os.path.splitext(image_file)
    filename = filename.split('\\')[-1]
    print(filename, ext)

    # 复制文件到新路径
    # new_path = os.path.join(output_folder, filename + ext)
    new_path = os.path.join(output_folder, str(counter)+ext)
    copy2(image_file, new_path)

8.2. 通用案例:代码

import os
from glob import glob
from shutil import copy2

# 指定要遍历的根文件夹
root_folder = r'E:\迅雷下载\FaceForensics++\data\region\*'
output_folder = r'E:\lxq\face\first-order-motion-model\data\input_box\region'

# 创建输出文件夹(如果不存在)
os.makedirs(output_folder, exist_ok=True)

# 遍历根文件夹及其子文件夹
image_files = glob(pathname=root_folder, recursive=False)
print(image_files)

# 初始化计数器变量
counter = 0

# 逐个复制每个图片文件到新路径
for image_file in image_files:
    # 将计数器加 1,以便下次保存时使用下一个序号
    counter += 1
    print(counter)

    # 使用 os.path.splitext() 函数获取文件名和扩展名
    filename, ext = os.path.splitext(image_file)
    filename = filename.split('\\')[-1]
    print(filename, ext)

    # 复制文件到新路径
    # new_path = os.path.join(output_folder, filename + ext)
    new_path = os.path.join(output_folder, str(counter)+ext)
    copy2(image_file, new_path)

9. 数据集制作

9.1. ImageNet 模板

9.1.1. split_data

import os
from shutil import copy, rmtree
import random
from tqdm import tqdm

def main():
    '''
    split_rate  : 测试集划分比例
    init_dataset: 未划分前的数据集路径
    new_dataset : 划分后的数据集路径
    
    '''
    def makedir(path):
        if os.path.exists(path):
            rmtree(path)
        os.makedirs(path)
    
    split_rate = 0.2
    init_dataset = r'E:\lxq\Awesome-Backbones-main\aigc_dataset'
    new_dataset = r'E:\lxq\Awesome-Backbones-main\datasets'
    random.seed(0)

    classes_name = [name for name in os.listdir(init_dataset)]

    makedir(new_dataset)
    training_set = os.path.join(new_dataset, "train")
    test_set = os.path.join(new_dataset, "test")
    makedir(training_set)
    makedir(test_set)
    
    for cla in classes_name:
        makedir(os.path.join(training_set, cla))
        makedir(os.path.join(test_set, cla))

    
    for cla in classes_name:
        class_path = os.path.join(init_dataset, cla)
        img_set = os.listdir(class_path)
        num = len(img_set)
        test_set_index = random.sample(img_set, k=int(num*split_rate))
        with tqdm(total=num,desc=f'Class : ' + cla, mininterval=0.3) as pbar:
            for _, img in enumerate(img_set):
                if img in test_set_index:
                    init_img = os.path.join(class_path, img)
                    new_img = os.path.join(test_set, cla)
                    copy(init_img, new_img)
                else:
                    init_img = os.path.join(class_path, img)
                    new_img = os.path.join(training_set, cla)
                    copy(init_img, new_img)
                pbar.update(1)
        print()

if __name__ == '__main__':
    main()

9.1.2. get_annotation

import os
import sys
sys.path.insert(0,os.getcwd())
from utils.train_utils import get_info

def main():
    classes_path    = r'E:\lxq\Awesome-Backbones-main\datas\annotations.txt'
    datasets_path   = r'E:\lxq\Awesome-Backbones-main\datasets'
    datasets        = ["train", "test"]
    classes, indexs = get_info(classes_path)
    
    for dataset in datasets:
        txt_file = open(r'E:\lxq\Awesome-Backbones-main\datas\\' + dataset + '.txt', 'w')
        datasets_path_ = os.path.join(datasets_path, dataset)
        classes_name      = os.listdir(datasets_path_)
        
        for name in classes_name:
            if name not in classes:
                continue
            cls_id = indexs[classes.index(name)]
            images_path = os.path.join(datasets_path_, name)
            images_name = os.listdir(images_path)
            for photo_name in images_name:
                _, postfix = os.path.splitext(photo_name)
                if postfix not in ['.jpg', '.png', '.jpeg','.JPG', '.PNG', '.JPEG']:
                    continue
                txt_file.write('%s'%(os.path.join(images_path, photo_name)) + ' ' + str(cls_id))
                txt_file.write('\n')
        txt_file.close()
if __name__ == "__main__":
    main()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值