当前位置: 首页 > news >正文

QT集成intel RealSense 双目摄像头

最近一个小项目,用到了双目相机,选用了Intel的RealSense双目相机。功能很简单,就是识别某一个物体,然后对对这个物体进行操作。具体功能随后再说,这里只介绍QT如何集成IntelRealSense相机,就是下面这个。

首先还是下载SDK,https://www.intelrealsense.com/developers/。这个页面有下载地址。不过下载地址是在github上,然后就比较尴尬,很难下载。下载安装完成以后,会得到一个官方提供的查看软件Intel RealSense Viewer。打开可以看图像,见下图。

相机获取了两个图像,上面颜色表示的是深度图。下面是常规照片。还可以用两个图像,合成一个3D的模型。见下图。

除查看软件外,还有用于开发的SDK和样例代码,文件夹结构如下图:

 大致看了一下官方提供的样例代码,都可以跑起来,但是都用了第三方的显示库,和opencv。并且都是用的VS。由于这个项目前期用的QT做的设备控制功能,再换VS可能性不大,所以需要在QT里面集成一下。网上搜了一下,资料很少,也不完全能用,还是自己弄把,正文开始:

第一步,给SDK相关文件拷贝到项目路径,lib,include,以及bin,就是dll。include是头文件,写代码的时候用的,只有头文件,没有具体实现,所以还需要lib文件,有了lib才能编译。编译完以后,再运行,就需要用dll文件。

第二步:在pro文件包含include文件夹,和lib文件。lib文件用的是x64。-L是lib文件所在路径,$$PWD是当前路径。-l是lib文件名称,后面是lib文件不带后缀。-L和-l两个后面都是没有空格,直接写。

第三步:创建一个Camera类,继承自QThread,在子线程获取图像,不卡主界面。

#include <QObject>
#include <QThread>
#include <librealsense2/rsutil.h>//包含sdk文件
#include <librealsense2/rs.hpp>//包含sdk文件
#include <QImage>
class Camera :public QThread
{Q_OBJECT
public:Camera();static Camera* getInstance();//单例模式void startCapture();        //开始采集void stopCapture();         //结束采集void run() override;        //线程函数
private slots:void doCam(int code,QString msg);   //用于接收线程信息,并弹出消息框
signals:void onCameraEvent(int code,QString msg);   //线程内部发送消息void onImage(QImage img);                   //线程内部发送图像采集成功信号private:bool isCapture;             //是否采集中rs2::pipeline pipe;         //采集采集对象};#endif // CAMERA_H

第三步:开始采集,按照官方SDK说法,只需要一个rs2::pipelie对象,start()开始采集,然后pipe.wait_for_frames()就ok了。

/*** @brief Camera::run 线程函数,用于打开相机和采集图像*/
void Camera::run(){try {pipe.start();       //尝试打开相机}catch (const std::exception& e){emit onCameraEvent(1, e.what() ); //如果没有成功,发送给主线程一个消息return;//返回,不继续了}emit onCameraEvent(0,"相机打开成功"); //如果打开成功,也发送一个rs2::colorizer color_map;//用于将深度数据,转换为图像数据色彩数据的map,isCapture=true;//循环控制变量while(isCapture){try {rs2::frameset data= pipe.wait_for_frames(); //获取一帧数据          rs2::frame color=data.get_color_frame();                    //获取彩色图像           const int w = color.as<rs2::video_frame>().get_width();     //获取图像宽度const int h = color.as<rs2::video_frame>().get_height();    //获取图像高度qDebug()<<"get frame"<<"width "<<w<<"height"<<h;}catch (const std::exception& e) {emit onCameraEvent(2,e.what());}}
}

代码运行,输出下面的结果,表示图像采集到了。这是获取的彩色图像的数据。

第四步:显示图像,官方提供的SDK是用openCV显示的,奈何只提供了VC编译的库,没有minGW版本的opencv库。无法使用。所以放弃opencv。 官方使用opencv代码如下:

// Create OpenCV matrix of size (w,h) from the colorized depth dataMat image(Size(w, h), CV_8UC3, (void*)depth.get_data(), Mat::AUTO_STEP);// Update the window with new dataimshow(window_name, image);

不难发现,这个图像的数据,实际上就是24位的RGB数据,也就是说,是标准的图像数据。有了这个结果,就简单了。不能用opencv,那就用QImage。反正是一样的用法,代码如下:

       rs2::frameset data= pipe.wait_for_frames(); //获取一帧数据          rs2::frame color=data.get_color_frame();                    //获取彩色图像           const int w = color.as<rs2::video_frame>().get_width();     //获取图像宽度const int h = color.as<rs2::video_frame>().get_height();    //获取图像高度qDebug()<<"get frame"<<"width "<<w<<"height"<<h;QImage img((uchar*)color.get_data(),w,h,QImage::Format_RGB888); //创建一个图片emit onImage(img);                                          //图片发送给主线程,mainwindow接收,并显示一下。

成功打开彩色图片

第五步:获取深度图像。咱们的目标是获取深度图。按官方说法,使用data.get_depth_frame();就可以。见下面代码:

    rs2::frame depth=data.get_depth_frame();                  //获取深度数据const int w = depth.as<rs2::video_frame>().get_width();     //获取图像宽度const int h = depth.as<rs2::video_frame>().get_height();    //获取图像高度qDebug()<<"get frame"<<"width "<<w<<"height"<<h;QImage img((uchar*)depth.get_data(),w,h,QImage::Format_RGB888); //创建一个图片emit onImage(img);                                          //图片发送给主线程,mainwindow接收,并显示一下。

运行,可以获取宽高,但是程序崩溃了。一般情况下,深度图像是单通道的,也就是说是一个8位灰度图或者是16位的灰度图。通过查看源码,确实是16位灰度图。

 创建QImage的时候,换成Grayscale16,见下图:

QImage img((uchar*)depth.get_data(),w,h,QImage::Format_Grayscale16); //创建一个图片

依稀能看出来是有数据的,但是直接显示不太好看,官方提供了一个深度转色彩的功能.apply_filter(color_map);可以转换为便于观看的色彩图片。

 完整Camera类代码:

#include "camera.h"
#include <QDebug>
#include <QException>
#include <common.h>Camera::Camera()
{connect(this,&Camera::onCameraEvent,this,&Camera::doCam);//链接线程内部的信号
}
/*** @brief Camera::getInstance 单例模式* @return*/
Camera* Camera::getInstance(){static Camera* ins=NULL;//static代码,唯一对象if(ins==NULL)ins=new Camera();//创建一个实力return ins;
}void Camera::startCapture(){loading("打开摄像头",0);//显示打开摄像头弹窗,一直显示,直到成功或是失败this->start();//开始子线程
}
/*** @brief Camera::stopCapture 停止采集*/
void Camera::stopCapture(){isCapture=false;//退出子线程pipe.stop();//停止相机
}
/*** @brief Camera::doCam 接收线程的消息,并弹窗显示* @param code 消息编码,0表示成功* @param msg 消息内容*/
void Camera::doCam(int code,QString msg){if(code==0)success(msg);else error(msg);
}
/*** @brief Camera::run 线程函数,用于打开相机和采集图像*/
void Camera::run(){try {pipe.start();       //尝试打开相机}catch (const std::exception& e){emit onCameraEvent(1, e.what() ); //如果没有成功,发送给主线程一个消息return;//返回,不继续了}emit onCameraEvent(0,"相机打开成功"); //如果打开成功,也发送一个rs2::colorizer color_map;//用于将深度数据,转换为图像数据色彩数据的map,isCapture=true;//循环控制变量while(isCapture){try {rs2::frameset data= pipe.wait_for_frames(); //获取一帧数据          rs2::frame color=data.get_color_frame();                    //获取彩色图像rs2::frame depth=data.get_depth_frame().apply_filter(color_map);  //获取深度数据,并转换为可见图const int w = depth.as<rs2::video_frame>().get_width();     //获取图像宽度const int h = depth.as<rs2::video_frame>().get_height();    //获取图像高度qDebug()<<"get frame"<<"width "<<w<<"height"<<h;QImage img((uchar*)depth.get_data(),w,h,QImage::Format_RGB888); //创建一个图片emit onImage(img);                                          //图片发送给主线程,mainwindow接收,并显示一下。}catch (const std::exception& e) {emit onCameraEvent(2,e.what());}}
}

后续准备同时显示深度和彩色图片,并在QT显示3D模型。


http://www.mrgr.cn/news/81593.html

相关文章:

  • 深度解析:Maven 和 Gradle 的使用比较及常见仓库推荐
  • KAFKA 权威指南笔记(一)究竟应该配置多少个BROKER?
  • fpgafor循环语句使用
  • 鸿蒙Next之har工程依赖库接口二次导出
  • Android U 多任务启动分屏——system_server流程(更新中)
  • 深入解析:Python中的决策树与随机森林
  • 新浪微博C++面试题及参考答案
  • 细说EEPROM芯片24C02的基础知识及其驱动程序设计
  • 【达梦数据库】小版本升级之bin文件替换
  • 是德 皮安表Keysight B2980 系列常用指令 附带说明书原件
  • E-commerce .net+React(一)——项目初始化
  • Java数组深入解析:定义、操作、常见问题与高频练习
  • 高性能编程,C++的无锁和有锁编程方法的性能对比
  • 2023 年 12 月青少年软编等考 C 语言四级真题解析
  • 字节跳动Java开发面试题及参考答案(数据结构算法-手撕面试题)
  • Anaconda搭建Python虚拟环境并在Pycharm中配置(小白也能懂)
  • 【物联网技术与应用】实验16:模拟霍尔传感器实验
  • YOLOv9-0.1部分代码阅读笔记-detect.py
  • 高精度问题
  • H5st5.0.0协议分析
  • 穷举vs暴搜vs深搜vs回溯vs剪枝系列一>括号生成
  • 【c语言】简单的c程序设计
  • 生成10级子目录,每个子目录下有100个不同大小的文件
  • 并发编程 - 死锁的产生、排查与解决方案
  • Javaweb maven单元测试
  • 前缀树介绍