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指标来评估模型预测结果。
img

对每个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 视频文件查看

  1. 记载并读取视频帧
	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模型,也能够很快的完成模型训练和推理。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值