6月回校才真正开始着手导师分配的kinect项目任务。在学习过程中先做一下简单的记录,有时间再完善。
1.kinect传感器构造与功能学习;
2.在官网下载kinect SDK v1.8—— http://www.microsoft.com/en-us/kinectforwindows/develop/
并安装到默认路径C:\Program Files\Microsoft SDKs\Kinect
3.点击Developer Toolkit Browser v1.8.0后,可以参看实用的例程文档,
我下载学习了samples:c++中的ColorBasics-D2D例程,在vs2010中打开学习了一下代码之后,就可以接入kinect测试。
也可以在接入kinect后点击browser里的三角运行按钮直接看应用程序运行效果。
3.1.接入kinect,需要插入电源和usb接口,之后会自动安装驱动,成功后xbox360前面的灯是绿色。
3.2.运行程序,便可以看到kinect捕捉到的彩色图像。
4.学习编写简单的功能程序
主要参看博文:http://blog.youkuaiyun.com/zouxy09/article/details/8163265
博主共发相关文档8篇,每一篇都非常实用,我主要学习了利用kinect结合opencv显示彩色图和深度图显示的功能程序。
4.1新建
新建项目:MyFirstKinectApp,并添加c++文件,命名为MyFirstKinectApp.cpp,我稍微改写了博主笔记四和笔记五的代码,
#include <iostream>
#include <NuiApi.h>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
void getColorImage(HANDLE &colorEvent, HANDLE &colorStreamHandle, Mat &colorImage);
void getDepthImage(HANDLE &depthEvent, HANDLE &depthStreamHandle, Mat &depthImage);
int main(int argc, char *argv[])
{
Mat colorImage;//用cv创建的代表单帧的变量。
colorImage.create(480, 640, CV_8UC3);
Mat depthImage;
depthImage.create(240, 320, CV_8UC3);
//2、定义事件句柄
//创建读取下一帧的信号事件句柄,控制KINECT是否可以开始读取下一帧数据
HANDLE colorEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
HANDLE depthEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
HANDLE colorStreamHandle = NULL; //保存图像数据流的句柄,用以提取数据
HANDLE depthStreamHandle = NULL; //保存图像数据流的句柄,用以提取数据
//1、初始化NUI
HRESULT hr = NuiInitialize(NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_DEPTH);
if (FAILED(hr))
{
cout<<"NuiInitialize failed"<<endl;
return hr;
}
//3、打开KINECT设备的彩色图信息通道,并用colorStreamHandle保存该流的句柄,以便于以后读取
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR, NUI_IMAGE_RESOLUTION_640x480,
0, 4, colorEvent, &colorStreamHandle);
if( FAILED( hr ) )//判断是否提取正确
{
cout<<"Could not open color image stream video"<<endl;
NuiShutdown();
return hr;
}
namedWindow("colorImage", CV_WINDOW_AUTOSIZE);
hr = NuiImageStreamOpen(NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX, NUI_IMAGE_RESOLUTION_320x240,
NULL, 2, depthEvent, &depthStreamHandle);
if( FAILED( hr ) )//判断是否提取正确
{
cout<<"Could not open color image stream video"<<endl;
NuiShutdown();
return hr;
}
namedWindow("depthImage", CV_WINDOW_AUTOSIZE);
//4、开始读取彩色图数据
while(1)
{
if(WaitForSingleObject(colorEvent, 0)==0)
getColorImage(colorEvent, colorStreamHandle, colorImage);
if(WaitForSingleObject(depthEvent, 0)==0)
getDepthImage(depthEvent, depthStreamHandle, depthImage);
imshow("colorImage", colorImage);
imshow("depthImage", depthImage);
if(cvWaitKey(1)==27)
break;
}
//7、关闭NUI链接
NuiShutdown();
return 0;
}
void getColorImage(HANDLE &colorEvent, HANDLE &colorStreamHandle, Mat &colorImage)
{
const NUI_IMAGE_FRAME *colorFrame = NULL;
NuiImageStreamGetNextFrame(colorStreamHandle, 0, &colorFrame);
INuiFrameTexture *pTexture = colorFrame->pFrameTexture;
NUI_LOCKED_RECT LockedRect;
pTexture->LockRect(0, &LockedRect, NULL, 0);
if( LockedRect.Pitch != 0 )
{
for (int i=0; i<colorImage.rows; i++)
{
uchar *ptr = colorImage.ptr<uchar>(i); //第i行的指针
//每个字节代表一个颜色信息,直接使用uchar
uchar *pBuffer = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch;
for (int j=0; j<colorImage.cols; j++)
{
ptr[3*j] = pBuffer[4*j]; //内部数据是4个字节,0-1-2是BGR,第4个现在未使用
ptr[3*j+1] = pBuffer[4*j+1];
ptr[3*j+2] = pBuffer[4*j+2];
}
}
}
else
{
cout<<"捕捉色彩图像出现错误"<<endl;
}
pTexture->UnlockRect(0);
NuiImageStreamReleaseFrame(colorStreamHandle, colorFrame );
}
void getDepthImage(HANDLE &depthEvent, HANDLE &depthStreamHandle, Mat &depthImage)
{
const NUI_IMAGE_FRAME * depthFrame = NULL;
NuiImageStreamGetNextFrame(depthStreamHandle, 0, &depthFrame);
INuiFrameTexture * pTexture = depthFrame->pFrameTexture;
NUI_LOCKED_RECT LockedRect;
pTexture->LockRect(0, &LockedRect, NULL, 0);
if( LockedRect.Pitch != 0 )
{
for (int i=0; i<depthImage.rows; i++)
{
uchar *ptr =depthImage.ptr<uchar>(i); //第i行的指针
//深度图像数据含有两种格式,这里像素的低12位表示一个深度值,高4位未使用;
//注意这里需要转换,因为每个数据是2个字节,存储的同上面的颜色信息不一样,
uchar *pBufferRun = (uchar*)(LockedRect.pBits) + i * LockedRect.Pitch;
USHORT * pBuffer = (USHORT*) pBufferRun;
for (int j=0; j<depthImage.cols; j++)
{
ptr[j] = 255 - (uchar)(256 * pBuffer[j]/0x0fff); //直接将数据归一化处理
}
}
}
else
{
cout<<"捕捉深度图像出现错误"<<endl;
}
pTexture->UnlockRect(0);
NuiImageStreamReleaseFrame(depthStreamHandle, depthFrame);
}
这样就能简单地同时显示彩色和深度图,必须说明,我改写的很少,博主的代码可读性很高,风格很清晰,并且博文有相关代码解释,有利于尽快入门。
4.2环境配置
我的开发平台:Win7 x86 + VS2010 + Kinect for Windows SDK v1.8 + OpenCV2.3.1
在项目-属性-配置属性-vc++目录中,包含目录中添加:
$(KINECTSDK10_DIR)\inc
D:\OpenCV2.3.1\build\include
D:\OpenCV2.3.1\build\include\opencv
D:\OpenCV2.3.1\build\include\opencv2
//简直太神奇!在包含目录中竟然是大小写区分的!!!刚刚才发现……涨姿势……
在库目录中添加:
$(KINECTSDK10_DIR)\lib\x86
D:\OpenCV2.3.1\build\x86\vc10\lib
在链接器-输入中,附加依赖库加:
opencv_highgui231d.lib
opencv_core231d.lib
opencv_video231d.lib
opencv_imgproc231d.lib
Kinect10.lib//这个很重要千万不要丢掉,否则kinect是不能用的。
至此环境配置完成。
现在就可以运行程序啦~