ROS Qt5 librviz人機交互界面開發十二(訂閱圖像話題並在界面中顯示)

本系列教程文章專欄:

ROS機器人GUI程序開發

本系列課程已上線古月學院,歡迎感興趣的小夥伴訂閱:

  1. ROS Qt開發環境搭建以及基礎知識介紹
  2. ROS人機交互軟件的界面開發
  3. ROS Rviz組件開發方法

在這裏插入圖片描述
開發交流QQ羣: 797497206
完整項目代碼:
github


這篇文章主要實現Qt中訂閱Ros圖像話題,並在界面中Label上顯示

一,實現效果

在這裏插入圖片描述

二,添加依賴

首先在功能包的CMakeLists.txt中添加依賴
(ensor_msgs
cv_bridge
image_transport)

find_package(catkin REQUIRED COMPONENTS rviz roscpp sensor_msgs
    cv_bridge
    std_msgs
    image_transport
    )

三,訂閱話題

 ros::NodeHandle n;
 image_transport::ImageTransport it_(n);
 image_sub=it_.subscribe(topic.toStdString(),100,&QNode::imageCallback0,this);

四,回調函數處理圖片數據


 //圖像話題的回調函數
 void QNode::imageCallback0(const sensor_msgs::ImageConstPtr& msg)
 {
     cv_bridge::CvImagePtr cv_ptr;

     try
       {
         //深拷貝轉換爲opencv類型
         cv_ptr = cv_bridge::toCvCopy(msg, msg->encoding);
         QImage im=Mat2QImage(cv_ptr->image);
         emit Show_image(0,im);
       }
       catch (cv_bridge::Exception& e)
       {

         log(Error,("video frame0 exception: "+QString(e.what())).toStdString());
         return;
       }
 }

在toCvCopy函數中,第二個參數需要指明圖像的編碼格式,否者會轉換失敗,通過msg->encoding可以獲取到圖像話題的編碼格式,傳入即可。

 //深拷貝轉換爲opencv類型
         cv_ptr = cv_bridge::toCvCopy(msg, msg->encoding);

其中:

 emit Show_image(0,im);

發送自定義信號

且將Mat類型的圖片轉爲QImage類型圖片函數:
Mat2QImage

 QImage QNode::Mat2QImage(cv::Mat const& src)
 {
   QImage dest(src.cols, src.rows, QImage::Format_ARGB32);

   const float scale = 255.0;

   if (src.depth() == CV_8U) {
     if (src.channels() == 1) {
       for (int i = 0; i < src.rows; ++i) {
         for (int j = 0; j < src.cols; ++j) {
           int level = src.at<quint8>(i, j);
           dest.setPixel(j, i, qRgb(level, level, level));
         }
       }
     } else if (src.channels() == 3) {
       for (int i = 0; i < src.rows; ++i) {
         for (int j = 0; j < src.cols; ++j) {
           cv::Vec3b bgr = src.at<cv::Vec3b>(i, j);
           dest.setPixel(j, i, qRgb(bgr[2], bgr[1], bgr[0]));
         }
       }
     }
   } else if (src.depth() == CV_32F) {
     if (src.channels() == 1) {
       for (int i = 0; i < src.rows; ++i) {
         for (int j = 0; j < src.cols; ++j) {
           int level = scale * src.at<float>(i, j);
           dest.setPixel(j, i, qRgb(level, level, level));
         }
       }
     } else if (src.channels() == 3) {
       for (int i = 0; i < src.rows; ++i) {
         for (int j = 0; j < src.cols; ++j) {
           cv::Vec3f bgr = scale * src.at<cv::Vec3f>(i, j);
           dest.setPixel(j, i, qRgb(bgr[2], bgr[1], bgr[0]));
         }
       }
     }
   }

   return dest;
 }

五,鏈接信號

在mainwindows.cpp鏈接剛纔回調函數中發出的信號:

//鏈接槽函數
   connect(&qnode,SIGNAL(Show_image(int,QImage)),this,SLOT(slot_show_image(int,QImage)));

六,槽函數中處理信號

在槽函數中更新ui界面顯示,在lable上顯示圖像:

void MainWindow::slot_show_image(int frame_id, QImage image)
{
 
        ui.label_video0->setPixmap(QPixmap::fromImage(image).scaled(ui.label_video0->width(),ui.label_video0->height()));
}

七,完整項目地址

在我自己學習的過程中目前發現沒有相關類似完整開源項目,爲了幫助其他人少走彎路,我決定將自己的完整項目開源:
github
創作不易,如果本教程對你有幫助,關注或點個贊吧,或者github標個星哦~~
您的支持就是我最大的動力~

(轉載請註明作者和出處:https://blog.csdn.net/qq_38441692 未經允許請勿用於商業用途)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章