2012-08-28 36 views
7

Ciao sto cercando di fare un po 'di elaborazione delle immagini. Io uso Microsoft Kinect per rilevare gli umani in una stanza. Ottengo dati di profondità, fare un po 'di lavoro sottrazione del fondo e finiscono con una sequenza video come questo, quando una persona entra in scena e va in giro:Come posso rimuovere il rumore da questa sequenza video?

http://www.screenr.com/h7f8

ho messo un video in modo da poter vedere il comportamento di il rumore nel video. Diversi colori rappresentano diversi livelli di profondità. Il bianco rappresenta vuoto. Come puoi vedere è piuttosto rumoroso, specialmente i rumori rossi.

Ho bisogno di liberarmi di tutto tranne l'umano il più possibile. Quando eseguo l'erosione/dilatazione (usando una dimensione molto grande della finestra) posso eliminare un sacco di rumore, ma mi chiedevo se ci sono altri metodi che posso usare. Soprattutto il rumore rosso nel video è difficile da rimuovere con l'erosione/dilatazione.

Alcune note:

1) Uno sfondo meglio sottrazione potrebbe essere fatto se sapevamo quando non ci sono esseri umani nella scena, ma la sottrazione dello sfondo che facciamo è completamente automatico e funziona anche quando ci sono gli esseri umani nel scena e anche quando la telecamera viene spostata ecc., quindi questa è la migliore sottrazione di sfondo che possiamo ottenere adesso.

2) L'algoritmo funzionerà su un sistema integrato, in tempo reale. Quindi, più efficiente e semplice è l'algoritmo, meglio è. E non deve essere perfetto. Sebbene siano anche ben accette le tecniche di elaborazione del segnale complicate (forse potremmo usarle su un altro progetto che non ha bisogno di elaborazione integrata in tempo reale).

3) Non è necessario un codice effettivo. Solo idee

+0

Sapere di più sulla sottrazione dello sfondo potrebbe aiutare; cioè perché c'è del rumore nell'immagine? – jpa

+0

Quale SDK/driver stai utilizzando (ad esempio, MS Kinect SDK, OpenNI, libfreenect, ecc.)? –

risposta

0

Questo è piuttosto semplice se si utilizza Kinect SDK. Io seguirei this video per basi di profondità, e fare qualcosa di simile:

private byte[] GenerateColoredBytes(DepthImageFrame depthFrame) 
    { 

     //get the raw data from kinect with the depth for every pixel 
     short[] rawDepthData = new short[depthFrame.PixelDataLength]; 
     depthFrame.CopyPixelDataTo(rawDepthData); 

     //use depthFrame to create the image to display on-screen 
     //depthFrame contains color information for all pixels in image 
     //Height x Width x 4 (Red, Green, Blue, empty byte) 
     Byte[] pixels = new byte[depthFrame.Height * depthFrame.Width * 4]; 

     //Bgr32 - Blue, Green, Red, empty byte 
     //Bgra32 - Blue, Green, Red, transparency 
     //You must set transparency for Bgra as .NET defaults a byte to 0 = fully transparent 

     //hardcoded locations to Blue, Green, Red (BGR) index positions  
     const int BlueIndex = 0; 
     const int GreenIndex = 1; 
     const int RedIndex = 2; 


     //loop through all distances 
     //pick a RGB color based on distance 
     for (int depthIndex = 0, colorIndex = 0; 
      depthIndex < rawDepthData.Length && colorIndex < pixels.Length; 
      depthIndex++, colorIndex += 4) 
     { 
      //get the player (requires skeleton tracking enabled for values) 
      int player = rawDepthData[depthIndex] & DepthImageFrame.PlayerIndexBitmask; 

      //gets the depth value 
      int depth = rawDepthData[depthIndex] >> DepthImageFrame.PlayerIndexBitmaskWidth; 

      //.9M or 2.95' 
      if (depth <= 900) 
      { 
       //we are very close 
       pixels[colorIndex + BlueIndex] = Colors.White.B; 
       pixels[colorIndex + GreenIndex] = Colors.White.G; 
       pixels[colorIndex + RedIndex] = Colors.White.R; 
      } 
      // .9M - 2M or 2.95' - 6.56' 
      else if (depth > 900 && depth < 2000) 
      { 
       //we are a bit further away 
       pixels[colorIndex + BlueIndex] = Colors.White.B; 
       pixels[colorIndex + GreenIndex] = Colors.White.G; 
       pixels[colorIndex + RedIndex] = Colors.White.R; 
      } 
      // 2M+ or 6.56'+ 
      else if (depth > 2000) 
      { 
       //we are the farthest 
       pixels[colorIndex + BlueIndex] = Colors.White.B; 
       pixels[colorIndex + GreenIndex] = Colors.White.G; 
       pixels[colorIndex + RedIndex] = Colors.White.R; 
      } 


      ////equal coloring for monochromatic histogram 
      //byte intensity = CalculateIntensityFromDepth(depth); 
      //pixels[colorIndex + BlueIndex] = intensity; 
      //pixels[colorIndex + GreenIndex] = intensity; 
      //pixels[colorIndex + RedIndex] = intensity; 


      //Color all players "gold" 
      if (player > 0) 
      { 
       pixels[colorIndex + BlueIndex] = Colors.Gold.B; 
       pixels[colorIndex + GreenIndex] = Colors.Gold.G; 
       pixels[colorIndex + RedIndex] = Colors.Gold.R; 
      } 

     } 


     return pixels; 
    } 

Questo trasforma tutto tranne gli esseri umani bianchi, e gli esseri umani sono in oro. Spero che questo ti aiuti!

EDIT

So che non necessariamente vuole codice solo idee, quindi direi trovare un algoritmo che trova la profondità, e uno che trova la quantità di esseri umani, e il colore bianco tutto tranne la gli esseri umani. Ho fornito tutto questo, ma non sapevo se sapessi cosa stava succedendo. Inoltre ho un'immagine del programma finale.

image1

Nota: ho aggiunto il secondo telaio di profondità per la prospettiva

0

Posso sbagliarmi (avrei bisogno il video senza elaborazione per questo), ma mi piacerebbe tendono a dire che si stanno cercando di sbarazzarsi dei cambiamenti di illuminazione.

Questo è ciò che rende davvero difficile il rilevamento delle persone negli ambienti "reali".

È possibile controllare this other SO question per alcuni collegamenti.

Ho usato per rilevare gli esseri umani in tempo reale nella stessa configurazione di te, ma con visione monoculare. Nel mio caso, un vero descrittore era il LBPs, che viene utilizzato principalmente per la classificazione delle texture. Questo è abbastanza semplice da mettere in pratica (ci sono implementazioni su tutto il web).

Gli LBP in cui fondamentalmente viene utilizzato per definire un'area di interesse in cui viene rilevato il movimento, in modo che sia possibile elaborare solo una parte dell'immagine e eliminare tutto il rumore.

Questa carta ad esempio utilizza LBP per la correzione della scala di grigi delle immagini.

Spero che porti nuove idee.

2

Solo i miei due centesimi:

Se non ti dispiace utilizzando l'SDK per questo, allora si può facilmente tenere solo i pixel persona che utilizza il PlayerIndexBitmask come dimostra Outlaw Lemur.

Ora è possibile che non si desideri essere affidabili sui driver e che si desideri farlo in un livello di elaborazione dell'immagine. Un approccio che avevamo provato in un progetto e funzionava piuttosto bene era basato sul contorno. Abbiamo iniziato con una sottrazione di sfondo e poi abbiamo rilevato il contorno più grande dell'immagine presumendo che questa fosse la persona (poiché di solito il rumore che rimaneva era molto piccolo di blob) e abbiamo riempito quel contorno e mantenuto quello. Puoi anche usare una sorta di filtraggio mediano come prima passata.

Naturalmente, questo non è perfetto né adatto in ogni caso e probabilmente ci sono metodi molto migliori. Ma lo sto lanciando solo se ti aiuta a trovare qualche idea.

+0

+1 Questo può valere per qualsiasi lingua/fonte –

1

Dai uno sguardo allo eyesweb.

È una piattaforma per la progettazione che supporta il dispositivo kinect ed è possibile applicare filtri antidisturbo sulle uscite. È uno strumento molto utile e semplice per la progettazione di sistemi multimodal.