Kinect + Emgu

Descupem lá a inactividade nos ultimos tempos. mas ter um trabalho a tempo inteiro e ter namorada as vezes deixa-nos sem tempo.

Comecei a brincar com Computer Vision e Kinect, não fiz grande coisa e desconhecia por completo como CV funciona e depois de ler um um pouco soube que o Emgu é um grande wrapper para a biblioteca do OpenCV.
De facto é possivel fazer reconhecimento facial sem grandes stresses.
Vamos la meter as mãos à obra neste biblioteca
Para este exemplo precisamos de:
e para tornar as coisas ainda mais faceis Coding4Fun Kinect Toolkit
Este ultima dll é excelent para passar os dados raw do kinect para bitmaps
Recomendo vivamente a lerem a documentação do Emgu, pode ser tricky para usar.
Então vamos começar por criar um novo windows project, depois vamos inserir todas as referencias
Adicionamo o Microsoft.Research.Kinect que pode ser encontrado nas referencias .NET. Depois é Coding4Fun dll, e todas as dlls necessarias para o Emgu.
Como podem ver o Emgu tem montes de referencias na pasta bin e devem colocar tambem as unmanage libraries como a
cvextern.dll, opencv_calib3d220 e por ai a fora… Como já referi, leiam a documentação do emgu…
Na vista de design adicionei o controlo EmguCV.UI.ImageBox e chamei-o de imageBox1.
No codigo adicionei isto:
using Emgu.CV;
using Emgu.CV.UI;
using Emgu.CV.Structure;
using Emgu.Util;
using Emgu.CV.CvEnum;
using Microsoft.Research.Kinect.Nui;
using Coding4Fun.Kinect.WinForm;
Estes são os usings que necessitam
e para isto tudo funcionar precisam destes objectos
Kinect.Nui.Runtime,
Emgu.CV.Image
e visto que vamos tentar detectar caras usando o algoritmo HaarCascade vamos usar o objecto HaarCascade.
O algortimo HaarCascade necessita de um ficheiro xml para aprender os padrões de moo a reconhecer caras, existem montes de ficheiros desses na internet e podem criar o vosso proprio ficheiro usando este  guia como exemplo (Existem muitos mais guias acerca deste topico)
ok então…
haar = new HaarCascade("haarcascade_frontalface_alt_tree.xml");

vai pupolar o objecto haar com o ficheiro xml

Bom agora vamos inicializar o kinect. Para isto apenas necessitamos da camera RGBpor isso vamos usar r RuntimeOption.UseColor.
Precisamos tambem de criar  evento VideoFrameReady para conseguir capturar a imagem e de seguia abrimos um VideoStream
Para quem não esta familiarizado com o metodo VideoStream.Open,  ele suporta 4 parametros: ImageStreamType, poolSize (o valor minimo é  2, isto vai funcionar como backbuffer para gravar dados em memoria), ImageResolution e finalmente ImageType:
kinect.Initialize(RuntimeOptions.UseColor);
kinect.VideoFrameReady += new EventHandler(kinect_VideoFrameReady);
kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
e pronto, o constructor deve ter este aspecto:
public Form1()
{
      InitializeComponent();
      haar = new HaarCascade("haarcascade_frontalface_alt_tree.xml");
      kinect.Initialize(RuntimeOptions.UseColor);
      kinect.VideoFrameReady += new EventHandler(kinect_VideoFrameReady);
      kinect.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
}

Agora que ja temos o event hanler do VideoFrameReady, ele vai receber no ImageFreameReayEventArgs todos os dados relevantes acerca da imagem. A primeira tarefa vai ser converter a imagem capturada num bitmap e converte-la outra vez para uma imagem do Emgu, de modo a podermos processa-la

 

 

 Image kinImage = new Image(e.ImageFrame.ToBitmap());
Ok ja temos uma image RGB no emgu e agora temos de converte-la para uma imagem em escala de cinzentos de modo a que o processamento do Emgu seja feito com melhor performance
Image grayframe = nextFrame.Convert();
e usamos o haarcascade para detectar todas as faces num determinado frame
 grayframe.DetectHaarCascade(
                                    haar, 1.4, 4,
                                    HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
                                    new Size(grayframe.Width / 8, grayframe.Height / 8)
                                    )[0];
…desenhamos um rectangulo a volta de cada face
  foreach (var face in faces)
{                         
    nextFrame.Draw(face.rect, new Bgr(0, double.MaxValue, 0), 3);                    
}
e finalmente desenhamos a imagem na imageBox1
imageBox1.Image = nextFrame;
para quem não gosta de ter trabalho aqui esta a source completa para fazer copy/paste:
void kinect_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
      {
            Image kinImage = new Image(e.ImageFrame.ToBitmap());
            using (Image; nextFrame = kinImage)
            {
                if (nextFrame != null)
                {
                    // there's only one channel (greyscale), hence the zero index
                    Image grayframe = nextFrame.Convert();
                    var faces =
                            grayframe.DetectHaarCascade(
                                    haar, 1.4, 4,
                                    HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,
                                    new Size(grayframe.Width / 14, grayframe.Height / 14)
                                    )[0];
                    foreach (var face in faces)
                    {
                        nextFrame.Draw(face.rect, new Bgr(0, double.MaxValue, 0), 3);
                    }
                    imageBox1.Image = nextFrame;
                }
            }
        }
Como podem ver é codigo facil 😀
podem fazer o download do ficheiro .cs
Aqui esta uma demo deste codigo a funcionar, peço desculpa pelo framerate baixo, o software de captura que usei é muito mau, tambem a luminusidade não é a melhor mas são 2 a manha e a minha namorada ja dorme no sofa ao meu lado por isso é melhor não meter mais luz a menos que queira levar com o rolo da massa.
No entanto é um excente proof-of-concept pois mesmo com má iluminação funcionou :)
Em excelentes condições de luminusidade a detecção de faces funciona na perfeição

13 pensamentos em “Kinect + Emgu

  1. Greetings Terry,

    You should can handle it with the code I posted! just give it a try.. if you have sugestions or comments please be free to tell me

  2. Hey!!

    I got the color input from the kinect and getting it on the window.

    But i couldn’t find any function as ImageFrame.ToBitmap() in ImageFrame object while creating Image(kinimage) in emgu.

    Can you please tell me how overcome this problem.

  3. I tried using your code, however the Covert() and DetectHaarCascade() methods seem to be unknown. (it says that such methods do not exist)
    Could you provide more insight on what exactly you have done there?

    • Did you instanciate the HaarCascade object from the Emgu dll?

      Those methods belong to that object…

      I explain and add those code snippets although I don’t provide the full code because I want people that is learning to explore it and figure out how it works otherwise you can do impressive things with only a copy/paste and I believe that is should be exciting not a copy paste task

  4. hi sir! I got the same problem as bagarwal…I was able to install the needed things (SDK’s, EmguCV’s, and the Coding4Fun stuff)…still I cannot find any function as ImageFrame.ToBitmap()…

  5. Hi killercode, first of all, thanks for the code. It`s has been usefull to me.

    But I had the same problem of Ralph. Could you help us?

  6. The initiate in the world of emguCv, the best way to learn is to give you a chance ….
    I give myself the opportunity to learn these development tools.

Deixar uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *