公司动态

自动标注-AI自主学习功能步骤

📅 2026/8/11 17:41:37
自动标注-AI自主学习功能步骤
yolov8的val.py的结果默认只在控制台显示其中主要包括Class Images Instances Box(P R mAP50 mAP50-95)本文就是要将这些个信息都输出到指定文件***.log文件中保存就不用每次要看数据都运行val.py了原理就是将官方用logging模块输出到控制台的所有信息全部再输出到.log文件中步骤一解决的是输出问题步骤二是往log文件添加提示信息步骤三解决的是.log文件的文件名字问题设置ultralytics/utils/__init__.pyset_logging添加筛选log类#*****************定义日志过滤功能类 start class KeywordFilter(logging.Filter): 自定义日志过滤器只记录包含特定关键字的日志行 def __init__(self, *keywords): self.keywords keywords def filter(self, record): # 仅当日志消息包含任意一个关键字时返回True return any(keyword in record.msg for keyword in self.keywords) class MultiFileFilter(logging.Filter): 自定义日志过滤器只记录来自指定源文件的日志信息。 def __init__(self, filenames): super().__init__() self.filenames set(filenames) # 将文件名集合化方便查找 def filter(self, record): # 仅当日志记录来自指定的源文件时返回 True return record.filename in self.filenames #*****************定义日志过滤功能类 end在set_logging方法中添加位置# ---------------将日志结果输出到文件中-----------------# log_path /home/luodehuan/workspace/test/runs/log/ #指定文件夹路径 os.makedirs(log_path, exist_okTrue) # from val import result_name # from auto_batch import result_name logfile log_path Val_Results.log #“result_name”是和val.py运行生成的“文件夹的名称”一致方便一一对应 print_handler logging.FileHandler(filenamelogfile, encodingutf-8) # 定义输出的文件名字 formatter logging.Formatter(%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s) # 设置日志格式 print_handler.setFormatter(formatter) # 设置处理器的日志格式 # 创建自定义过滤器只写入来自 my_script.py 的日志信息 allowed_files [validator.py, val.py] # 指定多个文件名 file_filter MultiFileFilter(allowed_files) print_handler.addFilter(file_filter) # 添加过滤器到日志处理器 # 获取Logger实例并设置日志级别和处理器 logger logging.getLogger() logger.setLevel(logging.INFO) # 设置日志级别为INFO或更高级别 logger.addHandler(print_handler) # 往logger对象中添加处理器 #*************筛选日志目录1.把相关实现函数写入tools.pyimport os from ultralytics import YOLO import shutil import random import numpy as np from sklearn.model_selection import train_test_split import yaml import warnings warnings.filterwarnings(ignore) class ImagePredictor: def __init__(self, img_path, model_path): 初始化图像预测器。 :param img_path: 要预测的图像文件夹路径 :param model_path: YOLO 模型的权重路径 self.img_path img_path self.model_path model_path self.model YOLO(model_path) # 加载模型 def process_images(self): 遍历文件夹中的图片文件并进行预测。 # 遍历文件夹中的文件 for filename in os.listdir(self.img_path): # 判断文件是否为图片文件支持 .jpg 和 .png 格式 if filename.endswith(.jpg) or filename.endswith(.png): # 拼接文件的完整路径 file_path os.path.join(self.img_path, filename) # 打印正在处理的文件 print(f正在处理: {file_path}) # 使用模型进行预测并保存结果 results self.model(file_path, saveTrue,save_txtTrue) print(f预测结果保存完成: {file_path}) # 打印保存标签的路径 labels_save_path self.model.predictor.save_dir / labels print(flabels_save_path: {labels_save_path}) # 返回保存标签的路径 return labels_save_path def run(self): 运行图像预测流程。 return self.process_images() class DatasetSplitter: def __init__(self, img_path, txt_path, output_path, val_size0.1, test_size0.1, postfixpng): 初始化数据集划分器。 :param img_path: 图片文件路径 :param txt_path: 标签文件路径 :param output_path: 数据集输出文件夹路径 :param val_size: 验证集比例 :param test_size: 测试集比例 :param postfix: 图片文件后缀 self.img_path img_path self.txt_path txt_path self.output_path output_path self.val_size val_size self.test_size test_size self.postfix postfix # 创建数据集文件夹 os.makedirs(os.path.join(self.output_path, images/train), exist_okTrue) os.makedirs(os.path.join(self.output_path, images/val), exist_okTrue) os.makedirs(os.path.join(self.output_path, images/test), exist_okTrue) os.makedirs(os.path.join(self.output_path, labels/train), exist_okTrue) os.makedirs(os.path.join(self.output_path, labels/val), exist_okTrue) os.makedirs(os.path.join(self.output_path, labels/test), exist_okTrue) def check_and_create_txt_files(self): 检查图片文件是否有对应的txt标签文件如果没有则创建空的txt文件。 # 获取所有的图片文件 image_files [f for f in os.listdir(self.img_path) if f.endswith(self.postfix)] # 检查并创建对应的txt文件 for image in image_files: txt_filename f{image[:-4]}.txt # 对应的txt文件名 txt_filepath os.path.join(self.txt_path, txt_filename) # 完整txt文件路径 if not os.path.exists(txt_filepath): # 如果txt文件不存在创建一个空文件 print(f{txt_filename} 不存在创建空文件...) with open(txt_filepath, w) as f: pass # 创建一个空文件 def split_dataset(self): 使用train_test_split划分数据集为训练集、验证集和测试集。 :return: 训练集、验证集、测试集的文件列表 # 获取所有的标签文件txt文件 listdir np.array([f for f in os.listdir(self.txt_path) if f.endswith(.txt)]) random.shuffle(listdir) # 随机打乱 # 使用train_test_split进行数据集划分 train_val, test train_test_split(listdir, test_sizeself.test_size, random_state0) train, val train_test_split(train_val, test_sizeself.val_size / (1 - self.test_size), random_state0) print(ftrain set size: {len(train)}) print(fval set size: {len(val)}) print(ftest set size: {len(test)}) return train, val, test def copy_files(self, file_list, split_name): 将图片和标签文件复制到指定的目录中。 :param file_list: 要复制的文件列表 :param split_name: 数据集的分组名称train/val/test for txt_file in file_list: try: # 拼接源图片文件和目标文件路径 img_file f{txt_file[:-4]}.{self.postfix} # 图片文件名 src_img_path os.path.join(self.img_path, img_file) # 源图片路径 src_txt_path os.path.join(self.txt_path, txt_file) # 源标签路径 # 目标文件夹 dst_img_dir os.path.join(self.output_path, fimages/{split_name}) # 目标图片目录 dst_txt_dir os.path.join(self.output_path, flabels/{split_name}) # 目标标签目录 # 复制图片和标签文件到目标目录 shutil.copy(src_img_path, os.path.join(dst_img_dir, img_file)) shutil.copy(src_txt_path, os.path.join(dst_txt_dir, txt_file)) except FileNotFoundError as e: print(f文件未找到: {e}) def run(self): 运行数据集划分流程依次进行标签文件检查、数据集划分和文件复制。 # 1. 检查并创建缺失的标签文件 self.check_and_create_txt_files() # 2. 划分数据集 train, val, test self.split_dataset() # 3. 复制训练集、验证集和测试集文件 self.copy_files(train, train) self.copy_files(val, val) self.copy_files(test, test) class YAMLPathUpdater: def __init__(self, yaml_file): 初始化 YAMLPathUpdater 类 :param yaml_file: YAML 文件路径 self.yaml_file yaml_file def update_path(self, new_path): 更新 YAML 文件中的 path 字段为新的路径只修改 path 字段 :param new_path: 要更新的路径 try: # 逐行读取文件 with open(self.yaml_file, r) as file: lines file.readlines() # 遍历文件的每一行寻找 path 字段 with open(self.yaml_file, w) as file: for line in lines: if line.strip().startswith(path:): # 找到 path 字段并更新 file.write(fpath: {new_path}\n) print(f旧的 path 字段已更新为: {new_path}) else: # 其他行保持不变 file.write(line) print(fYAML 文件保存成功: {self.yaml_file}) except FileNotFoundError: print(f文件 {self.yaml_file} 未找到) except Exception as e: print(f更新 YAML 文件时发生错误: {e}) def run(self, new_path): 执行更新 path 字段并保存文件的流程 :param new_path: 新的路径 self.update_path(new_path)2.主函数auto_project.pyfrom tools import * # 使用示例 if __name__ __main__: # 初始化设置 # 文件夹路径和模型路径 img_path /home/luodehuan/workspace/test/test_picture # 给定客户数据路径 model_path /home/luodehuan/workspace/test/runs/train/yolov8s/New11C/WIOU2/weights/best.pt #yolov8x模型路径 dataset_path /home/luodehuan/workspace/test/output/datasets # 指定生成数据集文件夹路径 yaml_file_path /home/luodehuan/workspace/test/ultralytics-main/auto_project/data.yaml # 替换为你的 yaml 文件路径 # 1.对输入客户数据进行 预打标 # 在指定 dataset_path 生成数据集 # 实例化 ImagePredictor 类 predictor ImagePredictor(img_path, model_path) # 运行预测 labels_save_path predictor.run() # 实例化 DatasetSplitter 并运行数据集划分 dataset_splitter DatasetSplitter(img_path, labels_save_path, dataset_path) dataset_splitter.run() # 实例化 YAMLPathUpdater 类并执行更新操作 # 生成的数据集路径更新到微调模型训练的 data.yaml中 new_dataset_path dataset_path # 替换为你想要的新的输出路径 yaml_updater YAMLPathUpdater(yaml_file_path) yaml_updater.run(new_dataset_path) # 2.定制YOLOv8n finetune # 设置data.yaml # 开始微调训练 # 输出FineTune_Base模型 model1 YOLO(/home/luodehuan/workspace/test/ultralytics-main/ultralytics/cfg/models/v8/yolov8n.yaml) model1.load(/home/luodehuan/workspace/ultralytics-main/runs/train/yolov8n/New11C/640/weights/best.pt) # loading pretrain weights model1.train(datayaml_file_path, cacheFalse, imgsz640, epochs100, batch63, close_mosaic0, workers40, device0,1,2, optimizerSGD, # using SGD # patience0, # close earlystop # resumeTrue, # 断点续训,YOLO初始化时选择last.pt # ampFalse, # close amp # fraction0.2, projectruns/train/yolov8n, #MPCA nameNew11C, ) # 获取FineTune_Base模型 保存路径 FineTune_weight_path model1.trainer.wdir / best.pt # 3.用img_path 客户提供数据分别输入预设的大模型、Base模型、FineTune_Base模型进行验证 # 验证1 大模型yolov8x model2 YOLO(model_path) model2.val(datayaml_file_path, splittrain, imgsz640, batch16, # iou0.7, # rectFalse, # save_jsonTrue, # if you need to cal coco metrice projectruns/val, nameyolov8x, ) # 验证2 大模型yolov8n model3 YOLO(/home/luodehuan/workspace/ultralytics-main/runs/train/yolov8n/New11C/640/weights/best.pt) model3.val(datayaml_file_path, splittrain, imgsz640, batch16, # iou0.7, # rectFalse, # save_jsonTrue, # if you need to cal coco metrice projectruns/val, nameyolov8n, ) #验证3 FineTune模型 #对客户数据用FineTune模型进行验证得出验证指标 model4 YOLO(FineTune_weight_path) model4.val(datayaml_file_path, splittrain, imgsz640, batch16, # iou0.7, # rectFalse, # save_jsonTrue, # if you need to cal coco metrice projectruns/val, nameFineTune, )3.读取log文件并画柱形图import re import matplotlib.pyplot as plt def extract_values_for_plot(log_file_path): 提取日志文件中所有包含 all 的行的第十四个数值并返回以供绘图 indices [] # 用于存储读取次数 values14 [] # 用于存储第十四个值 try: with open(log_file_path, r, encodingutf-8) as file: count 0 # 计数器初始化 for line in file: if all in line: # 查找包含 all 的行 count 1 # 每次找到 all 时计数加一 # 使用正则表达式提取数值 values re.findall(r[\d.], line) if len(values) 14: # 确保有足够的数值 indices.append(count) values14.append(float(values[13])*100) # 第十四个值 except FileNotFoundError: print(f文件 {log_file_path} 未找到。) except Exception as e: print(f发生错误: {e}) return indices, values14 def plot_and_save_values(indices, values14, output_path, custom_labels): 绘制柱形图并保存 width 0.35 # 柱子宽度 x range(len(indices)) bars plt.bar(x, values14, width, label, colorm, alpha0.7) plt.xlabel() plt.ylabel(Values) plt.title(Comparison) plt.xticks(x, custom_labels) # 使用自定义的横坐标标签 plt.legend() # 在每个柱形条右下角显示对应的数值 for bar in bars: yval bar.get_height() # 获取柱子的高度 plt.text(bar.get_x() bar.get_width() / 2, yval , f{yval:.3f}%, hacenter, vabottom) # 显示数值 plt.tight_layout() # 保存柱形图 plt.savefig(output_path) print(f柱形图已保存到 {output_path}) plt.close() # 关闭图像以释放内存 # 示例用法 log_file_path /home/luodehuan/workspace/test/runs/log/Val_Results.log # 替换为你的日志文件路径 output_image_path /home/luodehuan/workspace/test/runs/log/bar_chart.png # 替换为你想保存的图像路径 custom_labels [, , ] # 自定义横坐标标签 indices, values14 extract_values_for_plot(log_file_path) plot_and_save_values(indices, values14, output_image_path, custom_labels)