> 技术文档 > 视觉学习yolo+OpenCV(电赛准备)

视觉学习yolo+OpenCV(电赛准备)

       YOLO(You Only Look Once)是一种实时目标检测系统,它是一种基于深度学习的目标检测算法,具有速度快、易于集成和部署、对小目标检测效果好等优点。

一、yolo和opencv的安装

打开anaconda,切换到自己所需要的环境,然后输入下面的代码就能够安装了

pip install ultralytics opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple

二、修改yolo环境配置

笔者不喜欢很多东西都塞到C盘,所以一开始就修改了部分的默认设置,不过不知道后面会不会有啥影响,但是目前为止,暂时没有啥影响。

使用Python 通过导入 settings 对象的 ultralytics 模块。使用这些命令打印和返回设置:

from ultralytics import settings# View all settingsprint(settings)# Return a specific settingvalue = settings[\"runs_dir\"]

返回如下:

下表是关于参数的介绍

名称 示例值 数据类型 说明 settings_version \'0.0.6\' str Ultralytics 设置版本(有别于Ultralytics pip版本) datasets_dir \'/path/to/datasets\' str 存储数据集的目录 weights_dir \'/path/to/weights\' str 存储模型权重的目录 runs_dir \'/path/to/runs\' str 存储实验运行的目录 uuid \'a1b2c3d4\' str 当前设置的唯一标识符 sync True bool 将分析和崩溃同步到Ultralytics HUB的选项 api_key \'\' str Ultralytics HUBAPI 密钥 clearml True bool 使用以下选项 ClearML记录 comet True bool 使用Comet ML进行实验跟踪和可视化的选项 dvc True bool 可选择使用DVC 进行实验跟踪和版本控制 hub True bool 使用Ultralytics HUB集成选项 mlflow True bool 使用MLFlow进行实验跟踪的选项 neptune True bool 可选择使用 Neptune进行实验跟踪 raytune True bool 使用Ray Tune进行超参数调整的选项 tensorboard True bool 使用TensorBoard进行可视化的选项 wandb True bool 使用选项 Weights & Biases记录 vscode_msg True bool 检测到 VS Code 终端时,启用下载Ultralytics扩展的提示。

需要修改可以在json文件直接修改或者python输入以下代码

from ultralytics import settings# Update a settingsettings.update({\"runs_dir\": \"/path/to/runs\"})# Update multiple settings#settings.update({\"runs_dir\": \"/path/to/runs\", \"tensorboard\": False})# Reset settings to default values#settings.reset()

三、yolo部分python的快速使用

1、加载预训练模型进行照片和视频流的预测

首次运行自动下载,也可以看官方文档用v11,这里作者后面想移植到树莓派上结合opencv。

from ultralytics import YOLO#首次运行自动下载,也可以看官方文档用v11,这里主包后面想移植到树莓派a1 = YOLO(\'yolov5n.pt\')

之后作者随便找了一张图片

这个也是官方教程里下载下来的图片,然后运行下面的代码

model(\'bus.jpg\',show=True,save=True)

之后这个预测的图片就会保存到你的run下的文件夹

预测的效果如下:

接下来做的是视频流的追踪,不过作者忘记下载视频,就附上一段爬虫代码下载b站上的视频,爬取汽车流的代码如下:

#b站爬取代码# 导入数据请求模块import requests# 导入正则表达式模块import re# 导入json模块import json# TODO 记得更改你要的url和你自己的cookieurl = \'https://www.bilibili.com/video/BV1uS4y1v7qN/?spm_id_from=333.337.search-card.all.click&vd_source=f4f695a55bf2a7e583ebd8706d656a4f\'cookie = \"buvid3=2844B77E-F527-FB05-1DF5-9FDF834AE3E888277infoc; b_nut=1709986388; i-wanna-go-back=-1; b_ut=7; _uuid=6577D687-BED9-9AE2-106A10-551210627F5AC88087infoc; enable_web_push=DISABLE; buvid4=5ED5B3A0-A998-7D47-3815-9AD9A1B27A4989131-024030912-0Fw3r6dKwZLwPoWOl%2F8HuA%3D%3D; CURRENT_FNVAL=4048; rpdid=|(u|Jmkkuukk0J\'u~u|ulR~)~; header_theme_version=CLOSE; fingerprint=c27c0b59dd10dcdc4c14701a58f49669; buvid_fp_plain=undefined; buvid_fp=c27c0b59dd10dcdc4c14701a58f49669; LIVE_BUVID=AUTO6217111182462626; FEED_LIVE_VERSION=V_WATCHLATER_PIP_WINDOW3; bp_video_offset_691902317=925084214145056785; DedeUserID=691902317; DedeUserID__ckMd5=ead312019baad7ed; CURRENT_QUALITY=80; bili_ticket=eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTYwNDM3MDgsImlhdCI6MTcxNTc4NDQ0OCwicGx0IjotMX0.Rdjc9F5oiEXSn_GylRWm3s2L-Pn8GYfyQS5IZt_Y3-8; bili_ticket_expires=1716043648; SESSDATA=3d6f944f%2C1731336513%2C491d2%2A51CjD5jp6zedAz4nQallTN_akUjFzg2LzJhdKMiJbI1nnw2bs5sp8Y09F7Jj4PofjUyfsSVlktMkF0aDRLN196dVNTeWh0czllbFZTWDlidWRpcnFnaENSNVVNbGNFMGR5bFBqYkcwalhuVklyUGJLVHJtYXo3TVpaTENqQ21rS0RPbldWTDUzRFp3IIEC; bili_jct=2975523315e5bccfa606ac286df61f36; home_feed_column=4; browser_resolution=1396-639; sid=6gr3y4l0; PVID=4; bp_t_offset_691902317=932475264446758937; b_lsid=5E9C415B_18F86EC150D\"headers = { # Referer 防盗链 告诉服务器你请求链接是从哪里跳转过来的 # \"Referer\": \"https://www.bilibili.com/video/BV1454y187Er/\", \"Referer\": url, # User-Agent 用户代理, 表示浏览器/设备基本身份信息 \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36\", \"Cookie\": cookie}# 发送请求response = requests.get(url=url, headers=headers)html = response.text# 解析数据: 提取视频标题title = re.findall(\'title=\"(.*?)\"\', html)[0]print(title)# 提取视频信息info = re.findall(\'window.__playinfo__=(.*?)\', html)[0]# info -> json字符串转成json字典json_data = json.loads(info)# 提取视频链接video_url = json_data[\'data\'][\'dash\'][\'video\'][0][\'baseUrl\']print(video_url)video_content = requests.get(url=video_url, headers=headers).content# 保存数据with open(title + \'.mp4\', mode=\'wb\') as v: v.write(video_content)

爬取完视频后,再进行检测

进行检测,之后再进行识别

model(\'车辆检测和交通流量测试视频.mp4\',show=True,save=True)

2、构建自己的数据集并训练

接下来,做完基础的trace任务,开始训练自己的模型。

首先在自己的项目下创建文件夹如下:

同时我的py文件与task是同一个层级的

接下来先给大家介绍一下几个常见的标注工具

  • label studio:这是一款灵活的工具,支持多种标注任务,并具有管理项目和质量控制功能。
  • CVAT:功能强大的工具,支持各种注释格式和可定制的工作流程,适用于复杂的项目。
  • labelme:这是一款简单易用的工具,可使用多边形快速标注图像,非常适合完成简单的任务。
  • labelImg:易于使用的图形图像注释工具,尤其适合创建YOLO 格式的边界框注释。

这里作者最后使用了labelme这个工具进行数据标注(你可以直接点击上面的访问GitHub链接,查看如何下载)

作者这里是用pip下载的,但是由于自己电脑是win系统,所以可能只安装pyqt5不够的,还得多安装一个PyQt5-tools才能打开GUI

pip install labelme PyQt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple

如果还有啥其他的问题,读者可以留言或者自己debug,毕竟作者也是边学边记录。安装好后,也是如愿打开了GUI界面

之后作者决定抓取chiikawa的图片和视频进行训练。

这里先列一下labelme的一些指令参数(ps:可以用labelme -h查看),直接终端打labelme再选择文件也问题不大。

场景 关键参数 含义与示例 启动即标注 filename 直接给出待标注的图片或已有的 JSON 文件 批量输出 --output/-O/-o 指定结果保存位置
  预定义标签 --labels 一次性加载标签,避免每次手动输入 标签属性/多选 --flags 为每个实例打复选框属性,如遮挡、截断 标签专属属性 --labelflags 不同标签有不同的下拉属性 不保存原图 --nodata 生成的 JSON 中不再内嵌 base64 原图,体积更小 自动保存 --autosave 每改一次就自动写盘,避免断电丢失 保持上一帧标注 --keep-prev 视频/序列帧场景下,下一帧继承上一帧结果,仅需微调 关闭标签排序 --nosortlabels 标签按给定顺序显示,不自动按字母排序 标签严格匹配 --validatelabel exact 输入时强制用预定义标签名,防止拼错 捕捉容差 --epsilon 拖拽顶点吸附半径(像素),默认 10,精细标注可调小 日志级别 --logger-level 调 bug 时改成 debug:--logger-level debug 恢复默认配置 --reset-config UI 布局或快捷键错乱时一键还原 版本查看 --version/-V 快速确认当前 labelme 版本号

常见组合示例如下:

# 1) 单张图片,预设标签,结果保存同级目录labelme cat.jpg --labels \"cat,eye,nose\" --output cat.json --autosave# 2) 批量图片,预定义标签集文件,统一输出目录labelme imgs/ -o labels/ --labels mylabels.txt --nodata --autosave# 3) 视频帧继承标注,带复选属性labelme frames/ --labels person.txt --flags occluded,truncated --keep-prev

之后将labelme的标注保存在label文件下,并且需要把json文件格式转化成txt文件格式。

先在anaconda prompt环境下输入

pip install labelme2yolo -i https://pypi.tuna.tsinghua.edu.cn/simple

之后输入

labelme2yolo --json_dir labels/train --output_format bboxlabelme2yolo --json_dir labels/val --output_format bbox

脚本会在原目录旁自动生成 YOLODataset/labels/train|val/*.txt再把生成的 txt 拷回 labels/trainlabels/val 即可训练

准备好数据集。

接下来创建一个yaml格式的文件

之后输入以下代码:

from ultralytics import YOLOmodel = YOLO(\'yolov5nu.pt\')model.train( data = \'chiikawa_test.yaml\', #数据集配置文件路径 epochs = 100, #训练轮次 imgsz=640, #官方推荐640 batch=16, #每次训练的批量)

就可以开始训练了,不过应该还是gpu训练比较快,建议自己的电脑上训练完模型,把模型拷到树莓派玩。

作者的训练效果不大好,还需要调参一下,但是一个是数据集只有50个,另一个是我训练集和验证集都是一起的,还有标注可能不大行,还是得调参。

但是最后文件保存在train4文件夹下,看看有什么东西。

有一些曲线图,还有相关的权重文件,接下来,我们使用权重文件进行检测。

chiikawa_model = YOLO(r\'D:\\ProgramData\\yolo\\runs\\detect\\train4\\weights\\best.pt\')chiikawa_model(\'小八ai还原Chiikawa259话.mp4\',show = True,save=True)

最后识别出来的效果如下:

四、OpenCV快速应用

首先的话先补充一部分摄像头前端参数的知识,之后的OpenCV大部分是进行前端处理的作用。

参数类别 OpenCV 枚举名(C++/Python) 含义 典型取值范围 备注 分辨率 CAP_PROP_FRAME_WIDTH / HEIGHT 图像宽、高 如 640×480、1920×1080 需硬件支持;MJPG 格式才能跑高分辨率+高帧率 帧率 CAP_PROP_FPS 每秒帧数 5–120 同上 编码格式 CAP_PROP_FOURCC 像素格式/压缩格式 ‘MJPG’、‘YUYV’ 1080p 实时建议 MJPG 亮度 CAP_PROP_BRIGHTNESS 全局明暗 0–255(厂商不同) 实时可调 对比度 CAP_PROP_CONTRAST 动态范围 0–255 饱和度 CAP_PROP_SATURATION 颜色浓淡 0–255 色调 CAP_PROP_HUE 色盘偏移 0–255 伽马 CAP_PROP_GAMMA 非线性亮度映射 0–500 见示例 增益 CAP_PROP_GAIN 模拟增益 0–255 噪点随增益提升 曝光 CAP_PROP_EXPOSURE 曝光时间 -13(短)~ -1(长)或绝对毫秒 负值越大越短;关闭自动曝光后才生效 白平衡 CAP_PROP_WHITE_BALANCE_BLUE_U / RED_V 色温 2000–10000 K 部分相机仅支持自动/手动切换 对焦 CAP_PROP_FOCUS 绝对对焦距离 0–255 需要支持 UVC 连续对焦 缩放/平移 CAP_PROP_ZOOM / PAN / TILT 数码或光学变焦 0–255 高端 USB/工业相机才有

背光补偿:也称为逆光补偿,是早期应对强光或强逆光视频监控环境的方法

如果一个场景既有非常明亮的物体,也有非常黑暗的物体,亮度跨度很大,我们就称之为“高动态范围 High Dynamic Range(HDR)”场景

下面的是一些之前为了准备电赛的代码:

1、色域追踪

通过鼠标GUI的点击,从而获取点击位置hsv属性。

import numpy as npimport cv2 as cv#鼠标寻找色域函数def nothing(x): passdef show_hsv(event,x,y,flags,param): global ix, iy, drawing,mode if event == cv.EVENT_LBUTTONDOWN: ix,iy = x,y elif event ==cv.EVENT_LBUTTONUP: pixel_hsv = hsv[y, x] # 打印HSV值 print(f\"HSV pixel value at ({x}, {y}): Hue={pixel_hsv[0]}, Saturation={pixel_hsv[1]}, Value={pixel_hsv[2]}\") #print(type(pixel_hsv),pixel_hsv)# 创建一个VideoCapture对象cap = cv.VideoCapture(0)print(cap.get(cv.CAP_PROP_FRAME_WIDTH),cap.get(cv.CAP_PROP_FRAME_HEIGHT))while(True): ret, frame = cap.read() cv.namedWindow(\'image\') hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) cv.imshow(\'image\',frame) #设置鼠标状态 cv.setMouseCallback(\'image\',show_hsv)  #按q推出 if cv.waitKey(1) & 0xFF ==ord(\'q\'): break #释放VideoCapture对象cap.release()cv.destroyAllWindows()

通过鼠标GUI的点击,从而获取点击位置bgr属性。

import numpy as npimport cv2 as cv# 鼠标寻找色域函数def nothing(x): passdef show_bgr(event, x, y, flags, param): global ix, iy, drawing, mode if event == cv.EVENT_LBUTTONDOWN: ix, iy = x, y elif event == cv.EVENT_LBUTTONUP: bgr_pixel = frame[y, x] # 获取BGR像素值 # 打印BGR值 print(f\"BGR pixel value at ({x}, {y}): Blue={bgr_pixel[0]}, Green={bgr_pixel[1]}, Red={bgr_pixel[2]}\")# 创建一个VideoCapture对象cap = cv.VideoCapture(0)print(cap.get(cv.CAP_PROP_FRAME_WIDTH), cap.get(cv.CAP_PROP_FRAME_HEIGHT))while (True): ret, frame = cap.read() if not ret: break cv.namedWindow(\'image\') hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV) # 转换为HSV空间,虽然我们不需要显示它 cv.imshow(\'image\', frame) # 显示BGR图像 # 设置鼠标状态 cv.setMouseCallback(\'image\', show_bgr) # 按 \'q\' 退出 if cv.waitKey(1) & 0xFF == ord(\'q\'): break# 释放VideoCapture对象cap.release()cv.destroyAllWindows()

2、设置ROI

通过顺时针点击一个矩形的四个角确定ROI的大小

import cv2 as cvimport numpy as np# 初始化点的列表points = []# 定义鼠标回调函数def set_ROI(event, x, y, flags, param): global points if event == cv.EVENT_LBUTTONDOWN and len(points)<=4: points.append((x, y))# 读取视频cap = cv.VideoCapture(0)while True: # 读取视频帧 ret, frame = cap.read() if not ret: break # 显示视频帧 img = frame.copy() if len(points)==4: cv.imshow(\'Video\',img[points[0][0]:points[2][0],points[0][1]:points[2][1]]) if len(points)!=4: cv.imshow(\'Video\', img) # 鼠标回调函数 #顺时针设置ROI cv.setMouseCallback(\'Video\', set_ROI) # 等待按键,退出循环 k = cv.waitKey(1) & 0xFF if k == 27: # 按下ESC键退出 break# 释放视频捕获对象cap.release()cv.destroyAllWindows()

五、OpenCV视频流显示yolo检测的操作

原本想介绍一点opencv的知识,但是后面想了想,还是由读者自己去学习(如果有需要或者重新温习的话,还会更新这部分),可以看这个网址的知识https://apachecn.github.io/opencv-doc-zh/#/去学习

import cv2from ultralytics import YOLO# 加载 YOLOv8 模型model = YOLO(\"yolov8n.pt\")# 打开视频文件# cap = cv2.VideoCapture(\"path/to/your/video/file.mp4\")# 或使用设备“0”打开视频捕获设备读取帧cap = cv2.VideoCapture(0)# 设置视频帧大小cap.set(cv2.CAP_PROP_FRAME_WIDTH, 200)cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 200)title = \"YOLOv8 Inference\"# 设置窗口位置cv2.namedWindow(title, cv2.WINDOW_NORMAL)cv2.moveWindow(title, 200, 200)# 循环播放视频帧while cap.isOpened(): # 从视频中读取一帧 success, frame = cap.read() if success: # 在框架上运行 YOLOv8 推理 results = model(frame) # 在框架上可视化结果 annotated_frame = results[0].plot() # 显示带标注的框架 cv2.imshow(title, annotated_frame) # 如果按下“q”,则中断循环 if cv2.waitKey(1) & 0xFF == ord(\"q\"): break else: # 如果到达视频末尾,则中断循环 break# 释放视频捕获对象并关闭显示窗口cap.release()cv2.destroyAllWindows()

后续接下来做电赛的识别激光的训练,用树莓派试试

参考链接:

yolo文档

https://zhuanlan.zhihu.com/p/371756150

Labelme json文件转换为yolo标签格式文件_lableme json转yolo格式-CSDN博客

使用 OpenCV 和 YOLO 模型进行实时目标检测并在视频流中显示检测结果_yolo实时视频流检测-CSDN博客

海康培训--基础技术课程前端-摄像机常见参数解读_哔哩哔哩_bilibili

OpenCV中文文档