我创建了一个处理草图,它将每个点 Cloud 数据帧从kinect保存到文本文件,其中文件的每一行都是kinect注册的点(或顶点) . 我计划将数据拉入3d程序,以便在3d空间中可视化动画并应用各种效果 . 问题是,当我这样做时,第一帧似乎是正确的,其余的帧似乎吐出看起来像第一个图像,加上一堆随机噪声 . 这是我的全部代码 . 它需要简单的openni才能正常工作 . 你可以看到评论
import SimpleOpenNI.*;
//import processing.opengl.*;
SimpleOpenNI context;
float zoomF =0.5f;
float rotX = radians(180); // by default rotate the hole scene 180deg around the x-axis,
float rotY = radians(0); // the data from openni comes upside down
int maxZ = 2000;
Vector <Object> recording = new Vector<Object>();
boolean isRecording = false;
boolean canDraw = true;
boolean mouseMode = false;
int currentFile = 0;
int depthWidth = 640; //MH - assuming this is static?
int depthHeight = 480;
int steps = 5;
int arrayLength = (depthWidth/steps) * (depthHeight/steps); //total lines in each output file
void setup()
{
size(1024,768,P3D); // strange, get drawing error in the cameraFrustum if i use P3D, in opengl there is no problem
//size(1024,768,OPENGL);
context = new SimpleOpenNI(this);
context.setMirror(true);
depthWidth = context.depthWidth();
depthHeight = context.depthHeight();
// enable depthMap generation
if(context.enableDepth() == false)
{
println("Can't open the depthMap, maybe the camera is not connected!");
exit();
return;
}
stroke(255,255,255);
smooth();
perspective(radians(45),
float(width)/float(height),
10.0f,150000.0f);
}
void draw()
{
//println(isRecording);
// update the cam
context.update();
background(0,0,0);
// set the scene pos
translate(width/2, height/2, 0);
rotateX(rotX);
rotateY(rotY);
scale(zoomF);
// draw the 3d point depth map
int[] depthMap = context.depthMap();
int index = 0;
PVector realWorldPoint;
PVector[] frame = new PVector[arrayLength];
translate(0,0,-1000); // set the rotation center of the scene 1000 infront of the camera
stroke(200);
for(int y=0;y < context.depthHeight();y+=steps)
{
for(int x=0;x < context.depthWidth();x+=steps)
{
int offset = x + y * context.depthWidth();
realWorldPoint = context.depthMapRealWorld()[offset];
if (isRecording == true){
if (realWorldPoint.z < maxZ){
frame[index] = realWorldPoint;
} else {
frame[index] = new PVector(-0.0,-0.0,0.0);
}
index++;
} else {
if (realWorldPoint.z < maxZ){
if (canDraw == true){
point(realWorldPoint.x,realWorldPoint.y,realWorldPoint.z);
}
}
}
}
}
if (isRecording == true){
recording.add(frame);
}
if (mouseMode == true){
float rotVal = map (mouseX,0,1024,-1,1); //comment these out to disable mouse orientation
float rotValX = map (mouseY,0,768,2,4);
rotY = rotVal;
rotX = rotValX;
}
}
// -----------------------------------------------------------------
// Keyboard event
void keyPressed()
{
switch(key)
{
case ' ':
context.setMirror(!context.mirror());
break;
case 'm':
mouseMode = !mouseMode;
break;
case 'r':
isRecording = !isRecording;
break;
case 's':
if (isRecording == true){
isRecording = false;
canDraw = false;
println("Stopped Recording");
Enumeration e = recording.elements();
int i = 0;
while (e.hasMoreElements()) {
// Create one directory
boolean success = (new File("out"+currentFile)).mkdir();
PrintWriter output = createWriter("out"+currentFile+"/frame" + i++ +".txt");
PVector [] frame = (PVector []) e.nextElement();
for (int j = 0; j < frame.length; j++) {
output.println(j + ", " + frame[j].x + ", " + frame[j].y + ", " + frame[j].z );
}
output.flush(); // Write the remaining data
output.close();
//exit();
}
canDraw = true;
println("done recording");
}
currentFile++;
break;
}
switch(keyCode)
{
case LEFT:
if(keyEvent.isShiftDown())
maxZ -= 100;
else
rotY += 0.1f;
break;
case RIGHT:
if(keyEvent.isShiftDown())
maxZ += 100;
else
rotY -= 0.1f;
break;
case UP:
if(keyEvent.isShiftDown())
zoomF += 0.01f;
else
rotX += 0.1f;
break;
case DOWN:
if(keyEvent.isShiftDown())
{
zoomF -= 0.01f;
if(zoomF < 0.01)
zoomF = 0.01;
}
else
rotX -= 0.1f;
break;
}
}
我想循环是问题开始发生的地方:for(int y = 0; y <context.depthHeight(); y = steps){等等虽然它可能只是我为3d编写的python脚本的一个问题程序 . 无论如何,这是一个很酷的草图,我认为对于想要使用3d效果指向 Cloud 数据(或构建模型等)的人来说非常有用,但我现在卡住了 . 谢谢你的帮助!
1 回答
不幸的是,我可以在几个月前将类似的东西保存到PLY和CSV:
我正在使用if语句仅保存某个Z阈值内的点,但可以根据需要随意更改/使用 . 后处理的想法提醒Moullinex video for Catalina . 检查出来,它有详细记录,并包含源代码 .
Update 发布的代码每帧保存1个文件 . 即使播放速度较低,草图仍应保存每帧的文件 . 代码简化了一下:
预览可以与具有不同循环的录制分开,并且您可以具有低分辨率预览,但是保存更多数据,仍然会很慢 .
我还有另一个建议:记录到.oni format . 如果你已经安装了OpenNI,你可以使用几个样本,如NiViewer和NiBackRecorder . SimpleOpenNI还公开了这个功能,看看 RecorderPlay 样本 .
我建议尝试这样的事情:
将场景记录到.oni文件中 . 它应该快速/响应
当您重新录制时,处理每一帧(根据需要将深度转换为x,y,z点/过滤/保存到所需格式等)
这是另一个用于说明这个想法的草图:
当
recordFlag
设置为true时,数据将保存到.oni文件中 . 我没有't found anything in the docs to read how many frames there are in an .oni file so as a quick workaround I'已经添加了frame
计数器 . 如果你按空格键,录音将停止,但也会保存txt文件中的帧数,然后退出应用程序 . 这将在以后有用 .当
recordFlag
设置为false时,如果已有录音,则会播放 . 如果你在'mode'中占据空间,绘图将停止,帧编号将从.txt文件和每个帧加载:将更新上下文(移至下一帧)
深度图中的每个像素都将转换为一个点
所有点都将写入.ply文件(您可以使用meshlab进行处理)
保存所有帧后,草图将恢复绘制 . 由于没有3D绘图且草图相当简单,因此性能应该更好,但请记住,大的.oni文件需要大量的RAM . 您可以根据需要修改草图(例如,过滤掉您不想保存的信息等) .
还要注意上面,虽然应该保存到PLY每个单独的帧,但它保存相同 . 当调用noLoop()时,上下文似乎不会更新() . 这是一个使用3s的修改后的hacky版本 . 延迟(希望.ply fille将被写入磁盘) .
我不确定帧和文件是否同步,深度数据是否以中等质量保存,但我希望我的回答能提供一些想法 .