关于KINECT V2.0 C++ SDK 基础教程的笔记 EP1

最近忙着搞老师的任务,没来得及更新点云系列。
目前在做Kinect,在这里接着做个笔记。
原文地址: Kinect Tutorials
这仅仅是做一个笔记以及自己的实际操作记录



Kinect Tutorials
⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆⬆跟着网上的教程,学习Kinect c++ SDK。


1、准备工作

配置环境

我的配置
Windows 10 64
Kinect SDK 2.0
Visual Sdutio 2019

1.1 安装SDL

前往GLUT网站下载
在这里插入图片描述

解压
记住你解压的位置

1.2 新建Kinect test项目

1、首先在属性表中导入Kinect SDK的libs和includes

  • 在C/C++ > 常规 > 附加包含目录中,添加$(KINECTSDK20_DIR)/inc。
  • 在链接器 > 常规 > 附加库目录中,添加$(KINECTSDK20_DIR)/lib/amd64(32 位系统下为/x86)。
  • 在链接器 > 输入 > 附加依赖项中,添加kinect20.lib。
    在这里插入图片描述

2、根据教程要求,可以加入OpenGL库。
在这里参考了文章的加入opengl的简单方法,单项目安装了OpenGL。

3、在前面选择了GLUT作为 OpenGL 的接口,需要依据本节步骤配置 OpenGL 属性表。

右键 OpenGL 属性表,点击“属性”,在链接器 > 输入 > 附加依赖项中,添加以下内容:

opengl32.lib
glu32.lib
freeglut.lib

在附加库目录中加入你解压位置的x64:

D:\Work_Space\C++\Kinect_SDL_test\freeglut\lib\x64

至此,我们的项目就准备好了。


2、Kinect 基础

目标: 学习如何初始化一台 Kinect,并从中获取 RGB 类型的数据。
源码: 🖨1_Basics.zip

详细对源码中的代码进行解读。

2.1 包含文件、常量、全局变量

1、包含文件
加入kinect、可视化的SDL、Ole2和windows

// SDL
//包含文件
#include <Windows.h>
#include <Ole2.h>
//为了Kinect正常工作
#include <SDL_opengl.h>
#include <SDL.h>
//为可视化
#include <Kinect.h>
//kinect主要头文件

2、常量、全局变量
Kinect的RGB分辨率为1920*1080,输入通道为4通道
所以在此定义窗口宽高以及数据结构

//常量和全局变量
#define width 1920
#define height 1080

// OpenGL Variables 变量
GLuint textureId;              // ID of the texture to contain Kinect RGB Data 包含 Kinect RGB 数据的纹理 ID
GLubyte data[width * height * 4];  // BGRA array containing the texture data  包含纹理数据的 BGRA 数组

// Kinect variables 变量
IKinectSensor* sensor;         // Kinect sensor  Kinect传感器
IColorFrameReader* reader;     // Kinect color data source    Kinect 颜色数据源

2.2 Kinect代码

1、第一段是初始化Kinect代码

//Kinect初始化
//initKinect()函数的作用是初始化一个 Kinect 设备。它包含了两个部分:首先,我们需要找到一个已连接到电脑的 Kinect 传感器,然后将其初始化并准备从中读取数据。
bool initKinect() {
	if (FAILED(GetDefaultKinectSensor(&sensor))) {
		return false;
	}
	if (sensor) {
		sensor->Open();

		IColorFrameSource* framesource = NULL;
		sensor->get_ColorFrameSource(&framesource);
		framesource->OpenReader(&reader);
		if (framesource) {
			framesource->Release();
			framesource = NULL;
		}
		return true;
	}
	else {
		return false;
	}
}

一般的流程:

  1. 编写一个适当类型的数据帧输入源 (framesource),包括彩色 (Color)、深度 (Depth)、肢体 (Body) 等。
  2. 通过传感器接口来请求数据帧输入源。
  3. 从数据帧输入源中打开读取器。
  4. 安全地释放数据帧输入源。
  5. 从读取器中请求数据。

2、从Kinect中获取RGB帧

//从 Kinect 中获取 RGB 帧
void getKinectData(GLubyte* dest) {
	IColorFrame* frame = NULL; 
	if (SUCCEEDED(reader->AcquireLatestFrame(&frame))) {//如果有可用帧
		frame->CopyConvertedFrameDataToArray(width * height * 4, data, ColorImageFormat_Bgra);
	}//把它以适当格式复制到纹理(testure)数组中
	//也可以用frame->AccessUnderlyingBuffer()访问原始数据,后续会有提到
	if (frame) frame->Release();//结束后释放数据帧
}

函数——查询可用、复制到数组、释放。

题外话
如果你想访问数据帧的元数据,可以参看这个页面

2.3 窗口化,事件处理和主循环

本节将会解释与 GLUT——或 SDL——相关的代码,包括了窗口初始化、事件处理和主更新循环。
GLUT 版本的实现还会通过指定draw()函数在每次循环迭代中被调用来设置主循环。
主循环在execute()函数中启动。在 GLUT中,循环是在后台处理的,所以我们需要做的就是调用glutMainLoop()函数。

void draw() {
   drawKinectData();
   glutSwapBuffers();
}

void execute() {
    glutMainLoop();
}

bool init(int argc, char* argv[]) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
    glutInitWindowSize(width,height);
    glutCreateWindow("Kinect SDK Tutorial");
    glutDisplayFunc(draw);
    glutIdleFunc(draw);
    return true;
}

2.4 通过 OpenGL 显示

设置纹理->OpenGL绘制纹理->设置相机视点(正投影)

// Initialize textures
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
             0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid*) data);
glBindTexture(GL_TEXTURE_2D, 0);

// OpenGL setup
glClearColor(0,0,0,0);
glClearDepth(1.0f);
glEnable(GL_TEXTURE_2D);

// Camera setup
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

再塞入main()函数之中

int main(int argc, char* argv[]) {
    if (!init(argc, argv)) return 1;
    if (!initKinect()) return 1;

    /* ...OpenGL texture and camera initialization... */

    // Main loop
    execute();
    return 0;
}

2.5 完整代码

// SDL
//包含文件
//为了Kinect正常工作

#include <Windows.h>
#include <Ole2.h>
//为可视化
#include <gl/GL.h>
#include <gl/GLU.h>
#include <gl/glut.h>
//kinect主要头文件
#include <Kinect.h>

//常量和全局变量
#define width 1920
#define height 1080

// OpenGL Variables 变量
GLuint textureId;              // ID of the texture to contain Kinect RGB Data 包含 Kinect RGB 数据的纹理 ID
GLubyte data[width * height * 4];  // BGRA array containing the texture data  包含纹理数据的 BGRA 数组

// Kinect variables 变量
IKinectSensor* sensor;         // Kinect sensor  Kinect传感器
IColorFrameReader* reader;     // Kinect color data source    Kinect 颜色数据源

//Kinect初始化
//initKinect()函数的作用是初始化一个 Kinect 设备。它包含了两个部分:首先,我们需要找到一个已连接到电脑的 Kinect 传感器,然后将其初始化并准备从中读取数据。
bool initKinect() {
	if (FAILED(GetDefaultKinectSensor(&sensor))) {
		return false;
	}
	if (sensor) {
		sensor->Open();

		IColorFrameSource* framesource = NULL;
		sensor->get_ColorFrameSource(&framesource);
		framesource->OpenReader(&reader);
		if (framesource) {
			framesource->Release();
			framesource = NULL;
		}
		return true;
	}
	else {
		return false;
	}
}

//从 Kinect 中获取 RGB 帧
void getKinectData(GLubyte* dest) {
	IColorFrame* frame = NULL; 
	if (SUCCEEDED(reader->AcquireLatestFrame(&frame))) {//如果有可用帧
		frame->CopyConvertedFrameDataToArray(width * height * 4, data, ColorImageFormat_Bgra);
	}//把它以适当格式复制到纹理(testure)数组中
	//也可以用frame->AccessUnderlyingBuffer()访问原始数据
	if (frame) frame->Release();//结束后释放数据帧
}

void drawKinectData() {
	glBindTexture(GL_TEXTURE_2D, textureId);
	getKinectData(data);
	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, (GLvoid*)data);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glBegin(GL_QUADS);
	glTexCoord2f(0.0f, 0.0f);
	glVertex3f(0, 0, 0);
	glTexCoord2f(1.0f, 0.0f);
	glVertex3f(width, 0, 0);
	glTexCoord2f(1.0f, 1.0f);
	glVertex3f(width, height, 0.0f);
	glTexCoord2f(0.0f, 1.0f);
	glVertex3f(0, height, 0.0f);
	glEnd();
}
//具体的初始化代码取决于使用那种实现方式 (GLUT 或 SDL)。它只是使用适当的 API 初始化一个窗口,失败时返回 false。GLUT 版本的实现还会通过指定draw()函数在每次循环迭代中被调用来设置主循环。
//主循环在execute()函数中启动。在 GLUT中,循环是在后台处理的,所以我们需要做的就是调用glutMainLoop()函数。
void draw() {
	drawKinectData();
	glutSwapBuffers();
}

void execute() {
	glutMainLoop();
}

bool init(int argc, char* argv[]) {
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(width, height);
	glutCreateWindow("Kinect SDK Tutorial");
	glutDisplayFunc(draw);
	glutIdleFunc(draw);
	return true;
}


int main(int argc, char* argv[]) {
	if (!init(argc, argv)) return 1;
	if (!initKinect()) return 1;

	// Initialize textures
	//代码中描述了三个步骤——设置纹理以包含图像帧,准备 OpenGL 来绘制纹理,以及设置摄像机视点(对 2D 图像使用正投影)。
	glGenTextures(1, &textureId);
	glBindTexture(GL_TEXTURE_2D, textureId);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
		0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, (GLvoid*)data);
	glBindTexture(GL_TEXTURE_2D, 0);

	// OpenGL setup
	glClearColor(0, 0, 0, 0);
	glClearDepth(1.0f);
	glEnable(GL_TEXTURE_2D);

	// Camera setup
	glViewport(0, 0, width, height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, width, height, 0, 1, -1);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// Main loop
	execute();
	return 0;
}

最后的结果显示在这里插入图片描述

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值