動動画 DOUDOUGA -3.プログラム-

hoimei2009-08-10

動動画 DOUDOUGA -2.アイコン-←前


processingを使って作ってみました.


ファイル構成は

  1. projectionMovie/projectionMovie.pde
  2. projectionMovie/Tool.pde
  3. projectionMovie/data/video.mp4

という感じ.


projectionMovie/projectionMovie.pde

/**
 * projecting a movie using two reflection icons. 
 * hoimei: hoimei@acm.org
 * 2009.08.10
**/ 
 
import processing.video.*;

Movie myMovie;
Capture cam;
DynamicTV dytv;

boolean movfrg;
// you can select the camera device.
int CAMERA_DEVICE_NUM = 2;
// color threshold for detecting the two reflection icons.
float COLOR_THRE = 100;
// for crrecting the shake of the movie.
int CORRECTE_SHAKE_THRE = 9;


//////////////////////////////////////////////////////////////////
// SET UP
//////////////////////////////////////////////////////////////////
void setup() {
  size(800, 600, P2D);

  String[] devices = Capture.list();
  println(devices);
  
  cam = new Capture(this, 320, 240, devices[CAMERA_DEVICE_NUM]);
  dytv = new DynamicTV();
  movfrg = false;
  
  background(0);
}

//////////////////////////////////////////////////////////////////
// DRAW
//////////////////////////////////////////////////////////////////
void draw() {
  if (cam.available() == true) {
    loadPixels();
    cam.read();
    dytv.searchReflectiveSeal(COLOR_THRE);
    updatePixels();
  }
    
  dytv.searchMaxMinXY();
  dytv.correctShake();
  dytv.calcMovSize();
  
  if(movfrg){ // to project the movie, type the space key.
   dytv.display(myMovie);
  }
  //dytv.check();    
} 

//////////////////////////////////////////////////////////////////
void keyTyped() {
  myMovie = new Movie(this, "video.mp4");
  myMovie.loop();
  movfrg = true;  
}


void movieEvent(Movie myMovie) {
  myMovie.read();
}




projectionMovie/Tool.pde

class DynamicTV{ 
  color BLACK;
  color BLUE;
  
  int x, y, curr, currWin;
  int[] Buf;
  float r, g, b;
  float br;

  PImage backImg;

  int minX, minY, maxX, maxY;
  int pastminX, pastminY, pastmaxX, pastmaxY;

  float movSizeX, movSizeY;


  DynamicTV(){
     BLACK = color(0,0,0);
     BLUE = color(0, 0, 255);
     
     Buf = new int[cam.width*cam.height];
     minX = pastminX = cam.width;
     minY = pastminY = cam.height;
     maxX = maxY = pastmaxX = pastmaxY = 0;
  
     movSizeX = width/10;
     movSizeY = height/10;
     backImg = createImage(width, height, RGB);
     backImg.loadPixels();
     for(int n=0;n<width*height;n++)backImg.pixels[n] = BLACK;
  }
  
  void searchReflectiveSeal(float colThre){
    for(y=0;y<cam.height-1;y++){
        for(x=0;x<cam.width;x++){
          curr = y*cam.width + x;
          currWin = y*width + x;
          r = red(cam.pixels[curr]);
          g = green(cam.pixels[curr]);
          b = blue(cam.pixels[curr]);
          //br = brightness(cam.pixels[curr]);
          
          if((0<x && x<cam.width-1) && (0<y && y <cam.height-1)){
            if(COLOR_THRE<r && COLOR_THRE<g && COLOR_THRE<b){
                //if(BRIGHT_THRE<br){
                pixels[currWin] = BLUE;
                Buf[curr] = 1;
                
            }else{
                pixels[currWin] = cam.pixels[curr];
                Buf[curr] = 0;
            }
          }else{
            pixels[currWin] = cam.pixels[curr];
            Buf[curr] = 0;
          }
          
      }
    }
  }
  
  void searchMaxMinXY(){
     minX = minY = maxX = maxY = -1; 
   
     for(int i=0; i<cam.width*cam.height-3*cam.width; i++){
        if(Buf[i]==1 && Buf[i+1]==1 && Buf[i+2]==1){
          if(minX==-1){
            minX = i%cam.width;
          }else if(maxX < i%cam.width){
            maxX = i%cam.width;
          }
        }
    
        if(Buf[i]==1 && Buf[i+cam.width]==1 && Buf[i+cam.width*2]==1){
          if(minY==-1){
            minY = i/cam.width;
          }else if(maxY < i/cam.width){
            maxY = i/cam.width;
          }
        } 
    } 
  }

  void correctShake(){
    if((pastminX-minX)*(pastminX-minX)<CORRECTE_SHAKE_THRE){
      minX = pastminX;
    }
    if((pastminY-minY)*(pastminY-minY)<CORRECTE_SHAKE_THRE){
      minY = pastminY;
    }
    if((pastmaxX-maxX)*(pastmaxX-maxX)<CORRECTE_SHAKE_THRE){
      maxX = pastmaxX;
    }
    if((pastmaxY-maxY)*(pastmaxY-maxY)<CORRECTE_SHAKE_THRE){
      maxY = pastmaxY;
    }
  }
  
  //calculating the movie size 
  void calcMovSize(){
    if(minX != -1){
      movSizeX = maxX - minX;
      movSizeY = maxY - minY;
    }
  }
  
  void display(Movie mov){
    image(backImg, 0, 0);
    image(mov, minX*2.3, minY*2.3, movSizeX*3.3, movSizeY*3.3);
  }
  
  void check(){
    println("min X = " + minX + ", min Y = " + minY);
    println("max X = " + maxX + ", max Y = " + maxY);
    
    println("Movie size X = "+ movSizeX);
    println("Movie size Y = "+ movSizeY);
  }
}


これで完成.