参考网址:
-(1)http://blog.csdn.net/chenxin_130/article/details/8580636
-(2)https://social.msdn.microsoft.com/Forums/en-US/bae80fb0-fce5-468e-a292-fe46381af3e5/how-to-install-openni-22-nite-22-kinect-sdk-18-windows-7-3264-bit?forum=kinectsdk
-(3)http://www.cnblogs.com/tornadomeet/archive/2012/11/16/2772681.html
(1)一开始不要把kinect插在电脑上!先安装Kinect for Windows SDK 1.8(Kinect for Windows SDK 1.8 官方下载网址),再连接kinect,可以从设备管理器里面看或者通过运行sample检验是否安装成功。(如果一开始就先把kinect连上了,windows会自动装上不正确的驱动,后面在设备管理器里会发现不能识别kinect,只能识别为“未知设备”,这时候先把这个未知设备的驱动删了,然后把kinect拔了,装了SDK以后再插上kinect)
(2)安装好驱动以后,先安装openni2.2(64位openni2.2 CSDN下载网址,32位openni2.2 CSDN下载网址),再安装nite2.2(64位nite2.2 CSDN下载网址,32位nite2.2 CSDN下载网址)。安装包从网址(2)下载,或者从CSDN上搜。网址(2)中建议64位电脑需要同时安装openni2.2和nite2.2的64位和32位版本,但我尝试过两种版本都安装,安装后会导致打不开kinect,所以只装64位或者只装32位的openni和nite就好了。
(3)每次运行exe程序,将OpenNI2\Redist\文件夹下所有文件粘贴到exe同目录下。
(4)如果有kinect初始化失败的情况,可以尝试用管理员身份打开记事本,打开”C:\Program Files (x86)\OpenNI2\Redist\OpenNI2\Drivers\PS1080.ini”,将”;UsbInterface=2”修改为”UsbInterface=0”(记得去掉UsbInterface前的”;”)。(测试openni2 sample 如NiViewer时,需修改sample同目录下的”OpenNI2\Drivers\PS1080.ini”文件)
(4)配置VS开发环境,见参考网址(1)。
(1)获取彩色图和深度图程序
参考网址:http://blog.csdn.net/chenxin_130/article/details/8619909
(2)获取红外图像
代码如下:
#include <stdlib.h>
#include <iostream>
#include <string>
#include "OpenNI.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
using namespace openni;
void CheckOpenNIError(Status result, string status)
{
if (result != STATUS_OK)
cerr << status << " Error: " << OpenNI::getExtendedError() << endl;
}
int main(int argc, char** argv)
{
Status result = STATUS_OK;
//OpenNI2 image
VideoFrameRef oniIrImg;
//OpenCV image
cv::Mat cvIrImg;
cv::namedWindow("Ir");
char key = 0;
//【1】
// initialize OpenNI2
result = OpenNI::initialize();
CheckOpenNIError(result, "initialize context");
// open device
Device device;
result = device.open(openni::ANY_DEVICE);
//【2】
// create Ir stream
VideoStream oniIrStream;
result = oniIrStream.create(device, openni::SENSOR_IR);
//【3】
// set Ir video mode
VideoMode modeIr;
modeIr.setResolution(640, 480);
modeIr.setFps(30);
modeIr.setPixelFormat(PIXEL_FORMAT_GRAY16);
oniIrStream.setVideoMode(modeIr);
// start Ir stream
result = oniIrStream.start();
while (key != 27)
{
if (oniIrStream.readFrame(&oniIrImg) == STATUS_OK)
{
cv::Mat cvRawImg16U(oniIrImg.getHeight(), oniIrImg.getWidth(), CV_16UC1, (void*)oniIrImg.getData());
cvRawImg16U.convertTo(cvIrImg, CV_8U);
cv::imshow("Ir", cvIrImg);
}
key = cv::waitKey(20);
}
//cv destroy
cv::destroyWindow("Ir");
//OpenNI2 destroy
oniIrStream.destroy();
device.close();
OpenNI::shutdown();
return 0;
}
注意:假设project位置为”..\Visual Studio 2015\Projects\GetKinectIRImageProject\”,程序在Debug x86模式下运行,需要将”C:\Program Files (x86)\OpenNI2\Redist”下所有文件粘贴到”..\Visual Studio 2015\Projects\GetKinectIRImageProject\Debug\”文件夹下。
/*************************
OpenNI2 Deep, Color and Fusion Image
Author: Xin Chen, 2013.2
Blog: http://blog.csdn.net/chenxin_130
*************************/
/*************************
Add IR image getting and Image saving
Author: LuHaiyan, 2017.2
Blog: http://blog.csdn.net/u011988573
*************************/
//否则会出现错误:This function or variable may be unsafe.Consider using localtime_s instead
#pragma warning(disable:4996)
#include //获取时间
#include //创建文件夹
#include
#include
#include
#include "OpenNI.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
using namespace openni;
/*
博客(http://www.cnblogs.com/tornadomeet/archive/2012/11/16/2772681.html)中提到,
Kinect在使用时,微软官方推荐的距离为1220mm(4’)~3810mm(12.5’),
网友heresy在他的博文Kinect + OpenNI 的深度值中统计过,
kinect在距离为1.0m时其精度大概是3mm,而当距离是3.0m时,其精度大概是3cm,
因此当kinect在官方推荐的距离范围内使用时,
如果是1.2m时,其精度应该在3mm附近,
如果是3.6m时其精度就大于3cm了,
因此距离越远,其深度值精度越低。
另外,通过OpenNI获取到的深度信息(即z坐标)的单位是mm,
这一点在程序编程中要注意,且一般的深度值用12bit(其实是可以用13bit表示的)表示,即最大值为4095,也就是代表4.095m,
所以平时我们采集到的深度数据如果需要扩展到灰度图,可以乘以一个因子255/4095
(为了加快该结果,一般设置为256/4096,即转换后的灰度值每变化1,代表kinect采集到的深度值变化了16mm,
如果当人的距离为1米左右时,本来精度是3mm,现在经过归一化后精度确更加下降了,
如果其深度值为0表示该位置处侦测不到像素点的深度。
*/
#define DEPTH_SCALE_FACTOR 256./4096.
string getTime()
{
time_t rawtime;
struct tm * timeinfo;
char buffer[128];
time(&rawtime);
timeinfo = localtime(&rawtime);
strftime(buffer, sizeof(buffer), "%Y_%m_%d_%H_%M_%S", timeinfo);
string time_now = buffer;
cout << time_now << endl;
return time_now;
}
void CheckOpenNIError(Status result, string status)
{
if (result != STATUS_OK)
cerr << status << " Error: " << OpenNI::getExtendedError() << endl;
}
int main(int argc, char** argv)
{
Status result = STATUS_OK;
//OpenNI2 image
//VideoFrameRef oniDepthImg;
VideoFrameRef oniColorImg;
VideoFrameRef oniIrImg;
//OpenCV image
//cv::Mat cvDepthImg;
cv::Mat cvBGRImg;
//cv::Mat cvFusionImg;
cv::Mat cvIrImg;
//cv::namedWindow("depth");
cv::namedWindow("rgb");
//cv::namedWindow("fusion");
cv::namedWindow("Ir");
//【1】
// initialize OpenNI2
result = OpenNI::initialize();
CheckOpenNIError(result, "initialize context");
// open device
Device device;
result = device.open(openni::ANY_DEVICE);
//【2】
create depth stream
//VideoStream oniDepthStream;
//result = oniDepthStream.create(device, openni::SENSOR_DEPTH);
//
【3】
set depth video mode
//VideoMode modeDepth;
//modeDepth.setResolution(640, 480);
//modeDepth.setFps(30);
//modeDepth.setPixelFormat(PIXEL_FORMAT_DEPTH_1_MM);
//oniDepthStream.setVideoMode(modeDepth);
start depth stream
//result = oniDepthStream.start();
// create Ir stream
VideoStream oniIrStream;
result = oniIrStream.create(device, openni::SENSOR_IR);
//【3】
// set Ir video mode
VideoMode modeIr;
modeIr.setResolution(640, 480);
modeIr.setFps(30);
modeIr.setPixelFormat(PIXEL_FORMAT_GRAY16);
oniIrStream.setVideoMode(modeIr);
// start Ir stream
//result = oniIrStream.start();
// create color stream
VideoStream oniColorStream;
result = oniColorStream.create(device, openni::SENSOR_COLOR);
// set color video mode
VideoMode modeColor;
modeColor.setResolution(640, 480);
modeColor.setFps(30);
modeColor.setPixelFormat(PIXEL_FORMAT_RGB888);
oniColorStream.setVideoMode(modeColor);
//【4】
// set depth and color imge registration mode
/*if (device.isImageRegistrationModeSupported(IMAGE_REGISTRATION_DEPTH_TO_COLOR))
{
device.setImageRegistrationMode(IMAGE_REGISTRATION_DEPTH_TO_COLOR);
}*/
// start color stream
result = oniColorStream.start();
// mkdir
/*string path_of_all = "F:\\Data_kinect\\test\\";
string path_of_rgb_d = path_of_all + getTime();
_mkdir(const_cast(path_of_rgb_d.c_str()));*/
char pathOfAll[1024]= "F:\\Data_kinect\\test\\";
strcat(pathOfAll, getTime().c_str());
strcat(pathOfAll, "\\");
_mkdir(pathOfAll);
char path[200];
char path_rgb[200];
char path_ir[200];
//string path_of_rgb = path_of_rgb_d + "\\rgb_image";
//string path_of_depth = path_of_rgb_d + "\\depth_image";
//string path_of_ir = path_of_rgb_d + "\\ir_image";
//string path_of_fusion = path_of_rgb_d + "\\fusion_image";
//_mkdir(const_cast(path_of_rgb.c_str()));
//_mkdir(const_cast(path_of_depth.c_str()));
//_mkdir(const_cast(path_of_fusion.c_str()));
//_mkdir(const_cast(path_of_ir.c_str()));
// image index
int frame_index = 0;
char key = 'a';
while (key != 27)
{
// read frame
if (oniColorStream.readFrame(&oniColorImg) == STATUS_OK)
{
// convert data into OpenCV type
cv::Mat cvRGBImg(oniColorImg.getHeight(), oniColorImg.getWidth(), CV_8UC3, (void*)oniColorImg.getData());
cv::cvtColor(cvRGBImg, cvBGRImg, CV_RGB2BGR);
flip(cvBGRImg, cvBGRImg, 1);
cv::imshow("rgb", cvBGRImg);
}
//if (oniDepthStream.readFrame(&oniDepthImg) == STATUS_OK)
//{
// cv::Mat cvRawImg16U(oniDepthImg.getHeight(), oniDepthImg.getWidth(), CV_16UC1, (void*)oniDepthImg.getData());
// //cvRawImg16U.convertTo(cvDepthImg, CV_8U, 255.0 / (oniDepthStream.getMaxPixelValue()));
// cvRawImg16U.convertTo(cvDepthImg, CV_8U, DEPTH_SCALE_FACTOR);
// //cvRawImg16U.convertTo(cvDepthImg, CV_8U);
// //inverse depth color
// /*for (int i = 0; i < cvDepthImg.rows; i++)
// {
// uchar* pData = cvDepthImg.ptr(i);
// for (int j = 0; j < cvDepthImg.cols ; j++)
// {
// pData[j] = cv::saturate_cast(255-pData[j]);
// }
// }*/
// //【5】
// // convert depth image GRAY to BGR
// //cv::cvtColor(cvDepthImg, cvFusionImg, CV_GRAY2BGR);
// cv::imshow("depth", cvDepthImg);
//}
//【6】
//cv::addWeighted(cvBGRImg, 0.5, cvFusionImg, 1.0, 0, cvFusionImg);
//cv::imshow("fusion", cvFusionImg);
key = waitKey(1);
if (key == 's') {
//save image to certain path
/*stringstream stream;
stream << frame_index;
string frame_index_str = stream.str();*/
/*string rgb_path = path_of_rgb + "\\";
rgb_path += frame_index_str + ".jpg";*/
/*string depth_path = path_of_depth + "\\";
depth_path += frame_index_str + ".jpg";*/
//string fusion_path = path_of_fusion + "\\";
//fusion_path += frame_index_str + ".jpg";
/*string ir_path = path_of_ir + "\\";
ir_path += frame_index_str + ".jpg";*/
strcpy(path, pathOfAll);
sprintf(path_rgb, "%04d_rgb.jpg", frame_index);
strcat(path, path_rgb);
cout <<"rgb:"<< path << endl;
imwrite(path, cvBGRImg);
//imwrite(depth_path, cvDepthImg);
//imwrite(fusion_path, cvFusionImg);
oniColorStream.stop();
oniIrStream.start();
if (oniIrStream.readFrame(&oniIrImg) == STATUS_OK)
{
cv::Mat cvRawImg16U(oniIrImg.getHeight(), oniIrImg.getWidth(), CV_16UC1, (void*)oniIrImg.getData());
cvRawImg16U.convertTo(cvIrImg, CV_8U);
flip(cvIrImg, cvIrImg, 1);
cv::imshow("Ir", cvIrImg);
}
strcpy(path, pathOfAll);
sprintf(path_ir, "%04d_ir.jpg", frame_index);
strcat(path, path_ir);
cout << "ir:" << path << endl;
imwrite(path, cvIrImg);
cout <<"Index "<< frame_index << " rgb and ir image saved." << endl;
oniIrStream.stop();
oniColorStream.start();
frame_index++;
}
}
//cv destroy
//cv::destroyWindow("depth");
cv::destroyWindow("rgb");
//cv::destroyWindow("fusion");
cv::destroyWindow("Ir");
//OpenNI2 destroy
//oniDepthStream.destroy();
oniColorStream.destroy();
oniIrStream.destroy();
device.close();
OpenNI::shutdown();
return 0;
}