import hypermedia.video.*; import java.awt.Rectangle; import processing.video.*; OpenCV opencv; Capture camFake; Bot machine; import processing.serial.*; // serial communication import java.io.*; //Java import geomerative.*; // svg parsing // configuration boolean serialOn = false; boolean writeToFile = true; boolean printToConsole = true; PrintWriter writer; //--------------------------------------------------- // physical setup float MOTORSEP = 96.0;//72.0; // how far apart are the two steppers // paper size float PAGEW=24.0;// 11.0;//36.0;//17.0;//22.0;//44.0; // width float PAGEH=18.0;//8.5;//24.0;//14.0;//30;//30.0; // height // page location relative to motors float PAGE0X = (MOTORSEP-PAGEW)/2.0; // upper left float PAGE0Y = 33.0;//y61.0;//32.0;//6.0-PAGEH; // top of paper //12.0;//40.0; float HOMEA = 86.5;//81.0;//82.0;// 58.5225650924496; // 108 float HOMEB = 86.5;//81.0;//82.0;//56.02580320709378; // 108 float PPI = 640.0/PAGEW;//58.0; // 640 pixels / 11 inches // scale image to screen display int windowH = 900; float onScreenScale=windowH/(PAGEH*PPI); int windowW = int((PAGEW*PPI)*onScreenScale); //----------------------------------- // state variables boolean On = false;// USED SO THAT THE KEY 'S' AND 'G' START AND STOP THE DRAWING SEQUENCE, starts off to calibrate boolean jumping = false; boolean atPoint = false; float JUMPTHRESH = 50.0;//80.0; // contrast/brightness values int contrast_value = 0; int brightness_value = 0; PVector Last, Current; void setup() { // graphics size(1280, windowH);//windowW, windowH); println(Capture.list()); //camFake = new Capture(this, 640, 480, "Built-in iSight"); opencv = new OpenCV( this ); opencv.capture( 640, 480, 0 ); // open video stream opencv.cascade( OpenCV.CASCADE_FRONTALFACE_ALT ); // load detection description, here-> front face detection : "haarcascade_frontalface_alt.xml" // print usage println( "Drag mouse on X-axis inside this sketch window to change contrast" ); println( "Drag mouse on Y-axis inside this sketch window to change brightness" ); // setup drawing bot machine = new Bot(this); machine.waitForStart(); writer = createWriter("test.nc"); machine.setupWriting(writer); // calc home values for X and Y (upper left corner of page) //HOMEA = sqrt(pow(PAGE0X, 2)+pow(PAGE0Y, 2)); //HOMEB = sqrt(pow(MOTORSEP-(PAGE0X), 2)+pow(PAGE0Y, 2)); if (printToConsole) println("(HOME: "+HOMEA + " " +HOMEB+")"); machine.storeHome(); machine.penUp(); jumping=true; Last = new PVector(MOTORSEP/2, sqrt(81*81-(MOTORSEP/2*MOTORSEP/2)), 0); Current = new PVector(); fill(255); rect(640, 0, 640, 480); } void draw() { // grab a new frame // and convert to gray opencv.read(); opencv.flip(OpenCV.FLIP_HORIZONTAL); opencv.convert( GRAY ); opencv.contrast( contrast_value ); opencv.brightness( brightness_value ); // proceed detection Rectangle[] faces = opencv.detect( 1.2, 2, OpenCV.HAAR_DO_CANNY_PRUNING, 40, 40 ); // display the image //image( opencv.image(), 0, 0, 640*onScreenScale, 480*onScreenScale ); image( opencv.image(), 0, 0, 640, 480); // draw face area(s) noFill(); stroke(255, 0, 0); int biggest = -1; int biggestw = -1; for ( int i=0; i biggestw) { biggestw=faces[i].width; biggest=i; } rect( faces[i].x, faces[i].y, faces[i].width, faces[i].height ); } if (On) { if (faces.length>0) { Last.set(Current); Current.x=faces[biggest].x+(faces[biggest].width/2.0); Current.y=faces[biggest].y+(faces[biggest].width/2.0); println(Last.dist(Current)); if (Last.dist(Current)>JUMPTHRESH) { doMessage("(jumping, dist="+Last.dist(Current)+")"); jumping=true; } drawCrossHairs(Current.x, Current.y); drawCrossHairs(Current.x+640, Current.y); if (jumping) { doMessage("(jumping to "+Current.x+","+Current.y+")"); machine.penUp(); machine.sendVal(Current.x/PPI, Current.y/PPI, PEN_UP); // send current point machine.waitForOk(); machine.penDown(); jumping=false; } else { doMessage("(sending val "+Current.x+","+Current.y+")"); //machine.penDown(); drawScaledSegment(Last.x+640, Last.y, Current.x+640, Current.y); machine.sendVal(Current.x/PPI, Current.y/PPI, PEN_DOWN); // send current point machine.waitForOk(); } } else { // no face if (jumping) { } else { doMessage("(no face, lifting pen)"); machine.penUp(); jumping=true; } } } } /** * Changes contrast/brigthness values */ void mouseDragged() { contrast_value = (int) map( mouseX, 0, width, -128, 128 ); brightness_value = (int) map( mouseY, 0, width, -128, 128 ); } void stop() { doMessage("(stop)"); machine.penUp(); machine.DirectCommand("G0 X"+HOMEA+" Y"+HOMEB+" Z0.0"); machine.stop(); opencv.stop(); super.stop(); }; // keyboard interface void keyPressed() { if (key == 'g') { // start movement On = true; doMessage("(GO!)"); if (serialOn) { machine.DirectCommand("G100 S100"); //moves servo, push pen off page machine.waitForOk(); } jumping=true; } if (key == 's') { // stop movement On = false; if (printToConsole)println("(STOP)"); } if (key=='h') { machine.goHome(); } if (!On) { switch(key) { case '1': // top left machine.sendVal(0, 0, 0); break; case '2': // top right machine.sendVal(PAGEW, 0, 0); break; case '3': // lower right machine.sendVal(PAGEW, PAGEH, 0); break; case '4': // lower left machine.sendVal(0, PAGEH, 0); break; case '0': machine.penUp(); doMessage("(going to stored home position)"); machine.DirectCommand("G0 X"+HOMEA+" Y"+HOMEB+" Z0"); break; case 'd': machine.penDown(); break; case 'u': machine.penUp(); break; default: break; } } } // -------- terminal output and logging -------- // void doMessage(String message) { if (printToConsole) println(message); if (writeToFile) { writer.write(message+"\n"); writer.flush(); } } void drawScaledSegment(float x1, float y1, float x2, float y2) { stroke(192, 0, 0, 255); line(x1, y1, x2, y2);//*onScreenScale, y1*onScreenScale, x2*onScreenScale, y2*onScreenScale); }; void drawCrossHairs(float x, float y) { float px, py; px=x;//*onScreenScale; py=y;//*onScreenScale; //println(px+","+py); stroke(128, 0, 0, 255); // line(px-5, py, px+5, py); // line(px, py-5, px, py+5); fill(128, 0, 0, 255); ellipse(x,y,3,3); };