欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

YOLO通过darknet ros包实现物体识别

程序员文章站 2022-07-14 22:16:48
...

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文件
YOLO通过darknet ros包实现物体识别把Makefile文件中的GPU,CUDNN,OPENCV都设置为 1, 然后保存。
YOLO通过darknet ros包实现物体识别
回到~/catkin_ws 目录输入catkin_make
YOLO通过darknet ros包实现物体识别
如果成功编译的话应该是这样的
YOLO通过darknet ros包实现物体识别此时已经把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 文件。
YOLO通过darknet ros包实现物体识别
在 ros.yaml 文件里第一段就是要订阅的话题名,我们把默认的话题名改为我们刚刚自己定义的 /image_yolo 然后保存,这样 darknet 包运行的时候就能接收到图像的消息了。
YOLO通过darknet ros包实现物体识别

测试

第一步: roslaunch libuvc_camera.launch 启动我们的 Theta s 相机。
YOLO通过darknet ros包实现物体识别
第二部:打开第二个终端运行我们的上面的程序
YOLO通过darknet ros包实现物体识别
目前为止我们已经把变换后的图像发送到了 /image_yolo 话题上了,darknet 订阅的话题也改完了只需要启动 darknet 包就可以了。

第三步:打开第三个终端输出 roslaunch darknet_ros darknet_ros.launch 运行
YOLO通过darknet ros包实现物体识别
好了这时结果出来了
YOLO通过darknet ros包实现物体识别
识别准确率不是很高, 因为我的这个用的是 yolov2-tiny 模型,计算量相对小,在 gtx1060 6g 的显卡下fps在110左右。
darknet 包总共可以使用 yolov2-tiny, yolov2, yolov3 这几个模型,我们也可以做一下自定义的修改。修改位置在 ~/catkin_ws/src/darknet_ros/darknet_ros/launch 文件夹下的 darknet_ros.launch 文件。
YOLO通过darknet ros包实现物体识别把文件中默认的 yolov2-tiny.yaml 改成 /config 目录下的 yolov2.yaml 或 yolov3.yaml 就可以指定了。

yolov2
识别的物体数量减少了,fps大概38左右。
YOLO通过darknet ros包实现物体识别

yolov3
识别的物体又多了,fps大概17左右,感觉准确率提高了不少基本全对了。。

YOLO通过darknet ros包实现物体识别