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

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 data
        Mat image(Size(w, h), CV_8UC3, (void*)depth.get_data(), Mat::AUTO_STEP);

        // Update the window with new data
        imshow(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.kler.cn/a/454405.html

相关文章:

  • NLP 中文拼写检测开源-01-基于贝叶斯公式的拼写检查器 CSC
  • Leetcode 394-字符串解码
  • MinIO服务器文件复制(Windows环境Linux环境)
  • LLMs之o3:《Deliberative Alignment: Reasoning Enables Safer Language Models》翻译与解读
  • 基础排序算法
  • 如何使用 Flask 框架创建简单的 Web 应用?
  • LeetCode 3218.切蛋糕的最小总开销 I:记忆化搜索(深度优先搜索DFS)
  • AppAgent源码 (OpenAIModel 类)
  • 连锁餐饮行业数据可视化分析方案
  • CSS学习资源宝库:CSSnippets、CSS-Tricks与CodePen
  • Vite内网ip访问,两种配置方式和修改端口号教程
  • MySQL外键类型与应用场景总结:优缺点一目了然
  • Tomcat原理(6)——tomcat完整实现
  • 【UE5 C++课程系列笔记】14——GameInstanceSubsystem与动态多播的简单结合使用
  • webview+H5来实现的android短视频(短剧)音视频播放依赖控件资源
  • 【02-数据库面试】
  • 新手小白如何挖掘cnvd通用漏洞之存储xss漏洞(利用xss钓鱼)
  • 企业销售人员培训系统|Java|SSM|VUE| 前后端分离
  • OPPO Java面试题及参考答案
  • uniapp小程序实现弹幕不重叠