Vídeo Arte Interactiva

Vídeo Arte Interactiva

sexta-feira, 13 de junho de 2008

: Pós-produção

Durante a fase de experimentação do projecto Anatomias Urbanas foi possível compreender a componente lúdica intrínseca a este, o utilizador ao verificar que a sua identidade é ocultada por uma mascara sente-se livre para brincar e representar como se a mascara fosse de facto sua.
Contudo foi possível perceber que sem uma demonstração ou explicação prévia para a maior parte dos utilizadores, este projecto não é assim tão claro.
Visto que os utilizadores não entendem de imediato que a sua cara esta a ser detectada, colocando-se apenas por de trás das mascaras, á espera de alguma reacção na tela.
Apenas os mais curiosos conseguem descobrir que é necessário colocar a cara de frente para a webcam, para que esta seja detectada, após esta descoberta de imediato entendem todo o sentido da instalação passando a explorar e a dar-lhe vida.
A disposição das mascaras que se encontram no topo da tela na horizontal, talvez não tenha sido a melhor opção porque nem sempre é fácil escolher uma cara.

: Produção

: Listagem completa do código



import processing.video.*;
import processing.opengl.*;
import pFaceDetect.*;

MovieMaker mm;

//import JMyron.*;
BackgroundSubtraction bs = new BackgroundSubtraction(320, 240);

// o valor de threshold da subtraccao
int threshold = 10;

boolean showSubtraction = false;

//declarar

int alturaCara= 50;
int larguraCara = 50;
int larguraFerramentas = 200;
int alturaFerramentas = 200;
int larguraCaptura = 320;
int alturaCaptura= 240;
int cara_inicial = 0;

//PImage cara;
PImage caras [];
PImage cara_actual;

// detecÁ„o da cara
PFaceDetect face;


//webcam
import processing.video.*;
//JMyron myCapture;

boolean gravar = false;
void setup() {

size(1024, 768, OPENGL);

//frameRate(20);

face = new PFaceDetect(this,larguraCaptura, alturaCaptura, "haarcascade_frontalface_default.xml");
// myCapture = new JMyron();//make a new instance of the object
//myCapture.start(larguraCaptura, alturaCaptura);//start a capture at 320x240
caras = new PImage [10];

caras[0]=loadImage ("face_01.gif");
caras[1]=loadImage ("face_02.gif");
caras[2]=loadImage ("face_03.gif");
caras[3]=loadImage ("face_04.gif");
caras[4]=loadImage ("face_05.gif");
caras[5]=loadImage ("face_06.gif");
caras[6]=loadImage ("face_07.gif");
caras[7]=loadImage ("face_08.gif");
caras[8]=loadImage ("face_09.gif");
caras[9]=loadImage ("face_10.gif");

cara_actual = caras[0];
}

void draw() {

// background(0);
//myCapture.update ();
// actualizar a imagem da webcam
bs.update();

// subtrair o fundo
bs.subtract(threshold);

image (bs.pimage(), 0, 0, width, height);
face.findFaces(bs.pimage());
desenharFerramentas ();
desenhoCara ();

detectaFerramenta ();
showSubtraction();


println (frameRate);

if (gravar) {
mm.addFrame();
}

//public void mousePressed() {
//mm.finishMovie();
//}

}

void detectaFerramenta () {

// pedir a maior silhueta encontrada
Silhouette s = bs.getSilhouette(0);

if (s != null) {
s.setSize(width, height);
float[][]p = s.silhouette;
stroke(0, 0);
s.draw();

if (s.insideSilhouette (100, 200))
{
cara_actual = caras[0+cara_inicial] ;

}
if (s.insideSilhouette (300, 200))
{
cara_actual = caras[ 1 + cara_inicial];

}
if (s.insideSilhouette (500, 200))
{
cara_actual= caras[2 + cara_inicial];

}
if (s.insideSilhouette (700, 200))
{
cara_actual = caras[3 + cara_inicial];
}
if (s.insideSilhouette (900, 200))
{
cara_actual = caras[4 + cara_inicial];
}
}
}

void desenharFerramentas () {
int i;
for ( i = cara_inicial; i < cara_inicial+5; i = i + 1){
image (caras[i],larguraFerramentas*(i-cara_inicial) , 0, larguraFerramentas, alturaFerramentas);
}
if (frameCount % 100 == 0) {
cara_inicial= (cara_inicial + 1) % 6;
}
}

void desenhoCara () {

int [][] res = face.getFaces();
if (res.length>0) { // so desenhamos se foi encontrada pelo menos uma cara

int x = res[0][0];
int y = res[0][1];
int w = res[0][2];
int h = res[0][3];

image (cara_actual, x * width/larguraCaptura, y * height/alturaCaptura , w * width/larguraCaptura , h* height/alturaCaptura);
noFill ();
//rect (x * width/larguraCaptura, y * height/alturaCaptura , w * width/larguraCaptura , h* height/alturaCaptura);
// fill (255);
}
}

void showSubtraction() {
// para ajudar a ajustar a imagem
// se estiver ligado, mostramos a imagem de diferenca
if (showSubtraction) {
background(0);
PImage subtraction = new PImage(320, 240);
arraycopy(bs.subtraction, subtraction.pixels);
image(subtraction, 0, 0);
}
}

void keyPressed() {
if (key == ' ') {
bs.update();
bs.setBackgroundPixels(bs.image());
}
else if (key == 's') {
bs.settings();
}
else if (key == '+') {
threshold = threshold + 5;
println("Threshold: " + threshold);
}
else if (key == '-') {
threshold = threshold -5;
println("Threshold: " + threshold);
}
else if(key == 'd') {
showSubtraction = !showSubtraction;
println("Show subtraction: " + showSubtraction);
} else if (key =='m') {
gravar = !gravar;

if (gravar) {
mm = new MovieMaker(this,width,height,"p5test"+frameCount+".mov");//, MovieMaker.JPEG, MovieMaker.HIGH,30);
} else {
mm.finish();
}
}
}

: Produção

Mais tarde e para terminar foi necessário:
a) instalação da biblioteca de detecção da face.
b) reconhecimento de certos pontos da silhueta sobre as máscaras.
c) definir como um maior número de mascaras pode ser revelado ao utilizador.

: Produção

O terceiro passo no desenvolvimento do projecto foi:
a) a produção de quatro mascaras finais que que substituem os rectângulos (botões).
b) usar a captura de vídeo e substituir o fundo do ecrã pela imagem em tempo real.
c) criar outra versão do programa em que as mascaras são colocadas na horizontal, em cima.

_Versão do programa onde os rectângulos são substituídos por quarto mascaras finais e estas de encontram dispostas no topo de forma horizontal, neste protótipo não me preocupei com a interacção por isso com a passagem do rato nada do que é pretendido para o projecto acontece.

//declarar as variáveis
int alturaCara= 40;
int larguraCara = 40;
int larguraFerramentas = 50;
int alturaFerramentas = 50;

PImage cara01;
PImage cara02;
PImage cara03;
PImage cara04;

// inicialização do programa
void setup () {

//tamanho do ecrã
size (400, 450);

// nº de frames desenhadas por segundo
frameRate = 10;

//carregar os ficheiros das imagens e construir o objecto do tipo PImage
cara01=loadImage ("face_01.gif");
cara02=loadImage ("face_02.gif");
cara03=loadImage ("face_03.gif");
cara04=loadImage ("face_04.gif");
}

//desenho das várias frames
void draw () {

// cor do fundo do ecrã
background(0);

desenharFerramentas ();

//desenho de uma imagem na posição do rato
image(cara01,mouseX, mouseY, larguraCara, alturaCara);
}
//desenho das mascaras nas coordenadas dadas
void desenharFerramentas () {

image (cara01,larguraFerramentas, 10, larguraFerramentas, alturaFerramentas);
image (cara02, 2*larguraFerramentas, 10, larguraFerramentas, alturaFerramentas);
image ( cara03,3*larguraFerramentas, 10, larguraFerramentas, alturaFerramentas);
image ( cara04, 4*larguraFerramentas, 10, larguraFerramentas, alturaFerramentas);
}

: Produção

_Versão do programa onde os rectângulos são substituídos por quarto mascara finais e estas de encontram dispostas na vertical do lado direito, a passagem do rato a máscara surge no centro do ecrã.


//declarar as variáveis
int alturaCara= 40;
int larguraCara = 40;
int larguraFerramentas = 50;
int alturaFerramentas = 50;

PImage cara01;
PImage cara02;
PImage cara03;
PImage cara04;

// inicialização do programa
void setup () {

//tamanho do ecrã
size (400, 400);

// nº de frames desenhadas pos segundo
frameRate = 10;

//carregar os ficheiros das imagens e construir o objecto do tipo PImage
cara01=loadImage ("face_01.gif");
cara02=loadImage ("face_02.gif");
cara03=loadImage ("face_03.gif");
cara04=loadImage ("face_04.gif");
}

//desenho das várioas frames
void draw () {

// cor do fundo do ecrã
background(0);

desenharFerramentas ();

//desenho de uma imagem na posição do rato
image(cara01,mouseX, mouseY, larguraCara, alturaCara);
}

//desenho das mascaras nas coordenadas dadas
void desenharFerramentas () {

image (cara01, width - larguraFerramentas, 0, larguraFerramentas, alturaFerramentas);
image (cara02, width - larguraFerramentas, alturaFerramentas, larguraFerramentas, alturaFerramentas);
image ( cara03,width - larguraFerramentas, 2*alturaFerramentas, larguraFerramentas, alturaFerramentas);
image ( cara04, width - larguraFerramentas, 3*alturaFerramentas, larguraFerramentas, alturaFerramentas);
}

// quando o ponteiro do rato passa sobre alguma das mascaras esta surge no centro do ecrã
void mouseMoved () {
if (mouseX > width- larguraFerramentas && mouseX < width
&& mouseY > 0 && mouseY < alturaFerramentas)
{
image (cara01, 0,0);
}
if (mouseX > width- larguraFerramentas && mouseX < width
&& mouseY > alturaFerramentas && mouseY < alturaFerramentas*2)
{
image (cara02, 0,0);
}
if (mouseX > width- larguraFerramentas && mouseX < width
&& mouseY > alturaFerramentas*2 && mouseY < alturaFerramentas*3)
{
image (cara03, 0,0);
}
if (mouseX > width- larguraFerramentas && mouseX < width
&& mouseY > alturaFerramentas*3 && mouseY < alturaFerramentas*4)
{
image (cara04, 0,0);
}
}

: Produção

A primeira experiência baseou-se em:
a) simular a posição da cara usando a posição do rato.
b) através da passagem do ponteiro do rato sobre os rectângulos laterais, simular a sua activação, ou seja, o rectângulo que se encontra na posição do rato fica com a cor do último quadrado que passou.

Com o intuito de explorar o tipo de interactividade que vai ser aplicada neste projecto, o website www.dontclick.it que tem como objectivo o estudo do tipo de navegação da passagem do rato sobre os botões. Mostra diversas técnicas onde a passagem do rato pode ser mais eficaz do que o seu clicar.
Em Anatomias Urbanas o utilizador terá que activar os botões, quando a sua silhueta passa sobre as mascaras, desta forma o tipo de interactividade é similar.

: Pré-produção

: Tecnologias/Formatos

Neste projecto a webcam é utilizada para captar o movimento em tempo real com o objectivo de enviar informação para o programa Processing, este software é utilizado para criar o código que permite o controlo das acções da silhueta do utilizador e o reconhecimento da face do utilizador.
A possibilidade de definir parâmetros do movimento que permitem o dialogo interactivo, quando se dá a convergência entre certos pontos da silhueta se e as mascaras dispostas no ecrã.
Processing é uma ferramenta desenvolvida para contextos visuais e a sua linguagem simplificada permite a escrita e compilação de código.
A utilização de bibliotecas como Face Detection Library for Processing (PC) de Brian Chung, detecta a face do utilizador, contudo para que esta corra é necessário a instalação de Open C.V. (Open Computer Vision Library) uma biblioteca que colecciona algoritmos e amostras de código para resolver alguns problemas de computer vision.