CHARLES EARL LOVE YUST :: MAGIC++ :: Final Project - Magic Box :: ASSIGNMENT INDEX

Magic Box - Project Description  

The Magic Box appears as an ordinary sealed box, the walls are opaque, the content cannot be seen. An audience member is called onto the stage. The illusionist asks the volunteer to inspect the box and once satisfied make a wish. Using the Magic Box as a portal, the illusionist conjures the volunteers wish into existence, however it cannot be seen, the box is sealed and it's walls are opaque. The Illusionist presents the volunteer with another magical item, an X-ray flash light! When the volunteer shines the light on the box the opaque walls become translucent to reveal the volunteers wish. Everyone is stunned and amazed! But of course, there is no such thing as magic, so how was this trick pulled off? We used a complex orchestration of computer vision, state of the art projection technology, and a bit of "Magic" C++ to make this vision a reality. The box is in fact always empty. The wished contents is actually projected on the outside of the box. The flashlight, used to "dissolve" the walls, shines infrared light that only a special camera can see, because the light is infrared it doesn't effect the projection itself. We wrote custom software that finds the position of the IR light and generates a channel of transparency. The amount of transparency is a function of the presence of IR light over time. The transparency reveals an image of the volunteer's wish. I know what your thinking: this makes sense for common wishes, money, women, gummy bears... but what if the user wishes for something completely random, how does the illusionist account for every object in existence? Google. The Illusionist has an assistant positioned off stage who runs the Magic Box application. When a user makes a wish the assistant will do a Google image search for an appropriate corresponding image. When a suitable image is found it is dropped into a folder within the Magic Box app and the image name is entered into an XML config file and the trick is ready for execution.

 


This work into infrared x-ray simulations is a programming assignment inspired by the Out of Bounds piece by London-based media artist, Chris O'Shea. Click for a video of the original work installed at the Design Museum in London.

How to use the Magic Box  

How to use magic box.
What you'll need:
> a box, any will do.
> a projector
> an IR camera
> A computer.
> Some source code (see below)
> an infrared light source.

1) Hook up and calibrate the camera and projector to the computer.
2) Find an appropriate image and drop it into the apps data folder.
3) Open the XML file and add the image name to the appropriate tag (see example below).
4) Drop the source documents (found below) overtop of one of the openframeworks examples (v0.05)
5) uncomment line 12 of testapp.h to use live video
6) Launch the application.
7) Shine the light on the projected area and be amazed.

Key Commands
D: toggle debug mode
J: use white screen as background
K: use image as background
L: use video as background
P: pause light buildup
C: toggle "cumulate mode"

Sample Code - Download Source  
void testApp::update(){
	ofBackground(0,0,0);
    
    bool bNewFrame = false;
	
#ifdef _USE_LIVE_VIDEO
	vidGrabber.grabFrame();
	bNewFrame = vidGrabber.isFrameNew();
#else
	vidPlayer.idleMovie();
	bNewFrame = vidPlayer.isFrameNew();
#endif
	   
	if(prevState==2 && state!=2){
	   bgVideo.stop();
	} else if(prevState!=2 && state==2){
	   bgVideo.play();
    }
   
    if(state==2){
	   bgVideo.idleMovie();
    }
   
	if (bNewFrame){
		   
#ifdef _USE_LIVE_VIDEO
	 colorImg.setFromPixels(vidGrabber.getPixels(), 320,240);
#else
	 colorImg.setFromPixels(vidPlayer.getPixels(), 320,240);
#endif
		   
	 grayImage = colorImg;
	 grayImage2 +=grayImage;
		   
     grayImage.blur(11);
     pixels = grayImage.getPixels();
		   
		   
     for(int i=0;i<320*240;i++){
		   if(!isPaused){
			   if(isCumulate){
				   tempInt = (int)tempPixels[i*4+3];
				   if( (int)(32-pixels[i]*2) < tempInt ){
					   tempInt+=(int)(32-pixels[i]*2)/2;
				   }
			   } else {
				   tempInt = (int)tempPixels[i*4+3] +(int)(32-pixels[i]*2)/2;
			   }
			   tempInt = MAX(MIN(255,tempInt),0);
			   tempPixels[i*4+3] = tempInt;
			   tempPixels[i*4+0] = cpixels[i*3]*(255-tempInt)/128;
			   tempPixels[i*4+1] = cpixels[i*3+1]*(255-tempInt)/128;
			   tempPixels[i*4+2] = cpixels[i*3+2]*(255-tempInt)/255;
			}
		}
	}
	historyTex.loadData(tempPixels, 320,240, GL_RGBA); 
	prevState = state;
}

 

These are some images of the set up that Marco will use to perform the trick. An audience memebr will wish for something in the box and it will appear using a short throw projector (check out how wide it can project at such a short distance).