【start:2023.06.15】
1. FFmpeg
在以下视频图像数据集的制作流程中,绝大多数都要用到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 生成图片网站上爬取计算机视觉数据集时,需要先进行数据清洗以排除不需要的图像。以下是一些可能有用的技术:
-
利用正则表达式或字符串匹配来过滤文件名或 URL。例如,您可以使用正则表达式来匹配不需要的图像的名称、路径或 URL。
-
使用计算机视觉技术,例如物体检测、语义分割或人脸识别,来检测并排除不需要的图像。例如,您可以使用物体检测来检测广告标志或二维码,并将它们从数据集中移除。
-
使用人工审核的方法,手动筛选出需要的图像并删除不需要的图像。虽然这种方法可能比较耗时,但可以确保数据集是正确的。
-
结合多种技术进行数据清理。例如,结合正则表达式和计算机视觉技术来自动检测和过滤不需要的图像,然后再进行人工审核。
需要注意的是,即使采取了以上方法进行数据清洗,仍然存在误差的可能性。因此,建议在训练计算机视觉模型之前,对数据集进行进一步的验证和预处理,以确保数据质量。
4.1. 图像案例:去广告思路
filename, ext = os.path.splitext(image_file)
对于filename==纯数字+ext
的图片,有一部分是广告,
对于后缀名是".png"的图片,有一部分是广告,计算:
- 文件大小/分辨率<0.5
- 长和宽<100
则视该图为广告图,需要删除
为什么png图片的分辨率和大小不成正比?
PNG 图片是一种基于无损压缩的位图格式,它使用 DEFLATE 压缩算法来减小文件大小。因此,在 PNG 图片中,分辨率和文件大小不是成正比关系。
PNG 图片的文件大小取决于多个因素,包括图像的尺寸、颜色深度、颜色模式、压缩级别等。以下是一些可能影响 PNG 文件大小的因素:
-
图像尺寸:更大的图像尺寸将导致更大的文件大小。
-
颜色深度:PNG 支持 8 位和 16 位颜色深度。较高的颜色深度会导致更大的文件大小。
-
颜色模式:PNG 支持灰度、索引和 RGB 颜色模式。RGB 模式下的图片通常会比索引或灰度模式下的图片更大。
-
压缩级别: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()