三维视觉--基于Kinect2.0深度相机的点云获取方案实现(C++版)

2023-10-30

上一篇中使用的点云获取设备是Intel Realsense d455相机,这两天接触的相机不少,也发现很多点云检测和分割的论文中使用的都是Kinect相机,今天就再分享一篇使用Kinect2.0获取点云并使用C++实现。

首先还是相机SDK的下载和安装:可以去官网下载,也可以到我之前分享的百度网盘获取。

点云获取(深度相机)方案实现C++版_低调猫熊的博客-CSDN博客

安装后再配置环境:

环境配好后,就是代码编写, 

代码如下:

#include <iostream>
#include <fstream>

#include <Windows.h>
#include <Kinect.h>

#include <opencv2/opencv.hpp>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>

using namespace std;
using namespace cv;

template<class Interface>
inline void SafeRelease(Interface*& ptr)
{
    if (ptr)
    {
        ptr->Release();
        ptr = nullptr;
    }
}

int main()
{
    // 初始化Kinect
    IKinectSensor* pKinectSensor = nullptr;
    HRESULT hr = GetDefaultKinectSensor(&pKinectSensor);
    if (FAILED(hr))
    {
        cerr << "Failed to get default Kinect sensor." << endl;
        return -1;
    }

    hr = pKinectSensor->Open();
    if (FAILED(hr))
    {
        cerr << "Failed to open Kinect sensor." << endl;
        return -1;
    }

    // 打开深度数据流和彩色数据流
    IDepthFrameReader* pDepthFrameReader = nullptr;
    IColorFrameReader* pColorFrameReader = nullptr;

    IDepthFrameSource* pDepthFrameSource = nullptr;
    hr = pKinectSensor->get_DepthFrameSource(&pDepthFrameSource);
    if (SUCCEEDED(hr))
    {
        hr = pDepthFrameSource->OpenReader(&pDepthFrameReader);
    }
    SafeRelease(pDepthFrameSource);
    if (FAILED(hr))
    {
        cerr << "Failed to open depth frame reader." << endl;
        return -1;
    }

    IColorFrameSource* pColorFrameSource = nullptr;
    hr = pKinectSensor->get_ColorFrameSource(&pColorFrameSource);
    if (SUCCEEDED(hr))
    {
        hr = pColorFrameSource->OpenReader(&pColorFrameReader);
    }
    SafeRelease(pColorFrameSource);
    if (FAILED(hr))
    {
        cerr << "Failed to open color frame reader." << endl;
        return -1;
    }

    // 打开坐标映射器
    ICoordinateMapper* pCoordinateMapper = nullptr;
    hr = pKinectSensor->get_CoordinateMapper(&pCoordinateMapper);
    if (FAILED(hr))
    {
        cerr << "Failed to get coordinate mapper." << endl;
        return -1;
    }

    // 创建窗口
    namedWindow("Color", WINDOW_AUTOSIZE);
    namedWindow("Depth", WINDOW_AUTOSIZE);

    // 定义缓冲区
    ColorSpacePoint* pColorSpacePoints = new ColorSpacePoint[512 * 424];
    UINT16* pDepthData = new UINT16[512 * 424];

    // 定义点云对象
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr pPointCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    pPointCloud->width = 512;
    pPointCloud->height = 424;
    pPointCloud->points.resize(512 * 424);

    // 循环读取帧数据
    bool bSavePointCloud = false;
    while (true)
    {
        // 获取彩色帧
        IColorFrame* pColorFrame = nullptr;
        hr = pColorFrameReader->AcquireLatestFrame(&pColorFrame);
        if (SUCCEEDED(hr))
        {
            // 获取彩色帧数据
            UINT colorBufferSize = 1920 * 1080 * 4;
            BYTE* pColorBuffer = new BYTE[colorBufferSize];
            hr = pColorFrame->CopyConvertedFrameDataToArray(colorBufferSize, pColorBuffer, ColorImageFormat_Bgra);
            if (FAILED(hr))
            {
                cerr << "Failed to copy color frame data." << endl;
            }

            // 创建彩色图像
            Mat color(1080, 1920, CV_8UC4, pColorBuffer);
            // 显示彩色图像
            imshow("Color", color);

            // 释放彩色帧
            SafeRelease(pColorFrame);

            // 获取深度帧
            IDepthFrame* pDepthFrame = nullptr;
            hr = pDepthFrameReader->AcquireLatestFrame(&pDepthFrame);
            if (SUCCEEDED(hr))
            {
                // 获取深度帧数据
                hr = pDepthFrame->CopyFrameDataToArray(512 * 424, pDepthData);
                if (FAILED(hr))
                {
                    cerr << "Failed to copy depth frame data." << endl;
                }

                // 将深度图转换为彩色图的空间坐标
                pCoordinateMapper->MapDepthFrameToColorSpace(512 * 424, pDepthData, 512 * 424, pColorSpacePoints);

                // 释放深度帧
                SafeRelease(pDepthFrame);
            }
            else
            {
                cerr << "Failed to acquire latest depth frame." << endl;
            }
            // 显示深度图
            Mat depth(424, 512, CV_16UC1, pDepthData);
            imshow("Depth", depth);

            // 将深度图转换为点云
            for (int i = 0; i < 512 * 424; ++i)
            {
                pcl::PointXYZRGB& point = pPointCloud->points[i];
                ColorSpacePoint& colorSpacePoint = pColorSpacePoints[i];
                UINT16 depthValue = pDepthData[i];

                if (depthValue > 0 && colorSpacePoint.X >= 0 && colorSpacePoint.X < 1920 && colorSpacePoint.Y >= 0 && colorSpacePoint.Y < 1080)
                {
                    // 计算空间坐标
                    CameraSpacePoint cameraSpacePoint = { 0 };
                    pCoordinateMapper->MapDepthPointToCameraSpace({ (float)(i % 512), (float)(i / 512) }, depthValue, &cameraSpacePoint);

                    // 设置点云坐标和颜色
                    point.x = cameraSpacePoint.X;
                    point.y = cameraSpacePoint.Y;
                    point.z = cameraSpacePoint.Z;
                    point.r = color.at<Vec4b>((int)colorSpacePoint.Y, (int)colorSpacePoint.X)[2];
                    point.g = color.at<Vec4b>((int)colorSpacePoint.Y, (int)colorSpacePoint.X)[1];
                    point.b = color.at<Vec4b>((int)colorSpacePoint.Y, (int)colorSpacePoint.X)[0];
                }
                else
                {
                    // 设置无效点云坐标
                    //point.x = point.y = point.z = numeric_limits<float>::quiet_NaN();
                }
            }

        }
        else
        {
            cerr << "Failed to acquire latest color frame." << endl;
        }
        
        
       
        // 按下空格键保存点云数据为ply文件
        if (waitKey(30) == VK_SPACE)
        {
            if (!bSavePointCloud)
            {
                bSavePointCloud = true;

                // 保存点云数据为ply文件
                pcl::PLYWriter writer;
                
                writer.write("Kinect_point_cloud.ply", *pPointCloud);

                cout << "Saved point cloud data to point_cloud.ply" << endl;
            }
        }
    }

    // 释放资源
    SafeRelease(pDepthFrameReader);
    SafeRelease(pColorFrameReader);
    SafeRelease(pCoordinateMapper);
    if (pKinectSensor)
    {
        pKinectSensor->Close();
    }
    SafeRelease(pKinectSensor);
    delete[] pColorSpacePoints;
    delete[] pDepthData;

    return 0;
}

至此,就可以实现调用Kinect2.0相机获取点云了。

草稿代码可能不是那么严谨,但运行起来问题不大。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

三维视觉--基于Kinect2.0深度相机的点云获取方案实现(C++版) 的相关文章

  • 是否有与 posix_memalign 对应的 C++ 版本?

    当我打电话时posix memalign http man7 org linux man pages man3 posix memalign 3 html为类型的对象分配对齐的内存Foo在我的 C 代码中 我需要做一个reinterpret
  • C++ 维护子类对象的混合集合

    如果我在这里错过了一个相当基本的概念 我很抱歉 但我正在尝试弄清楚如何维护多个类类型的集合 所有类类型都派生自同一个父类 并且在检索它们时仍然可以访问它们的特定于子类的方法从集合中 作为上下文 我有一个基类 BaseClass 和许多类 例
  • CLR 2.0 与 4.0 性能比较?

    如果在 CLR 4 0 下运行 为 CLR 2 0 编译的 NET 程序会运行得更快吗 应用程序配置
  • 如何从 C# 中的 dataTable.Select( ) 查询中删除单引号?

    所以我有一个经销商名称列表 我正在我的数据表中搜索它们 问题是 一些傻瓜必须被命名为 Young s 这会导致错误 drs dtDealers Select DealerName dealerName 所以我尝试替换字符串 尽管它对我不起作
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • File.AppendText 尝试写入错误的位置

    我有一个 C 控制台应用程序 它作为 Windows 任务计划程序中的计划任务运行 此控制台应用程序写入日志文件 该日志文件在调试模式下运行时会创建并写入应用程序文件夹本身内的文件 但是 当它在任务计划程序中运行时 它会抛出一个错误 指出访
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • 类型约束

    我有以下类层次结构 class Header IEnumerable
  • 在视口中查找 WPF 控件

    Updated 这可能是一个简单或复杂的问题 但在 wpf 中 我有一个列表框 我用一个填充数据模板从列表中 有没有办法找出特定的数据模板项位于视口中 即我已滚动到其位置并且可以查看 目前我连接到了 listbox ScrollChange
  • 在 NaN 情况下 to_string() 可以返回什么

    我使用 VS 2012 遇到了非常令人恼火的行为 有时我的浮点数是 NaN auto dbgHelp std to string myFloat dbgHelp最终包含5008角色 你不能发明这个东西 其中大部分为0 最终结果是 0 INF
  • C++ int 前面加 0 会改变整个值

    我有一个非常奇怪的问题 如果我像这样声明一个 int int time 0110 然后将其显示到控制台返回的值为72 但是当我删除前面的 0 时int time 110 然后控制台显示110正如预期的那样 我想知道两件事 首先 为什么它在
  • 保护 APK 中的字符串

    我正在使用 Xamarin 的 Mono for Android 开发一个 Android 应用程序 我目前正在努力使用 Google Play API 添加应用内购买功能 为此 我需要从我的应用程序内向 Google 发送公共许可证密钥
  • C++ 中的双精度型数字

    尽管内部表示有 17 位 但 IEE754 64 位 浮点应该正确表示 15 位有效数字 有没有办法强制第 16 位和第 17 位为零 Ref http msdn microsoft com en us library system dou
  • 检测到严重错误 c0000374 - C++ dll 将已分配内存的指针返回到 C#

    我有一个 c dll 它为我的主 c 应用程序提供一些功能 在这里 我尝试读取一个文件 将其加载到内存 然后返回一些信息 例如加载数据的指针和内存块的计数到 c Dll 成功将文件读取到内存 但在返回主应用程序时 程序由于堆损坏而崩溃 检测
  • WPF DataGridTemplateColumn 组合框更新所有行

    我有这个 XAML 它从 ItemSource 是枚举的组合框中选择一个值 我使用的教程是 http www c sharpcorner com uploadfile dpatra combobox in datagrid in wpf h
  • C++ new * char 不为空

    我有一个问题 我在 ASIO 中开发服务器 数据包采用尖头字符 当我创建新字符时 例如char buffer new char 128 我必须手动将其清理为空 By for int i 0 i lt 128 i buffer i 0x00
  • 实体框架中的“it”是什么

    如果以前有人问过这个问题 请原谅我 但我的任何搜索中都没有出现 它 我有两个数据库表 Person 和 Employee 对每个类型的表进行建模 例如 Employee is a Person 在我的 edmx 设计器中 我定义了一个实体
  • 在 Windows Phone silverlight 8.1 上接收 WNS 推送通知

    我有 Windows Phone 8 1 silverlight 应用程序 我想使用新框架 WNS 接收通知 我在 package appxmanifest 中有
  • 堆栈是向上增长还是向下增长?

    我在 C 中有这段代码 int q 10 int s 5 int a 3 printf Address of a d n int a printf Address of a 1 d n int a 1 printf Address of a
  • Objective-C / C 给出枚举默认值

    我在某处读到过关于给枚举默认值的内容 如下所示 typedef enum MarketNavigationTypeNone 0 MarketNavigationTypeHeirachy 1 MarketNavigationTypeMarke

随机推荐

  • Java之美[从菜鸟到高手演变]之设计模式二

    在阅读过程中有任何问题 请及时联系 egg 邮箱 xtfggef gmail com 微博 http weibo com xtfggef 如有转载 请说明出处 http blog csdn net zhangerqing 我们接着讨论设计模
  • 变量的声明和定义

    1 声明和定义的区别 变量声明规定了变量的类型和名字 而定义是在声明的基础上还开辟了存储空间 可能还会为变量初始化一个初始值 2 c 为什么要将声明和定义分开 c 支持分离式编译机制 允许将程序分割为若干个文件 每个文件可被独立编译 而为了
  • 华为云云耀云服务器L实例评测

    目录 引出 起因 si因 解决报错 诶嘿 连上了 不出意外 就出意外了 打开数据库 what 找华为云求助 教训 备份 教训 密码 解决 1 改密码 2 新建一个MySQL 密码设置复杂一点 3 开启 binlog备份 MySQL的binl
  • Java二维数组静态以及动态初始化方法

    import java util Random public class test2 public static void main String args 二维数组静态初始化 int arr 1 2 3 4 5 6 7 8 9 Syste
  • java8 函数式接口与 Lambda 表达式

    函数式接口与 Lambda 表达式 1 函数式接口 举例复习接口的匿名实现 函数式接口 2 Lambda表达式 什么是Lambda Lambda的几种编写规则解释示例 Lambda 的方法引用与构造器引用 方法引用的解释与编写 方法引用示例
  • Winform实现ComboBox模糊查询

    1 新增项目 using System using System Collections Generic using System ComponentModel using System Data using System Drawing
  • 【Web3 系列开发教程——创建你的第一个 NFT(7)】创建一个 NFT DApp,给你的 NFT 赋予属性,例如图片

    在本文中 你将构建一个 NFT 铸币机 并学习如何通过使用 Metamask 和 Web3 工具将你的智能合约连接到 React 前端 来创建一个NFT dApp 我认为 对于具备 Web2 开发背景的开发者来说 最大的挑战之一是弄清楚如何
  • 故障诊断专家系统研究之五-----推理机制及可信度算法

    推理机制及可信度算法 在第三章和第四章中讨论了如何表示燃气轮机专家的知识以及如何把这些知识存储到知识库之中 即关于知识表示和知识库的问题 而故障诊断专家系统的另一个核心组件就是基于知识的诊断推理机 本章在前两章讨论的知识表示和知识库的基础之
  • 计算机专业大学生如何规划大学四年?

    首先必须学好计算机专业四大核心课程 数据结构 计算机网络 计算机组成原理 计算机操作系统 在此之前呢 建议学习一门面向过程和一门面向对象的语言 对我们进一步学习计算机大有裨益 比如C语言程序设计 Java程序设计 文末有福利 一 计算机专业
  • Mybatis中的StatementType

    原文 http luoyu ds iteye com blog 1517607 要实现动态传入表名 列名 需要做如下修改 添加属性statementType STATEMENT 同时sql里的属有变量取值都改成 xxxx 而不是 xxx
  • 雅可比(Jacobi)计算特征值和特征向量

    雅可比迭代法法 在图形图像中很多地方用到求矩阵的特征值和特征向量 比如主成分分析 OBB包围盒等 编程时一般都是用数值分析的方法来计算 这里介绍一下雅可比迭代法求解特征值和特征向量 雅可比迭代法的原理 网上资料很多 详细可见参考资料1 这里
  • 最小二乘法(OLS)python 实践

    参考链接 1 基本原理 https zhuanlan zhihu com p 149280941 2 python实现 https zhuanlan zhihu com p 22692029 实现结果 线性回归 coding utf 8 简
  • 2022 数学建模C题 高教社杯 含半成品论文 部分代码 全部数学模型 和全套思路

    2022 数学建模国赛B题 高教社杯 含半成品论文 部分代码 全部数学模型 和全套思路 定时更新 全部内容见 https mianbaoduo com o bread mbd Y5WUkpps 注 题目阅读后主要告诉我们的内容见标蓝的关键词
  • oracle 11g安装教程完整版

    64位WIN7 oracle11g plsql安装 上部转自Oracle 11g R2 for Win7旗舰版 64位 的安装步骤 1 下载Oracle 11g R2 for Windows的版本 下载地址 http www oracle
  • MemTest64内存测试

    MemTest64是一款测试电脑内存稳定性的测试 软件同时支持32位64位运行环境 界面如下 一 使用步骤 设定使用模式 点击开始 二 各个设置项说明 测试内存 可打开任务管理器查看内存和CPU使用情况 选择合适内存值 无限制运行 建议慎用
  • Spring Boot的底层原理

    一 Spring Boot简介 1 什么是Spring Boot Spring Boot是由Pivotal团队提供的框架 其设计目的是用来简化新Spring应用的初始搭建以及开发过程 该框架使用了特定的方式 继承starter 约定优先于配
  • Java基础:Stream流常用方法

    获取Stream流的方式 java util stream Stream 是Java 8新加入的流接口 并不是一个函数式接口 获取一个流非常简单 有以下几种常用的方式 所有 Collection 集合都可通过 stream 默认方法获取流
  • 【uniapp项目路由,配置,修改uni ui默认样式,小程序端不生效问题】

    1 对不同平台进行不同配置或样式 对不同端的css样式不一样 使用 ifdef endif 包裹 其中MP表示小程序端 表仅在小程序端是那个样式 ifdef APP PLUS margin top 88rpx endif ifdef H5
  • isis安装指南(Liunx版本)+ ASP

    ISIS Integrated Software for Imagers and Spectrometers 是一个数字图像处理软件包 用于处理当前和过去 NASA 和国际行星任务收集的图像 例如 从PDS下载的LRO月球影像数据源文件为I
  • 三维视觉--基于Kinect2.0深度相机的点云获取方案实现(C++版)

    上一篇中使用的点云获取设备是Intel Realsense d455相机 这两天接触的相机不少 也发现很多点云检测和分割的论文中使用的都是Kinect相机 今天就再分享一篇使用Kinect2 0获取点云并使用C 实现 首先还是相机SDK的下