kinect/ traitement / simple openni - données de nuages de points n'étant pas sortie correctement
J'ai créé un traitement esquisse qui enregistre chaque trame de données du nuage de points à partir de la kinect dans un fichier texte où chaque ligne du fichier est un point (ou vertex) que le kinect a enregistré. J'ai l'intention de tirer les données dans un logiciel 3d pour visualiser l'animation dans l'espace 3d et appliquer différents effets. Le problème c'est que quand je fais cela, la première image semble correcte, et le reste de la les cadres semblent être de recracher ce qui ressemble à la première image, en plus d'un tas de bruit aléatoire. C'est mon code, dans sa totalité. Il exige simple openni pour fonctionner correctement. Vous pouvez voir les commentaires
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;
}
}
J'imagine que la boucle est là que les problèmes commencent produit: for(int y=0;y < le contexte.depthHeight();y+=étapes)
{ , etc. bien qu'il pourrait être simplement un problème avec le script python que j'ai écrit pour le programme 3d. De toute façon, c'est une cool esquisse, et je pense que ce serait super utile pour toutes les personnes souhaitant faire des effets 3d de données de nuages de points (ou de construire des modèles, etc), mais je suis coincé pour le moment. Merci pour votre aide!
Vous devez vous connecter pour publier un commentaire.
Malheureusement je ne peux pas expliquer beaucoup de choses en ce moment, mais j'ai sone quelque chose de similaire il y a quelques mois d'économie pour PLIS et CSV:
Je suis en utilisant une instruction if pour enregistrer uniquement les points dans un certain Z seuil, mais n'hésitez pas à modifier/utiliser comme bon vous semble.
Le post-traitement idée rappelle de la Moullinex vidéo de Catalina. Check it out, il est bien documenté et inclut le code source ainsi.
Mise à jour
Posté le code enregistre 1 fichier par image. Même si la vitesse de lecture serait faible, le croquis doit encore enregistrer un fichier pour chaque image. Le code est simplifié un peu:
L'aperçu peut être séparé de l'enregistrement avec les différentes boucles et vous pourriez avoir un faible res aperçu, mais enregistrer plus de données, encore, il est lent.
J'en ai une autre suggestion: Enregistrement à la .oni format à la place. Si vous avez installé OpenNI, vous pourriez faire usage d'un couple d'échantillons comme NiViewer et NiBackRecorder. SimpleOpenNI expose également cette fonctionnalité, avoir un regard sur le RecorderPlay de l'échantillon.
Je vous propose d'essayer quelque chose comme ceci:
Voici un autre croquis pour illustrer l'idée:
Lorsque le
recordFlag
est définie sur true, les données seront enregistrées dans un .oni fichier.Je n'ai rien trouvé dans les docs à lire le nombre d'images il y a dans une .oni fichier donc comme une solution de rechange rapide, j'ai ajouté le
frame
compteur. Si vous appuyez sur espace pour arrêter l'enregistrement, mais également d'enregistrer le nombre d'images dans un fichier txt puis de quitter l'application. Ce sera utile plus tard.Lorsque le
recordFlag
est définie sur false, si il y a un enregistrement déjà, il sera la lecture.Si vous appuyez sur espace, dans ce "mode", le dessin va s'arrêter, le numéro de l'image seront à la charge de l' .fichier txt et pour chaque image:
Après toutes les images ont été enregistrées, le sketch va reprendre le dessin. Depuis il n'y a pas de dessin 3D et le dessin, c'est assez simple, le rendement devrait être mieux, mais garder à l'esprit que les grandes .oni fichier, il faudra beaucoup de RAM. N'hésitez pas à modifier l'esquisse à vos besoins (par exemple, filtre l'information que vous ne voulez pas sauvé, etc.).
Aussi remarque que ci-dessus, bien que devrait enregistrer dans les PLIS de chaque châssis séparé, il enregistre la même. Il semble que le contexte n'a pas de mise à jour() lorsque noLoop() a été appelé. Voici une version modifiée de hacky version qui utilise un 3s. retard (espérons-le .plis fille sera écrit sur le disque à l'époque).
Je ne suis pas sûr de cadres et de synchronisation de fichiers et la profondeur de sauvegarde des données de qualité moyenne, mais j'espère que ma réponse donne des idées.
if(realWorldPoint.z > minZ && realWorldPoint.z < maxZ){
et la}
qui lui appartient. Également en ce qui concerne la vitesse, plus la résolution est élevée plus la vitesse de l'aperçu (qui peut être séparé de l'ensemble des points que vous êtes en train d'enregistrer quoique)