ROS学习笔记(三):在ROS中使用USB网络摄像头传输图像

在上节已经实现了单张图片的ROS实现,而在现实中,我们一般是使用摄像头来获取图像,这次要实现在ROS中使用摄像头传输图像,我使用的是罗技的usb网络摄像头,首先我们需要获取摄像头的型号,如下所示:

yake@yake-K42JE:~$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 003: ID 04f2:b1e5 Chicony Electronics Co., Ltd 
Bus 002 Device 003: ID 046d:c058 Logitech, Inc. M115 Mouse
Bus 002 Device 008: ID 046d:0825 Logitech, Inc. Webcam C270

我所使用的是罗技的C270网络摄像头.接下来我们要为摄像头安装驱动,我使用的是cheese点击打开链接,这个驱动的好处是在ubuntu环境下直接apt-get获得

yake@yake-K42JE:~$ sudo apt-get install cheese

安装完成后,插上摄像头可以发现在dev/目录下多了一个viedo0的设备,这个说明摄像头驱动已经安装完成.接下来开始在ROS中使用它.使用的方式是通过opencv函数来实现.

首先还是要创建一个包,写一个驱动摄像头的文件,命名为my_publisher.cpp,作用是获取图像并打包成ros格式发送出去,创建包的方法与单张图片一样,my_publisher.cpp内容如下:

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
#include <sstream> // for converting the command line parameter to integer

int main(int argc, char** argv)
{
  // Check if video source has been passed as a parameter
  if(argv[1] == NULL) 
	{
     	    ROS_INFO("argv[1]=NULL\n");
 	    return 1;
	}

  ros::init(argc, argv, "image_publisher");
  ros::NodeHandle nh;
  image_transport::ImageTransport it(nh);
  image_transport::Publisher pub = it.advertise("camera/image", 1);

  // Convert the passed as command line parameter index for the video device to an integer
  std::istringstream video_sourceCmd(argv[1]);
  int video_source;
  // Check if it is indeed a number
  if(!(video_sourceCmd >> video_source)) 
  {
      ROS_INFO("video_sourceCmd is %d\n",video_source);
      return 1;
  }

  cv::VideoCapture cap(video_source);
  // Check if video device can be opened with the given index
  if(!cap.isOpened()) 
  {
      ROS_INFO("can not opencv video device\n");
      return 1;
  }
  cv::Mat frame;
  sensor_msgs::ImagePtr msg;

  ros::Rate loop_rate(5);
  while (nh.ok()) {
    cap >> frame;
    // Check if grabbed frame is actually full with some content
    if(!frame.empty()) {
      msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame).toImageMsg();
      pub.publish(msg);
      //cv::Wait(1);
    }

    ros::spinOnce();
    loop_rate.sleep();
  }
}

再写一个my_subscriber.cpp,作用是获取ROS图像并显示,内容如下:

#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>

void imageCallback(const sensor_msgs::ImageConstPtr& msg)
{
  try
  {
    cv::imshow("view", cv_bridge::toCvShare(msg, "bgr8")->image);
   // cv::WaitKey(30);
  }
  catch (cv_bridge::Exception& e)
  {
    ROS_ERROR("Could not convert from '%s' to 'bgr8'.", msg->encoding.c_str());
  }
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "image_listener");
  ros::NodeHandle nh;
  cv::namedWindow("view");
  cv::startWindowThread();
  image_transport::ImageTransport it(nh);
  image_transport::Subscriber sub = it.subscribe("camera/image", 1, imageCallback);
  ros::spin();
  cv::destroyWindow("view");
}

接下来要把设计到的各种包和opencv在CmakeList中声明一下,添加以下语句

find_package(OpenCV REQUIRED)
# add the publisher example
add_executable(my_publisher src/my_publisher.cpp)

target_link_libraries(my_publisher ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})

# add the subscriber example
add_executable(my_subscriber src/my_subscriber.cpp)
target_link_libraries(my_subscriber ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})

将这个包进行编译

yake@yake-K42JE:~/ros_ws$ catkin_make

编译过程可能会出现错误,其中一个就是cv::WaitKey不能识别,这个问题到最后依然没有解决,我是直接把它注释掉,这样也没什么影响.接下来开始运行程序,首先启动ROS.

yake@yake-K42JE:~$ roscore

运行my_publisher节点.(如果运行不起来,需要先source devel/setup.bash)

yake@yake-K42JE:~/video_ros$ rosrun learning_image_transport my_publisher 0
这时候会看到我们的摄像头灯已经亮起来了,0代表默认摄像头,如果有多个摄像头,则第二个是1,依次类推.

接下来运行my_subscriber节点来接收图像

yake@yake-K42JE:~/video_ros$ rosrun learning_image_transport my_subscriber

这时候如果没有错误的话就会弹出图像窗口

ROS学习笔记(三):在ROS中使用USB网络摄像头传输图像_第1张图片
可以看到我们摄像头传输出来的图像,到此,整个程序结束!


你可能感兴趣的:(linux,ARM,ROS,机器人平台)