Tema 14

Captura de moviment amb càmera

Converteix la teva càmera web en un sensor artístic. Captura vídeo en temps real amb createCapture({ video: true }), crea miralls digitals i aplica filtres visuals que reaccionen al moviment.

createCapture({ video: true }): la finestra al món real

A p5.js v2.3.0, la captura de vídeo es fa amb createCapture({ video: true }) dins d'un async setup() amb await. Aquesta és la nova sintaxi que substitueix l'antic createCapture(VIDEO).

Per començar, necessitem tres passos bàsics:

  • Crear la captura: video = await createCapture({ video: true });
  • Amagar l'element HTML extra: video.hide();
  • Dibuixar el vídeo al llenç: image(video, 0, 0, width, height);

Exemple bàsic: mostrar la càmera al llenç.

let video;

async function setup() {
  createCanvas(320, 240);
  video = await createCapture({ video: true });  // v2.3.0
  video.size(320, 240);
  video.hide();
}

function draw() {
  background(0);
  image(video, 0, 0, width, height);
}
Nota: El navegador demanarà permís per accedir a la càmera. En iframes pot no funcionar per restriccions de seguretat; en el teu editor local funcionarà perfectament.

Mirall digital: invertir horitzontalment

Per crear un efecte de mirall, podem dibuixar el vídeo invertit horitzontalment amb translate(width, 0) i scale(-1, 1).

function draw() {
  background(0);
  push();
  translate(width, 0);
  scale(-1, 1);
  image(video, 0, 0, width, height);
  pop();
}

Filtres en temps real: manipular píxels

Amb video.loadPixels() podem accedir a la matriu de píxels del vídeo. Cada píxel ocupa 4 posicions consecutives: R, G, B, Alfa.

Exemple: escala de grisos. Calculem la mitjana dels tres canals i l'assignem a tots tres.

function draw() {
  video.loadPixels();
  for (let i = 0; i < video.pixels.length; i += 4) {
    let r = video.pixels[i];
    let g = video.pixels[i+1];
    let b = video.pixels[i+2];
    let gris = (r + g + b) / 3;
    video.pixels[i] = gris;
    video.pixels[i+1] = gris;
    video.pixels[i+2] = gris;
  }
  video.updatePixels();
  image(video, 0, 0, width, height);
}

Filtres creatius: umbral, negatiu, posterització

  • Umbral (blanc i negre pur): si el gris > 128, blanc; sinó, negre.
  • Negatiu: video.pixels[i] = 255 - r per a cada canal.
  • Posterització: reduir el nombre de colors. Per exemple, floor(r / 64) * 64 dóna 4 nivells per canal.

Exemple combinat: umbral + negatiu (tecles 1, 2, 3 per canviar).

function keyPressed() {
  if (key === '1') mode = 0; // escala de grisos
  if (key === '2') mode = 1; // negatiu
  if (key === '3') mode = 2; // umbral
}

Detectar moviment amb la càmera

Podem comparar el fotograma actual amb l'anterior per detectar zones de canvi. Si la diferència de brillantor entre un píxel i el del fotograma anterior supera un llindar, considerem que hi ha moviment.

let prevPixels = [];

function draw() {
  video.loadPixels();
  if (prevPixels.length === 0) {
    prevPixels = [...video.pixels];
  }
  for (let i = 0; i < video.pixels.length; i += 4) {
    let grisActual = (video.pixels[i] + video.pixels[i+1] + video.pixels[i+2]) / 3;
    let grisAnterior = (prevPixels[i] + prevPixels[i+1] + prevPixels[i+2]) / 3;
    let diff = abs(grisActual - grisAnterior);
    if (diff > 30) {
      video.pixels[i] = 255;
      video.pixels[i+1] = 0;
      video.pixels[i+2] = 0;
    }
  }
  prevPixels = [...video.pixels];
  video.updatePixels();
  image(video, 0, 0, width, height);
}

Exemples creatius pas a pas

Pintar amb el moviment

Les zones en moviment deixen un rastre de color acumulatiu sobre un fons semi-transparent.

// Al draw, en lloc de image(), utilitzem blend() amb mode ADD:
blend(video, 0, 0, width, height, 0, 0, width, height, ADD);

Silueta cromàtica

Substituïm la imatge real per una silueta de color que canvia amb la posició del cos.

if (gris < 80) {
  video.pixels[i] = to;
  video.pixels[i+1] = 80;
  video.pixels[i+2] = 90;
} else {
  video.pixels[i] = video.pixels[i+1] = video.pixels[i+2] = 0;
}

Consells per treballar amb la càmera

  • Il·luminació: una bona llum millora la detecció de moviment i els filtres. Evita contraclars.
  • Rendiment: manipular tots els píxels cada frame pot alentir l'sketch. Redueix la mida del vídeo si cal.
  • Prova amb pixelDensity(1) al setup() per evitar problemes amb pantalles d'alta densitat (Retina).
  • Utilitza blend() per a efectes de superposició sense haver de manipular píxels manualment.
  • Experimenta amb el llindar de moviment (25-50 segons la sensibilitat desitjada).

Exercicis per practicar

  1. Implementa un efecte de caleidoscopi: divideix la imatge de la càmera en 4 sectors utilitzant scale() i translate().
  2. Crea un filtre de posterització que redueixi els colors a 3 nivells per canal (0, 127, 255).
  3. Fes un detector de presència: si la mitjana de moviment supera un cert valor, canvia el color de fons.
  4. Dissenya un mirall amb efecte d'ones: distorsiona la imatge amb funcions trigonomètriques.
  5. Repte: Crea un joc de moviment: divideix la pantalla en zones i fes que un cercle es desplaci cap a la zona on hi ha més moviment detectat.

Reflexió artística

La càmera web transforma el teu cos en pinzell, el teu moviment en música visual. Ja no dibuixes amb el ratolí, sinó amb la teva presència física. L'art interactiu amb càmera té una màgia especial: et veus a tu mateix dins de l'obra, convertit en part de la creació.

Mini-projecte del Tema 14

Crea un "Mirall màgic interactiu" amb les següents característiques:

  • Mostra la imatge de la càmera invertida horitzontalment (efecte mirall).
  • Implementa almenys tres filtres diferents (escala de grisos, negatiu, umbral, posterització, o un de propi).
  • Utilitza tecles per canviar entre filtres en temps real.
  • Afegeix detecció de moviment: les zones en moviment es ressalten amb un color o efecte diferent.
  • Inclou un indicador visual que mostri el filtre actiu.