QT集成IntelRealSense双目摄像头2,集成OpenGL

news2025/4/7 10:59:50

上一篇文章写了如何把IntelRealSense摄像头的SDK集成到QT项目,并成功采集数据,在没有用OpenCV的情况下完成色彩数据,以及深度数据的显示。

具体地址:https://blog.csdn.net/qujia121qu/article/details/144734163

本次主要写如何把深度数据和色彩数据,融合显示为3D数据。既然要显示为3D数据,那么肯定是要用OpenGL。所以第一步,就是要项目引入opengl。

第一步:引入OpenGL。

        引入OpenGL需要QT+=opengl,然后加载opengl的lib和glu的lib文件。代码如下。引入成功以后,#include <GL/gl.h>不会报错。

win32:LIBS += -lOpengl32\
-lglu32
unix:LIBS += -lglut -lGLU

第二步:创建一个用于显示3D图像的Widget

        因为要显示3D,所以这个Widget要继承自QGLWidget或者QOpenGLWidget。这两个差不多。头文件和CPP见下面代码,这个是最基本的一个QGLWidget框架,适合绘制平面图形,建议收藏。

#include <QObject>
#include <QGLWidget>
#include <GL/gl.h>
#include <GL/glu.h>
class GLWidget : public QGLWidget
{
    Q_OBJECT
public:
    GLWidget();
    static GLWidget* getInstance();          //单例模式
protected:
    void resizeGL(int w, int h) override;   //窗口大小改变的时候,gl重新初始化
    void initializeGL() override;           //初始化gl
    void paintGL() override;                //核心绘制
};

#endif // GLWIGET_H
#include "glwidget.h"

GLWidget::GLWidget()
{

}

/**
 * @brief GLWidget::getInstance 单例模式
 * @return
 */
GLWidget* GLWidget::getInstance(){
    GLWidget* ins=NULL;
    if(ins==NULL)ins=new GLWidget();
    return ins;
}
/**
 * @brief GLWidget::initializeGL 初始化opengl。可以步写
 */
void GLWidget::initializeGL(){

}
/**
 * @brief GLWidget::resizeGL 窗口大小改变
 * @param w
 * @param h
 */
void GLWidget::resizeGL(int w, int h){
    glViewport(0,0,w,h);            //重新适应窗口大小

}
/**
 * @brief GLWidget::paintGL 绘制核心方法
 */
void GLWidget::paintGL(){
    glClearColor(0,0,0,0);                       //背景色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);//清除上一次的缓存
    glLoadIdentity();  //加载单位矩阵
    glColor3f (1, 0, 1.0); //画笔颜色
    glRectf(-0.5, -0.5, 0.5, 0.5); // 绘制一个边长为1的矩形
}

以上代码绘制出来一个矩形,如下图。opengl窗口的宽高都是1,所以0.5,就是宽高的一半。

目前只是加载了opengl,但是绘制是依然是平面图形。要绘制3D图像,就需要设置投影矩阵,以及相机。大致的意思,就是设置相机焦距,远距离,近距离,视角,相机位置等。主要是两个函数

gluPerspective(视角角度,长宽比,近距离,远距离)
gluLookAt(相机x,相机y,相机z,        目标x,目标y,目标z,   相机方向x,相机方向y,相机方向z)

第三步:设置相机和投影矩阵

如下,就是在resizeGL里面增加了几行代码,这个设置完,就不用改了。在paintGL里面增加了一个gluLookAt,通过调整参数,可以改变相机位置。

/**
 * @brief GLWidget::resizeGL 窗口大小改变
 * @param w
 * @param h
 */
void GLWidget::resizeGL(int w, int h){
    glViewport(0,0,w,h);            //重新适应窗口大小
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1, 2000.0);           //设置相机投影参数
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

}
/**
 * @brief GLWidget::paintGL 绘制核心方法
 */
void GLWidget::paintGL(){
    glClearColor(0,0,0,0);                       //背景色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);//清除上一次的缓存
    glLoadIdentity();  //加载单位矩阵
    gluLookAt(0,0,100, 0,0,0,   0.0,1.0,0);                             //设置相机

    glColor3f (1, 0, 1.0); //画笔颜色
    glRectf(-0.5, -0.5, 0.5, 0.5); // 绘制一个边长为1的矩形
}

第四步:鼠标跟随

实际上就是控制相机位置,通过改变相机位置,达到鼠标控制3D画面的效果。为了实现效果,定义一个水平面的角度degZ,一个垂直面角度degY,一个相机距离中心点的半径R,实际上就是定义极坐标,通过极坐标转换为三维坐标。鼠标滚轮改变半径R,坐标左右移动改变水平面角度degZ,鼠标上下移动Y,改变垂直面角度。

以下是一个具备基本功能的GLWidget类代码,强烈建议收藏

#ifndef GLWIGET_H
#define GLWIGET_H

#include <QObject>
#include <QGLWidget>
#include <GL/gl.h>
#include <GL/glu.h>
#include <QMouseEvent>
#include <QWheelEvent>
class GLWidget : public QGLWidget
{
    Q_OBJECT
public:
    GLWidget();
    static GLWidget* getInstance();          //单例模式
protected:
    void resizeGL(int w, int h) override;   //窗口大小改变的时候,gl重新初始化
    void initializeGL() override;           //初始化gl
    void paintGL() override;                //核心绘制
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void wheelEvent(QWheelEvent *event) override;
private:
    double r;//相机距离中心的的半径
    double degZ;//在水平面的角度
    double degY;//在垂直面的角度
    double camx,camy,camz;//相机位置
    void refresh();//重新绘制
    QPoint old;//鼠标原始位置
    bool isPressed;//是否按下
};

#endif // GLWIGET_H
#include "glwidget.h"
#include <qmath.h>
#include <QDebug>
GLWidget::GLWidget()
{
    r=100;//默认距离
    degY=degZ=0;
    camz=r*qCos(degZ);
    camx=r*qSin(degZ);
    camy=r*qSin(degY);
}

/**
 * @brief GLWidget::getInstance 单例模式
 * @return
 */
GLWidget* GLWidget::getInstance(){
    GLWidget* ins=NULL;
    if(ins==NULL)ins=new GLWidget();
    return ins;
}
/**
 * @brief GLWidget::initializeGL 初始化opengl。可以步写
 */
void GLWidget::initializeGL(){

}
/**
 * @brief GLWidget::resizeGL 窗口大小改变
 * @param w
 * @param h
 */
void GLWidget::resizeGL(int w, int h){
    glViewport(0,0,w,h);            //重新适应窗口大小
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1, 2000.0);           //设置相机投影参数
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

}
/**
 * @brief GLWidget::paintGL 绘制核心方法
 */
void GLWidget::paintGL(){
    glClearColor(0,0,0,0);                       //背景色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);//清除上一次的缓存
    glLoadIdentity();  //加载单位矩阵
    gluLookAt(camx,camy,camz, 0,0,0,   0.0,1.0,0);                             //设置相机

    glColor3f (1, 0, 1.0); //画笔颜色
    glRectf(-50, -50, 50, 50); // 绘制一个边长为50的矩形
}
/**
 * @brief GLWidget::refresh 重新计算相机位置
 */
void GLWidget::refresh(){
    camz=r*qCos(degZ);
    camx=r*qSin(degZ);
    camy=r*qSin(degY);

    this->update();
}


void GLWidget::wheelEvent(QWheelEvent *event){
    qDebug()<<r<<event->delta();
    r+=event->delta()/20;
    if(r<20)r=20;
    if(r>1800)r=1800;
    refresh();
}
void GLWidget::mouseMoveEvent(QMouseEvent *event){
    if(isPressed){
        QPoint p=event->pos();
        degZ+=(p.x()-old.x())/5.0;
        degY+=(p.y()-old.y())/5.0;
        old=p;
        refresh();
    }
}

void GLWidget::mousePressEvent(QMouseEvent *event){

    if(event->button()==Qt::LeftButton){
        isPressed=true;
        old=event->pos();
    }
}
void GLWidget::mouseReleaseEvent(QMouseEvent *event){
    if(event->button()==Qt::LeftButton){
        isPressed=false;
    }
}

运行效果,可以通过鼠标来控制相机,达到3D效果

时间关系,就一篇就水到这里。周一再来一篇,写双面相机数据,如何显示到GLWidget。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【模块一】kubernetes容器编排进阶实战之kubernetes pod Affinity与pod antiaffinity

pod Affinity与pod antiaffinity Pod Affinity与anti-affinity简介&#xff1a; Pod亲和性与反亲和性可以基于已经在node节点上运行的Pod的标签来约束新创建的Pod可以调度到的 目的节点&#xff0c;注意不是基于node上的标签而是使用的已经运行在node上的pod标签匹配。 其规则…

从百度云网盘下载数据到矩池云网盘或者服务器内

本教程教大家如何快速将百度云网盘数据集或者模型代码文件下载到矩池云网盘或者服务器硬盘上。 本教程使用到了一个开源工具 BaiduPCS-Go&#xff0c;官方地址 &#xff1a; https://github.com/qjfoidnh/BaiduPCS-Go 这个工具可以实现“仿 Linux shell 文件处理命令的百度网…

使用maven-mvnd替换maven大大提升编译打包速度

先上结论&#xff01;&#xff01;&#xff01; 多模块清理并打包提升&#xff1a;约3.5倍 多模块不清理打包提升&#xff1a;约5.5倍 单模块提升&#xff1a;约2倍 从计算结果来看&#xff0c;多模块提升的效率更高。在使用mvnd package打包多模块式&#xff0c;可在控制台…

LeetCode - 初级算法 数组(删除排序数组中的重复项)

免责声明:本文来源于个人知识与公开资料,仅用于学术交流。 删除排序数组中的重复项 这篇文章讨论如何从一个非严格递增的数组 nums 中删除重复的元素,使每个元素只出现一次,并返回新数组的长度。因为数组是排序的,只要是相同的肯定是挨着的,所以我们需要遍历所有数组,然…

2024 年度总结

时光荏苒&#xff0c;2024 年即将画上句号&#xff0c;回顾这一年的写博历程&#xff0c;有付出、有收获、有成长&#xff0c;也有诸多值得回味与反思的瞬间。 一、内容创作 主题涉猎&#xff1a;这一年&#xff0c;我致力于探索多样化的主题&#xff0c;以满足不同读者群体的…

基于STM32位单片机的腕式运动体力监测装置设计

本设计基于STM32位单片机的腕式运动体力状态诊断系统装置。本系统内的使用的STM32单片机包含了心率检测电路、呼吸频率检测电路、OLED液晶显示电路、电源电路、蓝牙电路。通过心率传感器以及手指脉搏波动放大过后发送给比较器&#xff0c;结果处理后发送给单片机进行信息的收集…

LunarVim安装

LunarVim以其丰富的功能和灵活的定制性&#xff0c;迅速在Nvim用户中流行开来。它不仅提供了一套完善的默认配置&#xff0c;还允许用户根据自己的需求进行深度定制。无论是自动补全、内置终端、文件浏览器&#xff0c;还是模糊查找、LSP支持、代码检测、格式化和调试&#xff…

前端超大缓存IndexDB、入门及实际使用

文章目录 往期回顾项目实战初始化表获取列表新增表的数据项获取详情根据ID获取详情根据其他字段获取详情 删除数据 总结 往期回顾 在之前的文章中&#xff0c;我们介绍了IndexDB vs Cookies vs Session这几个的对比&#xff0c;但是没有做实际项目的演示&#xff0c;今天我们用…

面试题解,JVM的运行时数据区

一、请简述JVM运行时数据区的组成结构及各部分作用 总览 从线程持有的权限来看 线程私有区 虚拟机栈 虚拟机栈是一个栈结构&#xff0c;由许多个栈帧组成&#xff0c;一个方法分配一个栈帧&#xff0c;线程每执行一个方法时都会有一个栈帧入栈&#xff0c;方法执行结束后栈帧…

WAV文件双轨PCM格式详细说明及C语言解析示例

WAV文件双轨PCM格式详细说明及C语言解析示例 一、WAV文件双轨PCM格式详细说明1. WAV文件基本结构2. PCM编码方式3. 双轨PCM格式详细说明二、C语言解析WAV文件的代码示例代码说明一、WAV文件双轨PCM格式详细说明 WAV文件是一种用于存储未压缩音频数据的文件格式,广泛应用于音频…

QT------模型/视图

一、模型/视图结构概述 基本原理&#xff1a; Qt 的模型/视图&#xff08;Model/View&#xff09;架构将数据的存储和显示分离&#xff0c;提高了代码的可维护性和复用性。模型&#xff08;Model&#xff09;&#xff1a;负责存储和管理数据&#xff0c;提供数据的访问接口&am…

vue3+ts+element-plus 表单el-form取消回车默认提交

问题描述&#xff1a;在表单el-form中的el-input中按回车后&#xff0c;页面会刷新&#xff0c;url也会改变&#xff0c; 回车前&#xff1a; 回车后&#xff1a; 相关代码&#xff1a; 解决方法1&#xff1a;在 el-form 上阻止默认的 submit 事件&#xff0c;增加 submit.pre…

掌握大数据处理利器:Flink 知识点全面总结【上】

1.Flink的特点 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于对无界和有界数据流进行状态计算。 Flink主要特点如下&#xff1a; 高吞吐和低延迟。每秒处理数百万个事件&#xff0c;毫秒级延迟。结果的准确性。Flink提供了事件时间(event--time)和处理时间(proces…

国产数据库-崖山使用介绍

本文档基于崖山数据库23.3 个人版本&#xff0c;单机&#xff08;主备&#xff09;部署模式的情况下的使用介绍。 数据库实例状态&#xff1a; NOMOUNT&#xff1a;仅读取参数文件&#xff0c;不加载数据库 MOUNT&#xff1a;读取控制文件&#xff0c;加载数据库&#xff…

Pytest基础01: 入门demo脚本

目录 1 Pytest接口测试 1.1 最简单版hello world 1.2 pytest.ini 2 pytest兼容unittest 3 封装pytest执行入口 1 Pytest接口测试 Pyest是一个可以用于接口测试的强大框架&#xff0c;开源社区也有非常多的pytest插件。 按江湖传统&#xff0c;学习一个新语言或者新框架&…

如何在没有 iCloud 的情况下将数据从 iPhone 传输到 iPhone

概括 您可能会遇到将数据从 iPhone 转移到 iPhone 的情况&#xff0c;尤其是当您获得新的 iPhone 15/14 时&#xff0c;您会很兴奋并希望将数据转移到它。 使用iCloud最终可以做到这一点&#xff0c;但它的缺点也不容忽视&#xff0c;阻碍了你选择它。例如&#xff0c;您需要…

streamlit、shiny、gradio、fastapi四个web APP平台体验

streamlit、shiny、gradio、fastapi四个web APP平台体验 经常被问的问题就是&#xff1a;web APP平台哪个好&#xff1f;该用哪个&#xff1f;刚开始只有用streamlit和shiny&#xff0c;最近体验了一下gradio和fastapi&#xff0c;今天根据自己的体会尝试着回答一下。 使用R语…

HTML5滑块(Slider)

HTML5 的滑块&#xff08;Slider&#xff09;控件允许用户通过拖动滑块来选择数值。以下是如何实现一个简单的滑块组件的详细说明。 HTML5 滑块组件 1. 基本结构 使用 <input type"range"> 元素可以创建一个滑块。下面是基本实现的代码示例&#xff1a; <…

探索 .idea 文件夹:Java Maven 工程的隐形守护者

一、.idea文件夹深度解析&#xff1a;IntelliJ IDEA项目配置的核心 在Java Maven工程的开发环境中&#xff0c;.idea文件夹扮演着举足轻重的角色。这是IntelliJ IDEA项目特有的一个配置文件夹&#xff0c;它包含了项目所需的各种配置信息&#xff0c;以确保项目能够在不同的开发…

遥感图像车辆检测-目标检测数据集

遥感图像车辆检测-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接: https://pan.baidu.com/s/1XVlRTVWpXZFi6ZL_Xcs7Rg?pwdaa6g 提取码: aa6g 数据集信息介绍&#xff1a; 共有 1035 张图像和一一对应的标注文件 标注文件格式提供了…