什么样的网站利于百度优化,普洱建设单位网站,企业网站功能清单,亚马逊跨境电商开店文章目录 前言一、yolo板端部署推理二、目标深度测距三、目标方位解算与导航点设定1、相机成像原理2、Python实现目标定位 总结 前言 Darknet_ros是一个基于ROS#xff08;机器人操作系统#xff09;的开源深度学习框架#xff0c;它使用YOLO算法进行目标检测和识别。YOLO算… 文章目录 前言一、yolo板端部署推理二、目标深度测距三、目标方位解算与导航点设定1、相机成像原理2、Python实现目标定位 总结 前言 Darknet_ros是一个基于ROS机器人操作系统的开源深度学习框架它使用YOLO算法进行目标检测和识别。YOLO算法是一种实时物体检测算法它能够在单个前向传递中同时检测图像中的多个目标。
Darknet_ros将YOLO算法集成到ROS中使得机器人可以实时地检测和识别周围环境中的物体。它提供了一些ROS节点和服务可以在ROS系统中轻松使用YOLO算法进行目标检测和识别。同时它还提供了一些示例程序帮助用户快速了解如何在ROS中使用深度学习算法进行机器人视觉任务。
Darknet_ros的优点是速度快、准确度高可以在实时应用中使用。它还可以在不同的机器人项目中使用例如无人机、机器人车辆和机器人臂等。 一、yolo板端部署推理
首先确认CUDAOpenCVcuDNN已安装可以用命令查看CUDA是否安装
ls -l /usr/local | grep cuda查看opencv版本
opencv_version接着从gitee上克隆darknet_ros源码下来
git clone https://gitee.com/bluesky_ryan/darknet_ros.git按照如下指引下载权重文件将下载的weights权重文件放在 darknet_ros/darknet_ros/yolo_network_config/weights
cd catkin_workspace/src/darknet_ros/darknet_ros/yolo_network_config/weights/COCO data set (Yolo v2):wget http://pjreddie.com/media/files/yolov2.weightswget http://pjreddie.com/media/files/yolov2-tiny.weightsVOC data set (Yolo v2):wget http://pjreddie.com/media/files/yolov2-voc.weightswget http://pjreddie.com/media/files/yolov2-tiny-voc.weightsYolo v3:wget http://pjreddie.com/media/files/yolov3.weightswget http://pjreddie.com/media/files/yolov3-voc.weights使用jetson nano自带的opencv4.x编译会报错需要安装opencv3.4.2版本配置opencv cmake桥接目录
sudo vim /opt/ros/melodic/share/cv_bridge/cmake/cv_bridgeConfig.cmake 接着cd到工作空间下编译darknet_ros功能包
catkin_make -DCATKIN_WHITELIST_PACKAGESdarknet_ros配置launch文件图像输入的topic可以打开摄像头节点后用rostopic命令查看
rostopic list我的RGB图像发布的话题是/camera/rgb/image_raw接着配置yolo网络参数我用的是yolov2-tiny权重文件检查一下ros.yaml文件也要配置成/camera/rgb/image_raw 打开终端source一下工作空间下ros的环境变量
source /catkin_ws/devel/setup.bash首先启动相机节点需要有/camera/rgb/image_raw的话题输出再运行darknet_ros 节点
roslaunch darknet_ros darknet_ros.launch接着会弹出一个窗口展示识别到的物体
二、目标深度测距
目标的深度测距的实现我们可以结合darknet_ros功能包我这里用的是RGBD相机型号是Astra_Pro深度相机节点在启动后会输出深度图的话题
rostopic list/camera/depth/image_rect_raw查看一下darknet_ros功能包的msg消息文件下面是BoundingBoxes.msg消息文件
Header header
Header image_header
BoundingBox[] bounding_boxes下面是BoundingBox.msg消息文件
float64 probability
int64 xmin
int64 ymin
int64 xmax
int64 ymax
int16 id
string Class用rostopic info命令可以看到/darknet_ros/bounding_boxes话题的具体内容
rostopic info /darknet_ros/bounding_boxesType: darknet_ros_msgs/BoundingBoxesPublishers: * /darknet_ros (http://localhost:43545/)这个话题就是我们需要的目标检测框的信息将目标检测框输出到深度图我们就可以读取目标的深度
首先创建一个scripts文件夹创建ObjectLocation.py文件
touch ObjectLocation.py目标深度测距的代码思路首先导入rospy、cv2、numpy、darknet_ros_msgs等包创建一个目标定位的类实例化类的一些参数订阅深度图话题并转化为深度矩阵订阅目标检测框将坐标信息对齐到深度图中按照3x3滑动窗口遍历检测框进行中值滤波最后取中心深度作为目标的估计深度并发布距离话题
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import rospy
import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image
from darknet_ros_msgs.msg import BoundingBoxes
import numpy as np
from scipy.ndimage import median_filter
import mathclass ObjectLocation:def __init__(self):self.bridge CvBridge()self.depth_image Noneself.bounding_boxes Noneself.probability 0self.Class Noneself.distance 0self.centerx 0self.centery 0self.x_h 0self.y_h 0self.w_h 0cv2.destroyAllWindows()get depth distance from found object rectdef depthDistanceFromCoordinate(self, data):try:self.depth_image self.bridge.imgmsg_to_cv2(data, passthrough)depth_array np.array(self.depth_image, dtypenp.float32)filter_depth_array np.zeros_like(depth_array)if self.bounding_boxes ! None:for bounding_box in self.bounding_boxes:# bounding box coordinates # less than 0 and larger than width or heightxmin 0 if bounding_box.xmin 0 else bounding_box.xminxmax bounding_box.xmax if bounding_box.xmax len(depth_array[0]) else len(depth_array[0])ymin 0 if bounding_box.ymin 0 else bounding_box.yminymax bounding_box.ymax if bounding_box.ymax len(depth_array) else len(depth_array)dep_aver 0filter_depth_array median_filter(depth_array, size(3, 3))dep_aver filter_depth_array[int((ymin ymax) / 2), int((xmin xmax) / 2)]self.probability bounding_box.probabilityself.Class bounding_box.Classself.distance dep_averself.centerx (xmin xmax) / 2self.centery (ymin ymax) / 2rospy.loginfo(Class%s, Probability%f, Distance%f, self.Class, self.probability, self.distance)pub rospy.Publisher(/darknet_ros/distance, self.distance, queue_size 100)pub.publish(self.distance)except Exception as e:print(e)def bbox_callback(self, msg):self.bounding_boxes msg.bounding_boxesif __name__ __main__:od ObjectLocation()rospy.init_node(ObjectLocation, anonymousTrue)rospy.Subscriber(/darknet_ros/bounding_boxes, BoundingBoxes, od.bbox_callback)rospy.Subscriber(/camera/depth/image_rect_raw, Image, od.depthDistanceFromCoordinate)rate rospy.Rate(10)rate.sleep()rospy.spin()三、目标方位解算与导航点设定
1、相机成像原理
我们需要根据相机内外参去解算目标的方位相机内参外参原理参照下面链接依据成像原理我们可以将在像素坐标系下的目标映射到相机坐标系 https://zhuanlan.zhihu.com/p/389653208
2、Python实现目标定位
运行标定相机的demo就可以得到相机的内参外参矩阵我的是出厂就标定好的附带内参矩阵放在 home/wheeltec/.ros/camera_info/camera.yaml 文件里内参矩阵是相机出厂时就决定了的
image_width: 640
image_height: 480
camera_name: camera
camera_matrix:rows: 3cols: 3data: [ 581.88585, 0. , 314.2472 ,0. , 592.27138, 210.27091,0. , 0. , 1. ]
camera_model: plumb_bob
distortion_model: plumb_bob
distortion_coefficients:rows: 1cols: 5data: [0.221666, -0.575455, -0.014215, 0.003895, 0.000000]
rectification_matrix:rows: 3cols: 3data: [ 1., 0., 0.,0., 1., 0.,0., 0., 1.]
projection_matrix:rows: 3cols: 4data: [ 591.88599, 0. , 315.96148, 0. ,0. , 603.39893, 205.72873, 0. ,0. , 0. , 1. , 0. ]相机的外参矩阵则要确定机器人坐标系下的相机位姿才能将目标方位解算到机器人bse_link坐标系下。用Python程序设定导航目标点的主要通过ROS中名为move_base的动作服务器Action Server负责接收和处理导航目标我们将导航目标点位姿信息解算好发送到move_base节点即可。
在原有的ObjectLocation.py上导入actionlib、tf、move_base_msgs等包使用矩阵求逆加内积来将像素坐标系下的目标位置映射到相机坐标系再通过tf坐标变换映射到机器人坐标系实例化导航目标点将目标点位姿发送到move_base节点等待动作服务器响应即可
#!/usr/bin/env python
#-*- coding: utf-8 -*-
import rospy
import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image
from darknet_ros_msgs.msg import BoundingBoxes
import numpy as np
from scipy.ndimage import median_filter
import actionlib
from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal
import tf.transformations as tr
import mathclass ObjectLocation:def __init__(self):self.bridge CvBridge()self.depth_image Noneself.bounding_boxes Noneself.probability 0self.Class Noneself.distance 0self.centerx 0self.centery 0self.x_h 0self.y_h 0self.w_h 0cv2.destroyAllWindows()get depth distance from found object rectdef depthDistanceFromCoordinate(self, data):try:self.depth_image self.bridge.imgmsg_to_cv2(data, passthrough)depth_array np.array(self.depth_image, dtypenp.float32)filter_depth_array np.zeros_like(depth_array)if self.bounding_boxes ! None:for bounding_box in self.bounding_boxes:# bounding box coordinates # less than 0 and larger than width or heightxmin 0 if bounding_box.xmin 0 else bounding_box.xminxmax bounding_box.xmax if bounding_box.xmax len(depth_array[0]) else len(depth_array[0])ymin 0 if bounding_box.ymin 0 else bounding_box.yminymax bounding_box.ymax if bounding_box.ymax len(depth_array) else len(depth_array)dep_aver 0filter_depth_array median_filter(depth_array, size(3, 3))dep_aver filter_depth_array[int((ymin ymax) / 2), int((xmin xmax) / 2)]self.probability bounding_box.probabilityself.Class bounding_box.Classself.distance dep_averself.centerx (xmin xmax) / 2self.centery (ymin ymax) / 2rospy.loginfo(Class%s, Probability%f, Distance%f, self.Class, self.probability, self.distance)if self.Class pottedplant:fx 581.88585fy 592.27138cx 314.2472cy 210.27091K np.array([[fx, 0., cx], [0., fy, cy], [0., 0., 1.]])point_pixel np.array([self.centerx, self.centery, 1])point_camera np.dot(np.linalg.inv(K), point_pixel) * self.distanceself.y_h - point_camera[0] - 460self.x_h point_camera[2] 110orientation tr.quaternion_from_euler(0, 0, math.atan2(self.y_h, self.x_h))self.w_h orientation[3]rospy.loginfo(%s Goal location is x_h %f, y_h %f, w_h%f, pottedplant, self.x_h, self.y_h, self.w_h)self.movebase_callback()pub rospy.Publisher(/darknet_ros/distance, self.distance, queue_size 100)pub.publish(self.distance)except Exception as e:print(e)def movebase_callback(self):try:client actionlib.SimpleActionClient(move_base, MoveBaseAction)client.wait_for_server()goal MoveBaseGoal()goal.target_pose.header.frame_id base_linkgoal.target_pose.pose.position.x self.x_h * 4 / 5000goal.target_pose.pose.position.y self.y_h * 4 / 5000goal.target_pose.pose.orientation.w self.w_hclient.send_goal(goal)rospy.loginfo(move_base set goal success!)client.wait_for_result()except Exception as e:print(movebase_callback service failed)def bbox_callback(self, msg):self.bounding_boxes msg.bounding_boxesif __name__ __main__:od ObjectLocation()rospy.init_node(ObjectLocation, anonymousTrue)rospy.Subscriber(/darknet_ros/bounding_boxes, BoundingBoxes, od.bbox_callback)rospy.Subscriber(/camera/depth/image_rect_raw, Image, od.depthDistanceFromCoordinate)rate rospy.Rate(10)rate.sleep()rospy.spin()下面是演示结果其实还可以用其他滤波方法让深度估计更加精确用重采样方法让方位估计更加精准 总结
darknet_ros软件包将ROS和YOLO很好的融合在一起为机器人视觉任务开发提供了更多可能性。通过实时目标检测和识别机器人能够感知和理解环境实现人机交互提高安全性并在各种应用中发挥更智能和自主的作用。通过实时目标检测和识别可以帮助机器人识别不同类型的物体并根据目标物体的位置和特征来理解当前场景。这对于机器人在导航、路径规划和任务执行中具有重要意义。