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 未经允许请勿用于商业用途)

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