图像和标签数字重新命名升序
- 使用教程
- 如果跑不出来
使用图像采集程序后,我们会得到由1升序排列的一组图像,这是USB摄像头真实采集到的图像。在正常的比赛过程中,如果不涉及一些严密的数字计算,我们是不需要进行图像标定的。当我们的数据集到达一定规模之后,人工数据标注会浪费大量的时间,因此我在后期做目标检测的时候通常用摄像头按照多种角度采集图像(这个是密码,实验室的同学肯定知道,纯经验,唯手熟尔),最多一次采集大约600左右,然后使用数据增强进行扩充数据集达到过万的一个规模。增强后的图像由于本人的代码水平不行会出现很多后缀名,所以写了一个基本上不改变图像和标签顺序的情况下对图像进行重新用数字升序命名。
使用教程
代码结构还是比较清晰的,用到了函数和类。为了减少等待时间,这次我用了多线程和进度条可以直观感受(数据集少于一万的几乎没有体验感)
folder1=folder1:图像文件夹
folder2=folder2:标签文件夹
start_number:图像命名首数字,第一张图像会以此进行升序
num_workers:多线程数量
show_progress:是否展示进度条等操作流程
注意:记得删除临时文件夹,一般不显示,属于隐藏文件
import os
import sys
import time
import signal
import platform
import shutil
from concurrent.futures import ProcessPoolExecutor, as_completed
from tqdm import tqdm
def rename_task(src_path, dst_path, pair_id, show_progress=True):
"""独立的重命名任务"""
try:
temp_dir = os.path.join(os.path.dirname(src_path), ".rename_temp")
os.makedirs(temp_dir, exist_ok=True)
if os.path.exists(dst_path):
shutil.move(dst_path, os.path.join(temp_dir, os.path.basename(dst_path)))
os.rename(src_path, dst_path)
return True, (src_path, dst_path, pair_id)
except Exception as e:
error_msg = f"重命名错误: {os.path.basename(src_path)} -> {os.path.basename(dst_path)}: {str(e)}"
if show_progress:
tqdm.write(error_msg)
return False, error_msg
class ParallelRenamer:
def __init__(self, folder1, folder2, start_number=15190, num_workers=None, show_progress=True):
self.folder1 = folder1
self.folder2 = folder2
self.start_number = start_number
self.show_progress = show_progress
self.num_workers = num_workers or min(os.cpu_count() or 8, 8)
if platform.system() == "Windows":
self.num_workers = min(self.num_workers, 4)
self.progress_bar = None
def set_total_files(self, total):
"""设置总文件数并初始化进度条"""
if self.show_progress and total > 0:
self.progress_bar = tqdm(total=total, unit="file", desc="处理进度")
def get_sorted_file_list(self, folder_path):
"""获取并排序文件列表"""
files = []
for file_name in os.listdir(folder_path):
file_path = os.path.join(folder_path, file_name)
if os.path.isfile(file_path):
base_name, ext = os.path.splitext(file_name)
if not base_name: # 跳过隐藏文件
continue
files.append((base_name, ext, file_name, file_path))
files.sort(key=lambda x: x[0])
if self.show_progress:
tqdm.write(f"文件夹 {folder_path} 中的文件: {[(f[2], f[1]) for f in files]}")
return files
def find_common_files(self):
"""找出匹配的文件对"""
files1 = self.get_sorted_file_list(self.folder1)
files2 = self.get_sorted_file_list(self.folder2)
name_map1 = {name: (ext, file_name, path) for name, ext, file_name, path in files1}
name_map2 = {name: (ext, file_name, path) for name, ext, file_name, path in files2}
common_files = []
for name in name_map1:
if name in name_map2 and name_map1[name][0] != name_map2[name][0]:
common_files.append((
name_map1[name][1], # file1_name
name_map2[name][1], # file2_name
name_map1[name][2], # file1_path
name_map2[name][2] # file2_path
))
self.set_total_files(len(common_files) * 2) # 每对文件包含两个重命名任务
if self.show_progress:
tqdm.write(f"找到 {len(common_files)} 对匹配文件")
return common_files
def rename_files(self, common_files):
"""使用多进程重命名文件"""
start_time = time.time()
tasks = []
current_number = self.start_number
# 生成重命名任务
for file1_name, file2_name, file1_path, file2_path in common_files:
new_name = str(current_number)
new_file1 = new_name + os.path.splitext(file1_name)[1]
new_file2 = new_name + os.path.splitext(file2_name)[1]
tasks.append((file1_path, os.path.join(self.folder1, new_file1), current_number))
tasks.append((file2_path, os.path.join(self.folder2, new_file2), current_number))
current_number += 1
# 多进程执行重命名
success_count = 0
error_count = 0
error_messages = []
with ProcessPoolExecutor(max_workers=self.num_workers) as executor:
futures = {executor.submit(rename_task, task[0], task[1], task[2], self.show_progress): task for task in tasks}
for future in as_completed(futures):
result = future.result()
if result[0]:
success_count += 1
if self.progress_bar:
self.progress_bar.update(1)
else:
error_count += 1
error_messages.append(result[1])
# 打印统计信息
if self.show_progress:
elapsed = time.time() - start_time
tqdm.write(f"\n重命名统计:\n✓ 成功文件对: {success_count // 2}/{len(common_files)}\n✗ 失败重命名: {error_count}\n⏱ 处理时间: {elapsed:.2f}秒")
if error_messages:
tqdm.write("\n错误详情:")
for msg in error_messages:
tqdm.write(f" • {msg}")
return error_count == 0
def cleanup(self):
"""清理资源"""
if self.progress_bar:
self.progress_bar.close()
self.progress_bar = None
def run(self):
"""主运行流程"""
try:
common_files = self.find_common_files()
if not common_files:
if self.show_progress:
tqdm.write("没有找到匹配的文件对")
return True
if self.show_progress:
tqdm.write(f"使用 {self.num_workers} 个工作进程")
return self.rename_files(common_files)
except Exception as e:
if self.show_progress:
tqdm.write(f"严重错误: {str(e)}")
return False
finally:
self.cleanup()
def main():
folder1 = "images"
folder2 = "Annotations"
def signal_handler(sig, frame):
print("\n操作已由用户中断")
sys.exit(1)
signal.signal(signal.SIGINT, signal_handler)
renamer = ParallelRenamer(
folder1=folder1,
folder2=folder2,
start_number=29937,
num_workers=8,
show_progress=True
)
success = renamer.run()
sys.exit(0 if success else 1)
if __name__ == "__main__":
main()
如果跑不出来
回家吧孩子,回家吧~
看看是不是解释器版本有问题,我一般常用3.8,3.9或者3.6。这种代码我一般不会为了性能而对解释器版本特性进行使用,所以想想自己有没有努力~
实在不行点杯奶茶喝完回来继续干!!!
1000

被折叠的 条评论
为什么被折叠?



