Erste Schritte mit Kinect und Verarbeitung

Der Microsoft Kinect-Sensor ist ein Peripheriegerät (für XBox und Windows-PCs), das wie eine Webcam funktioniert. Zusätzlich zur Bereitstellung eines RGB-Bildes bietet es jedoch auch eine Tiefenkarte. Bedeutung Für jedes vom Sensor gesehene Pixel misst der Kinect die Entfernung zum Sensor. Dies macht eine Vielzahl von Computer-Vision-Problemen wie Hintergrundentfernung, Blob-Erkennung und mehr einfach und macht Spaß!

Der Kinect-Sensor selbst misst nur Farbe und Tiefe. Sobald sich diese Informationen jedoch auf Ihrem Computer befinden, können Sie viel mehr tun, z. B. das „Skelett“ -Tracking (dh das Erkennen eines Modells einer Person und das Verfolgen ihrer Bewegungen). Um das Skelett-Tracking durchzuführen, müssen Sie Thomas Lenglings Kinect v2 Processing Libray nur für Windows verwenden. Wenn Sie sich jedoch auf einem Mac befinden und nur Rohdaten von der Kinect möchten, haben Sie Glück! Diese Bibliothek verwendet libfreenect- und libfreenect2-Open-Source-Treiber, um auf diese Daten für Mac OS X zuzugreifen (Windows-Unterstützung in Kürze).

Welche Hardware benötige ich?

Zuerst benötigen Sie eine „eigenständige“ Kinect. Sie müssen keine Xbox kaufen.

  • Eigenständiger Kinect-Sensor v1. Ich glaube, dieser kommt mit der Stromversorgung, so dass Sie keinen separaten Adapter benötigen, der als nächstes aufgeführt ist. Wenn Sie jedoch eine Kinect v1 haben, die mit einer XBox geliefert wurde, ist das Netzteil des Kinect-Sensors nicht enthalten.
  • Eigenständiger Kinect-Sensor v2. Sie benötigen wahrscheinlich auch den Kinect-Adapter für Windows. Lassen Sie sich nicht abwerfen, obwohl Windows angezeigt wird, können Sie es über USB an Ihren Mac anschließen. Schließlich sollten Sie auch sicherstellen, dass Ihr Computer USB 3 unterstützt. Die meisten modernen Maschinen tun dies, aber wenn Sie sich nicht sicher sind, können Sie hier mehr für Mac OS X erfahren.

Einige zusätzliche Hinweise zu verschiedenen Modellen:

  • Kinect 1414: Dies ist das Original Kinect und arbeitet mit der Bibliothek auf dieser Seite in der Verarbeitung 3.0 Beta-Serie dokumentiert.
  • Kinect 1473: Dies sieht identisch mit dem 1414 aus, ist jedoch ein aktualisiertes Modell. Es sollte mit dieser Bibliothek funktionieren, aber ich habe keine zum Testen. Bitte lassen Sie mich wissen, ob es tut oder nicht!
  • Kinect für Windows Version 1: ???? Hilfe? Funktioniert dieser?
  • Kinect für Windows Version 2: Dies ist die brandneue Kinect mit allen Funktionen der XBox One Kinect. Funktioniert auch mit dieser Bibliothek!

SimpleOpenNI

Sie können auch die SimpleOpenNI-Bibliothek verwenden und Greg Borensteins Making Things See-Buch lesen. OpenNI verfügt über Funktionen (Skelettverfolgung, Gestenerkennung usw.), die in dieser Bibliothek nicht verfügbar sind. Leider wurde OpenNI kürzlich von Apple gekauft, und obwohl ich dachte, es sei geschlossen, scheint es einige Bemühungen zu geben, es wiederzubeleben!. Es ist unklar, was die Zukunft von OpenNI und SimpleOpenNI sein wird.

Ich bin bereit, jetzt loszulegen

Der einfachste Weg, um die Bibliothek zu installieren, ist mit dem Processing Library Manager Sketch → Bibliotheken importieren → Bibliothek hinzufügen und nach „Kinect“ suchen. Eine Schaltfläche mit der Bezeichnung „Installieren“ wird angezeigt.Wenn Sie es manuell installieren möchten, laden Sie die neueste Version herunter und extrahieren Sie sie in den Ordner libraries. Starten Sie die Verarbeitung neu, öffnen Sie eines der Beispiele im Ordner Beispiele und los geht’s!

Was ist Verarbeitung?

Processing ist eine Open-Source-Programmiersprache und -Umgebung für Menschen, die Bilder, Animationen und Interaktionen erstellen möchten. Ursprünglich entwickelt, um als Software-Skizzenbuch zu dienen und Grundlagen der Computerprogrammierung in einem visuellen Kontext zu vermitteln, hat sich Processing auch zu einem Werkzeug zur Erstellung fertiger professioneller Arbeiten entwickelt. Heute gibt es Zehntausende von Studenten, Künstlern, Designern, Forschern und Hobbyisten, die Processing zum Lernen, Prototyping und zur Produktion verwenden.

Was ist, wenn ich die Verarbeitung nicht verwenden möchte?

Wenn Sie mit C ++ vertraut sind, empfehlen wir Ihnen, openFrameworks oder Cinder mit Kinect zu verwenden. Diese Umgebungen verfügen über einige zusätzliche Funktionen und Sie können auch einen C ++ – Geschwindigkeitsvorteil bei der Verarbeitung der Tiefendaten usw. erzielen.:

  • ofxKinect
  • Kinect CinderBlock
  • Weitere Ressourcen von: Das OpenKinect-Projekt

Welchen Code schreibe ich?

Als erstes müssen Sie die richtigen Importanweisungen oben in Ihren Code einfügen:

import org.openkinect.processing.*;

Sowie einen Verweis auf ein Kinect-Objekt, d.h.

Kinect kinect;

Dann können Sie in setup() dieses Kinect-Objekt initialisieren:

void setup() { kinect = new Kinect(this); kinect.initDevice();}

Wenn Sie eine Kinect v2 verwenden, verwenden Sie stattdessen ein Kinect2-Objekt.

Kinect2 kinect2;void setup() { kinect2 = new Kinect2(this); kinect2.initDevice();}

Sobald Sie dies getan haben, können Sie auf Daten vom Kinect-Sensor zugreifen. Derzeit stellt Ihnen die Bibliothek Daten auf fünf Arten zur Verfügung:

  • PImage (RGB) von der Kinect-Videokamera.
  • PImage (grayscale) von der Kinect IR-Kamera.
  • PImage (grayscale) wobei die Helligkeit jedes Pixels der Tiefe zugeordnet ist (heller = näher).
  • PImage (RGB) wobei der Farbton jedes Pixels der Tiefe zugeordnet ist.
  • int array mit rohen Tiefendaten (11 Bit Zahlen zwischen 0 und 2048).

Schauen wir uns diese einzeln an. Wenn Sie die Kinect wie eine normale alte Webcam verwenden möchten, können Sie als PImage auf das Videobild zugreifen!

PImage img = kinect.getVideoImage();image(img, 0, 0);

Sie können jedoch einfach in draw() nach diesem Bild fragen, wenn Sie auch videoEvent() verwenden können, um zu erfahren, wann ein neues Bild verfügbar ist.

void videoEvent(Kinect k) { // There has been a video event!}

Wenn sie wollen die IR bild:

kinect.enableIR(true);

Mit kinect v1 nicht erhalten sowohl die video bild und die IR bild. Sie werden beide über getVideoImage() zurückgegeben, sodass Sie das zuletzt aktivierte getVideoImage() erhalten. Mit der Kinect v2 sind sie jedoch beide als separate Methoden verfügbar:

PImage video = kinect2.getVideoImage();PImage ir = kinect2.getIrImage();

Wenn Sie nun das Tiefenbild wünschen, können Sie das Graustufenbild anfordern:

PImage img = kinect.getDepthImage();image(img, 0, 0);

Sowie die rohen Tiefendaten:

int depth = kinect.getRawDepth();

Für den Kinect v1 liegen die Rohtiefenwerte zwischen 0 und 2048, für den Kinect v2 zwischen 0 und 4500.

Verwenden Sie für das Farbtiefenbild kinect.enableColorDepth(true);. Und genau wie beim Videobild gibt es ein Tiefenereignis, auf das Sie bei Bedarf zugreifen können.

void depthEvent(Kinect k) { // There has been a depth event!}

Leider, b/c die RGB kamera und die IR kamera sind nicht physisch in der gleichen stelle, es ist eine stereo vision problem. Pixel XY in einem Bild ist nicht das gleiche XY in einem Bild von einer Kamera einen Zoll nach rechts. Die Kinect v2 bietet ein sogenanntes „registriertes“ Bild, das alle Tiefenwerte mit den RGB-Kamerawerten ausrichtet. Dies kann wie folgt erreicht werden:

PImage img = kinect2.getRegisteredImage()

Schließlich können Sie für Kinect v1 (aber nicht v2) den Kamerawinkel auch mit der setTilt() -Methode anpassen.

float angle = kinect.getTilt();angle = angle + 1;kinect.setTilt(angle);

Hier finden Sie alle nützlichen Funktionen, die Sie möglicherweise benötigen, um die Kinect-Verarbeitungsbibliothek zu verwenden:

  • initDevice() — starten Sie alles (Video, Tiefe, IR)
  • activateDevice(int) – aktivieren Sie ein bestimmtes Gerät, wenn mehrere Geräte verbunden sind
  • initVideo() — nur Video starten
  • enableIR(boolean) — ein- oder Ausschalten des IR-Kamerabildes (nur v1)
  • initDepth() — nur Starttiefe
  • enableColorDepth(boolean) — ein- oder Ausschalten der Tiefenwerte als Farbbild
  • enableMirror(boolean) — spiegeln Sie die Bild- und Tiefendaten (nur v1)
  • PImage getVideoImage() — schnappen Sie sich das RGB (oder IR für v1) Videobild
  • PImage getIrImage() — greifen die IR bild (v2 nur)
  • PImage getDepthImage() — schnapp dir die Tiefenkarte bild
  • PImage getRegisteredImage() — schnappen Sie sich das registrierte Tiefenbild (nur v2)
  • int getRawDepth() — holen Sie sich die rohen Tiefendaten
  • float getTilt() — ermitteln Sie den aktuellen Sensorwinkel (zwischen 0 und 30 Grad) (nur v1)
  • setTilt(float) — einstellen des Sensorwinkels (zwischen 0 und 30 Grad) (nur v1)

Für alles andere können Sie sich auch die Javadoc-Referenz ansehen.

Beispiele

Es gibt vier grundlegende Beispiele für v1 und v2.

Anzeige von RGB-, IR- und Tiefenbildern

Code für v1:RGBDepthTest

Code für v2:RGBDepthTest2

In diesem Beispiel werden alle oben aufgeführten Funktionen verwendet, um die Daten des Kinect-Sensors anzuzeigen.

Mehrere Geräte

Sowohl v1 als auch v2 unterstützen mehrere Kinect.

Code für v1: MultiKinect

Code für v2: MultiKinect2

Punktwolke

Code für v1: PunktWolke

Code für v2: PunktWolke

Hier machen wir etwas Schickeres. Erstens verwenden wir die 3D-Fähigkeiten der Verarbeitung, um Punkte im Raum zu zeichnen. Sie sollten sich mit translate() , rotate() , pushMatrix() , popMatrix () vertraut machen. Dieses Tutorial ist auch ein guter Anfang. Darüber hinaus verwendet das Beispiel einen PVector, um einen Punkt im 3D-Raum zu beschreiben. Mehr hier: PVector Tutorial.

Die eigentliche Arbeit dieses Beispiels kommt jedoch überhaupt nicht von mir. Die Rohtiefenwerte von Kinect sind nicht direkt proportional zur physischen Tiefe. Vielmehr skalieren sie mit der Umkehrung der Tiefe nach dieser Formel:

depthInMeters = 1.0 / (rawDepth * -0.0030711016 + 3.3309495161);

Anstatt diese Berechnung ständig durchzuführen, können wir alle diese Werte in einer Nachschlagetabelle vorberechnen, da nur 2048 Tiefenwerte vorhanden sind.

float depthLookUp = new float;for (int i = 0; i < depthLookUp.length; i++) { depthLookUp = rawDepthToMeters(i);}float rawDepthToMeters(int depthValue) { if (depthValue < 2047) { return (float)(1.0 / ((double)(depthValue) * -0.0030711016 + 3.3309495161)); } return 0.0f;}

Vielen Dank an Matthew Fisher für die obige Formel. (Hinweis: Damit die Ergebnisse genauer sind, müssten Sie Ihr spezifisches Kinect-Gerät kalibrieren, aber die Formel ist mir nahe genug, also bleibe ich vorerst dabei. Mehr über die Kalibrierung in einem Moment.)

Schließlich können wir einige Punkte basierend auf den Tiefenwerten in Metern zeichnen:

 for(int x = 0; x < w; x += skip) { for(int y = 0; y < h; y += skip) { int offset = x + y * kinect.width; // Convert kinect data to world xyz coordinate int rawDepth = depth; PVector v = depthToWorld(x, y, rawDepth); stroke(255); pushMatrix(); // Scale up by 200 float factor = 200; translate(v.x * factor, v.y * factor, factor-v.z * factor); // Draw a point point(0,0); popMatrix(); } }

Durchschnittliche Punktverfolgung

Die wahre Magie des Kinect liegt in seinen Computer-Vision-Funktionen. Mit Tiefeninformationen können Sie alle möglichen lustigen Dinge tun, wie zum Beispiel: „Der Hintergrund ist alles jenseits von 5 Fuß. Ignoriere es!“ Ohne Tiefe beinhaltet die Hintergrundentfernung alle Arten von sorgfältigen Pixelvergleichen. Als schnelle Demonstration dieser Idee ist hier ein sehr einfaches Beispiel, das die durchschnittliche xy-Position von Pixeln vor einer bestimmten Tiefenschwelle berechnet.

Quelle für v1: AveragePointTracking

Quelle für v2: AveragePointTracking2

In diesem Beispiel deklariere ich zwei Variablen, um alle geeigneten x und y zu addieren, und eine Variable, um zu verfolgen, wie viele es gibt.

float sumX = 0;float sumY = 0;float count = 0;

Wenn wir dann einen bestimmten Punkt finden, der unserem Schwellenwert entspricht, addiere ich x und y zur Summe:

 if (rawDepth < threshold) { sumX += x; sumY += y; count++; }

Wenn wir fertig sind, berechnen wir den Durchschnitt und zeichnen einen Punkt!

if (count != 0) { float avgX = sumX / count; float avgY = sumY / count; fill(255, 0, 0); ellipse(avgX, avgY, 16, 16);}

Was fehlt?

  • Alles wird über Github-Probleme verfolgt.

FAQ

  1. Was sind Schatten im Tiefenbild (v1)? Kinect-Schattendiagramm
  2. Welchen Tiefenbereich kann der Kinect sehen? (v1) ~ 0,7-6 Meter oder 2,3-20 Fuß. Beachten Sie, dass Sie an beiden Elementen, die zu weit entfernt und zu nahe sind, schwarze Pixel (oder einen rohen Tiefenwert von 2048) erhalten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.