基于ros和yolov5的视觉识别部署测试
引言
随着计算机视觉技术的快速发展,目标检测已成为众多应用的核心部分,尤其是在机器人技术和自动化领域。YOLOv5作为一种先进的目标检测模型,因其高效、准确且易于部署而受到广泛欢迎。ROS(Robot Operating System)作为机器人软件开发的事实标准,为机器人系统的开发提供了强大的支持。本文旨在探讨如何将YOLOv5模型集成到ROS环境中,以实现对实时视频流的目标检测。
本文首先介绍了YOLOv5模型的基本结构和工作原理,随后详细阐述了在ROS环境下部署YOLOv5的步骤,包括创建虚拟环境、安装必要的软件包、获取YOLOv5源码以及设置ROS节点来处理来自摄像头的数据流。我们还提供了具体的脚本实例,展示了如何使用ROS节点来捕获图像或视频,并将这些数据送入YOLOv5模型进行目标检测。
Yolov5的网络结构和工作原理
Yolov5采用了一种轻量级的网络结构,由一系列卷积层、池化层和全连接层组成。它通过不同尺度的特征图来检测不同大小的目标,并使用置信度和类别概率来判断检测框的准确性。
Yolov5的工作原理可以分为三个主要步骤:特征提取、目标检测和后处理。在特征提取阶段,Yolov5使用一系列卷积层来提取输入图像的特征。这些特征图具有不同的尺度和语义信息,能够捕捉目标的不同特征。
在目标检测阶段,Yolov5将特征图分为不同的网格,并为每个网格预测一组目标框。每个目标框包含目标位置和类别概率信息。通过调整目标框的位置和大小,并计算其与真实目标框的相似度,Yolov5能够准确地检测出图像中的目标。
在后处理阶段,Yolov5通过非极大值抑制(NMS)算法来消除重叠的检测框,并选择置信度最高的检测结果作为最终输出。通过这种方式,Yolov5能够实现准确且高效的目标检测。
Yolov5在不同数据集上的性能和应用场景
Yolov5在多个数据集上进行了训练和测试,并在目标检测任务中取得了优秀的性能。例如,在COCO数据集上,Yolov5能够达到较高的平均精度和较低的检测时间。这使得Yolov5在实时应用和资源有限的场景中具有广泛的应用前景。
此外,Yolov5还可以应用于不同的目标检测场景。它可以用于车辆检测和识别,人脸检测和识别,物体跟踪和行人检测等任务。Yolov5的高效和准确性使得它在无人驾驶、安防监控、智能交通等领域具有很大的潜力。
在ros里面的部署流程
这里以工控机为例,树莓派等ros主控的部署也与在工控机的部署流程类似,以下步骤以睿抗智能侦查赛道的小车为例。
创建自己的虚拟环境
在这一步之前,首先确保自己的工控机已经安装好conda等基础依赖,这些在工控机中已经存在。
打开终端,使用 annaconda 的 conda 命令创建虚拟环境
conda create -n yolov5 python=3.8
主要基于这段指令:conda create -n <环境名称自定义> python=<python 的版本号>
工控机已安装的python版本可通过以下指令在终端进行查询:
python --version
当显示以下结果,则说明创建环境成功。
可以通过以下指令进行验证:
conda activate yolov5
运行之后终端会进行刚刚创建好的虚拟环境。
安装pytorch
接下来打开浏览器进入以下网址安装pytorch:https://pytorch.org/get-started/locally/
选择好 conda 版本和 cpu 版本,在下面便得到安装指令
conda install pytorch torchvision torchaudio cpuonly -c pytorch
粘贴到终端之后回车执行,注意终端首先要进入刚刚创建好的虚拟环境。等待一段时间之后出现以下结果说明安装成功。
可通过依次输入以下指令回车执行观察输出,验证是否安装成功。若出现 pytorch 版本号就代表安装成功。
python3
import torch
torch.__version__
下载yolov5源码
之后在浏览器输出以下网址获取Yolov5 源码,在其中任选一个即可,这里选择的是monkey_cici/
yolov5。
https://so.gitee.com/?q=yolov5
点击进入–>点击克隆/下载–>下载 zip
下载完成后,在文件夹下载中找到 yolo-master 压缩包,将其提取。然后再将解压后的文件夹复制到主目录。
打开终端,进入文件夹目录:
cd yolov5-master
输入以下指令进入虚拟环境:
conda activate yolov5
yolov5是我自己刚刚创建的虚拟环境名。
在终端指定清华源安装所需的环境:
pip install -U -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
看到以下结果说明所有包和环境安装完成。
测试yolov5
在终端继续输入以下指令测试yolov5:
python detect.py
等待一段时间后,模型完成下载。当运行成功后,结果会保存在 runs/detect/exp。即以下结果:
进入上述路径便可查看 yolov5 实现目标检测结果。
路径~/yolov5-master/data/images是 yolov5 获取源图片的位置,我们将需要自定义检测的图片放入即可完成对识别对象的替换。替换完成之后再运行以下指令便可完成识别
python detect.py
yolov5相关二次开发
如果要实现使用小车相机进行目标检测,则打开 detect.py 文件,将 default = ROOT / “data/images”改为 default=ROOT / “0” 【0 表示使用笔记本默认摄像头】,完成之后再次运行python detect.py。若想用其他外接摄像头进行检测操作,则需要将这里的 default = ‘0’改为 default = ‘1’或者‘2’等,需 usb 摄像头搭载在哪里,输入指令 ls -l /dev/video* 查看。
由于yolov5的识别对象存储在路径~/yolov5-master/data/images下,因此我们可以自己编写一个脚本完成拍照或者录像,再将拍照所得到的jpg格式图片或者录像截取的jpg格式图片存储在yolov5获取识别对象路径下即可。这里提供拍照的脚本demo:
#!/usr/bin/env python3
# encoding=utf-8
import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
import os
import cv2 # 导入cv2模块
import time
class ImageSaverNode:
def __init__(self):
# 初始化ROS节点
rospy.init_node('image_saver', anonymous=True)
# 创建一个CvBridge对象,用于在ROS图像消息和OpenCV图像格式之间转换
self.bridge = CvBridge()
# 订阅图像话题,不同相机驱动获取的图像话题名称可能不一致,需要调试
self.image_sub = rospy.Subscriber("/camera/color/image_raw", Image, self.callback)
# 设置保存图像的文件夹
self.save_folder = "/home/mowen/桌面/yolov5/test1"
if not os.path.exists(self.save_folder):
os.makedirs(self.save_folder)
# 设置连拍张数和间隔时间(秒)
self.num_photos = 3
self.interval = 0.01 # 每秒拍一张,调整间隔时间为1秒
# 初始化计数器
self.count = 0
# 等待直到拍摄完所有照片或节点被关闭
while not rospy.is_shutdown() and self.count < self.num_photos:
# 这里不需要调用rospy.spin(),因为我们在循环中等待
time.sleep(0.1) # 简单的轮询等待,可以根据需要调整
# 拍摄完所有照片后关闭节点
rospy.signal_shutdown("Finished taking photos")
def callback(self, data):
# 检查是否还有图片需要保存
if self.count < self.num_photos:
try:
# 将ROS图像消息转换为OpenCV图像
cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
# 保存图像
file_name = os.path.join(self.save_folder, "image_{}.jpg".format(self.count))
cv2.imwrite(file_name, cv_image)
rospy.loginfo("Saved {}".format(file_name))
# 更新计数器
self.count += 1
# 如果需要间隔拍摄,则等待
if self.interval > 0:
time.sleep(self.interval)
except CvBridgeError as e:
rospy.logerr(e)
if __name__ == '__main__':
try:
image_saver = ImageSaverNode()
except rospy.ROSInterruptException:
pass
如果是通过录像,这里也提供脚本demo:
#!/usr/bin/env python3
# encoding=utf-8
import rospy
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
import os
import cv2
class VideoRecorderNode:
def __init__(self):
# 初始化ROS节点
rospy.init_node('video_recorder', anonymous=True)
self.bridge = CvBridge()
# 订阅图像话题
self.image_sub = rospy.Subscriber("/camera/color/image_raw", Image, self.callback)
# 设置保存视频的文件夹和文件名
self.save_folder = "/home/mowen/test_ws/src/cam/scripts/saved_videos"
if not os.path.exists(self.save_folder):
os.makedirs(self.save_folder)
self.video_file = os.path.join(self.save_folder, "output.avi")
self.fourcc = cv2.VideoWriter_fourcc(*'XVID')
self.out = cv2.VideoWriter(self.video_file, self.fourcc, 20.0, (640, 480))
# 注册一个回调函数,在ROS节点关闭时释放视频文件
rospy.on_shutdown(self.cleanup)
# 保持节点运行,等待回调函数执行
rospy.spin()
def callback(self, data):
try:
# 将ROS图像消息转换为OpenCV图像
cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
# 写入视频文件
self.out.write(cv_image)
except CvBridgeError as e:
rospy.logerr(e)
def cleanup(self):
# 确保视频文件正确关闭
self.out.release()
rospy.loginfo("Video file released and closed.")
if __name__ == '__main__':
try:
video_recorder = VideoRecorderNode()
except rospy.ROSInterruptException:
pass
这个脚本demo得到的视频文件是avi格式的,要转换成mp4格式,这里也提供脚本demo:
#!/usr/bin/env python3
#encoding=utf-8
import subprocess
import os
def convert_video_to_mp4(input_video_path, output_video_path):
try:
# 构造ffmpeg命令
ffmpeg_command = [
'ffmpeg',
'-i', input_video_path, # 输入文件
'-c:v', 'libx264', # 使用H.264视频编码器
'-crf', '23',
output_video_path # 输出文件
]
subprocess.run(ffmpeg_command, check=True)
print(f"Video converted successfully: {output_video_path}")
except subprocess.CalledProcessError as e:
print(f"Failed to convert video: {e}")
def play_video(video_path):
if not os.path.exists(video_path):
print(f"Video file not found: {video_path}")
return
try:
subprocess.run(['smplayer', video_path], check=True)
except subprocess.CalledProcessError as e:
print(f"Failed to play video with SMPlayer: {e}")
except FileNotFoundError:
print("SMPlayer not found. Please ensure it is installed and in your system PATH.")
if __name__ == '__main__':
input_avi_path = '/home/mowen/test_ws/src/cam/scripts/saved_videos/output.avi' # AVI视频文件的完整路径
output_mp4_path = '/home/mowen/test_ws/src/cam/scripts/saved_videos/output.mp4' # MP4视频文件的完整路径
if os.path.exists(input_avi_path):
convert_video_to_mp4(input_avi_path, output_mp4_path)
play_video(output_mp4_path) # 转换后播放视频
else:
print(f"AVI video file not found: {input_avi_path}")
通过这个脚本可以将avi格式视频转换成mp4格式视频。
Yolov5的改进和未来发展方向
尽管Yolov5已经取得了很大的成功,但仍然存在一些改进的空间和发展方向。首先,Yolov5在处理小目标和密集目标方面仍然存在一定的挑战。这是由于Yolov5的特征提取方式和目标检测算法的限制所导致的。未来的发展方向可以包括设计更加复杂的网络结构和引入更多的数据增强技术。
此外,Yolov5还可以进一步优化其目标检测和分类性能。可以通过引入注意力机制、多尺度特征融合和级联检测等技术来提高Yolov5的准确性和鲁棒性。此外,还可以通过引入预训练模型和迁移学习等方法来提高Yolov5在不同数据集和任务上的泛化能力。
小结
通过上述步骤,希望可以帮助大家了解到如何在ROS环境下成功部署YOLOv5进行目标检测,并能够利用ROS的强大功能来实现复杂的应用场景。这种结合使得YOLOv5能够在各种机器人和自动化系统中发挥重要作用,特别是在需要实时处理大量视觉信息的情况下。