Introduzione a Kinect ed elaborazione

Il sensore Microsoft Kinect è un dispositivo periferico (progettato per XBox e PC Windows) che funziona come una webcam. Tuttavia, oltre a fornire un’immagine RGB, fornisce anche una mappa di profondità. Significato per ogni pixel visto dal sensore, il Kinect misura la distanza dal sensore. Questo rende una varietà di problemi di visione artificiale come la rimozione di sfondo, rilevamento blob, e più facile e divertente!

Il sensore Kinect misura solo colore e profondità. Tuttavia, una volta che le informazioni sono sul computer, molto di più può essere fatto come il monitoraggio “scheletro” (cioè rilevare un modello di una persona e monitorare i suoi movimenti). Per eseguire il tracciamento dello scheletro è necessario utilizzare il libray di elaborazione Kinect v2 solo per Windows di Thomas Lengling. Tuttavia, se siete su un Mac e tutto quello che volete è dati grezzi dal Kinect, siete fortunati! Questa libreria utilizza libfreenect e libfreenect2 driver open source per accedere a tali dati per Mac OS X (supporto di Windows in arrivo).

Di quale hardware ho bisogno?

Per prima cosa è necessario un kinect “stand-alone”. Non è necessario acquistare una Xbox.

  • Sensore Kinect autonomo v1. Credo che questo venga fornito con l’alimentatore in modo da non aver bisogno di un adattatore separato elencato di seguito. Tuttavia, se si dispone di un kinect v1 fornito con una XBox, non includerà l’alimentatore del sensore Kinect.
  • Sensore Kinect autonomo v2. Probabilmente hai anche bisogno dell’adattatore Kinect per Windows. Non essere buttato fuori, anche se dice di Windows, questo vi permetterà di collegarlo al vostro Mac tramite USB. Infine, ti consigliamo anche di assicurarsi che il computer supporta USB 3. La maggior parte delle macchine moderne lo fa, ma se non sei sicuro puoi saperne di più qui per Mac OS X.

Alcune note aggiuntive sui diversi modelli:

  • Kinect 1414: Questo è il kinect originale e funziona con la libreria documentata in questa pagina nella serie Processing 3.0 beta.
  • Kinect 1473: Sembra identico al 1414, ma è un modello aggiornato. Dovrebbe funzionare con questa libreria, ma non ne ho uno da testare. Per favore fatemi sapere se lo fa o no!
  • Kinect per Windows versione 1:???? Aiuto? Questo funziona?
  • Kinect per Windows versione 2: Questo è il marchio spanking nuovo kinect con tutte le funzionalità presenti in Xbox One Kinect. Funziona anche con questa libreria!

SimpleOpenNI

Potresti anche considerare di utilizzare la libreria SimpleOpenNI e leggere il libro di Greg Borenstein Making Things See. OpenNI ha caratteristiche (tracciamento dello scheletro, riconoscimento dei gesti, ecc.) che non sono disponibili in questa libreria. Sfortunatamente, OpenNI è stato recentemente acquistato da Apple e, mentre pensavo che fosse chiuso, sembrano esserci alcuni sforzi per rianimarlo!. Non è chiaro quale sarà il futuro di OpenNI e SimpleOpenNI.

Sono pronto per iniziare in questo momento

Il modo più semplice per installare la libreria è con lo schizzo di Gestione contributi di elaborazione → Importa librerie → Aggiungi libreria e cerca “Kinect”. Apparirà un pulsante con l’etichetta “installa”.Se si desidera installarlo manualmente, scaricare la versione più recente ed estrarla nella cartella libraries. Riavvia l’elaborazione, apri uno degli esempi nella cartella esempi e sei a posto!

Che cos’è l’elaborazione?

Processing è un linguaggio di programmazione open source e ambiente per le persone che vogliono creare immagini, animazioni e interazioni. Inizialmente sviluppato per servire come sketchbook software e per insegnare i fondamenti della programmazione di computer all’interno di un contesto visivo, l’elaborazione si è evoluta anche in uno strumento per la generazione di lavoro professionale finito. Oggi, ci sono decine di migliaia di studenti, artisti, designer, ricercatori e hobbisti che utilizzano l’elaborazione per l’apprendimento, la prototipazione e la produzione.

Cosa succede se non voglio usare l’elaborazione?

Se hai dimestichezza con C++ ti suggerisco di considerare l’utilizzo di openFrameworks o Cinder con Kinect. Questi ambienti hanno alcune funzionalità aggiuntive e potresti anche ottenere un vantaggio di velocità C++ durante l’elaborazione dei dati di profondità, ecc.:

  • ofxKinect
  • Kinect CinderBlock
  • Ulteriori risorse da: Il progetto OpenKinect

Che codice scrivo?

La prima cosa è includere le istruzioni di importazione corrette nella parte superiore del codice:

import org.openkinect.processing.*;

Così come un riferimento a un oggetto Kinect, cioè

Kinect kinect;

Quindi in setup() puoi inizializzare quell’oggetto kinect:

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

Se si utilizza un Kinect v2, utilizzare invece un oggetto Kinect2.

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

Una volta fatto questo è possibile iniziare ad accedere ai dati dal sensore kinect. Attualmente, la libreria rende i dati disponibili in cinque modi:

  • PImage (RGB) dalla videocamera kinect.
  • PImage (grayscale) dalla telecamera kinect IR.
  • PImage (grayscale) con la luminosità di ogni pixel mappata alla profondità (più luminosa = più vicina).
  • PImage (RGB) con la tonalità di ogni pixel mappata alla profondità.
  • int array con dati di profondità grezzi (numeri a 11 bit tra 0 e 2048).

Diamo un’occhiata a questi uno alla volta. Se si desidera utilizzare il Kinect proprio come una normale vecchia webcam, è possibile accedere all’immagine video come un PImage!

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

Puoi semplicemente chiedere questa immagine in draw(), tuttavia, se puoi anche usare videoEvent() per sapere quando è disponibile una nuova immagine.

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

Se si desidera che l’immagine IR:

kinect.enableIR(true);

Con kinect v1 non è possibile ottenere sia l’immagine video che l’immagine IR. Entrambi vengono restituiti tramite getVideoImage (), quindi quello che è stato abilitato più di recente è quello che otterrai. Tuttavia, con il Kinect v2, sono entrambi disponibili diversi metodi:

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

Ora, se si desidera che la profondità dell’immagine, è possibile richiedere l’immagine in scala di grigi:

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

così Come il raw i dati di profondità:

int depth = kinect.getRawDepth();

Per il kinect v1, il raw profondità i valori sono compresi tra 0 e 2048, per il kinect v2 l’intervallo è compreso tra 0 e 4500.

Per l’immagine profondità colore, utilizzare kinect.enableColorDepth(true);. E proprio come con l’immagine video, c’è un evento di profondità a cui puoi accedere se necessario.

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

Sfortunatamente, b / c la telecamera RGB e la telecamera IR non si trovano fisicamente nello stesso punto, c’è un problema di visione stereo. Pixel XY in un’immagine non è lo stesso XY in un’immagine da una fotocamera un pollice a destra. Kinect v2 offre ciò che viene chiamato un’immagine “registrata” che allinea tutti i valori di profondità con quelli della fotocamera RGB. Questo è possibile accedere come segue:

PImage img = kinect2.getRegisteredImage()

Infine, per kinect v1 (ma non v2), è anche possibile regolare l’angolazione della telecamera con il metodo setTilt().

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

Quindi, il gioco è fatto, ecco tutte le funzioni utili che potrebbe essere necessario utilizzare la libreria di elaborazione kinect:

  • initDevice() — avviare il tutto (video, profondità, IR)
  • activateDevice(int) – attivare un dispositivo specifico quando più dispositivi di connettersi
  • initVideo() — avviare il video solo
  • enableIR(boolean) — accendere o spegnere la macchina fotografica di IR di immagine (v1 solo)
  • initDepth() — avviare profondità solo
  • enableColorDepth(boolean) — attivare o disattivare i valori di profondità di colore come da immagine
  • enableMirror(boolean) — specchio l’immagine e i dati di profondità (v1 solo)
  • PImage getVideoImage() — afferrare la RGB (o PI v1) immagine video
  • PImage getIrImage() — afferrare l’immagine IR (solo v2)
  • PImage getDepthImage() — afferrare la mappa di profondità immagine
  • PImage getRegisteredImage() — afferrare registrato profondità dell’immagine (solo v2)
  • int getRawDepth() — afferrare il raw i dati di profondità
  • float getTilt() — ottenere il sensore di corrente ad angolo (tra 0 e 30 gradi) e (v1 solo)
  • setTilt(float) — regolare l’angolo del sensore (tra 0 e 30 gradi) e (v1 solo)

Per tutto il resto, si può anche dare un’occhiata al javadoc di riferimento.

Esempi

Esistono quattro esempi di base per v1 e v2.

Visualizza immagini RGB, IR e profondità

Codice per v1: RGBDepthTest

Codice per v2:RGBDepthTest2

Questo esempio utilizza tutte le funzioni sopra elencate per visualizzare i dati dal sensore kinect.

Più dispositivi

Sia v1 e v2 ha più kinect supporto.

Codice per v1:MultiKinect

Codice per v2:MultiKinect2

Nuvola di punti

Codice per v1: PointCloud

Codice per v2: PointCloud

Qui, stiamo facendo qualcosa di un po ‘ più elaborato. Numero uno, stiamo usando le funzionalità 3D dell’elaborazione per disegnare punti nello spazio. Ti consigliamo di familiarizzare con translate(), rotate(), pushMatrix (), popMatrix (). Questo tutorial è anche un buon punto di partenza. Inoltre, l’esempio utilizza un PVector per descrivere un punto nello spazio 3D. Più qui: tutorial PVector.

Il vero lavoro di questo esempio, tuttavia, non viene affatto da me. I valori di profondità grezzi del kinect non sono direttamente proporzionali alla profondità fisica. Piuttosto, si ridimensionano con l’inverso della profondità secondo questa formula:

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

Piuttosto che fare questo calcolo tutto il tempo, possiamo precalcolare tutti questi valori in una tabella di ricerca poiché ci sono solo 2048 valori di profondità.

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;}

Grazie a Matthew Fisher per la formula di cui sopra. (Nota: affinché i risultati siano più accurati, è necessario calibrare il dispositivo kinect specifico, ma la formula è abbastanza vicina per me, quindi per ora mi attengo. Maggiori informazioni sulla calibrazione in un momento.)

Infine, possiamo disegnare alcuni punti in base ai valori di profondità in metri:

 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(); } }

Average Point Tracking

La vera magia del kinect sta nelle sue capacità di visione artificiale. Con informazioni approfondite, puoi fare ogni sorta di cose divertenti come dire: “lo sfondo è qualcosa al di là di 5 piedi. Ignoralo!”Senza profondità, la rimozione dello sfondo comporta tutti i tipi di accurati confronti dei pixel. Come una rapida dimostrazione di questa idea, ecco un esempio molto semplice che calcola la posizione media xy di qualsiasi pixel di fronte a una data soglia di profondità.

Sorgente per v1: AveragePointTracking

Sorgente per v2: AveragePointTracking2

In questo esempio, dichiaro due variabili per sommare tutte le x e y appropriate e una variabile per tenere traccia di quante ce ne sono.

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

Quindi, ogni volta che troviamo un dato punto conforme alla nostra soglia, aggiungo x e y alla somma:

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

Quando abbiamo finito, calcoliamo la media e disegniamo un punto!

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

Cosa manca?

  • Tutto viene monitorato tramite problemi github.

FAQ

  1. Quali sono le ombre nell’immagine di profondità (v1)? Diagramma ombra Kinect
  2. Qual è l’intervallo di profondità che il kinect può vedere? (v1) ~0.7-6 metri o 2.3-20 piedi. Nota otterrai pixel neri (o valore di profondità grezzo di 2048) su entrambi gli elementi che sono troppo lontani e troppo vicini.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.