Point Cloud


Processing 2.0

Der Kinect Sensor bietet die einzigartige Möglichkeit die Distanz der einzelnen Bildpunkte zur Kamera zu messen. Wir nutzen diese Möglichkeit jetzt und zeichnen alle einzelnen Bildpunkte, die der Sensor liefert einfach im 3-dimensionalen Raum darzustellen. Das ganze bezeichnet man als Point Cloud.

141104_113108_52

/** Copyright 2014 Thomas Koberger
 */

// https://lernprocessing.wordpress.com/
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import SimpleOpenNI.*;
import java.util.Calendar;

SimpleOpenNI kinect;

void setup() {
  size(1200, 768, P3D);
  kinect = new SimpleOpenNI(this);
  kinect.enableDepth();
  stroke(255);
}

void draw() {
  background(0);
  kinect.update();

  // Verschiebe die Szene in den Mittelpunkt des Fensters
  translate(width/2, height/2, -500);
  // vertikal drehen, damit die Szene nicht auf dem Kopf steht
  rotateX(radians(180));
  // Rotationspunkt in die Mitte der Szene verschieben

  translate(0, 0, 1500);
  randomSeed(20);
  // Damit die Szene automatisch rotiert.
  rotateY((float)frameCount/50);
  translate(0, 0, -1500);

  // Einkommentieren, wenn man die Szene per Maus rotieren will!
  //  rotateY(map(mouseX, 0, width, -PI, PI));
  //  rotateX(map(mouseY, 0, width, -PI, PI));

  // Hier liefert die Kinect ein Array mit Vektoren
  PVector[] depthPoints = kinect.depthMapRealWorld();

  // Wir zeichnen nicht jeden Punkt, um die Sache zu beschleunigen
  for (int i = 0; i < depthPoints.length; i+= (int)random(2, 10)) {
    PVector currentPoint = depthPoints[i];
    stroke(map(currentPoint.z, 0, 7000, 255, 80));
    point(currentPoint.x, currentPoint.y, currentPoint.z);
  }
}

void keyReleased() {
  if (key == DELETE || key == BACKSPACE) background(360);
  if (key == 's' || key == 'S') saveFrame(timestamp()+"_##.png");
} 

//timestamp
String timestamp() {
  Calendar now = Calendar.getInstance();
  println("Frame saved");
  return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now);
}

Farbe

Nun können wir auch beide Kameras der Kinect nutzen und den Punkten ihre entsprechende Farbe zuweisen. Dabei kommen die Tiefeninformationen von der IR und die Farbinformationen von der RGB Kamera. Die dafür notwendigen mathematischen Operationen, nämlich das Auffinden der korrespondierenden Punkte der beiden Kameras, erledigt die Kinect.

141107_164425_59

</pre>
<pre>/** Copyright 2014 Thomas Koberger
 */

// https://lernprocessing.wordpress.com/
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import SimpleOpenNI.*;
import java.util.Calendar;

SimpleOpenNI kinect;

void setup() {
  size(1200, 768, P3D);
  kinect = new SimpleOpenNI(this);
  kinect.enableDepth();
  // Aktiviert die RGB Kamera der Kinect
  kinect.enableRGB();
  //Berechnet die korresponierenden Punkte der beiden Kameras
  //Dadurch bekommen die korrespondierenden Punkte der Tiefen- und der RGB Kamera
  //die gleichen Indizes
  kinect.alternativeViewPointDepthToImage();
}

void draw() {
  background(0);
  kinect.update();

  // Verschiebe die Szene in den Mittelpunkt des Fensters
  translate(width/2, height/2, -500);
  // vertikal drehen, damit die Szene nicht auf dem Kopf steht
  rotateX(radians(180));
  // Rotationspunkt in die Mitte der Szene verschieben

  translate(0, 0, 1500);
 
  // Damit die Szene automatisch rotiert.
  rotateY((float)frameCount/50);
  translate(0, 0, -1500);

  // Einkommentieren, wenn man die Szene per Maus rotieren will!
  //  rotateY(map(mouseX, 0, width, -PI, PI));
  //  rotateX(map(mouseY, 0, width, -PI, PI));

  // Hier liefert die Kinect ein Array mit Vektoren
  PVector[] depthPoints = kinect.depthMapRealWorld();
  PImage rgbImage = kinect.rgbImage();
 
  // Wir zeichnen nicht jeden Punkt, um die Sache zu beschleunigen
  for (int i = 0; i < depthPoints.length; i+= 10) {
    PVector currentPoint = depthPoints[i];
    
    // Hiermit färben wir die Punkte der Tiefeninformation mit der entsprechend
    // Farbe aus der RGB Kamera ein.
    stroke(rgbImage.pixels[i],map(currentPoint.z,0,7000,255,80));
    point(currentPoint.x, currentPoint.y, currentPoint.z);
  }
  println(frameRate);
}

void keyReleased() {
  if (key == DELETE || key == BACKSPACE) background(360);
  if (key == 's' || key == 'S') saveFrame(timestamp()+"_##.png");
} 

//timestamp
String timestamp() {
  Calendar now = Calendar.getInstance();
  println("Frame saved");
  return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now);
}

Linien

Nun kann man die einzelnen Punkte auch mit Linien verbinden.

 

/** Copyright 2014 Thomas Koberger
 */

// https://lernprocessing.wordpress.com/
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import SimpleOpenNI.*;
import java.util.Calendar;

SimpleOpenNI kinect;

void setup() {
  size(1200, 768, P3D);
  kinect = new SimpleOpenNI(this);
  kinect.enableDepth();
  // Aktiviert die RGB Kamera der Kinect
  kinect.enableRGB();
  //Berechnet die korresponierenden Punkte der beiden Kameras
  //Dadurch bekommen die korrespondierenden Punkte der Tiefen- und der RGB Kamera
  //die gleichen Indizes
  kinect.alternativeViewPointDepthToImage();
  noSmooth();
}

void draw() {
  background(0);
  kinect.update();

  // Verschiebe die Szene in den Mittelpunkt des Fensters
  translate(width/2, height/2, -500);
  // vertikal drehen, damit die Szene nicht auf dem Kopf steht
  rotateX(radians(180));
  // Rotationspunkt in die Mitte der Szene verschieben

  translate(0, 0, 1500);

  // Damit die Szene automatisch rotiert.
  rotateY((float)frameCount/50);
  translate(0, 0, -1500);

  // Einkommentieren, wenn man die Szene per Maus rotieren will!
  //  rotateY(map(mouseX, 0, width, -PI, PI));
  //  rotateX(map(mouseY, 0, width, -PI, PI));

  // Hier liefert die Kinect ein Array mit Vektoren
  PVector[] depthPoints = kinect.depthMapRealWorld();
  PImage rgbImage = kinect.rgbImage();
  strokeWeight(1);
  PVector prevPoint, currentPoint;
  prevPoint = new PVector(0, 0, 0);
  // Wir zeichnen nicht jeden Punkt, um die Sache zu beschleunigen
  for (int i = 20; i < depthPoints.length; i+= 3) {

    currentPoint = depthPoints[i];

    stroke(rgbImage.pixels[i]); 

    if (prevPoint.x!=0 && currentPoint.x!=0) {
      line(currentPoint.x, currentPoint.y, currentPoint.z, prevPoint.x, prevPoint.y, prevPoint.z);
    }
    
    // Wie speichern die Koordinaten des aktuellen Punkts als letzten Punkt
    prevPoint = currentPoint;
  }
  println(frameRate);
}

void keyReleased() {
  if (key == DELETE || key == BACKSPACE) background(360);
  if (key == 's' || key == 'S') saveFrame(timestamp()+"_##.png");
} 

//timestamp
String timestamp() {
  Calendar now = Calendar.getInstance();
  println("Frame saved");
  return String.format("%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS", now);
}

Advertisements

2 Kommentare

  1. Pingback: Processing – Über dieses Weblog | processing - tutorial

  2. Anja

    Vielen Dank für den Beitrag. Er war mir eine sehr große Hilfe 🙂

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: