之前一直不知道如何实时保存RGB-D数据,每次都写入PCD文件不现实,对于30fps的,每秒就有30个PCD文件,硬盘速度绝逼跟不上。保存color和depth视频吧,总觉得不方便,而且depth压缩与解压缩会有精度损失。
后来老外提醒我:
/OpenNI2/Source/Tools/NiViewer press s to record oni file
感觉很方便,于是自己参考了《openni cookbook》,开始罗代码了。没有解释,有 问题自己看那本书吧。
生成含有RBG-D的ONI文件:
#include <OpenNI.h> #include <stdio.h> using namespace openni; char ReadLastCharOfLine() { int newChar = 0; int lastChar; fflush(stdout); do { lastChar = newChar; newChar = getchar(); }while ((newChar != '\n')&& (newChar != EOF)); return (char)lastChar; } bool HandleStatus(Status status) { if (status == STATUS_OK) return true; printf("ERROR: #%d, %s", status,OpenNI::getExtendedError()); ReadLastCharOfLine(); return false; } int main() { Status status = STATUS_OK; printf("Scanning machine for devices and loading " "modules/drivers ...\r\n"); status = OpenNI::initialize(); if (!HandleStatus(status)) return 1; printf("Completed.\r\n"); Device device; printf("Opening first device ...\r\n"); status = device.open(ANY_DEVICE); if (!HandleStatus(status)) return 1; printf("%s Opened, Completed.\r\n", device.getDeviceInfo().getName()); printf("Checking if stream is supported ...\r\n"); if (!device.hasSensor(SENSOR_DEPTH)) { printf("Stream not supported by this device.\r\n"); return 1; } printf("Asking device to create a depth stream ...\r\n"); VideoStream depthSensor; VideoStream colorSensor; status = depthSensor.create(device, SENSOR_DEPTH); if (!HandleStatus(status)) return 1; status = colorSensor.create(device, SENSOR_COLOR); if (!HandleStatus(status)) return 1; printf("Starting stream ...\r\n"); status = depthSensor.start(); if (!HandleStatus(status)) return 1; status = colorSensor.start(); if (!HandleStatus(status)) return 1; printf("Done.\r\n"); printf("Creating a recorder ...\r\n"); Recorder recorder; status = recorder.create("sample.oni"); if (!HandleStatus(status)) return 1; printf("Done.\r\n"); printf("Attaching to depth sensor ...\r\n"); status = recorder.attach(depthSensor); if (!HandleStatus(status)) return 1; status = recorder.attach(colorSensor); if (!HandleStatus(status)) return 1; printf("Done.\r\n"); printf("Starting recorder ...\r\n"); status = recorder.start(); if (!HandleStatus(status)) return 1; printf("Done. Now recording ...\r\n"); ReadLastCharOfLine(); recorder.destroy(); depthSensor.destroy(); colorSensor.destroy(); device.close(); OpenNI::shutdown(); return 0; }
读取上述ONI文件的RGB信息,并保存到PNG文件【代码是转载的,如果要读取深度信息,再加个 openni::SENSOR_DEPTH分支就行了】
#include <iostream> #include <OpenNI.h> #include <opencv2/photo.hpp> #include <opencv2/highgui.hpp> using namespace std; int main() { //定义oni文件中视频的总帧数以及得到的图片的保存目录 int total = 0; char* imagefile = "/home/jst/Data"; //初始化OpenNI环境 openni::OpenNI::initialize(); //声明设备并打开oni文件 openni::Device fromonifile; fromonifile.open("sample.oni"); //声明控制对象,这对视频流的控制起到了关键作用 openni::PlaybackControl* pController = fromonifile.getPlaybackControl(); //声明视频流对象以及帧对象 openni::VideoStream streamColor; openni::VideoFrameRef frameColor; //验证是否有彩色传感器(是否有彩色视频)和建立与设备想关联的视频流 if(fromonifile.hasSensor(openni::SENSOR_COLOR)) { if(streamColor.create( fromonifile, openni::SENSOR_COLOR ) == openni::STATUS_OK ) { cout<<"建立视频流成功"<<endl; } else { cerr<<"ERROR: 建立视频流没有成功"<<endl; system("pause"); return -1; } } else { cerr << "ERROR: 该设备没有彩色传感器" << endl; system("pause"); return -1; } //建立显示窗口 cv::namedWindow("Image"); //获取总的视频帧数并将该设备的速度设为-1以便能留出足够的时间对每一帧进行处理、显示和保存 total = pController->getNumberOfFrames(streamColor); pController->setSpeed(-1); //开启视频流 streamColor.start(); for (int i = 1;i <= total; ++ i) { //读取视频流的当前帧 streamColor.readFrame(&frameColor); cout<<"当前正在读的帧数是:"<<frameColor.getFrameIndex()<<endl; cout<<"当前的循环次数是: "<<i<<endl; //将帧保存到Mat中并且将其转换到BGR模式,因为在OpenCV中图片的模式是BGR cv::Mat rgbImg(frameColor.getHeight(), frameColor.getWidth(), CV_8UC3, (void*)frameColor.getData()); cv::Mat bgrImg; cvtColor(rgbImg, bgrImg, CV_RGB2BGR); //将每一帧按顺序帧保存到图片目录下 char imagefullname[255]; char imagenum[50]; sprintf(imagenum,"/%03d.png",i); strcpy(imagefullname,imagefile); strcat(imagefullname,imagenum); cv::imwrite(imagefullname,bgrImg); //显示当前帧 cv::imshow("Image",bgrImg); if (cv::waitKey(30) == 27) { break; } } //销毁显示窗口 cv::destroyWindow("Image"); //关闭视频流 streamColor.destroy(); //关闭设备 fromonifile.close(); //关闭OpenNI openni::OpenNI::shutdown(); return 0; }