/////////////////////////This code is a modification of two individual source codes by Dan O'Sullivan and Daniel Shiffman, respectively///////////////////////// /* KEY THINGS: -pay attention to the ratio of brightness between glint and pupil. as one changes, so does the other. -depending upon camera placement the glint could always be under or above the pupil. only look in certain places. (find out how) -control control control the environment -make the program clever. make it learn. -angles and vectors are techniques i am assuming professional video tarcking employs // along with a sleu of other factors. -throw in some serial and get it running. */ import processing.video.*; //import video import processing.serial.*; //import serial Capture video; Serial myPort; float targetGlint = 244.0; //initialize empirical "glint" birghtness float targetPupil = 68; //initialize empirical "pupil" brightness float measure = 0; //initialize a variable for the ratio between the glint & pupil int closeness = 0; //TRYING TO GET VARIABLE TO DUMP INTO myPupilRect FOR LOOP int glintThreshold = 50; //initialize a certain 'bandwidth' for the glint brightness int pupilThreshold = 2; //initialize a certain 'bandwidth' for the pupil brightness ////***SETUP***////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setup(){ background (0); video = new Capture(this, 320, 240, 10); //initiate the video, resolution and frame rate size(320, 240); //give you Processing window a size / common video dimensions println(Serial.list()); myPort = new Serial(this, Serial.list()[2], 9600); } void captureEvent(Capture camera){ camera.read(); } ////***DRAW***//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void draw(){ float pupilBright = 0; //initialize local variable for pupil brightness int bx = 0; int by = 0; Rectangle myPupilRect = null; for ( int x = 30; x < video.width - 30; x++) { //for each column FIX for ( int y = 30; y < video.height - 30; y++) { //for each row FIX // our pixel loc calculation int loc = x + y*video.width; //what is the brightness at current loc and at brightest loc float p = brightness(video.pixels[loc]); float pupilDiff = abs(targetPupil - p); // find the difference between a pixel and the target brightness if (pupilDiff < pupilThreshold) { // if the difference is small enough (i.e. if they are the same enough), pupilBright = p; // the first instance of "p" is the winner // finding a group of pixels may be a better option, however this has given me the // most consistent results to date. bx = x; //save x and y locs by = y; //save x and y locs if (myPupilRect == null) myPupilRect = new Rectangle(bx, by,1,1); // if this is the first thing found, make a new Rect //myPupilRect.add(bx, by); //it seems to track better without adding to the area of the Rect } } } if (myPupilRect != null) { //the code only seems to work when this statement reads as it is. The original statement began: "if (myPupilRect == null) {" Rectangle myGlintRect = null; for(int row = myPupilRect.y + myPupilRect.height; row 10)) { //distance between the red and white verticle cross-hairs gives an eye position myPort.write(67); //send serial println("REW"); //react accordingly } if ((measure < 65) && (measure > 30)) { myPort.write(65); //send serial println("PLAY"); //react accordingly } if ((measure < 90) && (measure > 65)) { myPort.write(66); //send serial println("FFW"); //react accordingly } else{ myPort.write(65); //send serial //println("PLAY"); } } noFill(); stroke (255); if ((myPupilRect != null) && (myPupilRect.width < 50) && (myPupilRect.height < 50)) { //rect(myPupilRect.x, myPupilRect.y, myPupilRect.width, myPupilRect.height); line (myPupilRect.x, 0, myPupilRect.x, video.height); line (0, myPupilRect.y, video.width, myPupilRect.y); myPupilRect.y = closeness; //TRYING TO GET VARIABLE TO DUMP INTO myPupilRect FOR LOOP //measure = abs(myPupilRect.x - myGlintRect.x); } ////***TWEAKING***////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } } void keyPressed(){ //convenieces for changing variables while the applet is running if (keyCode ==38) { //up arrow targetGlint = targetGlint + 1; // if glint is brighter than present track } else if(keyCode == 40){ //down arrow targetGlint = targetGlint - 1; // if glint is dimmer than present track } else if(keyCode == 39){ //right arrow targetPupil = targetPupil + 1; // if pupil is brigher than present track } else if(keyCode == 37){ //left arrow targetPupil = targetPupil - 1; // if pupil is dimmer than present track } println ("key: " + keyCode); // immediate feedback even if the tracking does not change } void mousePressed(){ //allow the target color to be changed color pix = video.pixels[mouseY*video.width+mouseX]; // formula to determine mouse position targetPupil = brightness(pix); //brightness of clicked-on pixel println(targetPupil); //prints value of selected pixel }