网站首页 > 开源技术 正文
YOLOv10是清华大学最近开源的一个实时端到端的目标检测算法,继承了YOLO系列的实时端到端检测优势,解决了以往版本YOLO系列目标检测算法在后处理和模型架构方面的不足。通过消除非极大值抑制(NMS)操作和优化模型架构,YOLOv10在显著降低计算开销的同时还实现了最先进的性能。作为YOLO系列的最新版本,YOLOv10已被纳入Ultralytics的官方项目,进一步推动了端侧目标检测技术的发展。
一、引 言
实时目标检测一直是计算机视觉领域的研究重点,其目标是在低延迟下准确预测图像中目标的类别和位置。它被广泛应用于各种实际应用中,包括自动驾驶、机器人导航和物体跟踪等。近年来,研究人员集中精力设计基于CNN的物体检测器以实现实时检测。其中,YOLO因其在性能和效率之间的巧妙平衡而越来越受欢迎。 YOLO的检测流程由两部分组成:模型前处理和NMS后处理。然而,它们仍然存在缺陷,导致精度-延迟边界不理想。
在过去的几年里,由于其在计算成本和检测性能之间的有效平衡,YOLOS已经成为实时目标检测领域的主导范例。研究人员已经探索了YOLOS的架构设计、优化目标、数据增强策略等,并取得了显著进展。然而,对用于后处理的非最大抑制(NMS)的依赖妨碍了YOLOS的端到端部署,并且影响了推理延迟。此外,YOLOS中各部件的设计缺乏全面和彻底的检查,导致明显的计算冗余,限制了模型的性能。这导致次优的效率,以及相当大的性能改进潜力。
清华大学研究团队首先提出了用于YOLOs无NMS训练的持续双重分配,该方法带来了有竞争力的性能和低推理延迟。此外,还从效率和精度两个角度对YOLOS的各个组件进行了全面优化,大大降低了计算开销,增强了性能。
二、YOLOv10模型架构
YOLOv10的模型架构由以下几个部分组成:
- 主干网络:使用增强版的CSPNet来提取图像特征,它能改善梯度流并减少计算量。
- 颈部:采用PAN结构汇聚不同尺度的特征,有效地实现多尺度特征融合。
- 一对多预测头:在训练过程中为每个对象生成多个预测,用来提供丰富的监督信号从而提高学习的准确性;在推理阶段不生效,从而减少计算量。
- 一对一预测头:在推理过程中为每个对象生成一个最佳预测,无需NMS操作,从而减少延迟并提高推理效率。
三、YOLOv10的主要特点
1. 无NMS训练
YOLOv10的一大亮点是其无NMS训练。传统的YOLO模型使用NMS来过滤重叠的预测,这增加了推理延迟。YOLOv10引入了一种双重分配策略,消除了NMS的需求,从而实现了更快、更高效的目标检测。双重分配策略解释:
- 一对多分配:在训练过程中使用,以提供丰富的监督信号。
- 一对一分配:在推理过程中使用,以避免冗余预测。
通过使用一致的匹配度量协调这两种策略,YOLOv10在不牺牲性能的情况下实现了高效率。
2. 整体效率-准确性驱动设计
YOLOv10采用了一种全面的模型设计方法,优化了各种组件以提高效率和准确性。以下是一些关键创新:
- 轻量化分类头:通过使用深度可分离卷积,减少分类头的计算开销,而不显著影响性能。
- 空间-通道解耦下采样:通过分离空间缩减和通道增加操作,增强下采样效率,减少信息损失。
- 秩引导块设计:根据模型不同阶段的内在冗余,调整构建块的复杂度,确保参数的最佳利用。
3. 大核卷积和部分自注意力
为了进一步提高准确性,YOLOv10集成了大核卷积和部分自注意力(PSA)模块。这些组件提高了模型捕捉全局信息的能力,同时保持计算效率。
- 大核卷积:在较深阶段有选择地使用,以扩大感受野而不显著增加I/O开销。
- PSA模块:以成本效益的方式引入自注意力,提升模型学习全局表示的能力。
性能和效率:双赢组合
实验结果表明,YOLOv10在准确性和速度方面均优于其前代和其他最新模型。例如,YOLOv10-S(一个较小的变体)比RT-DETR-R18快1.8倍,性能相似,且参数量减少了2.8倍。与YOLOv9-C相比,YOLOv10-B(一个平衡的变体)延迟减少了46%,参数量减少了25%,同时保持了相同的性能水平。
四、YOLOv10的现实应用
YOLOv10在各个行业中具有实际意义:
- 自动驾驶
在自动驾驶车辆中,实时目标检测对于安全导航至关重要。YOLOv10的高效性和高准确性使其能够理想地识别行人、其他车辆和障碍物,确保顺畅安全的驾驶体验。
2. 机器人
对于从事仓库管理或救援任务的机器人来说,快速准确地检测物体的能力至关重要。YOLOv10增强了这些能力,使机器人能够在动态环境中更有效地运行。
3. 监控
在安防系统中,实时检测潜在威胁可以在事件升级前预防。YOLOv10的强大性能确保了可靠的监控,使其成为提高公共安全的宝贵工具。
五、YOLOv10的安装
- conda建议使用虚拟环境。
conda create -n yolov10 python=3.9
conda activate yolov10
- 下载YOLOv10源码
git clone https://github.com/THU-MIG/yolov10.git
cd yolov10
- 演示
python app.py
# Please visit 127.0.0.1:7860
执行后,打开127.0.0.1:7860 即可看到以下界面
测试一:
测试二:
六、主入口app.py代码解析
import gradio as gr
import cv2
import tempfile
from ultralytics import YOLOv10
# 定义YOLOv10推理函数
def yolov10_inference(image, video, model_id, image_size, conf_threshold):
# 从预训练模型加载YOLOv10模型
model = YOLOv10.from_pretrained(f'jameslahm/{model_id}')
# 如果输入是图像
if image:
# 对图像进行预测
results = model.predict(source=image, imgsz=image_size, conf=conf_threshold)
# 绘制标注框
annotated_image = results[0].plot()
# 返回标注后的图像和None(表示没有视频输出)
return annotated_image[:, :, ::-1], None
else:
# 创建临时文件路径用于保存视频
video_path = tempfile.mktemp(suffix=".webm")
# 将输入视频写入临时文件
with open(video_path, "wb") as f:
with open(video, "rb") as g:
f.write(g.read())
# 打开视频文件
cap = cv2.VideoCapture(video_path)
# 获取视频的帧率
fps = cap.get(cv2.CAP_PROP_FPS)
# 获取视频的宽度和高度
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 创建输出视频的临时文件路径
output_video_path = tempfile.mktemp(suffix=".webm")
# 创建视频写入器
out = cv2.VideoWriter(output_video_path, cv2.VideoWriter_fourcc(*'vp80'), fps, (frame_width, frame_height))
# 逐帧处理视频
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 对当前帧进行预测
results = model.predict(source=frame, imgsz=image_size, conf=conf_threshold)
# 绘制标注框
annotated_frame = results[0].plot()
# 将标注后的帧写入输出视频
out.write(annotated_frame)
# 释放视频捕获和写入器
cap.release()
out.release()
# 返回None(表示没有图像输出)和标注后的视频路径
return None, output_video_path
# 定义用于示例的YOLOv10推理函数
def yolov10_inference_for_examples(image, model_path, image_size, conf_threshold):
# 调用YOLOv10推理函数并返回标注后的图像
annotated_image, _ = yolov10_inference(image, None, model_path, image_size, conf_threshold)
return annotated_image
# 定义Gradio应用
def app():
with gr.Blocks():
with gr.Row():
with gr.Column():
# 图像输入组件
image = gr.Image(type="pil", label="Image", visible=True)
# 视频输入组件
video = gr.Video(label="Video", visible=False)
# 输入类型选择组件
input_type = gr.Radio(
choices=["Image", "Video"],
value="Image",
label="Input Type",
)
# 模型选择组件
model_id = gr.Dropdown(
label="Model",
choices=[
"yolov10n",
"yolov10s",
"yolov10m",
"yolov10b",
"yolov10l",
"yolov10x",
],
value="yolov10m",
)
# 图像尺寸选择组件
image_size = gr.Slider(
label="Image Size",
minimum=320,
maximum=1280,
step=32,
value=640,
)
# 置信度阈值选择组件
conf_threshold = gr.Slider(
label="Confidence Threshold",
minimum=0.0,
maximum=1.0,
step=0.05,
value=0.25,
)
# 推理按钮
yolov10_infer = gr.Button(value="Detect Objects")
with gr.Column():
# 标注后的图像输出组件
output_image = gr.Image(type="numpy", label="Annotated Image", visible=True)
# 标注后的视频输出组件
output_video = gr.Video(label="Annotated Video", visible=False)
# 更新组件可见性的函数
def update_visibility(input_type):
image = gr.update(visible=True) if input_type == "Image" else gr.update(visible=False)
video = gr.update(visible=False) if input_type == "Image" else gr.update(visible=True)
output_image = gr.update(visible=True) if input_type == "Image" else gr.update(visible=False)
output_video = gr.update(visible=False) if input_type == "Image" else gr.update(visible=True)
return image, video, output_image, output_video
# 输入类型改变时更新组件可见性
input_type.change(
fn=update_visibility,
inputs=[input_type],
outputs=[image, video, output_image, output_video],
)
# 运行推理的函数
def run_inference(image, video, model_id, image_size, conf_threshold, input_type):
if input_type == "Image":
return yolov10_inference(image, None, model_id, image_size, conf_threshold)
else:
return yolov10_inference(None, video, model_id, image_size, conf_threshold)
# 推理按钮点击事件
yolov10_infer.click(
fn=run_inference,
inputs=[image, video, model_id, image_size, conf_threshold, input_type],
outputs=[output_image, output_video],
)
# 示例数据
gr.Examples(
examples=[
[
"ultralytics/assets/bus.jpg",
"yolov10s",
640,
0.25,
],
[
"ultralytics/assets/zidane.jpg",
"yolov10s",
640,
0.25,
],
],
fn=yolov10_inference_for_examples,
inputs=[
image,
model_id,
image_size,
conf_threshold,
],
outputs=[output_image],
cache_examples='lazy',
)
# 创建Gradio应用实例
gradio_app = gr.Blocks()
with gradio_app:
# 应用标题
gr.HTML(
"""
YOLOv10: Real-Time End-to-End Object Detection
""")
# 应用链接
gr.HTML(
"""
arXiv | github
""")
with gr.Row():
with gr.Column():
# 调用应用函数
app()
# 启动Gradio应用
if __name__ == '__main__':
gradio_app.launch()
猜你喜欢
- 2025-03-25 阿里数据中台核心产品揭秘(阿里数据中台技术架构)
- 2025-03-25 读《飘》42章7(飘章节读后感)
- 2025-03-25 一文深入理解Linux内核进程调度(纯干货)
- 2025-03-25 我用 Rust 改写了自己的 C++ 项目:这两个语言都很折磨人!
- 2025-03-25 迄今为止最完整的DDD实践(圣女果中哪种物质是迄今为止自然界中被发现的最强抗氧化剂)
- 2025-03-25 前端学习路线全解析:从入门到进阶
- 2024-08-19 当我接到一个DAU几十w的项目,并开始维护它
- 2024-08-19 Rust与网络编程:同步网络I/O(python 网络编程)
- 2024-08-19 vue3中使用图片懒加载(性能优化)(vue 图片加载优化)
- 2024-08-19 Github 2024-06-10 开源项目日报 Top10
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- jdk (81)
- putty (66)
- rufus (78)
- 内网穿透 (89)
- okhttp (70)
- powertoys (74)
- windowsterminal (81)
- netcat (65)
- ghostscript (65)
- veracrypt (65)
- asp.netcore (70)
- wrk (67)
- aspose.words (80)
- itk (80)
- ajaxfileupload.js (66)
- sqlhelper (67)
- express.js (67)
- phpmailer (67)
- xjar (70)
- redisclient (78)
- wakeonlan (66)
- tinygo (85)
- startbbs (72)
- webftp (82)
- vsvim (79)
本文暂时没有评论,来添加一个吧(●'◡'●)