ROS-indigo釋出Mat影象以及解決cv_bridge與OpenCV3.3.1版本不相容問題
1、在ROS-indigo中釋出Mat型別的影象
本人近期開始在ROS上研究視覺定位與導航,過程中不免用要到OpenCV庫對影象進行採集和處理。如果我們想把OpenCV中採集或處理以後的Mat格式的影象利用ROS以topic的形式釋出出去,那麼我們就要藉助cv_bridge這個功能包。cv_bridge就像它的名字一樣,是ROS與OpenCV之間連線的橋樑。cv_bridge位於vision_opencv功能包集下的cv_bridge功能包內。
cv_bridge定義了一個CvImage資料類,該型別包括了OpenCV影象、編碼和一個ROS標頭檔案。CvImage準確包含了sensor_msgs/Image具有的資訊,因此可以在兩種表達方式之間切換。
ROS釋出Mat影象的兩種常用方法
(1)讀取本地圖片釋出
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "image_publisher");
ros::NodeHandle nh;
image_transport: :ImageTransport it(nh);
image_transport::Publisher pub = it.advertise("camera/image", 1);
cv::Mat image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);
sensor_msgs::ImagePtr msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", image).toImageMsg();
ros::Rate loop_rate(5);
while (nh.ok()) {
pub.publish(msg);
ros: :spinOnce();
loop_rate.sleep();
}
}
(2)獲取本地相機或視訊檔案釋出
#include <ros/ros.h>
#include <image_transport/image_transport.h>
#include <opencv2/highgui/highgui.hpp>
#include <cv_bridge/cv_bridge.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "image_publisher");
ros::NodeHandle nh;
image_transport::ImageTransport it(nh);
image_transport::Publisher pub = it.advertise("camera/image", 1);
cv::VideoCapture TheVideoCapture;
TheVideoCapture.open(0);
cv::Mat image;
char key;
ros::Rate loop_rate(100);
while (nh.ok() && key != 27) {
if(TheVideoCapture.grab()){
TheVideoCapture.retrieve(image);
cv_bridge::CvImage out_msg;
out_msg.header.stamp = ros::Time::now();
out_msg.encoding = sensor_msgs::image_encodings::BGR8;
out_msg.image = image;
pub.publish(out_msg.toImageMsg());
// cv::imshow("image", image);
key = cv::waitKey(1);
}
loop_rate.sleep();
}
以上兩塊程式碼都需要新增依賴image_transport和cv_bridge(如何新增依賴這裡不再贅述,個人認為在Roboware_Studio裡面比較好操作),如果不出現OpenCV版本相容的問題,編譯完成後它們都是可以以ROS節點的形式正常執行的。但是不幸的是,博主在一開始用第二種方法釋出topic的時候就遇到了cv_bridge與OpenCV3不相容的問題,導致程式無法執行,下面介紹一種解決該問題的方法。
2、對ROS-indigo中OpenCV版本不相容問題的一種解決方法
由於某些原因,博主需要用到OpenCV3以上的版本,但據網上介紹說ROS-indigo版本中的cv_bridge好像預設是依賴OpenCV2.4.8編譯的,所以通常會與我們自己安裝的較高版本的OpenCV3產生一些衝突。但是我又不想換高版本的ROS,所以,在網上翻閱大神們的解決方案,說可以解除安裝預設安裝的cv_bridge,重新編譯安裝。鄙人試了一下,果然解決了我的問題,現將該方法總結一下,供大家參考。
- Step1:
首先確保你的Ubuntu已正確安裝了OpenCV3某版本,並可以find到它的安裝路徑,不然 cv_bridge 是無法編譯的。你可以嘗試在終端執行以下命令來檢視當前系統安裝的OpenCV版本。
$ pkg-config --modversion opencv
正常情況下它會顯示你的OpenCV版本號,比如博主的執行結果為:
$ 3.3.1
- Step2:
解除安裝ROS-indigo預設安裝的cv_bridge,在終端執行命令:
$ sudo apt-get remove ros-indigo-cv-bridge
敲完命令列回車輸入使用者密碼,我們會發現系統提示說要解除安裝好多軟體包,這是因為我們在解除安裝cv_bridge功能包時,其他所有依賴於它的功能包也要同時被解除安裝,不然cv_bridge沒了這些功能包也就沒法用了(我是這麼理解的)。不過不用擔心,卸完以後我們還可以再編譯安裝嘛,所以,輸入 y 敲回車狠心解除安裝。
- Step3
解除安裝完cv_bridge我們就要去GitHub上下載原始碼自己編譯了(indigo版本的原始碼地址在這裡),我們也可以通過命令列下載。博主預設親們至少已經有了自己的一個ROS工作空間,我的 ~/catkin_ws 工作空間就是專門用來編譯重灌ROS原始碼的,所以我的命令列如下:
$ cd ~/catkin_ws/src
$ git clone https://github.com/ros-perception/vision_opencv.git --branch=indigo
$ cd ..
$ catkin_make
以上工作空間可自行修改,正常情況下編譯不會出現問題,除非你的OpenCV安裝有錯誤。如果沒有 source 過你的工作空間的要把工作空間中的 devel/setup.bash 新增到 ~/.bashrc 中,以我的為例:
$ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
$ source ~/.bashrc
- Step4
因為前面在解除安裝 cv_bridge 時把依賴於它的其他很多功能包也同時解除安裝了,導致很多功能無法使用,比如我經常要用到的 image_view 功能包,所以,現在就要把其他的功能包用同樣的方法也裝上。我們可以通過在ROS官網查詢 image_view 來定位它的原始碼地址,在這裡可以發現,image_view其實是功能包集image_pipeline中的一個功能包,所以我們直接把 image_pipeline下載下來編譯安裝就行了(前面一併解除安裝的其他功能包大部分都在這個功能包集裡面)。
$ cd ~/catkin_ws/src
$ git clone https://github.com/ros-perception/image_pipeline --branch=indigo
$ cd ..
$ catkin_make
- Step5
至此,cv_bridge 與 OpenCV3 的版本相容問題基本已經解決了,還有其他一些卸掉的功能包,用到的時候可以用上述同樣的方法再安裝。鄙人的方法可能不是太好,如果大神們有更好的解決方案,希望不吝賜教!