YOLO通过darknet ros包实现物体识别
darknet ros 物体识别
在之前的《ubuntu系统THETA S全景相机 通过ROS图像变换 》这篇博客中,介绍了将图像Theta S原图像变换成全景图像。本篇博客介绍通过darknet ros包对全景图像进行物体识别。darknet ros包是对YOLO的在ros系统下的实现。下载地址在github。
darknet ros 调试
安装好darknet包之后,需要对里面的一些功能进行自定义的设置。darknet 可以用CPU和GPU两种模式运行。根据作者所述GPU模式比CPU模式快500倍。如果用GPU模式需要安装cuda,相关安装教程网上有不少不错的可以参考。下面介绍一下把 darknet 包设置为GPU模式。
需要修改的文件地址在catkin_ws目录下~/catkin_ws/src/darknet_ros/darknet
的Makefile文件
把Makefile文件中的GPU,CUDNN,OPENCV都设置为 1, 然后保存。
回到~/catkin_ws
目录输入catkin_make
如果成功编译的话应该是这样的
此时已经把darknet设置成GPU模式了,接下来对这darknet包发送图像信息将就可以了。
发送图像信息
这里对《ubuntu系统THETA S全景相机 通过ROS图像变换 》这篇博客中的程序进行改进,加入一个消息的发布功能,将变换完的图像发送到 /image_yolo
话题。程序如下
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*
import rospy
from sensor_msgs.msg import Image
import cv2
import cv_bridge
import numpy as np
class Follower:
def __init__(self):
self.bridge = cv_bridge.CvBridge()
self.image_sub = rospy.Subscriber('/image_raw', Image, self.image_callback)
self.image_pub = rospy.Publisher('/image_yolo', Image)
def image_transfer(self, img):
self.vertex = 640
self.src_cx = 319
self.src_cy = 319
self.src_r = 283
self.src_cx2 = 1280 - self.src_cx
map_x = np.zeros((self.vertex, self.vertex*2))
map_y = np.zeros((self.vertex, self.vertex*2))
range_arr_y = np.array([range(self.vertex)])
range_arr_x = np.array([range(self.vertex*2)])
phi1 = (np.pi * range_arr_x) / self.vertex
theta1 = (np.pi * range_arr_y.T) / self.vertex
X = np.sin(theta1) * np.cos(phi1)
Y = np.sin(theta1) * np.sin(phi1)
Z = np.cos(theta1)
phi2 = np.arccos(- X)
theta2 = np.sign(Y) * np.arccos(-Z/np.sqrt(Y*Y + Z*Z))
map_x = np.squeeze(np.where([phi2 < np.pi / 2], self.src_r * (phi2 / np.pi * 2) * np.cos(theta2) + self.src_cx\
, self.src_r * ((np.pi - phi2)/np.pi * 2) * np.cos(np.pi - theta2) + self.src_cx2))
map_y = np.squeeze(np.where([phi2 < np.pi / 2], self.src_r * (phi2 / np.pi * 2) * np.sin(theta2) + self.src_cy\
, self.src_r * ((np.pi - phi2)/np.pi * 2) * np.sin(np.pi - theta2) + self.src_cy))
map_x = map_x.astype('float32')
map_y = map_y.astype('float32')
img = cv2.remap( img, map_x, map_y, cv2.INTER_LINEAR, cv2.BORDER_CONSTANT)
img = cv2.resize(img, (0, 0), fx=0.7, fy=0.7, interpolation=cv2.INTER_CUBIC)
return img
def image_callback(self,msg):
image = self.bridge.imgmsg_to_cv2(msg,desired_encoding='bgr8')
image = self.image_transfer(image)
# cv2.imshow("a",image)
# cv2.waitKey(1)
try:
self.image_pub.publish(self.bridge.cv2_to_imgmsg(image, "bgr8"))
except CvBridgeError as e:
print('error')
rospy.init_node('follower_1')
follower = Follower()
rospy.spin()
此时图像消息己经发布到了 /image_yolo
话题,然而 darknet 目前还没有订阅我们刚刚自定义的话提,所以还需要对 darknet 配置文件进行修改。修改的地址在 /catkin_ws/src/darknet_ros/darknet_ros/config
目录下的 ros.yaml 文件。
在 ros.yaml 文件里第一段就是要订阅的话题名,我们把默认的话题名改为我们刚刚自己定义的 /image_yolo 然后保存,这样 darknet 包运行的时候就能接收到图像的消息了。
测试
第一步: roslaunch libuvc_camera.launch 启动我们的 Theta s 相机。
第二部:打开第二个终端运行我们的上面的程序
目前为止我们已经把变换后的图像发送到了 /image_yolo 话题上了,darknet 订阅的话题也改完了只需要启动 darknet 包就可以了。
第三步:打开第三个终端输出 roslaunch darknet_ros darknet_ros.launch 运行
好了这时结果出来了
识别准确率不是很高, 因为我的这个用的是 yolov2-tiny 模型,计算量相对小,在 gtx1060 6g 的显卡下fps在110左右。
darknet 包总共可以使用 yolov2-tiny, yolov2, yolov3 这几个模型,我们也可以做一下自定义的修改。修改位置在 ~/catkin_ws/src/darknet_ros/darknet_ros/launch
文件夹下的 darknet_ros.launch 文件。
把文件中默认的 yolov2-tiny.yaml 改成 /config 目录下的 yolov2.yaml 或 yolov3.yaml 就可以指定了。
yolov2
识别的物体数量减少了,fps大概38左右。
yolov3
识别的物体又多了,fps大概17左右,感觉准确率提高了不少基本全对了。。