Introdução ao Kinect e ao processamento

o sensor Microsoft Kinect é um dispositivo periférico (projetado para PCs XBox e Windows) que funciona como uma webcam. No entanto, além de fornecer uma imagem RGB, ela também fornece um mapa de profundidade. Ou seja, para cada pixel visto pelo sensor, o Kinect mede a distância do sensor. Isso torna uma variedade de problemas de visão do computador, como remoção de fundo, detecção de blob e mais fácil e divertido!

o próprio sensor Kinect mede apenas a cor e a profundidade. No entanto, uma vez que essa informação está no seu computador, muito mais pode ser feito como rastreamento de “esqueleto” (ou seja, detectar um modelo de uma pessoa e rastrear seus movimentos). Para fazer o rastreamento de esqueleto, você precisará usar o Libray de processamento Kinect v2 apenas para Windows de Thomas Lengling. No entanto, se você estiver em um Mac e tudo o que quiser são dados brutos do Kinect, você está com sorte! Esta biblioteca usa drivers de código aberto libfreenect e libfreenect2 para acessar esses dados para Mac OS X (Suporte do windows em breve).

que hardware eu preciso?

primeiro você precisa de um kinect “autônomo”. Você não precisa comprar um Xbox.

  • Sensor Kinect autônomo V1. Acredito que este vem com a fonte de alimentação para que você não precise de um adaptador separado listado a seguir. No entanto, se você tiver um kinect v1 que veio com um XBox, ele não incluirá a fonte de Alimentação Do Sensor Kinect.
  • Sensor Kinect autônomo V2. Você também provavelmente precisa do adaptador Kinect para Windows. Não seja jogado fora, embora diga windows, isso permitirá que você o conecte ao seu mac via USB. Finalmente, você também vai querer ter certeza de que seu computador suporta USB 3. A maioria das máquinas modernas faz, mas se você não tiver certeza, pode descobrir mais aqui para Mac OS X.

algumas notas adicionais sobre diferentes modelos:

  • Kinect 1414: este é o kinect original e funciona com a biblioteca documentada nesta página na série Beta Processing 3.0.
  • Kinect 1473: parece idêntico ao 1414, mas é um modelo atualizado. Deve funcionar com esta biblioteca, mas não tenho uma para testar. Por favor, deixe-me saber se ele faz ou não!
  • Kinect para Windows Versão 1:???? Socorro? Este funciona?
  • Kinect para Windows Versão 2: Esta é a marca spanking novo kinect com todos os recursos encontrados no Xbox One Kinect. Também funciona com esta biblioteca!

SimpleOpenNI

você também pode considerar o uso da biblioteca SimpleOpenNI e ler o livro Making Things See de Greg Borenstein. OpenNI tem recursos (rastreamento de esqueleto, reconhecimento de gestos, etc.) que não estão disponíveis nesta biblioteca. Infelizmente, o OpenNI foi comprado recentemente pela Apple e, enquanto eu pensava que estava fechado, parece haver alguns esforços para revivê-lo!. Não está claro qual será o futuro de OpenNI e SimpleOpenNI.

estou pronto para começar agora

a maneira mais fácil de instalar a Biblioteca é com o Gerenciador de contribuições de processamento Sketch → importar bibliotecas → adicionar biblioteca e pesquisar por “Kinect”. Um botão aparecerá rotulado como “instalar”.Se você quiser instalá-lo, baixe manualmente a versão mais recente e extraia-a na pasta Bibliotecas. Reinicie o processamento, abra um dos exemplos na pasta exemplos e você está pronto para ir!

o que é Processamento?O processamento é uma linguagem de programação de código aberto e um ambiente para pessoas que desejam criar imagens, animações e interações. Inicialmente desenvolvido para servir como um sketchbook de software e ensinar fundamentos de programação de computadores dentro de um contexto visual, o processamento também evoluiu para uma ferramenta para gerar trabalho profissional acabado. Hoje, existem dezenas de milhares de estudantes, artistas, designers, pesquisadores e amadores que usam o processamento para aprendizagem, prototipagem e produção.

e se eu não quiser usar o processamento?

se você estiver confortável com C++, sugiro que considere usar openFrameworks ou Cinder com o Kinect. Esses ambientes têm alguns recursos adicionais e você também pode obter uma vantagem de Velocidade C++ ao processar os dados de profundidade, etc.:

  • ofxKinect
  • Kinect CinderBlock
  • mais recursos de: O projeto OpenKinect

que código eu escrevo?

a primeira coisa é incluir as instruções de importação adequadas na parte superior do seu código:

import org.openkinect.processing.*;

bem como uma referência a um objeto Kinect, ou seja,

Kinect kinect;

em Seguida, em setup() você pode inicializar o kinect objeto:

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

Se você estiver usando um Kinect v2, use um Kinect2 objeto em vez disso.

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

depois de fazer isso, você pode começar a acessar dados do sensor kinect. Atualmente, a biblioteca disponibiliza dados de cinco maneiras:

  • PImage (RGB) da câmera de vídeo kinect.
  • PImage (grayscale) da Câmara Kinect IR.
  • PImage (grayscale) com o brilho de cada pixel mapeado para Profundidade (mais brilhante = mais próximo).
  • PImage (RGB) com o matiz de cada pixel mapeado para profundidade.
  • int array com dados de profundidade bruta (números de 11 bits entre 0 e 2048).

vamos olhar para estes um de cada vez. Se você quiser usar o Kinect como uma webcam antiga normal, você pode acessar a imagem de vídeo como um PImage!

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

Você pode simplesmente pedir para esta imagem em draw(), no entanto, se você também pode usar videoEvent() para saber quando uma nova imagem está disponível.

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

Se você quiser IR imagem:

kinect.enableIR(true);

Com o kinect v1 não é possível obter a imagem de vídeo e o IR imagem. Ambos são passados de volta via getVideoImage (), portanto, o que foi ativado mais recentemente é o que você obterá. No entanto, com o Kinect v2, eles estão disponíveis como métodos separados:

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

Agora, se você deseja que a imagem de profundidade, você pode solicitar a imagem em tons de cinza:

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

bem como as matérias dados de profundidade:

int depth = kinect.getRawDepth();

Para o kinect v1, as matérias de profundidade, os valores variam entre 0 e 2048, para o kinect v2 o intervalo entre 0 e 4500.

para a imagem de profundidade de cor, use kinect.enableColorDepth(true);. E assim como com a imagem de vídeo, Há um evento de profundidade que você pode acessar, se necessário.

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

infelizmente, b / c A câmera RGB e a câmera IR não estão fisicamente localizadas no mesmo local, há um problema de visão estéreo. Pixel XY em uma imagem não é o mesmo XY em uma imagem de uma câmera de uma polegada para a direita. O Kinect V2 oferece o que é chamado de imagem “registrada” que alinha todos os valores de profundidade com os da câmera RGB. Isso pode ser acessado da seguinte forma:

PImage img = kinect2.getRegisteredImage()

finalmente, para kinect v1 (mas não v2), você também pode ajustar o ângulo da câmera com o método setTilt().

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

então, aí está, aqui estão todas as funções úteis que você pode precisar para usar a Biblioteca Processing kinect:

  • initDevice() — começar tudo (vídeo, profundidade, IR)
  • activateDevice(int) – activar um dispositivo específico quando vários dispositivos são ligue
  • initVideo() — vídeo apenas
  • enableIR(boolean) — ligar ou desligar a câmera do IR da imagem (v1 apenas)
  • initDepth() — iniciar profundidade de apenas
  • enableColorDepth(boolean) — ativar ou desativar a profundidade de valores como a cor da imagem
  • enableMirror(boolean) — espelho de imagem e dados de profundidade (v1 apenas)
  • PImage getVideoImage() — pegue o RGB (ou IR para v1) imagem de vídeo
  • PImage getIrImage() — pegue a IR imagem (v2 apenas)
  • PImage getDepthImage() — pegue o mapa de profundidade imagem
  • PImage getRegisteredImage() — pegue o registrado imagem de profundidade (v2 apenas)
  • int getRawDepth() — pegue a matérias dados de profundidade
  • float getTilt() — obter o sensor de ângulo (entre 0 e 30 graus) (v1 apenas)
  • setTilt(float) — ajustar o sensor de ângulo (entre 0 e 30 graus) (v1 apenas)

Para tudo o resto, você também pode dar uma olhada no javadoc referência.

exemplos

existem quatro exemplos básicos para v1 e v2.

exibir imagens RGB, IR e profundidade

código para v1: RGBDepthTest

código para V2:RGBDepthTest2

este exemplo usa todas as funções listadas acima para exibir os dados do sensor kinect.

vários dispositivos

ambos v1 e v2 tem suporte kinect múltipla.

Código para v1:MultiKinect

Código para v2:MultiKinect2

Nuvem de pontos

Código para v1: PointCloud

Código para v2: PointCloud

Aqui, nós estamos fazendo algo um pouco mais sofisticado. Número um, estamos usando os recursos 3D de processamento para desenhar pontos no espaço. Você vai querer se familiarizar com translate (), rotate (), pushMatrix (), popMatrix (). Este tutorial também é um bom lugar para começar. Além disso, o exemplo usa um PVector para descrever um ponto no espaço 3D. Mais aqui: tutorial do PVector.

o verdadeiro trabalho deste exemplo, no entanto, não vem de mim. Os valores de profundidade bruta do kinect não são diretamente proporcionais à profundidade física. Em vez disso, eles escalam com o inverso da profundidade de acordo com esta fórmula:

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

em vez de fazer esse cálculo o tempo todo, podemos pré-calcular todos esses valores em uma tabela de pesquisa, pois existem apenas 2048 valores de profundidade.

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

obrigado a Matthew Fisher pela fórmula acima. (Nota: para que os resultados sejam mais precisos, você precisaria calibrar seu dispositivo kinect específico, mas a fórmula está próxima o suficiente para mim, então estou aderindo a ela por enquanto. Mais sobre calibração em um momento.)

finalmente, podemos desenhar alguns pontos com base nos valores de profundidade em metros:

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

rastreamento médio de pontos

a verdadeira magia do kinect está em seus recursos de visão computacional. Com informações de profundidade, você pode fazer todos os tipos de coisas divertidas como dizer: “o fundo é qualquer coisa além de 5 pés. Ignore!”Sem profundidade, a remoção de fundo envolve todos os tipos de comparações meticulosas de pixels. Como uma demonstração rápida dessa ideia, aqui está um exemplo muito básico que calcula a localização xy média de quaisquer pixels na frente de um determinado limite de profundidade.

Fonte para v1: AveragePointTracking

Fonte para v2: AveragePointTracking2

neste exemplo, declaro duas variáveis para somar todos os x’s e y’s apropriados e uma variável para acompanhar quantos existem.

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

então, sempre que encontramos um determinado ponto que está em conformidade com o nosso limite, eu adiciono o x e y à soma:

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

quando terminamos, calculamos a média e desenhamos um ponto!

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

o que falta?

  • tudo está sendo rastreado por meio de problemas do github.

FAQ

  1. o Que há sombras na imagem de profundidade (v1)? Diagrama de sombra Kinect
  2. Qual é o intervalo de profundidade que o kinect pode ver? (v1) ~0.7–6 metros ou 2.3-20 pés. Observe que você obterá pixels pretos (ou valor de profundidade bruta de 2048) em ambos os elementos que estão muito longe e muito próximos.

Deixe uma resposta

O seu endereço de email não será publicado.