datawhale X AI夏令营 CV竞赛学习活动task1

运行task1baseline

下载baseline相关文件
运行前三段代码

如上图左边是运行后生成的文件,第一行代码是下载相关python三方库 opencv-python、pandas、matplotlib、ultralytics

第二行代码是导入相关库

第三行代码是下载压缩文件zip、解压文件unzip和unar,

下图是下载虚拟机的相关文件

然后是下载训练集与测试集的数据资料共计2.8G

训练集与测试集下载

数据读取

train_anno = json.load(open('训练集(有标注第一批)/标注/45.json', encoding='utf-8'))  #加载一个JSON文件,并访问该文件中的数据

train_anno[0], len(train_anno)  # 访问 train_anno 中的第一个元素,使用 len() 函数计算 train_anno 的长度。对于列表,返回元素的数量;对于字典,返回键值对的数量
数据读取
pd.read_json('训练集(有标注第一批)/标注/45.json')  # 使用了 pandas 库中的 read_json 方法来读取一个 JSON 文件

video_path = '训练集(有标注第一批)/视频/45.mp4'
cap = cv2.VideoCapture(video_path) #cv2.VideoCapture 方法创建一个 VideoCapture 对象,并将视频文件路径作为参数传递给构造函数。cap 对象用于与视频文件进行交互,读取视频帧。
while True:  # 循环语句
    # 读取下一帧
    ret, frame = cap.read()  # 调用 cap.read() 方法读取视频中的下一帧。cap.read() 方法返回一个元组,第一个元素 ret 是布尔值,表示读取是否成功;第二个元素 frame 是读取到的图像帧,通常是一个 NumPy 数组。
    if not ret: # 检查 ret 的值。如果 ret 为 False,则表示已经到达视频的末尾,无法再读取新的帧。
        break # 如果 ret 为 False,则执行 break 语句,跳出 while 循环。
    break    # 这个 break 语句会立即终止循环,无论 ret 的值是什么。这意味着在读取第一帧之后就会退出循环
frame.shape  #视频帧是 1080x1920 的彩色图像
# (1080, 1920, 3)


# 获取视频文件中的总帧数,并将其转换为整数类型
int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

# 读取到frame
bbox = [746, 494, 988, 786] # 这四个值分别代表矩形框的左上角坐标 (746, 494) 和右下角坐标 (988, 786)
# pt1 和 pt2 分别定义了矩形框的两个对角点坐标。
pt1 = (bbox[0], bbox[1]) # pt1 是左上角的坐标 (746, 494)。
pt2 = (bbox[2], bbox[3]) # pt2 是右下角的坐标 (988, 786)

color = (0, 255, 0) # 定义了绘制矩形框的颜色,绿色
thickness = 2  # 定义了矩形框边界的线条粗细

cv2.rectangle(frame, pt1, pt2, color, thickness) # cv2.rectangle 方法在图像 frame 上绘制一个矩形框

frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # cv2.cvtColor 方法将图像 frame 从 BGR 色彩空间转换为 RGB 色彩空间
# OpenCV 默认使用 BGR 色彩空间,而 Matplotlib 默认使用 RGB 色彩空间
plt.imshow(frame) # 使用 Matplotlib 的 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 和 train_videos 两个列表中的元素进行排序
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) # pandas 库中的 read_json 函数读取标注文件(JSON 格式),并将数据加载到一个 DataFrame 中,方便后续处理。
    cap = cv2.VideoCapture(video_path) # 使用 cv2.VideoCapture 创建一个视频捕获对象,用于读取视频文件。
    frame_idx = 0 # 初始化一个变量 frame_idx 用于记录当前帧的索引。
    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] # 从标注 DataFrame 中筛选出当前帧的标注信息。假设标注文件中的 frame_id 列包含了对应帧的索引。
        # 将当前帧保存为图片文件。文件名由标注文件名(去掉 .json 扩展名)和帧索引组成,保存在 ./yolo-dataset/train/ 目录下
        cv2.imwrite('./yolo-dataset/train/' + anno_path.split('/')[-1][:-5] + '_' + str(frame_idx) + '.jpg', frame)

        # 如果当前帧有标注信息,则打开一个标签文件用于写入。文件名与图片文件名相同,但扩展名为 .txt
        if len(frame_anno) != 0:
            with open('./yolo-dataset/train/' + anno_path.split('/')[-1][:-5] + '_' + str(frame_idx) + '.txt', 'w') as up:
                # 遍历当前帧的所有标注信息,将标注框的坐标转换为 YOLO 格式所需的归一化坐标,并写入标签文件。
                for category, bbox in zip(frame_anno['category'].values, frame_anno['bbox'].values):
                    # category_idx 为类别索引,通过查找 category_labels 列表获得。
                    category_idx = category_labels.index(category)
                    # bbox 包含标注框的四个坐标点,通过计算获得中心点坐标、宽度和高度。
                    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_center 大于 1,则打印 bbox 用于调试
                    if x_center > 1:
                        print(bbox)
                    # 将转换后的坐标写入标签文件
                    up.write(f'{category_idx} {x_center} {y_center} {width} {height}\n')
        
        # 更新帧索引,以便读取下一帧
        frame_idx += 1

然后下载YOLO的yolov8n.pt和Arial.ttf

# 导入os模块
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
# 导入 Python 的 warnings 模块
import warnings
warnings.filterwarnings('ignore')

# 从 ultralytics 库中导入 YOLO 类
from ultralytics import YOLO
# 创建一个 YOLO 模型实例,加载预训练的 yolov8n.pt 模型
model = YOLO("yolov8n.pt")
# 使用 model.train() 方法来训练模型
results = model.train(data="yolo-dataset/yolo.yaml", epochs=2, imgsz=1080, batch=16)
category_labels = ["非机动车违停", "机动车违停", "垃圾桶满溢", "违法经营"]
# 检查当前目录下是否存在名为 'result/' 的目录.如果不存在则创建一个名为 'result/' 的目录
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,用于存储每个视频文件的检测结果。
    submit_json = []
    # 使用 model 对视频文件 path 进行目标检测
    # 设置置信度阈值为 0.05,低于这个阈值的检测结果将被过滤掉
    # 设置是否在控制台输出详细的检测信息,默认为 False。
    results = model(path, conf=0.05, imgsz=1080,  verbose=False)
    # 使用 enumerate 函数遍历检测结果中的每一帧,idx 是当前帧的索引,result 是该帧的检测结果
    for idx, result in enumerate(results):
        boxes = result.boxes  # 包含边界框信息的对象
        masks = result.masks  # 包含分割掩码信息的对象
        keypoints = result.keypoints  # 包含关键点信息的对象
        probs = result.probs  # 包含分类概率信息的对象
        obb = result.obb  # 包含定向边界框信息的对象

        # 检查 boxes.cls 的长度,如果为 0,则表示当前帧没有检测到任何目标,跳过当前帧继续处理下一个帧。
        if len(boxes.cls) == 0:
            continue
        
        # 提取边界框的坐标信息 xywh、类别索引 cls 和置信度 conf。
        xywh = boxes.xyxy.data.cpu().numpy().round() # xywh 是一个包含边界框坐标的 NumPy 数组。
        cls = boxes.cls.data.cpu().numpy().round() # cls 是一个包含类别索引的 NumPy 数组。
        conf = boxes.conf.data.cpu().numpy() # conf 是一个包含置信度的 NumPy 数组。
        # 遍历每个检测结果,ci 是类别索引,xy 是边界框坐标,confi 是置信度。
        for i, (ci, xy, confi) in enumerate(zip(cls, xywh, conf)):
            # 检测结果以字典的形式添加到 submit_json 列表中。
            submit_json.append(
                {
                    'frame_id': idx, # 当前帧的索引。
                    'event_id': i+1, # 当前检测事件的 ID,从 1 开始计数。
                    'category': category_labels[int(ci)], # 类别名称,通过 category_labels 列表获取。
                    'bbox': list([int(x) for x in xy]), # 边界框坐标,转换为整数。
                    "confidence": float(confi)  # 置信度,转换为浮点数。
                }
            )

    # 将 submit_json 列表写入 JSON 文件。
    # path.split('/')[-1][:-4]:获取视频文件名(去掉 .mp4 扩展名)。
    # ./result/:指定保存结果的目录。
    with open('./result/' + path.split('/')[-1][:-4] + '.json', 'w', encoding='utf-8') as up:
        # 将列表写入 JSON 文件,indent=4 用于美化输出,ensure_ascii=False 用于保留非 ASCII 字符。
        json.dump(submit_json, up, indent=4, ensure_ascii=False)

最后就是保存结果并压缩result到result.zip,然后下载到本地

result文件夹

提分方法

这个本人不确定这个方法是不是正确的哈

就是可以修改在第十六段代码的,yolov8n.pt的模型,或者修改epochs=2的参数

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)

将改为epochs=4后的分数提升很大,有0.055269507247802

 或者训练时训练所有的训练集数据。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值