0


Datawhale AI 夏令营(第五期)

Datawhale AI 夏令营---task1笔记

Datawhale是一个专注于数据科学与AI领域的开源组织,汇集了众多领域院校和知名企业的优秀学习者,聚合了一群有开源精神和探索精神的团队成员。 本期(第五期)是本次夏令营活动的最后一期,本次的活动是伴随着“2024“大运河杯”数据开发应用创新大赛——城市治理”活动一起进行开展进行的。

一、赛题内容

1、赛题目标

利用图像处理和计算机视觉技术 开发一套智能识别系统,自动检测和分类摄像头捕获的视频中,城市管理中的违规行为

2、社会价值

通过对摄像头捕获的视频进行分析,自动准确识别违规行为,并及时向管理部门发出告警,以实现更高效的城市管理。

3、赛事资源分析

初赛提供城管视频监控数据与对应违规行为标注。违规行为包括垃圾桶满溢、机动车违停、非机动车违停等。视频数据为mp4格式,标注文件为json格式,每个视频对应一个json文件。

  • frame_id:违规行为出现的帧编号
  • event_id:违规行为ID
  • category:违规行为类别
  • bbox:检测到的违规行为矩形框的坐标,[xmin,ymin,xmax,ymax]形式

4、评分规则

使用F1score、MOTA指标来评估模型预测结果。

对每个json文件得到两个指标的加权求和,最终得分为所有文件得分取均值。

注1:若真实目标框与预测框IOU大于0.5,则判定目标正确识别。若MOTA指标为负,则该类别精度得分为0。

注2:若该视频中没有某个类别的目标,则此类别计算均值时,忽略该视频。

二、baseline代码解析

按照手册指示,在终端中执行下面代码,从而得到数据集和代码等文件内容

apt install git-lfs
git lfs install
git clone https://www.modelscope.cn/datasets/Datawhale/AI_Camp5_baseline_CV.git

baseline解析如下:

1、导入所需要的库

import os, sys  # 导入操作系统和系统级操作库
import cv2, glob, json  # 导入计算机视觉、文件路径匹配和JSON处理库
import numpy as np  # 导入数值计算库
import pandas as pd  # 导入数据处理和分析库
import matplotlib.pyplot as plt  # 导入数据可视化库

2、安装必须的解压工具

!apt install zip unzip -y  # 安装zip和unzip用于处理压缩文件
!apt install unar -y  # 安装unar用于解压.zip文件

3、 下载和解压数据集

!wget "https://comp-public-prod.obs.cn-east-3.myhuaweicloud.com/dataset/2024/%E8%AE%AD%E7%BB%83%E9%9B%86%28%E6%9C%89%E6%A0%87%E6%B3%A8%E7%AC%AC%E4%B8%80%E6%89%B9%29.zip?AccessKeyId=583AINLNMLDRFK7CC1YM&Expires=1739168844&Signature=9iONBSJORCS8UNr2m/VZnc7yYno%3D"   -O 训练集\(有标注第一批\).zip  # 下载训练集压缩文件
!unar -q 训练集\(有标注第一批\).zip  # 使用“unar”解压训练集文件

4、下载和解压测试集

!wget "https://comp-public-prod.obs.cn-east-3.myhuaweicloud.com/dataset/2024/%E6%B5%8B%E8%AF%95%E9%9B%86.zip?AccessKeyId=583AINLNMLDRFK7CC1YM&Expires=1739168909&Signature=CRsB54VqOtrzIdUHC3ay0l2ZGNw%3D"   -O 测试集.zip  # 下载测试集压缩文件
!unar -q 测试集.zip  # 使用“unar”解压测试集文件

5、加载和查看标注文件

  • 加载一个标注文件 45.json,读取JSON格式的数据。
  • 输出标注数据的第一个条目和标注条目的总数量。
train_anno = json.load(open('训练集(有标注第一批)/标注/45.json', encoding='utf-8'))  # 加载训练集中的标注文件
train_anno[0], len(train_anno)  # 输出标注数据的第一个条目和总数

6、读取并查看标注文件

pd.read_json('训练集(有标注第一批)/标注/45.json')  # 使用Pandas读取标注文件,以表格形式查看

7、记载并读取视频帧

video_path = '训练集(有标注第一批)/视频/45.mp4'  # 指定视频文件路径
cap = cv2.VideoCapture(video_path)  # 打开视频文件
while True:
    ret, frame = cap.read()  # 读取视频的第一帧
    if not ret:
        break  # 如果没有读取到帧则跳出循环
    break  # 只读取一帧后跳出循环

8、查看视频帧的尺寸

frame.shape  # 查看视频帧的尺寸(高度、宽度、通道数)

9、获取视频的总帧数

int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 获取视频的总帧数

10、在帧上绘制边界框

bbox = [746, 494, 988, 786]  # 定义边界框的坐标
pt1 = (bbox[0], bbox[1])  # 边界框左上角坐标
pt2 = (bbox[2], bbox[3])  # 边界框右下角坐标
color = (0, 255, 0)  # 颜色为绿色
thickness = 2  # 线条粗细为2

cv2.rectangle(frame, pt1, pt2, color, thickness)  # 在帧上绘制边界框

11、显示处理后的帧

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)  # 将帧从BGR颜色空间转换为RGB
plt.imshow(frame)  # 使用matplotlib显示处理后的帧

12、创建用于YOLO数据集的文件夹结构

if not os.path.exists('yolo-dataset/'):  # 如果目录不存在则创建yolo-dataset文件夹
    os.mkdir('yolo-dataset/')
if not os.path.exists('yolo-dataset/train'):  # 如果目录不存在则创建train文件夹
    os.mkdir('yolo-dataset/train')
if not os.path.exists('yolo-dataset/val'):  # 如果目录不存在则创建val文件夹
    os.mkdir('yolo-dataset/val')

13、生成YOLO配置文件

dir_path = os.path.abspath('./') + '/'  # 获取当前目录的绝对路径
# 生成YOLO配置文件yolo.yaml
with open('yolo-dataset/yolo.yaml', 'w', encoding='utf-8') as up:
    up.write(f'''
path: {dir_path}/yolo-dataset/  # 数据集的根路径
train: train/  # 训练数据集路径
val: val/  # 验证数据集路径

names:
    0: 非机动车违停  # 类别0
    1: 机动车违停  # 类别1
    2: 垃圾桶满溢  # 类别2
    3: 违法经营  # 类别3
''')

14、获取训练数据的文件路径列表

train_annos = glob.glob('训练集(有标注第一批)/标注/*.json')  # 获取所有标注文件的路径
train_videos = glob.glob('训练集(有标注第一批)/视频/*.mp4')  # 获取所有视频文件的路径
train_annos.sort(); train_videos.sort()  # 对标注文件和视频文件路径进行排序

15、定义类别标签

category_labels = ["非机动车违停", "机动车违停", "垃圾桶满溢", "违法经营"]

16、生成YOLO训练集

# 生成YOLO训练集
for anno_path, video_path in zip(train_annos[:5], train_videos[:5]):  # 遍历前5个标注文件和视频文件
    print(video_path)  # 打印视频路径
    anno_df = pd.read_json(anno_path)  # 加载标注文件
    cap = cv2.VideoCapture(video_path)  # 打开视频文件
    frame_idx = 0 
    while True:
        ret, frame = cap.read()  # 读取视频帧
        if not ret:
            break  # 如果没有读取到帧则跳出循环

        img_height, img_width = frame.shape[:2]  # 获取帧的高度和宽度
        
        frame_anno = anno_df[anno_df['frame_id'] == frame_idx]  # 获取当前帧的标注信息
        cv2.imwrite('./yolo-dataset/train/' + anno_path.split('/')[-1][:-5] + '_' + str(frame_idx) + '.jpg', frame)  # 保存当前帧图像

        if len(frame_anno) != 0:  # 如果当前帧有标注信息
            with open('./yolo-dataset/train/' + anno_path.split('/')[-1][:-5] + '_' + str(frame_idx) + '.txt', 'w') as up:
                for category, bbox in zip(frame_anno['category'].values, frame_anno['bbox'].values):  # 遍历每个标注
                    category_idx = category_labels.index(category)  # 获取类别的索引
                    
                    x_min, y_min, x_max, y_max = bbox  # 解压边界框坐标
                    x_center = (x_min + x_max) / 2 / img_width  # 计算中心点x坐标
                    y_center = (y_min + y_max) / 2 / img_height  # 计算中心点y坐标
                    width = (x_max - x_min) / img_width  # 计算边界框宽度
                    height = (y_max - y_min) / img_height  # 计算边界框高度

                    if x_center > 1:
                        print(bbox)  # 如果中心点超出图像边界则打印边界框信息
                    up.write(f'{category_idx} {x_center} {y_center} {width} {height}\n')  # 将标注信息写入txt文件
        
        frame_idx += 1  # 处理下一帧

17、生成YOLO验证集

# 生成YOLO验证集
for anno_path, video_path in zip(train_annos[-3:], train_videos[-3:]):  # 遍历最后3个标注文件和视频文件
    print(video_path)  # 打印视频路径
    anno_df = pd.read_json(anno_path)  # 加载标注文件
    cap = cv2.VideoCapture(video_path)  # 打开视频文件
    frame_idx = 0 
    while True:
        ret, frame = cap.read()  # 读取视频帧
        if not ret:
            break  # 如果没有读取到帧则跳出循环

        img_height, img_width = frame.shape[:2]  # 获取帧的高度和宽度
        
        frame_anno = anno_df[anno_df['frame_id'] == frame_idx]  # 获取当前帧的标注信息
        cv2.imwrite('./yolo-dataset/val/' + anno_path.split('/')[-1][:-5] + '_' + str(frame_idx) + '.jpg', frame)  # 保存当前帧图像

        if len(frame_anno) != 0:  # 如果当前帧有标注信息
            with open('./yolo-dataset/val/' + anno_path.split('/')[-1][:-5] + '_' + str(frame_idx) + '.txt', 'w') as up:
                for category, bbox in zip(frame_anno['category'].values, frame_anno['bbox'].values):  # 遍历每个标注
                    category_idx = category_labels.index(category)  # 获取类别的索引
                    
                    x_min, y_min, x_max, y_max = bbox  # 解压边界框坐标
                    x_center = (x_min + x_max) / 2 / img_width  # 计算中心点x坐标
                    y_center = (y_min + y_max) / 2 / img_height  # 计算中心点y坐标
                    width = (x_max - x_min) / img_width  # 计算边界框宽度
                    height = (y_max - y_min) / img_height  # 计算边界框高度

                    up.write(f'{category_idx} {x_center} {y_center} {width} {height}\n')  # 将标注信息写入txt文件
        
        frame_idx += 1  # 处理下一帧

18、下载YOLOv8模型权重

!wget http://mirror.coggle.club/yolo/yolov8n-v8.2.0.pt   -O yolov8n.pt  # 下载YOLOv8预训练模型权重

19、相关设置(设置字体,设置CUDA设备,忽略警告信息)

!mkdir -p ~/.config/Ultralytics/  # 创建Ultralytics配置文件夹
!wget http://mirror.coggle.club/yolo/Arial.ttf   -O ~/.config/Ultralytics/Arial.ttf  # 下载Arial字体文件到Ultralytics目录
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"  # 设置使用的CUDA设备(GPU)
import warnings
warnings.filterwarnings('ignore')  # 忽略警告信息

20、训练YOLO模型

使用下载的YOLOv8模型权重,基于生成的训练集数据进行模型训练,训练2个epoch,图像输入尺寸为1080,批量大小为16。

from ultralytics import YOLO
model = YOLO("yolov8n.pt")  # 加载YOLOv8模型
results = model.train(data="yolo-dataset/yolo.yaml", epochs=2, imgsz=1080, batch=16)  # 训练模型,指定数据集、训练轮数、输入尺寸和批量大小

21、创建结果保存文件夹

category_labels = ["非机动车违停", "机动车违停", "垃圾桶满溢", "违法经营"]  # 再次定义类别标签

if not os.path.exists('result/'):  # 如果result文件夹不存在则创建
    os.mkdir('result')

22、使用训练好的YOLO模型对测试集视频进行目标检测

from ultralytics import YOLO
model = YOLO("runs/detect/train/weights/best.pt")  # 加载训练好的模型权重
import glob

for path in glob.glob('测试集/*.mp4'):  # 遍历测试集中的所有视频文件
    submit_json = []  # 初始化保存检测结果的列表
    results = model(path, conf=0.05, imgsz=1080,  verbose=False)  # 对视频进行目标检测,设置置信度阈值和输入尺寸
    for idx, result in enumerate(results):  # 遍历每一帧的检测结果
        boxes = result.boxes  # 获取边界框
        masks = result.masks  # 获取分割掩码
        keypoints = result.keypoints  # 获取关键点
        probs = result.probs  # 获取分类概率
        obb = result.obb  # 获取定向边界框

        if len(boxes.cls) == 0:
            continue  # 如果没有检测到任何物体,跳过当前帧
        
        xywh = boxes.xyxy.data.cpu().numpy().round()  # 获取边界框坐标并转换为numpy数组
        cls = boxes.cls.data.cpu().numpy().round()  # 获取类别索引并转换为numpy数组
        conf = boxes.conf.data.cpu().numpy()  # 获取置信度并转换为numpy数组
        for i, (ci, xy, confi) in enumerate(zip(cls, xywh, conf)):  # 遍历每个检测到的物体
            submit_json.append(
                {
                    'frame_id': idx,  # 帧ID
                    'event_id': i+1,  # 事件ID
                    'category': category_labels[int(ci)],  # 类别名称
                    'bbox': list([int(x) for x in xy]),  # 边界框坐标
                    "confidence": float(confi)  # 置信度
                }
            )

    with open('./result/' + path.split('/')[-1][:-4] + '.json', 'w', encoding='utf-8') as up:  # 保存检测结果为JSON文件
        json.dump(submit_json, up, indent=4, ensure_ascii=False)

23、清理和压缩结果文件

!\rm result/.ipynb_checkpoints/ -rf  # 删除不必要的文件夹
!\rm result.zip  # 删除旧的压缩文件
!zip -r result.zip result/  # 将结果文件夹压缩成ZIP文件

24、总结概括:

baseline的代码实现了一个完整的目标检测流程,从环境准备、数据加载与预处理、到模型训练与推理,以及最终的结果保存。首先,代码安装了必要的工具,并从指定的 URL 下载了训练集和测试集的压缩文件,随后解压这些文件以便使用。接着,代码通过

cv2

读取视频文件并提取视频帧,同时使用

pandas

读取 JSON 格式的标注文件,从中提取出目标的类别和边界框等信息。

在数据预处理阶段,代码将视频帧保存为图像文件,并基于标注信息生成与之对应的 YOLO 格式标注文件。这些图像和标注文件被分别组织并保存到训练集和验证集的目录中,为模型训练做准备。随后,代码下载了 YOLOv8 的预训练模型权重,并使用准备好的数据集进行模型训练。训练过程生成了经过优化的模型权重文件。

训练完成后,代码使用训练好的 YOLO 模型对测试集中的视频进行推理,对每一帧进行目标检测,并将检测结果(包括目标类别、边界框位置、置信度等)保存为 JSON 文件。最后,代码对生成的检测结果进行整理,删除不必要的文件,并将结果打包为一个压缩文件,便于后续的处理和提交。整个流程自成一体,涵盖了从数据获取到结果输出的完整过程,适用于YOLOv8的目标检测任务。

三、初次测试结果

四、进阶尝试

标签: 人工智能

本文转载自: https://blog.csdn.net/weixin_52520094/article/details/141463281
版权归原作者 小萌新加速中 所有, 如有侵权,请联系我们删除。

“Datawhale AI 夏令营(第五期)”的评论:

还没有评论