« November 2006 | Main

December 14, 2006

Final - Documentation and Special Thanks!

My documenation for the final project is availabe at:

http://evasivhologram.wordpress.com/

I would like to say a special Thank you to Christian Bovine for helping me build the enclosure. He showed me the basics of wood working, and without him, my project wouldn't be complete!

December 10, 2006

Final - 4 week mark

Little creature

animated yellow monster.GIF

This is the monster that will run around the screen. He will do the following things:
a. run away from you. He runs away and flaps his arms as his feet move unreasonably fast.
b. if no one is trying to catch him, he stands around for a while.
c. after standing around, he'll get bored and start waving at you.
d. after a while, he'll taunt you, by sticking his tounge out at you.

The animation responds to mouse-x, y positions. It is a series of GIF images that are pulled dynamically in processing, depending on the state of the creature and his relationship with the user.

Motion Tracking
I decided to start all over. I discovered a reason not to use jitter: the JMyron library in processing! This library uses DirectX for video capturing, and so all my problems are solved. I am more comfortable with code than with graphical programming (Jitter), so I decided to start all over for the motion tracking part.

A JMyron is a camera object that uses directX and that allows us to specify things like how sensitive a camera is how often it adapts, etc. I relied heavily on the code examples that came with the library. But this is the basic logic: I take a picture of the current background before startting the motion tracking part. Then I call the differenceImage function of the camera object that will take a difference of the "control" image and the new image and finds the difference between. This differenced image is what I use for tracking. The differenced image will create white spots/areas where the differences are, and the JMyron will track white in the Matrix. All the points of change are then averaged to get a center point, or the average location of motion.

Camera Location
The camera is now located at the ceiling of the box, pointing downwards at a 20 degree angle. The plexi will be angled at 45 degree, and the monitor will be angled to create the illusion of a hollogram in the camera's direct line of sight.

Todo:
Now I need to build an enclosure to hide everything. I also need to make a button to reset things, and maybe (if I have time) allow the user to scroll through different hollographic characters using a variable restistor.

The Code

import JMyron.*;

JMyron m;//a camera object

//variables to maintain the floating green circle
float objx = 640; //160;
float objy = 350; //120;
float objdestx = 640; //160;
float objdesty = 350; //120;

//animated creature clips
AniSprite waving, walking, teasing, standing;
//float xpos, ypos;
float drag = 30.0;

int TEASE_STATE = 500;
boolean teaseState = false;
int teaseframes = 31;
int currentSt = 0;

int CAMERA_WIDTH = 320;
int CAMERA_HEIGHT = 240;

void setup()
{
size(1280, 800); //960);
background(0,0,0); //255, 204, 0);
frameRate(30);
waving = new AniSprite("wave", 17);
walking = new AniSprite("step", 9);
teasing = new AniSprite("tease", teaseframes);
standing = new AniSprite("stand", 11);

//capturing junk
m = new JMyron();//make a new instance of the object
m.start(CAMERA_WIDTH, CAMERA_HEIGHT);//start a capture at 320x240
m.trackColor(255,255,255,256*3-100);//track white
m.update(); //called once per frame, updates vision processing and camera updating
m.adaptivity(10); //how fast/often retina image adapts!
m.adapt();// immediately take a snapshot of the background for differencing
println("Myron " + m.version());
rectMode(CENTER);
noStroke();


}

void draw()
{

m.update();//update the camera view
drawCamera();

int[][] centers = m.globCenters();//get the center points
println("centers size = " + centers.length);
//draw all the dots while calculating the average.
float avX=0;
float avY=0;
for(int i=0;i fill(80);
rect(centers[i][0],centers[i][1],5,5);
avX += centers[i][0];
avY += centers[i][1];
}
if(centers.length-1>0){
avX/=centers.length-1;
avY/=centers.length-1;
}

//draw the average of all the points in red.
fill(255,0,0);
rect(avX,avY,5,5);

//update the location of monster
if(!(avX==0&&avY==0)&¢ers.length>0){
objdestx = avX*3.75;
objdesty = avY*3.75;
println("X = " + avX + ", Y = " + avY);
println("objx = " + objx);
println("objdestx - ojx = " + ( (objdestx - objx)/10.0f));
} //else there is no movement, pull out teasing here

objx += (objdestx-objx)/10.0f;
objy += (objdesty-objy)/10.0f;

objx = constrain(objx, 0, width - walking.getWidth());
objy = constrain(objy, 0, height - walking.getHeight());

/*
//DRAWING THE CREATURE
//think of difx as the new direction and drag as the speed /
float difx = objdestx - objx; //mouseX - xpos;
float dify = objdesty - objy; //mouseY - ypos;
if(abs(difx) > 1.0) {
objx = objx + difx/drag;
objx = constrain(objx, 0, width);
//xpos = xpos + difx/drag;
//xpos = constrain(xpos, 0, width);
}

if(abs(dify) > 1.0) {
objy = objy + dify/drag;
objy = constrain(objy, 0, width);
//ypos = ypos + dify/drag;
//ypos = constrain(ypos, 0, width);
}*/

background(0,0,0);

println("currentSt = " + currentSt);

// Display the sprite at the position xpos, ypos
/* if(mousePressed) {
//background(153, 153, 0);
//waving.display(xpos-waving.getWidth()/2, ypos);
//waving.display(objx, objy);
teasing.display(objx-waving.getWidth()/2, objy);
}
else */
if(centers.length == 0){

currentSt++;
if(currentSt == TEASE_STATE){
teaseState = true;
currentSt = 0;
}

if(teaseState){
if(currentSt <= teaseframes) teasing.display(objx, objy);
else {
currentSt = 0;
teaseState = false;
waving.display(objx, objy);
}
}
else {
//make monster wave at the user, but only after an interval of boredeom (just standing)
if((currentSt < 150) || ((currentSt > 300) && (currentSt < 400)) ) {
standing.display(objx, objy);
}else waving.display(objx, objy); //objx-waving.getWidth()/2, objy);
}

} else {
//background(255, 204, 0);
walking.display(objx, objy); //xpos-waving.getWidth()/2, ypos);
}
}


void drawCamera(){
//for debug:
//m.cameraImage returns reg image
//m.retinaImage returns image adapting to camera
//m.globsImage returns globs preview
//m.differenceImage returns image diff
int[] img = m.differenceImage(); //get the normal image of the camera
loadPixels();
//for(int i=0;i // pixels[i] = img[i]; //draw each pixel to the screen
//}
updatePixels();
}

/*
void mousePressed(){
m.settings();//click the window to get the settings
}*/

public void stop(){
m.stop();//stop the object
super.stop();
}

// Class for animating GIFs

class AniSprite
{
PImage[] ani;
int frame;
int numFrames;

AniSprite(String imageName, int frameCount) {
numFrames = frameCount;
ani = new PImage[numFrames];
loadImages(imageName);
}

void loadImages(String name) {
for(int i=0; i String imageName = name + i + ".gif";
ani[i] = loadImage(imageName);
}
}

void display(float xpos, float ypos)
{
frame = (frame+1)%numFrames;
image(ani[frame], xpos, ypos);
}

int getWidth() {
return ani[0].width;
}

int getHeight(){
return ani[0].height;
}
}

December 09, 2006

My HD Crashed !

Of all weeks for something like this to happen, it had to be during FINALS week. My hardrive failed me. I wasn't able to long onto my computer or access any of my files. I called the technical support and they had to run a few system checks and concluded that something is wrong with my hardrive. I will be getting a new HD in January, and I cannot acces my FINALS or retrieve them.

It took a day to figure out a way to hack into the hardrive without logging into my computer, using the command prompt. I manually copied every file, by file, that I needed into an external drive. It was tedious, annoying, but I'm thankful I didn't lose all my work.