Código no GitHub · English

YOLO-people-projection

Uma câmara observa pessoas num chão. O computador calcula onde cada uma está, em metros, envia isso por OSC, e um projetor desenha no chão exatamente debaixo dos seus pés.

Este guia mostra como funciona: a montagem física, a calibração que alinha tudo, e como os ficheiros se alimentam uns aos outros. Os comandos passo a passo estão no README.

1. Como funciona, numa imagem

Cada imagem da câmara passa pela mesma cadeia. O YOLO, um modelo de reconhecimento de imagem, encontra cada pessoa e os seus tornozelos. Os tornozelos são convertidos de píxeis da câmara para metros no chão. Um seguidor (tracker) acompanha cada pessoa de imagem para imagem e dá-lhe um id. As posições saem como mensagens OSC, que qualquer programa pode receber. Um sketch de Processing desenha em metros, e o seu desenho é ajustado ao projetor para aparecer onde as pessoas estão.

O seguidor (Python: track_osc.py) Câmara cada imagem Tornozelos YOLO pose Metros no chão calibração da câmara Seguir suaviza, mantém ids OSC /person id x y UDP, porta 12000 Um sketch (Processing, ou qualquer programa que fale OSC) People quem está onde O seu desenho em metros, no retângulo da fita Ajustar ao projetor calibração do projetor Luz no chão debaixo dos pés
Em cima: track_osc.py. Em baixo: um sketch de Processing (a aba People, o seu desenho, a aba Projection). Qualquer outro programa que fale OSC pode ocupar o lugar da linha de baixo.

2. A montagem física

É preciso um projetor apontado para o chão, uma câmara que veja toda a área projetada, e um retângulo marcado com fita no chão, dentro de ambos. Nada precisa de ficar de frente: a calibração corrige os ângulos da câmara e do projetor.

Projetor Câmara retângulo de fita (medido em metros) Computador projetor = 2.º ecrã câmara = USB luz do projetor vista da câmara
Vista de lado. Monte a câmara alta e a olhar para baixo: vistos de um ângulo rasante, os pés das pessoas (e os marcadores da calibração) ficam achatados e difíceis de encontrar.
vista da câmara área projetada 1 2 3 4 (0, 0) (W, 0) (W, H) (0, H) x (metros, ao longo da largura W) y (ao longo da altura H) uma pessoa em (1,9; 0,9) m
Vista de cima. O retângulo de fita tem de ficar dentro da área projetada e da vista da câmara. Todas as posições (OSC, sketches) se medem em metros a partir da marca 1: x em direção à marca 2, y em direção à marca 4.

1Projetor

Aponte-o para o chão e ligue-o como segundo ecrã (estendido, não duplicado). Tome nota da sua resolução e da sua posição no ambiente de trabalho, p. ex. 1280x800 em 1920,0.

2Câmara

Monte-a alta, a olhar para baixo, a ver toda a área projetada. Serve qualquer câmara, resolução ou cadência: uma webcam, uma câmara USB melhor, ou a imagem a cores de uma câmara de profundidade.

3Fita

Marque os quatro cantos de um retângulo dentro de ambas, meça a largura e a altura em metros, e lembre-se de qual é a marca 1.

4Escuridão

Calibre com a sala o mais escura possível, para a câmara conseguir ler os marcadores projetados.

3. Três maneiras de medir o chão

O mesmo ponto do chão tem três endereços diferentes: um píxel na imagem da câmara, um píxel na imagem do projetor, e uma posição em metros a partir da marca 1. A câmara e o projetor veem o chão de lado, por isso os seus píxeis esticam-se de maneira diferente ao longo dele. A calibração mede como converter entre os três, sob a forma de duas homografias: transformações que levam qualquer superfície plana vista de um ângulo para a mesma superfície vista de outro.

Imagem da câmara píxeis O chão metros a partir da marca 1 (0,0) (W,H) Imagem do projetor píxeis H_cam_to_floor H_floor_to_proj das 4 marcas de fita em que clica na imagem da câmara dos marcadores projetados + os mesmos 4 cliques Ambas ficam guardadas em calibration.json. O seguidor usa a primeira; os sketches, a segunda.
Uma pessoa encontrada num píxel da câmara passa a ser uma posição em metros (seta da esquerda), que o seguidor envia. Um sketch desenha em metros, e o seu desenho passa a píxeis do projetor (seta da direita), para aparecer debaixo da mesma pessoa.

4. Calibração

A calibração faz-se com dois scripts, depois de saber que câmara usar. Repita-a sempre que a câmara ou o projetor mudarem de sítio.

Escolher a câmara

As câmaras escolhem-se por número. O cameras.py lista as que o computador vê, e --snapshots guarda uma imagem de cada, para as distinguir:

$ python cameras.py --snapshots
  camera 0: 1280x720 (V4L2), average brightness 104, saved camera_0.jpg
  camera 2: 1920x1080 (V4L2), average brightness 97, saved camera_2.jpg

Depois calibre com esse número. Peça uma resolução, uma cadência ou imagens comprimidas se quiser mais do que a câmara dá por omissão:

python calibrate.py --source 2 --proj-pos 1920,0 --proj-size 1280x800 --floor-size 2.4x1.4

python calibrate.py --source 2 --width 1920 --height 1080 --fps 60 --fourcc MJPG \
    --proj-pos 1920,0 --proj-size 1280x800 --floor-size 2.4x1.4

A câmara, a resolução, e a cadência e o formato se os pediu, ficam guardados com a calibração, por isso tudo o que vem depois as usa sem ser preciso dizer-lhe. Uma câmara por HDMI (uma DSLR ou uma câmara de vídeo) funciona da mesma maneira, através de um dispositivo de captura HDMI para USB.

calibrate.py: câmara, projetor e chão

1Marcadores

O projetor mostra uma grelha de marcadores ArUco quadrados, cada um com o seu padrão. A câmara encontra-os (carregue em ESPAÇO) e, como se sabe a posição de cada marcador no projetor, isto liga os píxeis da câmara aos píxeis do projetor.

2Chão

O projetor fica branco. Clique nas quatro marcas de fita na imagem da câmara, pela ordem. Com as medidas do retângulo, isso liga os píxeis da câmara a metros e, através do passo 1, os metros a píxeis do projetor.

3Verificação

O projetor desenha uma grelha em metros. Se o contorno ficar em cima da fita, carregue em s para guardar.

foot_calibrate.py: onde assentam os pés

O YOLO encontra tornozelos, não o ponto onde o pé toca no chão, e visto de lado a diferença é de vários centímetros. O projetor mostra alvos um de cada vez; põe-se em cada um com a cruz entre os pés, e o script aprende uma pequena correção entre o sítio onde foi detetado e o sítio onde estava realmente. Nos testes, o erro passou de cerca de 30 cm para cerca de 4 cm.

O que fica guardado

calibration.json
├── floor        width_m, height_m              o retângulo de fita
├── cameras
│   └── cam0     source, resolution             que câmara, a que resolução
│                fps, fourcc                    se os pediu
│                H_cam_to_floor                 píxeis da câmara → metros
│                foot_correction                do foot_calibrate.py
└── projectors
    └── proj0    resolution, position           que ecrã é
                 H_floor_to_proj                metros → píxeis do projetor

É específico do seu espaço, por isso não faz parte do repositório. Os sketches de Processing encontram-no na sua própria pasta ou na mais próxima acima dela.

5. Pôr uma peça a funcionar

Correm dois programas lado a lado: o seguidor, e o que transformar as posições numa peça.

track_osc.py lê a câmara encontra e segue pessoas envia mensagens /person --show: janela da câmara para confirmar um sketch de Processing recebe as mensagens desenha em metros em ecrã inteiro no projetor ou TouchDesigner, Max, Pd... OSC por UDP · 127.0.0.1:12000 (--osc-host para enviar a outro computador) calibration.json
Arranque-os por qualquer ordem. Sem câmara, track_osc.py --simulate 3 envia três pessoas imaginárias a passear pelo chão; --simulate 2 --with-camera junta duas às reais.

O follow.py é o teste tudo-em-um: segue as pessoas e desenha ele próprio um círculo debaixo de cada uma, diretamente no projetor, sem precisar de sketch nem de OSC. Use-o para confirmar a calibração e o seguimento antes de pôr uma peça a funcionar.

6. As mensagens OSC

Uma mensagem por cada pessoa seguida, sempre que o seguidor processa uma imagem: tantas vezes quanto a câmara e o computador permitirem, ou conforme --max-fps.

/person  id x y
ArgumentoTipoSignificado
idinto mesmo enquanto a pessoa estiver a ser seguida
xfloatmetros a partir da marca 1 ao longo da largura, de 0 a W
yfloatmetros a partir da marca 1 ao longo da altura, de 0 a H

Não se envia nada quando alguém sai. Esqueça quem não tiver dado notícias há quase um segundo. Se o seguidor perder alguém e o voltar a encontrar dentro de uns segundos, perto de onde o perdeu, volta a enviá-lo com o mesmo id: guarde a pessoa durante esse tempo se quiser que volte como ela mesma.

O README mostra como recebê-las no TouchDesigner, Max, Pure Data e Python.

7. Como os ficheiros encaixam

As setas vão de cada ficheiro para os ficheiros que ele usa.

Scripts que corre calibrate.py foot_calibrate.py follow.py track_osc.py os quatro usam calib_utils.py · cameras.py · recording.py pipeline.py da imagem ao seguimento osc.py também no follow models.py + foot_calibrate tracking.py o pipeline usa calib_utils, cameras calibration.json escrito pelo calibrate.py e pelo foot_calibrate.py, lido por todos os outros, sketches incluídos processing/: cada sketch tem as mesmas duas abas, mais a sua aba principal People.pde: OSC → pessoas Projection.pde: canvas → projetor o seu sketch: desenha no canvas
O pipeline.py é o coração do seguimento, usado pelo follow.py e pelo track_osc.py; o foot_calibrate.py usa a sua deteção dos pés e o models.py diretamente. (O p_track.py, um teste rápido do YOLO, usa só o cameras.py e o models.py.)
FicheiroO que faz
calibrate.pyMarcadores, cliques nas marcas de fita e uma verificação: cria o calibration.json.
foot_calibrate.pyAlvos para pisar: acrescenta a correção dos pés.
follow.pyCírculos debaixo das pessoas, desenhados diretamente no projetor, para confirmar o seguimento.
track_osc.pyO seguidor para pôr uma peça a funcionar: envia OSC, sem janela de projetor. --simulate para pessoas imaginárias.
pipeline.pyUma imagem da câmara → pés (o ponto médio entre os tornozelos, ou a base do retângulo da pessoa se os tornozelos não forem claros) → metros no chão, dentro da fita → seguimento.
models.pyCarrega o YOLO no melhor hardware desta máquina: uma placa NVIDIA, se houver, senão o processador, com um limite de threads para deixar espaço ao sketch.
tracking.pyAssocia os pés de cada imagem às pessoas já conhecidas, suaviza o seu movimento e mantém os seus ids quando falham por um momento.
cameras.pyImagens de qualquer câmara, escolhida pelo número, ou de um ficheiro de vídeo, tudo igual para o resto. Corra-o para listar as suas câmaras.
calib_utils.pyA matemática da calibração (homografias), o padrão de marcadores e funções para as janelas.
osc.pyConstrói e envia as mensagens OSC, sem nenhum pacote extra.
recording.pyAs teclas c / p / f gravam a imagem da câmara, a imagem do projetor ou o ecrã, em recordings/.
processing/…/People.pdeRecebe o OSC, faz cada pessoa deslizar entre mensagens e fá-la aparecer e desaparecer gradualmente.
processing/…/Projection.pdeEncontra a calibração e o ecrã do projetor, e ajusta o canvas do sketch, em escala de metros, ao chão.