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模型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/945576.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端小案例——520表白信封

前言&#xff1a;我们在学习完了HTML和CSS之后&#xff0c;就会想着使用这两个东西去做一些小案例&#xff0c;不过又没有什么好的案例让我们去练手&#xff0c;本篇文章就提供里一个案例——520表白信封 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主…

Golang的发展历程

Golang的发展历程可以分为以下几个阶段&#xff1a; 设计阶段&#xff1a;2007年&#xff0c;Google开始研究开发一种新的编程语言&#xff0c;主要出于对C和Java等编程语言的不足之处的反思。经过一年多的研究和讨论&#xff0c;Golang的设计方案得到确定&#xff0c;主要包括…

硬件设计-硬件 EMC 设计规范

目录 引言&#xff1a; 常见原因 总体概念及考虑 布局 屏蔽 滤波 引言&#xff1a; 本规范只简绍 EMC 的主要原则与结论&#xff0c;为硬件工程师们在开发设计中抛砖引玉。 电磁干扰的三要素是干扰源、干扰传输途径、干扰接收器。EMC 就围绕这些 问题进行研究。最基本的…

后端开发-Maven

环境说明&#xff1a; windows系统&#xff1a;11版本 idea版本&#xff1a;2023.3.2 Maven 介绍 Apache Maven 是一个 Java 项目的构建管理和理解工具。Maven 使用一个项目对象模型&#xff08;POM&#xff09;&#xff0c;通过一组构建规则和约定来管理项目的构建&#xf…

C++ 编译过程全解析:从源码到可执行文件的蜕变之旅

引言 C 作为一种广泛应用于系统开发、游戏编程、嵌入式系统等领域的高级编程语言&#xff0c;其代码需要经过编译才能转换为计算机可执行的机器语言。编译过程涵盖多个复杂阶段&#xff0c;每个阶段对最终生成的可执行文件的性能、稳定性及兼容性都有着深远影响。深入理解 C 编…

数据库的概念和操作

目录 1、数据库的概念和操作 1.1 物理数据库 1. SQL SERVER 2014的三种文件类型 2. 数据库文件组 1.2 逻辑数据库 2、数据库的操作 2.1 T-SQL的语法格式 2.2 创建数据库 2.3 修改数据库 2.4 删除数据库 3、数据库的附加和分离 1、数据库的概念和操作 1.1 物理数据库…

【CSS in Depth 2 精译_096】16.4:CSS 中的三维变换 + 16.5:本章小结

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 16.2.1 放大图标&am…

期权懂|个股期权的流动性如何?

锦鲤三三每日分享期权知识&#xff0c;帮助期权新手及时有效地掌握即市趋势与新资讯&#xff01; 个股期权的流动性如何&#xff1f; 个股期权作为场外交易工具&#xff0c;具有较高的灵活性。场外交易意味着交易双方可以直接协商交易条款&#xff0c;这有助于满足不同投资者的…

关于在M系列的Mac中使用SoftEtherClient软件

1. 前言 本文说明的是在M系列的苹果的MacBook中如何使用SoftetherClient这款软件&#xff0c;是直接在MacOS操作系统中安装连接使用&#xff0c;不是在PD环境或者非ARM架构的Mac中安装使用。 PS&#xff1a;别费劲百度了&#xff0c;很少有相关解决方案的&#xff0c;在国内会…

linux自动化批量分发SSH密钥同时批量测试SSH连接教程(包含自动化脚本代码)

1、检查端口 检查分发对象22端口是否打开 nmap -p22 ip地址如果要批量检查端口可以参考我写的这篇文章&#xff1a;linux自动化一键批量检查主机端口 2、命令行分发密钥原理 Linux分发密钥原理主要涉及SSH&#xff08;Secure Shell&#xff09;协议&#xff0c;该协议用于…

vue3学习笔记(9)-pinia、storeToRefs、getters

1.新的集中式状态&#xff08;数据&#xff09;管理库&#xff0c;redux vuex pinia 搭建 2.ref拆包 如果在reactive里面定义ref&#xff0c;则打印c时&#xff0c;无需.value 他自动拆包&#xff0c;如果直接在外面定义的ref则需要.value,他没有拆包 3.pinia存储读取数据 存…

Oracle 11G还有新BUG?ORACLE 表空间迷案!

前段时间遇到一个奇葩的问题&#xff0c;在开了SR和oracle support追踪两周以后才算是有了不算完美的结果&#xff0c;在这里整理出来给大家分享。 1.问题描述 12/13我司某基地MES全厂停线&#xff0c;系统卡死不可用&#xff0c;通知到我排查&#xff0c;查看alert log看到是…

深度学习:基于MindSpore NLP的数据并行训练

什么是数据并行&#xff1f; 数据并行&#xff08;Data Parallelism, DP&#xff09;的核心思想是将大规模的数据集分割成若干个较小的数据子集&#xff0c;并将这些子集分配到不同的 NPU 计算节点上&#xff0c;每个节点运行相同的模型副本&#xff0c;但处理不同的数据子集。…

机器学习-高斯混合模型

文章目录 高斯混合模型对无标签的数据集&#xff1a;使用高斯混合模型进行聚类对有标签的数据集&#xff1a;使用高斯混合模型进行分类总结实战 高斯混合模型 对无标签的数据集&#xff1a;使用高斯混合模型进行聚类 对有标签的数据集&#xff1a;使用高斯混合模型进行分类 总结…

android studio android sdk下载地址

android studio安装后&#xff0c;因为公司网络原因&#xff0c;一直无法安装android sdk 后经过手机网络&#xff0c;安装android sdk成功如下&#xff0c;也可以手动下载后指定android sdk本地目录 https://dl.google.com/android/repository/source-35_r01.zip https://dl…

【RK3588 Linux 5.x 内核编程】-内核I2C子系统介绍

内核I2C子系统介绍 文章目录 内核I2C子系统介绍1、内核中的I2C子系统2、内核中的I2C驱动2.1 获取I2C适合器2.2 创建i2c_board_info与设备2.3 创建设备ID和I2C驱动2.4 数据传输2.4.1 发送数据2.4.2 读取数据3、I2C总线如何工作I2C 是一种用于双线接口的串行协议,用于连接低速设…

更新本地项目到最新git版本脚本

由于平时工作中项目较多&#xff0c;每天刚上班都需要更新一下项目代码&#xff0c;一个一个更新感觉稍微麻烦了一些&#xff0c;所以写了一个简单的shell脚本&#xff0c;每天到公司先执行一遍即可。 #!/bin/bash# 进入指定的目录 target_dir"$1"; cd "$targe…

向量检索+大语言模型,免费搭建基于专属知识库的 RAG 智能助手

随着生成式人工智能技术的飞速发展&#xff0c;越来越多的人和企业开始应用AI到日常的工作和生活中。但公域的AI助手其数据来自互联网上的大量公开文本&#xff0c;虽然具有广泛的知识&#xff0c;但在面对一些特定领域的专业问题时&#xff0c;可能会出现回答不够准确或深入的…

python读写文件的三种做法

对于文件操作&#xff0c;python提供了3种做法&#xff1a;open(), os.open() 和with open()语句。 1. open()函数&#xff1a;一般用于更高级的文件读写操作&#xff0c;即人能读懂的用法&#xff0c;如果是写入数据&#xff0c;可用传入字符串。 用法&#xff1a;open(path…

RCE-PLUS (学习记录)

源码 <?php error_reporting(0); highlight_file(__FILE__); function strCheck($cmd) {if(!preg_match("/\;|\&|\\$|\x09|\x26|more|less|head|sort|tail|sed|cut|awk|strings|od|php|ping|flag/i", $cmd)){return($cmd);}else{die("i hate this"…