Datawhale AI夏令营第五期CV方向-城市管理违规行为智能识别-Task1

赛题解析

城市管理违规行为智能识别

初赛任务是根据给定的城管视频监控数据集,进行城市违规行为的检测。违规行为主要包括垃圾桶满溢、机动车违停、非机动车违停等。

选手需要能够从视频中分析并标记出违规行为,提供违规行为发生的时间和位置信息。

数据可视化

首先对现有数据可视化,直观地了解数据集。

import os
import cv2
import json
from PIL import Image, ImageDraw, ImageFont

# 文件夹路径
video_folder = r"D:\Illegal_behavior_detection\训练集(有标注第一批)\视频"
annotation_folder = r"D:\Illegal_behavior_detection\训练集(有标注第一批)\标注"
output_folder = r"D:\Illegal_behavior_detection\训练集(有标注第一批)\标注视频"

# 如果输出文件夹不存在,则创建
os.makedirs(output_folder, exist_ok=True)

# 获取所有视频文件
video_files = [f for f in os.listdir(video_folder) if f.endswith('.mp4')]
labeled_video_files = [f for f in os.listdir(output_folder) if f.endswith('.mp4')]
# 类别对应的颜色
category_colors = {
    "非机动车违停": (0, 0, 255),    # 红色
    "机动车违停": (0, 255, 255),    # 黄色
    "垃圾桶满溢": (255, 0, 0),      # 蓝色
    "违法经营": (0, 255, 0)         # 绿色
}

# 加载字体,指定一个支持中文的字体文件路径
font = ImageFont.truetype("simhei.ttf", 24) 

for video_file in video_files:
    if video_file in labeled_video_files: continue
    video_path = os.path.join(video_folder, video_file)
    annotation_path = os.path.join(annotation_folder, video_file.replace('.mp4', '.json'))
    
    # 读取视频
    cap = cv2.VideoCapture(video_path)
    if not cap.isOpened():
        print(f"无法打开视频文件: {video_file}")
        continue
    
    # 获取视频的宽、高、帧率
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps = cap.get(cv2.CAP_PROP_FPS)
    
    # 创建保存视频的对象
    output_path = os.path.join(output_folder, video_file)
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(output_path, fourcc, fps, (width, height))
    
    # 读取标注文件
    with open(annotation_path, 'r', encoding='utf-8') as f:
        annotations = json.load(f)
    
    frame_id_to_annotations = {}
    for annotation in annotations:
        frame_id = annotation['frame_id']
        if frame_id not in frame_id_to_annotations:
            frame_id_to_annotations[frame_id] = []
        frame_id_to_annotations[frame_id].append(annotation)
    
    frame_id = 0
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        
        if frame_id in frame_id_to_annotations:
            # 将OpenCV的图像转换为PIL图像
            frame_pil = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
            draw = ImageDraw.Draw(frame_pil)
            
            for ann in frame_id_to_annotations[frame_id]:
                bbox = ann['bbox']
                category = ann['category']
                
                # 获取类别对应的颜色
                color = category_colors.get(category, (255, 255, 255))  # 如果类别不在字典中,则默认白色
                
                # 绘制矩形框
                draw.rectangle([bbox[0], bbox[1], bbox[2], bbox[3]], outline=color, width=2)
                
                # 添加类别标签
                draw.text((bbox[0], bbox[1] - 25), category, font=font, fill=color)
            
            # 将PIL图像转换回OpenCV格式
            frame = cv2.cvtColor(np.array(frame_pil), cv2.COLOR_RGB2BGR)
        
        # 写入当前帧
        out.write(frame)
        
        frame_id += 1
    
    cap.release()
    out.release()

print("标注视频已成功生成并保存到输出文件夹。")

在观看视频中,发现部分数据标注严重错误,需要用标注软件进行修正。

标注格式转换

由于视频趋于同质化,且帧之间区别不大,将所有帧(60000+)用于训练没有意义,故进行抽帧,将数据集大小减小至6000。

for anno_path, video_path in zip(annos, videos):
    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
        if frame_idx % 10 == 0:
            img_height, img_width = frame.shape[:2]
            
            frame_anno = anno_df[anno_df['frame_id'] == frame_idx]
            cv2.imwrite(img_path + os.path.basename(anno_path).split('.')[0] + '_' + str(frame_idx) + '.jpg', frame)

            if len(frame_anno) != 0:
                with open(label_path + os.path.basename(anno_path).split('.')[0] + '_' + 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 or y_center > 1:
                            print(bbox)
                        up.write(f'{category_idx} {x_center} {y_center} {width} {height}\n')
        frame_idx += 1

标注清洗

针对标注严重错误的视频,使用X-Anylabeling重新进行标注,导出yolo标注文件。

模型训练

最后遵循教程进行训练并提交结果。

个人思考

  1. 标注有待优化。
  2. 训练集位置单一,测试集场景和训练集完全隔离,预估必须增加数据集训练。
  3. 如何区分正常停放车辆和违规停放车辆是个需要思考的问题。
相关推荐
张人玉29 分钟前
人工智能——猴子摘香蕉问题
人工智能
草莓屁屁我不吃33 分钟前
Siri因ChatGPT-4o升级:我们的个人信息还安全吗?
人工智能·安全·chatgpt·chatgpt-4o
小言从不摸鱼37 分钟前
【AI大模型】ChatGPT模型原理介绍(下)
人工智能·python·深度学习·机器学习·自然语言处理·chatgpt
AI科研视界1 小时前
ChatGPT+2:修订初始AI安全性和超级智能假设
人工智能·chatgpt
jiao000011 小时前
数据结构——队列
c语言·数据结构·算法
霍格沃兹测试开发学社测试人社区1 小时前
人工智能 | 基于ChatGPT开发人工智能服务平台
软件测试·人工智能·测试开发·chatgpt
小R资源1 小时前
3款免费的GPT类工具
人工智能·gpt·chatgpt·ai作画·ai模型·国内免费
迷迭所归处2 小时前
C++ —— 关于vector
开发语言·c++·算法
leon6253 小时前
优化算法(一)—遗传算法(Genetic Algorithm)附MATLAB程序
开发语言·算法·matlab
CV工程师小林3 小时前
【算法】BFS 系列之边权为 1 的最短路问题
数据结构·c++·算法·leetcode·宽度优先