ROS下配置OpenCV

一.環境準備

Ubuntu16.04
ROS-kinetic
opencv3.3.1
video-stream-opencv(Python)
或者usb_cam (c++) 一個USB攝像頭

 

video-stream-opencv是USB攝像頭驅動,關於它的介紹,請看github:https://github.com/ros-drivers/video_stream_opencv 

 

二. 在ROS下創建工作空間

在歡迎界面, 點擊「新建工作區」按鈕(或選擇「文件 - 新建工作區」 ) , 選擇路徑並
填寫工作區名稱, 如「catkin_ws」, 則會創建一個名爲「catkin_ws」工作區, 並顯示在資源管理
器窗口:

三、在工作空間下創建程序包

1、安裝video-stream-opencv

$ cd ~/catkin_ws/src/
$ git clone https://github.com/ros-drivers/video_stream_opencv.git
$ cd ..
$ catkin_make

2、編譯好之後,添加編譯好的文件到環境變量:

$ source devel/setup.bash

3、測試是否安裝成功

在終端輸入:

$ rosrun video_stream_opencv test_video_resource.py 0  #後面的0是攝像頭編號

https://yq.aliyun.com/ziliao/203675

https://blog.csdn.net/Gpwner/article/details/78961362

1、安裝usb_cam

進入創建好的工作空間:

cd ~/catkin_ws/src
git clone https://github.com/bosch-ros-pkg/usb_cam.git

然後退回到工作空間,編譯代碼:

cd ~/catkin_ws
catkin_make

編譯好之後,添加編譯好的文件到環境變量:

source devel/setup.bash

2、然後接下來測試usb_cam:
先運行usb_cam節點:

rosrun usb_cam usb_cam_node

運行上面命令發現沒有顯示圖像,只看到攝像頭打開了。這是因爲ros發佈的topic是/usb_cam/image_raw。新打開一個終端,可以通過如下命令查看:

rostopic list

所以我們需要運行如下命令纔可以看到圖像:

rosrun image_view image_view image:=/usb_cam/image_raw

或者直接寫launch文件,這樣就不用一個終端運行node,一個終端看圖像。新建usb_cam_test.launch:

<launch>
  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
    <param name="video_device" value="/dev/video0" />
    <param name="image_width" value="640" />
    <param name="image_height" value="480" />
    <param name="pixel_format" value="yuyv" />
    <param name="camera_frame_id" value="usb_cam" />
    <param name="io_method" value="mmap"/>
  </node>
  <node name="image_view" pkg="image_view" type="image_view" respawn="false" output="screen">
    <remap from="image" to="/usb_cam/image_raw"/>
    <param name="autosize" value="true" />
  </node>
</launch>

然後終端直接運行:

roslaunch usb_cam usb_cam_test.launch

 

右鍵點擊 ROS 工作區下的「src」, 選擇「新建 ROS 包」,輸入包名稱及其依賴包的名
稱,如:
robot_vision roscpp std_msgs cv_bridge image_transport sensor_msgs

回車後,會創建名爲「robot_vision 」、以「roscpp std_msgs cv_bridge image_transport sensor_msgs」爲依賴的 ROS 包:

3、創建.cpp源文件

  在創建的程序包的src文件中創建一個文本文件,並命名爲opencv_test.cpp,選擇添加到可執行文件中。具體代碼和註釋如下:

#include<ros/ros.h> //ros標準庫頭文件
#include<image_transport/image_transport.h>/* image_transport 頭文件用來在ROS系統中的話題上發佈和訂閱圖象消息*/
#include<cv_bridge/cv_bridge.h>/* cv_bridge中包含CvBridge庫 */
#include<sensor_msgs/image_encodings.h>/* ROS圖象類型的編碼函數*/
#include<iostream> //C++標準輸入輸出庫

//OpenCV3標準頭文件
#include<opencv2/opencv.hpp>


static const std::string OPENCV_WINDOW = "Image window"; //定義輸入窗口名稱


//定義一個轉換的類
class ImageConverter
{
private:
    ros::NodeHandle nh_; //定義ROS句柄
    image_transport::ImageTransport it_; //定義一個image_transport實例
    image_transport::Subscriber image_sub_; //定義ROS圖象接收器
    image_transport::Publisher image_pub_; //定義ROS圖象發佈器
public:
    ImageConverter()
      :it_(nh_) //構造函數
    {    //這裏是usb攝像頭的topic,官網默認是/camera/image_raw,這裏修改爲usb攝像頭/usb_cam/image_raw。
              //定義圖象接受器,訂閱話題是「/usb_cam/image_raw」
        image_sub_ = it_.subscribe("/usb_cam/image_raw", 1, &ImageConverter::convert_callback, this); 
        image_pub_ = it_.advertise("/image_converter/output_video", 1); //定義圖象發佈器
        //初始化輸入輸出窗口
        cv::namedWindow(OPENCV_WINDOW);
    }
    ~ImageConverter() //析構函數
    {
         cv::destroyWindow(OPENCV_WINDOW);
    }
    /*這是一個ROS和OpenCV的格式轉換回調函數,將圖象格式從sensor_msgs/Image--->cv::Mat*/
    void convert_callback(const sensor_msgs::ImageConstPtr& msg) 
    {
        cv_bridge::CvImagePtr cv_ptr; // 聲明一個CvImage指針的實例

        try
        {   //將ROS消息中的圖象信息提取,生成新cv類型的圖象,複製給CvImage指針
            cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
        }
        catch(cv_bridge::Exception& e)  //異常處理
        {
            ROS_ERROR("cv_bridge exception: %s", e.what());
            return;
        }

        image_process(cv_ptr->image); //得到了cv::Mat類型的圖象,在CvImage指針的image中,將結果傳送給處理函數   
         // Output modified video stream
         image_pub_.publish(cv_ptr->toImageMsg());
    }
    /*這是圖象處理的主要函數,一般會把圖像處理的主要程序寫在這個函數中。這裏的例子只是一個彩色圖象到灰度圖象的轉化
    到時候要修改就修改這裏的函數即可    */
    void image_process(cv::Mat& img) 
    {
        // Draw an example circle on the video stream 
        if (img.rows > 60 && img.cols > 60) 
            {
                cv::circle(img, cv::Point(50, 50), 10, CV_RGB(255,0,0)); 
            }
        // Update GUI Window
         cv::imshow(OPENCV_WINDOW, img);
         cv::waitKey(5);
    }
};

//主函數
int main(int argc, char** argv)
{
    ros::init(argc, argv, "image_converter");
    ImageConverter ic;
    ros::spin();
    return 0;
}

 

4.CMakeLists.txt

進入包的目錄,修改CmakeList.txt,在文件最後添加:

 
   
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
add_executable(opencv_test src/opencv_test.cpp) #根據自己的文件名修改裏面opencv_test的內容
target_link_libraries(opencv_test ${catkin_LIBRARIES} ${OpenCV_LIBRARIES})

 

其中, Debug 和 Release 選項分別表示構建調試版和發佈版, 默認構建方式爲本地構建 。

有兩種構建方法:

編譯完成後,執行:

source devel/setup.bash

 

先打開一個終端運行roscore,用以節點之間的通信交互。
再打開一個終端運行rosrun usbcam usbcam_node
再打開一個終端運行rosrun opencvtest opencv_testcam
之後即可看到opencv處理後攝像頭的圖像。

如果找不到包,執行命令

rospack profile
source ~/catkin_ws/devel/setup.bash