Datawhale AI 夏令营第五期 CV竞赛方向Task1笔记--初识yolo模型
本期(第五期)是Datawhale AI 夏令营的最后一期,本次的活动是伴随着“2024“大运河杯”数据开发应用创新大赛——城市治理”活动一起进行开展进行的。
一、赛题简介
1.赛题目标
开发一套智能识别系统,能够自动检测和分类城市管理中的违规行为。该系统应利用先进的图像处理和计算机视觉技术,通过对摄像头捕获的视频进行分析,自动准确识别违规行为,并及时向管理部门发出告警,以实现更高效的城市管理。
2.赛题类型
本赛题为计算机视觉中的目标检测问题。
计算机视觉方向有:
1、图像分类
2、目标检测
3、图像分割
4、目标跟踪
5、图像滤波与降噪
6、图像增强
7、三维重建
8、图像检索。
目标检测
1.目标检测概念
目标检测(Object Detection)是计算机视觉领域中的一项核心技术,它旨在让计算机能够像人眼一样识别和定位图像中的物体。具体来说,它不仅需要识别出图像中有哪些对象,还要确定它们在图像中的位置(通常以边界框的形式表示)以及它们的类别。
目标检测的本质是对视觉信息进行解析,使计算机能够理解图像中的内容。这涉及到图像处理、特征提取、模式识别和机器学习等多个层面。在技术层面,目标检测要解决的问题包括但不限于:对象分类、位置估计、尺寸变化、遮挡处理、背景干扰以及实时处理能力等。
2. 主流解决方式
目前,基于深度学习的方法是目标检测领域的主流解决方式,它通常分为两类:
- 两阶段检测方法:这种方法先从图像中提取出潜在的对象候选区域,然后对这些区域进行详细的分类和边界框精调。代表模型包括R-CNN系列(如Fast R-CNN, Faster R-CNN)和基于区域的全卷积网络(如Mask R-CNN)。
- 单阶段检测方法:这种方法直接在图像上预测对象的类别和位置,速度通常更快,但在准确度上可能略逊于两阶段方法。代表模型包括YOLO(You Only Look Once)、SSD(Single Shot MultiBox Detector)和RetinaNet等。
近年来,Transformer架构也被引入到目标检测中,如DETR(Detection Transformer)模型,这标志着目标检测技术的一个新的发展方向。参考:
1.目标检测简介
3.赛题分析
3.1 问题定义:
根据给定的城管视频监控数据集,进行城市违规行为的检测。违规行为主要包括垃圾桶满溢、机动车违停、非机动车违停等。
选手需要能够从视频中分析并标记出违规行为,提供违规行为发生的时间和位置信息。
【机动车违停】
机动车在设有禁止停车标志、标线的路段停车,或在非机动车道、人行横道、施工地段等禁止停车的地方停车。具体包含以下:
1、无论有无禁停标志,机动车道禁止车辆停放;
2、距路口、桥梁50米以内禁止车辆停放;
3、距公交车站、消防栓、消防队、医院30米以内禁止使用上述设施以外的车辆停放;
4、禁止车辆双排停放、靠左侧停放、横向停放、逆向停放;
5、人行道仅允许在已设置的停车泊位内停车,禁止在停车泊位外停车;
6、在设有禁停标志、标线的路段,人行横道、施工路段,不得停车。
【非机动车违停】
非机动车(如自行车、电动车等)未按照规定停放在指定的非机动车停车泊位或停车线内,而是在非机动车禁停区域或未划定的区域(消防通道、盲道、非机动车停车区线外、机动车停车区等)随意停放。
【垃圾满溢】
生活垃圾收集容器内垃圾超过三分之二以上即为满溢。垃圾桶无法封闭、脏污且周边有纸屑、污渍、塑料、生活垃圾及杂物堆放。
【占道经营】
经营者占用城市道路、桥梁、城市广场等公共场所进行盈利性买卖商品或服务的行为。
3.1 数据集介绍
数据集包括包括视频数据与对应的JSON文件。
json文件的内容是每帧检测到的违规行为,包括以下字段:
- frame_id:违规行为出现的帧编号
- event_id:违规行为ID
- category:违规行为类别
- bbox:检测到的违规行为矩形框的坐标,[xmin,ymin,xmax,ymax]形式
标注示例如下:
[
{
"frame_id": 20,
"event_id": 1,
"category": "机动车违停",
"bbox": [200, 300, 280, 400]
},
{
"frame_id": 20,
"event_id": 2,
"category": "机动车违停",
"bbox": [600, 500, 720, 560]
},
{
"frame_id": 30,
"event_id": 3,
"category": "垃圾桶满溢",
"bbox": [400, 500, 600, 660]
}
]
3.2 提交格式
提交名为result
的文件夹,文件夹中包含每个视频对应的json结果文件,文件名与视频名对应。选手需要将文件夹打包成result.zip
进行上传。
json文件中包含了检测到的违规行为列表,若未检测到违规行为,则列表为空。
每个违规行为包含的字段如下:
- frame_id:违规行为出现的帧编号
- event_id:违规行为ID
- category:违规行为类别
- bbox:检测到的违规行为矩形框的坐标,[xmin,ymin,xmax,ymax]形式
- confidence:置信度
提交的json示例如下:
[
{
"frame_id": 20,
"event_id": 1,
"category": "机动车违停",
"bbox": [200, 300, 280, 500],
"confidence": 0.85
},
{
"frame_id": 20,
"event_id": 2,
"category": "垃圾桶满溢",
"bbox": [600, 500,720, 560],
"confidence": 0.90
},
{
"frame_id": 30,
"event_id": 3,
"category": "垃圾桶满溢",
"bbox": [400, 500, 500, 560],
"confidence": 0.78
}
]
3.3 评估指标
使用F1score、MOTA指标来评估模型预测结果。
对每个json文件得到两个指标的加权求和,最终得分为所有文件得分取均值。
注1:若真实目标框与预测框IOU大于0.5,则判定目标正确识别。若MOTA指标为负,则该类别精度得分为0。
注2:若该视频中没有某个类别的目标,则此类别计算均值时,忽略该视频。
评估指标补充:
- 精确率(Precision):精确率也叫查准率,是在识别出的物体中,正确的正向预测 (True Positive,TP) 所占的比率。
- 召回率 (Recall):召回率 (Recall)是正确识别出的物体占总物体数的比率。
- 准确率(Accuracy):准确率是指模型正确预测的样本数量占总样本数量的比例。
- F1分数(F1 Score):F1分数是精确率和召回率的调和平均值,它综合考虑了模型的查准率和查全率。
PR曲线:Precision-Recall曲线- AP( Average Precision ):PR曲线下的面积,综合考量了 recall 和 precision 的影响,反映了模型对某个类别识别的好坏。
- mAP ( mean Average Precision ):, 即各类别AP的平均值,衡量的是在所有类别上的平均好坏程度。
- 交并比(Intersection over Union,IoU)是一种常用的评估目标检测和图像分割模型性能的指标。IoU用于衡量模型预测的边界框(或分割结果)与真实标注之间的重叠程度。
- 其中,交集表示模型预测的边界框与真实边界框的交集区域的面积,并集表示两个边界框的并集区域的面积。
- IoU的取值范围在0到1之间,值越接近1表示模型的预测结果与真实情况重合程度越高,性能也越好。通常情况下,当IoU大于一个设定的阈值(如0.5或0.75)时,我们会将模型的预测结果视为正确的检测或分割。
二、BaseLine分析
1.数据集可视化
1.1 JSON标签读取
使用Visual Studio Code 查看:
1.加载和查看标注文件
train_anno = json.load(open('训练集(有标注第一批)/标注/45.json', encoding='utf-8')) # 加载训练集中的标注文件
train_anno[0], len(train_anno) # 输出标注数据的第一个条目和总数
- 加载一个标注文件 45.json,读取JSON格式的数据。
- 输出标注数据的第一个条目和标注条目的总数量。
2.读取并查看标注文件
json_data = pd.read_json('训练集(有标注第一批)/标注/45.json')
print(jason_data)
结果如图:
1.2 视频文件查看
- 记载并读取视频帧
video_path = '训练集(有标注第一批)/视频/45.mp4'
cap = cv2.VideoCapture(video_path)
while True:
# 读取下一帧
ret, frame = cap.read()
if not ret:
break
break
print(frame.shape)
print(int(cap.get(cv2.CAP_PROP_FRAME_COUNT)))
结果:
2. 绘制矩形框并保存
video_path = '训练集(有标注第一批)/视频/45.mp4'
cap = cv2.VideoCapture(video_path)
while True:
# 读取下一帧
ret, frame = cap.read()
if not ret:
break
break
print(frame.shape)
print(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)
cv2.imwrite('./a.jpg', frame[:,:,::-1])
结果:
2. 数据处理
1.建立存放数据集的文件夹
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: 违法经营
''')
2.检索训练集数据
train_annos = glob.glob('训练集(有标注第一批)/标注/*.json')
train_videos = glob.glob('训练集(有标注第一批)/视频/*.mp4')
train_annos.sort(); train_videos.sort();
category_labels = ["非机动车违停", "机动车违停", "垃圾桶满溢", "违法经营"]
3.将视频转换为jpg图片,保存json文件为txt文件
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
3.模型运行
1.下载模型权重
!wget http://mirror.coggle.club/yolo/yolov8n-v8.2.0.pt -O yolov8n.pt
2.下载文字设置以及框架
!mkdir -p ~/.config/Ultralytics/
!wget http://mirror.coggle.club/yolo/Arial.ttf -O ~/.config/Ultralytics/Arial.ttf
Ultralytics是一个开源的计算机视觉和深度学习框架,旨在简化训练、评估和部署视觉模型的过程。该框架提供了一系列流行的视觉模型,包括YOLOv5、YOLOv4、YOLOv3、YOLOv3-tiny、YOLOv5-tiny、EfficientDet、PAN、PP-YOLO等,并提供了训练、评估和推理的工具和实用程序。
Ultralytics框架的一些主要特点包括:
- 简单易用:Ultralytics提供了简洁的API和命令行工具,使用户可以轻松地训练、评估和部署视觉模型。
多种视觉模型支持:Ultralytics支持多种流行的目标检测和图像分割模型,用户可以根据自己的需求选择合适的模型进行训练和部署。- 高性能:Ultralytics框架基于PyTorch深度学习框架,具有优秀的性能和灵活性,同时提供了一系列优化和加速的功能,可加快训练和推理速度。
- 开源社区支持:Ultralytics是一个开源项目,拥有活跃的开发者社区,用户可以在GitHub上查看源代码、提交问题和贡献代码。
3.环境设置
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
import warnings
warnings.filterwarnings('ignore')
4.模型训练
from ultralytics import YOLO
model = YOLO("yolov8n.pt")
results = model.train(data="yolo-dataset/yolo.yaml", epochs=2, imgsz=1080, batch=16)
5.创建验证结果文件夹
category_labels = ["非机动车违停", "机动车违停", "垃圾桶满溢", "违法经营"]
if not os.path.exists('result/'):
os.mkdir('result')
6.模型推理
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)
三、初步总结
baseline的代码实现了一个完整的目标检测流程,从环境配置、数据预处理、模型训练、模型推理等。
使用YOLO进行视频的目标检测,需要将视频文件转换为jpg影像,再将图片文件输入网络模型进行检查。这期中主要涉及到不同格式的数据转换问题,需要清楚所使用的深度学习框架所需要的图像、标签输入格式。
BaseLine使用Ultralytics
框架,大大简化了模型的组织、模型的构建等过程。如果想要对模型进行改进,需要进一步了解框架的使用。
BaseLine教程十分易于上手,对于新手十分友好,即使没有了解过YOLO模型,也能够很快的完成模型训练和推理。