2024“大运河杯”数据开发应用创新大赛——城市治理 #AI夏令营 #Datawhale

1.相关学习资料

赛事链接:https://www.marsbigdata.com/competition/details?id=3839107548872
DataWhale参考资料:https://linklearner.com/activity/16/16/49

2.了解比赛

用YOLO去进行违规行为检测识别
开发智能识别系统,自动检测和分类,摄像头捕获的视频中的城市管理中的违规行为

3.数据集

提供mp4视频数据和标注的JSON文件

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

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

4.评分规则介绍

F1score
F1 Score(F1值)是一个常用的评估分类模型性能的指标,尤其是在二分类问题中。它是精确率(Precision)和召回率(Recall)的调和平均数
取值范围是从 0 到 1,其中 1 表示最佳性能,0 表示最差性能。当模型既需要有高的精确率也需要有高的召回率时,F1 Score 是一个非常有用的指标
名词解释
精确率(Precision):在所有被模型预测为正类的样本中,实际为正类的比例。
召回率(Recall):在所有实际为正类的样本中,被模型正确预测为正类的比例。
TP(True Positives):真正例,即模型正确预测为正类的数量
FP(False Positives):假正例,即模型错误地将负类预测为正类的数量。
FN(False Negatives):假反例,即模型错误地将正类预测为负类的数量。
在这里插入图片描述在这里插入图片描述

分数越高越好使用F1score、MOTA指标来评估模型预测结果。
在这里插入图片描述

MOTA(Multiple Object Tracking Accuracy)是多目标跟踪精度的指标,用于评估计算机视觉系统或机器人系统中对多个物体进行跟踪的准确性。它是一个综合性的度量标准,考虑了误报(False Positives, FP)、漏检(False Negatives, FN)、ID Switches(身份切换错误)等因素。
GT 是 Ground Truth 的缩写,表示真实情况下的标签或位置信息。
FN 是 False Negative 的缩写,表示未检测到但实际上存在的目标数量。
FP 是 False Positive 的缩写,表示被错误地检测为目标但实际上不存在的对象的数量。
IDSW 是 Identity Switch 的缩写,表示由于跟踪算法的错误而导致的目标身份混淆次数。
MOTA 值越接近于 1,则说明跟踪系统的性能越好;反之,如果值越小甚至为负数,则说明跟踪系统的性能较差

对每个json文件得到两个指标的加权求和,最终得分为所有文件得分取均值。
注1:若真实目标框与预测框IOU大于0.5,则判定目标正确识别。若MOTA指标为负,则该类别精度得分为0。
注2:若该视频中没有某个类别的目标,则此类别计算均值时,忽略该视频。

5.任务提交格式说明

39个test.json文件组成的压缩包
以下是一个JSON中识别结果的例子
{
“frame_id”: 0,
“event_id”: 1,
“category”: “机动车违停”,
“bbox”: [
1540,
435,
1920,
755
],
“confidence”: 0.10815975815057755
},

初赛需提交:
初赛任务是根据给定的城管视频监控数据集,进行城市违规行为的检测。违规行为主要包括垃圾桶满溢、机动车违停、非机动车违停等。
选手需要能够从视频中分析并标记出违规行为,提供违规行为发生的时间和位置信息。

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

6.YOLO

将目标检测任务视为一个单一的回归问题: 在传统的两阶段方法中,首先会生成候选区域(Region Proposals),然后对每个候选区域分别进行分类和边界框回归。而YOLO则简化了这个过程,直接在一个网络中完成目标检测的所有任务。

YOLO模型的核心思想:
1.单一回归问题:在YOLO模型中,输入图像被分割成一个网格,并且每个网格单元负责预测其内部的物体及其边界框(Bounding Boxes)和类别概率。这种设计使得整个检测过程可以被视为一个端到端的回归问题,即从输入图像到输出边界框坐标和类别标签的直接映射。
2.全局信息利用:由于YOLO模型在整个图像上运行一次,它可以利用图像的全局信息来进行检测,这有助于提高小物体和密集物体的检测能力。
3.实时性:YOLO的设计目标之一是实现高速的实时检测。通过减少计算量和简化模型结构,YOLO可以在保证一定精度的情况下实现实时的处理速度。
4.端到端训练:YOLO模型可以使用端到端的方式进行训练,这意味着不需要预先生成候选区域,而是直接从原始图像学习到最终的检测结果
5.统一框架:YOLO将分类和定位的任务结合在一起,避免了候选区域生成阶段,从而简化了整体架构并提高了效率。

YOLO,全称为“You Only Look Once”(你只看一眼),是一种流行的实时目标检测系统,由Joseph Redmon等人在2015年提出。YOLO模型的核心思想是将目标检测任务视为一个单一的回归问题,通过一个卷积神经网络(CNN)直接从图像像素到边界框坐标和类别概率的映射。YOLO模型经过了多次迭代,包括YOLOv2(YOLO9000)、YOLOv3和YOLOv4等版本,每个版本都在性能和速度上有所提升,同时也引入了一些新的技术,如更深的网络结构、更好的锚框机制、多尺度特征融合等。

7.YOLO模型需要什么训练格式?

每张图像一个文本文件
类别索引+边界框中心点相对于图像宽度和高度的比例+边界框的宽度和高度相对于图像宽度和高度的比例

YOLO使用的标注格式是每张图像一个文本文件,文件名与图像文件名相对应。
文本文件中每一行对应一个边界框,
格式为: <x_center> <y_center> 。
其中,是类别索引,
<x_center>和<y_center>是边界框中心点相对于图像宽度和高度的比例,
和是边界框的宽度和高度相对于图像宽度和高度的比例。

在这里插入图片描述

8.如何训练YOLO模型?

Ultraalytics 是一个提供多种计算机视觉模型的库,包括 YOLO 系列。

9.代码解读

代码做了啥?
主要用于使用YOLOv8模型进行视频目标检测任务。
首先,代码下载并解压了包含标注数据的训练集和测试集
接着,将训练视频帧提取并与标注数据结合,生成符合YOLO格式的训练数据集
之后,代码下载并加载YOLOv8的预训练模型,并使用生成的训练数据集进行模型训练。
训练完成后,代码使用训练得到的最佳模型对测试集视频进行目标检测,并将检测结果保存为JSON文件
最后,代码将结果文件打包压缩,以便提交或进一步处理。

代码做了啥(细节版)?
这段代码实现了一个完整的YOLOv8目标检测任务的流程,包括数据准备、模型训练、目标检测和结果保存。以下是更详细的分步骤总结:

  1. 环境设置与依赖安装
    代码首先安装了一些必要的Python库,包括OpenCV(用于图像和视频处理)、Pandas(用于数据处理)、Matplotlib(用于绘图)和Ultralytics(YOLO库)。此外,还安装了一些系统工具,如zip、unzip和unar,用于处理压缩文件。

  2. 数据下载与解压
    代码从指定的URL下载了两个数据集——标注好的训练集和未标注的测试集。下载完成后,使用unar命令解压这两个数据集,解压后的文件包括训练视频、标注文件和测试视频。

  3. 读取和检查标注数据
    代码使用json.load函数读取了一个训练集的标注文件,并通过Pandas库的read_json函数展示了标注数据的结构。随后,代码利用OpenCV打开相应的视频文件,读取视频的第一帧,并检查该帧的大小(即分辨率)。这些步骤有助于理解标注文件的内容及其与视频帧的对应关系。

  4. 生成YOLO格式的数据集
    代码创建了一个新的目录结构,用于存储按照YOLO格式生成的训练和验证数据。接着,代码编写了一个配置文件yolo.yaml,指定了训练集和验证集的路径,并定义了目标检测任务中的类别标签。

    随后,代码读取了训练集中的前五个标注文件和对应的视频文件,并逐帧读取视频,同时根据标注文件的信息生成相应的图片和标注文件,保存到YOLO格式的训练集目录中。同样的操作也应用于最后三个标注文件和视频文件,用于生成验证集。

  5. 模型训练
    代码下载并配置了YOLOv8的预训练权重文件,并加载了Ultralytics库的YOLO模型。在训练模型之前,代码设置了GPU设备和忽略警告信息。然后,代码调用model.train函数,使用生成的YOLO格式数据集进行模型训练。训练参数包括训练轮数(epochs)、图像大小(imgsz)和批量大小(batch)。

  6. 目标检测
    在训练完成后,代码加载了训练过程中保存的最佳模型权重文件,并使用该模型对测试集中的视频进行目标检测。代码逐帧处理每个视频,并从检测结果中提取边界框、类别和置信度信息。然后,将这些信息按照指定格式保存为JSON文件。

  7. 结果保存与压缩
    代码创建了一个目录用于保存检测结果,并将这些结果文件压缩为一个ZIP文件,便于提交或进一步分析。在生成ZIP文件之前,代码还删除了不必要的文件或目录,如IPython的检查点目录和以前生成的压缩文件。

总结
这段代码实现了从数据准备到模型训练,再到目标检测和结果保存的完整工作流程。通过使用YOLOv8模型,代码能够有效地处理视频中的目标检测任务,并生成符合指定格式的检测结果文件,最终打包压缩以便进一步使用。这种完整的流程可以用于各种计算机视觉任务,特别是需要处理视频数据并进行目标检测的场景。

# 安装必要的Python库,包括OpenCV(用于处理视频和图像)、Pandas(用于数据操作)、Matplotlib(用于绘图)、Ultralytics(用于YOLO模型)。
/opt/miniconda/bin/pip install opencv-python pandas matplotlib ultralytics

# 导入所需的Python标准库模块。
import os, sys  # os和sys模块用于操作系统和Python运行环境的功能。
import cv2, glob, json  # cv2用于图像和视频处理,glob用于文件路径匹配,json用于处理JSON数据。
import numpy as np  # numpy用于数值计算和数组操作。
import pandas as pd  # pandas用于数据操作,特别是处理数据表。
import matplotlib.pyplot as plt  # matplotlib.pyplot用于绘制图表和显示图像。

# 使用系统包管理器安装zip、unzip和unar工具,用于处理压缩文件。
!apt install zip unzip -y
!apt install unar -y

# 从远程服务器下载训练集压缩文件,并将其重命名为“训练集(有标注第一批).zip”。
!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

# 下载测试集压缩文件,并将其重命名为“测试集.zip”。
!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

# 加载一个JSON文件中的训练集标注数据,这里加载的是第45个视频的标注文件。
train_anno = json.load(open('训练集(有标注第一批)/标注/45.json', encoding='utf-8'))
# 显示第一个标注信息以及标注信息的总长度。
train_anno[0], len(train_anno)

# 使用Pandas读取并显示JSON格式的标注数据。
pd.read_json('训练集(有标注第一批)/标注/45.json')

# 指定要处理的视频文件路径。
video_path = '训练集(有标注第一批)/视频/45.mp4'
# 使用OpenCV打开视频文件。
cap = cv2.VideoCapture(video_path)
while True:
    # 读取视频中的下一帧。
    ret, frame = cap.read()
    if not ret:
        # 如果没有读取到帧(视频结束),则退出循环。
        break
    # 只读取第一帧后退出循环。
    break    
# 显示读取的帧的形状(高度、宽度和通道数)。
frame.shape

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

# 定义一个边界框的坐标:[左上角x, 左上角y, 右下角x, 右下角y]。
bbox = [746, 494, 988, 786]

# 定义边界框的左上角坐标点。
pt1 = (bbox[0], bbox[1])
# 定义边界框的右下角坐标点。
pt2 = (bbox[2], bbox[3])

# 定义矩形的颜色(绿色)和线条的粗细。
color = (0, 255, 0) 
thickness = 2  # 线条粗细

# 在图像上绘制边界框矩形。
cv2.rectangle(frame, pt1, pt2, color, thickness)

# 将图像从BGR格式转换为RGB格式,以便使用Matplotlib显示。
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 使用Matplotlib显示带有矩形框的图像。
plt.imshow(frame)

# 检查目录是否存在,如果不存在则创建“yolo-dataset/”目录。
if not os.path.exists('yolo-dataset/'):
    os.mkdir('yolo-dataset/')
# 如果训练集目录不存在,则创建。
if not os.path.exists('yolo-dataset/train'):
    os.mkdir('yolo-dataset/train')
# 如果验证集目录不存在,则创建。
if not os.path.exists('yolo-dataset/val'):
    os.mkdir('yolo-dataset/val')

# 获取当前目录的绝对路径,并存储在dir_path变量中。
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: 非机动车违停
    1: 机动车违停
    2: 垃圾桶满溢
    3: 违法经营
''')

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

# 定义类别标签列表,包含四种类别。
category_labels = ["非机动车违停", "机动车违停", "垃圾桶满溢", "违法经营"]

# 处理前5个标注文件和视频文件。
for anno_path, video_path in zip(train_annos[:5], train_videos[:5]):
    print(video_path)  # 输出视频文件路径。
    # 使用Pandas读取当前的标注文件。
    anno_df = pd.read_json(anno_path)
    # 使用OpenCV打开当前的视频文件。
    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]
        # 将当前帧保存为JPEG格式文件。
        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
                    y_center = (y_min + y_max) / 2 / img_height
                    width = (x_max - x_min) / img_width
                    height = (y_max - y_min) / img_height

                    # 检查中心点的x坐标是否大于1(数据是否有问题)。
                    if x_center > 1:
                        print(bbox)  # 输出边界框信息以便调试。
                    # 将类别索引和归一化后的边界框信息写入文本文件中。
                    up.write(f'{category_idx} {x_center} {y_center} {width} {height}\n')
        
        frame_idx += 1  # 增加帧索引以处理下一帧。

# 处理最后3个标注文件和视频文件,过程与前5个文件类似,只是保存的目录不同(验证集目录)。
for anno_path, video_path in zip(train_annos[-3:], train_videos[-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
                    y_center = (y_min + y_max) / 2 / img_height
                    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')
        
        frame_idx += 1

# 下载YOLOv8模型的预训练权重文件,并将其重命名为“yolov8n.pt”。
!wget http://mirror.coggle.club/yolo/yolov8n-v8.2.0.pt -O yolov8n.pt

# 创建Ultralytics的配置目录,并下载字体文件。
!mkdir -p ~/.config/Ultralytics/
!wget http://mirror.coggle.club/yolo/Arial.ttf -O ~/.config/Ultralytics/Arial.ttf

# 设置环境变量,指定使用的GPU设备。
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

# 忽略警告信息。
import warnings
warnings.filterwarnings('ignore')

# 导入YOLO库,加载预训练的YOLOv8模型,并开始训练。
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
# 使用刚刚生成的YOLO数据集进行训练,指定训练的参数,如epochs(训练轮数)、imgsz(图像大小)和batch(批量大小)。
results = model.train(data="yolo-dataset/yolo.yaml", epochs=2, imgsz=1080, batch=16)

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

# 如果result目录不存在,则创建。
if not os.path.exists('result/'):
    os.mkdir('result')

# 导入YOLO库并加载在训练中得到的最佳模型。
from ultralytics import YOLO
model = YOLO("runs/detect/train/weights/best.pt")
import glob

# 对测试集中的每个视频进行处理。
for path in glob.glob('测试集/*.mp4'):
    submit_json = []  # 初始化存放检测结果的JSON列表。
    # 使用YOLO模型对视频进行预测,设置置信度阈值为0.05,并禁止详细输出。
    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()
        cls = boxes.cls.data.cpu().numpy().round()
        conf = boxes.conf.data.cpu().numpy()
        # 遍历每个检测结果,将其添加到提交的JSON列表中。
        for i, (ci, xy, confi) in enumerate(zip(cls, xywh, conf)):
            submit_json.append(
                {
                    'frame_id': idx,  # 帧号。
                    'event_id': i+1,  # 事件编号。
                    'category': category_labels[int(ci)],  # 检测到的类别名称。
                    'bbox': list([int(x) for x in xy]),  # 边界框的坐标。
                    "confidence": float(confi)  # 检测置信度。
                }
            )

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

# 删除IPython检查点文件(如果有)。
!\rm result/.ipynb_checkpoints/ -rf
# 删除以前生成的压缩文件(如果有)。
!\rm result.zip
# 将结果目录压缩为result.zip文件。
!zip -r result.zip result/

官方代码部分

!/opt/miniconda/bin/pip install opencv-python pandas matplotlib ultralytics
import os, sys
import cv2, glob, json
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
!apt install zip unzip -y
!apt install unar -y

!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

!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

train_anno = json.load(open('训练集(有标注第一批)/标注/45.json', encoding='utf-8'))
train_anno[0], len(train_anno)

pd.read_json('训练集(有标注第一批)/标注/45.json')

video_path = '训练集(有标注第一批)/视频/45.mp4'
cap = cv2.VideoCapture(video_path)
while True:
    # 读取下一帧
    ret, frame = cap.read()
    if not ret:
        break
    break    
frame.shape

int(cap.get(cv2.CAP_PROP_FRAME_COUNT))	

bbox = [746, 494, 988, 786]

pt1 = (bbox[0], bbox[1])
pt2 = (bbox[2], bbox[3])

color = (0, 255, 0) 
thickness = 2  # 线条粗细

cv2.rectangle(frame, pt1, pt2, color, thickness)

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
plt.imshow(frame)

if not os.path.exists('yolo-dataset/'):
    os.mkdir('yolo-dataset/')
if not os.path.exists('yolo-dataset/train'):
    os.mkdir('yolo-dataset/train')
if not os.path.exists('yolo-dataset/val'):
    os.mkdir('yolo-dataset/val')

dir_path = os.path.abspath('./') + '/'

# 需要按照你的修改path
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: 非机动车违停
    1: 机动车违停
    2: 垃圾桶满溢
    3: 违法经营
''')

train_annos = glob.glob('训练集(有标注第一批)/标注/*.json')
train_videos = glob.glob('训练集(有标注第一批)/视频/*.mp4')
train_annos.sort(); train_videos.sort();

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

for anno_path, video_path in zip(train_annos[:5], train_videos[: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
                    y_center = (y_min + y_max) / 2 / img_height
                    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')
        
        frame_idx += 1

for anno_path, video_path in zip(train_annos[-3:], train_videos[-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
                    y_center = (y_min + y_max) / 2 / img_height
                    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')
        
        frame_idx += 1
!wget http://mirror.coggle.club/yolo/yolov8n-v8.2.0.pt -O yolov8n.pt

!mkdir -p ~/.config/Ultralytics/
!wget http://mirror.coggle.club/yolo/Arial.ttf -O ~/.config/Ultralytics/Arial.ttf

import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"

import warnings
warnings.filterwarnings('ignore')


from ultralytics import YOLO
model = YOLO("yolov8n.pt")
results = model.train(data="yolo-dataset/yolo.yaml", epochs=2, imgsz=1080, batch=16)

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

if not os.path.exists('result/'):
    os.mkdir('result')

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  # Boxes object for bounding box outputs
        masks = result.masks  # Masks object for segmentation masks outputs
        keypoints = result.keypoints  # Keypoints object for pose outputs
        probs = result.probs  # Probs object for classification outputs
        obb = result.obb  # Oriented boxes object for OBB outputs

        if len(boxes.cls) == 0:
            continue
        
        xywh = boxes.xyxy.data.cpu().numpy().round()
        cls = boxes.cls.data.cpu().numpy().round()
        conf = boxes.conf.data.cpu().numpy()
        for i, (ci, xy, confi) in enumerate(zip(cls, xywh, conf)):
            submit_json.append(
                {
                    'frame_id': idx,
                    'event_id': i+1,
                    '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.dump(submit_json, up, indent=4, ensure_ascii=False)

!\rm result/.ipynb_checkpoints/ -rf
!\rm result.zip
!zip -r result.zip result/

10.提高成绩办法之一

# 使用刚刚生成的YOLO数据集进行训练,指定训练的参数,如epochs(训练轮数)、imgsz(图像大小)和batch(批量大小)。
results = model.train(data="yolo-dataset/yolo.yaml", epochs=2, imgsz=1080, batch=16)

# 增加数据多样性,提高模型泛化能力,修改为
results = model.train(data="yolo-dataset/yolo.yaml", epochs=50, imgsz=1080, batch=32, lr=0.001, augment=True)
  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值