Calibrate works?

This commit is contained in:
jan 2016-07-10 00:36:44 -07:00
commit cc711c6343
1104 changed files with 636510 additions and 75 deletions

121
src/Calibrator.java Normal file
View file

@ -0,0 +1,121 @@
/* Session when program is initially started, screen changes when
doodle button is pressed */
import processing.core.*;
class Calibrator {
boolean active;
PImage drawnScreen;
ProjectorApplet projector;
/////////////////////// proj img screen alignment
float offsetx, offsety, magx, magy, rot;
void reset() {
magx = 7.4f; // reduction factor in X
magy = 6.0f ; // reduction factor in Y
offsetx = 0.423f; // starts projectorApplet screen at distance from right most edge
offsety = 0.44f; // distance from topmost edge
rot = 0; // rotation of projection starts at 0 degrees
}
Calibrator(ProjectorApplet projector){
this.projector = projector;
this.reset();
this.active = false;
}
void toggle() {
if (this.active) {
this.deactivate();
} else {
this.activate();
}
}
void activate() {
this.active = true;
this.drawnScreen = projector.get(0, 0, projector.width, projector.height);
}
void deactivate() {
projector.clear();
projector.set(projector.width, 0, this.drawnScreen);
this.active = false;
}
void buttonPressed(int keyCode){
if (!this.active) {
return;
}
// Calibration of projectorApplet field of view
switch(keyCode) {
case PApplet.UP:
offsety = offsety - .001f; //Moves projections up in app view
break;
case PApplet.DOWN:
offsety = offsety + .001f; //Moves projections down
break;
case PApplet.LEFT:
offsetx = offsetx - .001f; // Moves projections left
break;
case PApplet.RIGHT:
offsetx = offsetx + .001f; // Moves projections right
break;
case 36:
magx = magx + .05f; // HOME button reduces width of projections
break;
case 35:
magx = magx - .05f; // END button increases width of projections
break;
case 33:
magy = magy + .05f; // PAGE UP button reduces height of projections
break;
case 34:
magy = magy - .05f; // PAGE DOWN button increases height of projections
break;
case PApplet.SHIFT:
PApplet.println("x-offset: " + offsetx + " | y-offset: " + offsety);
PApplet.println("x-magnification: " + magx + " | y-magnification: " + magy);
default:
break;
}
}
void draw(EuglenaApplet a) {
if (!this.active) {
return;
}
projector.clear();
float x0 = a.width * offsetx;
float y0 = a.height * offsety;
float dx = (a.width - a.menu.width)/magx;
float dy = a.height/magy;
// Hello World on 2nd Monitor
projector.noStroke();
projector.textSize(50);
projector.fill(projector.color(0, 90, 0));
projector.text("hello,", x0+20, y0+60);
projector.fill(projector.color(0, 0, 90));
projector.text("world!", x0+20, y0+110);
// Four dots used for calibration (may need to change code so that it better matches the math used to convert other points)
projector.fill(projector.color(0, 0, 190));
projector.ellipse(x0, y0, 5, 5);
projector.fill(projector.color(190,0,0));
projector.ellipse(x0, y0+dy-10, 5, 5);
projector.fill(255);
projector.ellipse(x0+dx-5, y0+dy-10, 5, 5);
projector.fill(projector.color(0, 190, 0));
projector.ellipse(x0+dx-5, y0, 5, 5);
}
}

99
src/EllipseClass.java Normal file
View file

@ -0,0 +1,99 @@
import processing.core.*;
//class EllipseDrawer {
//
// Ellipse ellipseinprogress;
//
// boolean centerpointcomplete;
// boolean widthcomplete;
//
// void reset() {
// ellipseinprogress = new Ellipse(-1, -1, 0, 0);
// ellipseinprogress.visible = false;
// centerpointcomplete = false;
// widthcomplete = false;
//
// }
//
// EllipseDrawer(){
// this.reset();
// }
//
// void mouseClicked(ProjectorApplet p, float x, float y){
// if (!centerpointcomplete){
// ellipseinprogress.centerx = x;
// ellipseinprogress.centery = y;
// centerpointcomplete = true;
//
// } else if (!widthcomplete) {
// ellipseinprogress.width = PApplet.abs(ellipseinprogress.centerx - x) * 2;
// widthcomplete = true;
//
// } else {
// ellipseinprogress.height = PApplet.abs(ellipseinprogress.centery - y) * 2;
// ellipseinprogress.visible = true;
// //ellipses.add(ellipseinprogress);
//
// ellipseinprogress.draw(p);
// this.reset();
// }
// }
//}
class Ellipse {
float centerx, centery, width, height;
int red, green, blue, brushSize;
boolean visible;
Ellipse(float centerx, float centery, float width, float height, int rVal, int gVal, int bVal, int penWidth) {
this.centerx = centerx;
this.centery = centery;
this.width = width;
this.height = height;
this.red = rVal;
this.green = gVal;
this.blue = bVal;
this.brushSize = penWidth;
this.visible = true;
}
void draw(ProjectorApplet p) {
if (visible) {
float old_strokeWeight = p.g.strokeWeight;
int old_strokeColor = p.g.strokeColor;
p.ellipseMode(PApplet.CENTER);
p.strokeWeight(brushSize);
p.stroke(p.color(red, green, blue));
p.noFill();
p.ellipse(p.convertXCoord(centerx), p.convertYCoord(centery),
p.convertXDistance(width), p.convertYDistance(height));
p.strokeWeight(old_strokeWeight);
p.stroke(old_strokeColor);
/*
print(rVal);
print(",");
print(gVal);
print(",");
print(bVal);
print("\n");
*/
/*
print(convertXCoord(centerx));
print("\n");
print(convertYCoord(centery));
print("\n");
print(convertXDistance(width));
print("\n");
print(convertYDistance(height));
print("\n");
*/
}
}
}

84
src/ExpandClass.java Normal file
View file

@ -0,0 +1,84 @@
class Expand {
ExpandWindow expandinprogress;
boolean corner1complete;
void reset() {
expandinprogress = new ExpandWindow(-1,-1,0,0,0);
corner1complete = false;
}
Expand(){
corner1complete = false;
}
void mouseClicked(float x, float y){
if (!corner1complete){
expandinprogress.corner1x = x;
expandinprogress.corner1y = y;
corner1complete = true;
} else {
expandinprogress.corner2x = x;
expandinprogress.corner2y = y;
expandinprogress.speed = speed;
expandinprogress.millisInit = millis();
expandinprogress.saveExpandRegion();
expandwindows.add(expandinprogress);
this.reset();
}
}
}
class ExpandWindow {
float corner1x, corner1y, corner2x, corner2y, speed;
int timeElapsed, millisInit;
PImage expandRegion;
ExpandWindow(float corner1x, float corner1y, float corner2x, float corner2y, float speed) {
this.corner1x = corner1x;
this.corner1y = corner1y;
this.corner2x = corner2x;
this.corner2y = corner2y;
this.speed = speed;
}
float aspectRatio() {
return abs((corner2x - corner1x) / (corner2y - corner1y));
}
float centerx() {
return (corner1x + corner2x) / 2;
}
float centery() {
return (corner1y + corner2y) / 2;
}
void saveExpandRegion() {
this.expandRegion = get(int(convertXCoord(corner1x)), int(convertYCoord(corner1y)),
int(convertXDistance(corner2x - corner1x)),int(convertYDistance(corner2y - corner1y)));
}
void draw() {
timeElapsed = millis() - millisInit;
if (convertYDistance(corner2y - corner1y) + speed * (timeElapsed / 1000) < convertYDistance(screenHeight)) {
noFill();
noStroke();
rectMode(CORNER);
rect(convertXCoord(corner1x), convertYCoord(corner1y),
convertXDistance(corner2x - corner1x), convertYDistance(corner2y - corner1y));
imageMode(CENTER);
image(expandRegion, convertXCoord(this.centerx()), convertYCoord(this.centery()),
convertXDistance(corner2x - corner1x) + speed * this.aspectRatio() * (timeElapsed / 1000),
convertYDistance(corner2y - corner1y) + speed * (timeElapsed / 1000));
}
}
}

View file

@ -10,23 +10,23 @@ class LEDControl {
LEDControl(PApplet applet, int whichArduino) {
// Arduino - initialize correct arduino
String[] arduinos = Arduino.list();
// if (arduinos.length == 0) {
// PApplet.println("There are no arduinos available for use.");
// applet.exit();
// } else {
// PApplet.println("Available arduinos:");
// for(int i = 0; i < arduinos.length; i++) {
// PApplet.println(arduinos[i]);
// }
// PApplet.print("Using arduino ");
// PApplet.println(arduinos[whichArduino]);
//
if (arduinos.length == 0) {
PApplet.println("There are no arduinos available for use.");
applet.exit();
} else {
PApplet.println("Available arduinos:");
for( String ard : arduinos) {
PApplet.println(ard);
}
PApplet.print("Using arduino ");
PApplet.println(arduinos[whichArduino]);
// this.arduino = new Arduino(applet, arduinos[whichArduino], comRate);
//
// for (Direction dir : Direction.values()) {
// this.arduino.pinMode(dir.pin, Arduino.OUTPUT);
// }
// }
}
}
boolean isActive(Direction dir) {

79
src/LineClass.java Normal file
View file

@ -0,0 +1,79 @@
class LineDrawer {
Line lineinprogress;
boolean point1complete;
void reset() {
lineinprogress = new Line(-1,-1,-1,-1);
lineinprogress.visible = false;
point1complete = false;
}
LineDrawer(){
this.reset();
}
void mouseClicked(float x, float y){
if (!point1complete){
lineinprogress.x1 = x;
lineinprogress.y1 = y;
point1complete = true;
} else {
lineinprogress.x2 = x;
lineinprogress.y2 = y;
lineinprogress.visible = true;
lines.add(lineinprogress);
lineinprogress.draw();
this.reset();
}
}
}
class Line {
float x1, y1, x2, y2;
int red, green, blue, brushSize;
boolean visible;
Line(float x1, float y1, float x2, float y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.red = rVal;
this.green = gVal;
this.blue = bVal;
this.brushSize = penWidth;
this.visible = true;
}
void draw() {
if (visible) {
float old_strokeWeight = g.strokeWeight;
int old_strokeColor = g.strokeColor;
strokeWeight(brushSize);
stroke(color(red, green, blue));
line(convertXCoord(x1), convertYCoord(y1), convertXCoord(x2), convertYCoord(y2));
strokeWeight(old_strokeWeight);
stroke(old_strokeColor);
print(rVal);
print(",");
print(gVal);
print(",");
print(bVal);
print("\n");
print(red);
print(",");
print(green);
print(",");
print(blue);
print("\n");
}
}
}

313
src/Menu.java Normal file
View file

@ -0,0 +1,313 @@
import processing.core.*;
import org.firmata.*;
import gab.opencv.*;
import cc.arduino.*;
import controlP5.*;
class Menu {
final int width = 200; // Width of toolbar on left side of display
private Button resetButton, calibrateButton, commitButton, lineButton, freehandButton, eraserButton, goButton;
private Textfield redField, greenField, blueField, backgroundField, penwidthField,
lagField, totaltimeField, speedField;
private DropdownList shapesList, animateList, presetsList, gamesList;
private ControlP5 cp5;
private Group g1, g2, g3;
Menu(PApplet applet){
cp5 = new ControlP5(applet).setPosition(applet.width - width, 0);
g1 = cp5.addGroup("Textfields");
g2 = cp5.addGroup("Dropdown2");
g3 = cp5.addGroup("Dropdown1");
resetButton = cp5.addButton("Reset")
.setPosition(20, 200)
.setSize(70, 35)
.moveTo(g1);
calibrateButton = cp5.addButton("Calibrate")
.setPosition(110, 200)
.setSize(70, 35)
.moveTo(g1);
redField = cp5.addTextfield("Red (0-255)")
.setPosition(20, 275)
.setSize(70, 35)
.setAutoClear(false)
.moveTo(g1);
greenField = cp5.addTextfield("Green (0-255)")
.setPosition(20, 325)
.setSize(70, 35)
.setAutoClear(false)
.moveTo(g1);
blueField = cp5.addTextfield("Blue (0-255)")
.setPosition(20, 375)
.setSize(70, 35)
.setAutoClear(false)
.moveTo(g1);
backgroundField = cp5.addTextfield("Background (0-255)")
.setPosition(20, 425)
.setSize(70, 35)
.setAutoClear(false)
.moveTo(g1);
penwidthField = cp5.addTextfield("Pen Width")
.setPosition(20, 475)
.setSize(70, 35)
.setAutoClear(false)
.moveTo(g1);
speedField = cp5.addTextfield("Speed")
.setPosition(110, 275)
.setSize(70, 35)
.setAutoClear(false)
.moveTo(g1);
lagField = cp5.addTextfield("Timelapse lag")
.setPosition(110, 325)
.setSize(70, 35)
.setAutoClear(false)
.moveTo(g1);
totaltimeField = cp5.addTextfield("Total time")
.setPosition(110, 375)
.setSize(70, 35)
.setAutoClear(false)
.moveTo(g1);
commitButton = cp5.addButton("Commit")
.setPosition(110, 450)
.setSize(70, 35)
.moveTo(g1);
lineButton = cp5.addButton("Line")
.setPosition(20, 550)
.setSize(50, 35)
.moveTo(g1);
freehandButton = cp5.addButton("Freehand")
.setPosition(75, 550)
.setSize(50, 35)
.moveTo(g1);
eraserButton = cp5.addButton("Eraser")
.setPosition(130, 550)
.setSize(50, 35)
.moveTo(g1);
shapesList = cp5.addDropdownList("Shapes")
.setPosition(20, 650)
.setSize(70, 100)
.setBarHeight(35)
.addItem("Ellipse", "Ellipse")
.addItem("Rectangle", "Rectangle")
.addItem("Triangle", "Triangle")
.addItem("None", "Default")
.close()
.moveTo(g3);
animateList = cp5.addDropdownList("Animate")
.setPosition(110, 650)
.setSize(70, 100)
.setBarHeight(35)
.addItem("Shrink", "Shrink")
.addItem("Expand", "Expand")
.addItem("Translate", "Translate")
.addItem("Rotate", "Rotate")
.addItem("None", "Default")
.close()
.moveTo(g3);
presetsList = cp5.addDropdownList("Presets")
.setPosition(20, 700)
.setSize(70, 100)
.setBarHeight(35)
.addItem("Clear screen", "Clear screen")
.addItem("Flow up", "Flow up")
.addItem("Flow down", "Flow down")
.addItem("Flow right", "Flow right")
.addItem("Flow left", "Flow left")
.addItem("Contain", "Contain")
.addItem("Split", "Split")
.addItem("Merge", "Merge")
.addItem("Slow move", "Slow move")
.addItem("Fast move", "Fast move")
.addItem("Slow compress", "Slow compress")
.addItem("Fast compress", "Fast compress")
.addItem("??","??")
.close()
.moveTo(g2);
// goButton = cp5.addButton("Go")
// .setPosition(20, 750)
// .setSize(70, 20)
// .moveTo(g1);
gamesList = cp5.addDropdownList("Games")
.setPosition(110, 700)
.setSize(70, 100)
.setBarHeight(35)
.addItem("Level 1", "Level 1")
.addItem("Level 2", "Level 2")
.addItem("Level 3", "Level 3")
.close()
.moveTo(g2);
}
void draw(EuglenaApplet a, LEDControl led) {
drawBackground(a);
drawArrows(a, led);
}
void drawArrows(EuglenaApplet a, LEDControl leds) {
a.strokeWeight(8);
int onColor = a.color(255, 255, 51);
int offColor = a.color(255, 255, 255);
int xOffset = a.width - width;
a.stroke(leds.isActive(LEDControl.Direction.RIGHT) ? onColor : offColor);
a.drawArrow(xOffset + 120, 80, 30, 0);
a.stroke(leds.isActive(LEDControl.Direction.DOWN) ? onColor : offColor);
a.drawArrow(xOffset + 100, 100, 30, 90);
a.stroke(leds.isActive(LEDControl.Direction.LEFT) ? onColor : offColor);
a.drawArrow(xOffset + 80, 80, 30, 180);
a.stroke(leds.isActive(LEDControl.Direction.UP) ? onColor : offColor);
a.drawArrow(xOffset + 100, 60, 30, 270);
}
void drawBackground(EuglenaApplet a) {
a.rectMode(EuglenaApplet.CORNER);
a.noStroke();
a.fill(0);
a.rect(a.width - width, 0, width, a.height);
}
/*
void controlEvent(ControlEvent theEvent) {
if (theEvent.isFrom(shapesList)) {
switch((int) shapesList.getValue()) {
case 0:
ellipseDrawer.reset();
drawtype = 'e';
break;
case 1:
rectangleDrawer.reset();
drawtype = 'r';
break;
case 2:
triangleDrawer.reset();
drawtype = 't';
break;
}
}
if (theEvent.isFrom(animateList)){
switch((int) animateList.getValue()) {
case 0:
shrink.reset();
drawtype = 's';
break;
case 1:
expand.reset();
drawtype = 'x';
break;
case 2:
translate.reset();
drawtype = 'm';
break;
case 3:
rotate.reset();
drawtype = 'c';
break;
}
}
if (theEvent.isFrom(presetsList)){
preset = (int) presetsList.getValue();
}
}
*/
}
/*
*/
/* Adds all features to initial display including toolbar and camera display */
/*
void Commit() {
rVal = int(menu.redField.getText());
gVal = int(menu.greenField.getText());
bVal = int(menu.blueField.getText());
penWidth = int(menu.penwidthField.getText());
bgVal = int(menu.backgroundField.getText());
lagTime = float(menu.lagField.getText());
totalTime = int(menu.totaltimeField.getText());
speed = int(menu.speedField.getText());
// print(rVal);
// print(",");
// print(gVal);
// print(",");
// print(bVal);
// print("\n");
// print(speed);
// print("\n");
}
void Reset() {
if (calibrator.active = true){
calibrator.toggle();
} else {
calibrator.active = false;
clearDisplay();
lines.clear();
ellipses.clear();
rectangles.clear();
triangles.clear();
shrinkwindows.clear();
expandwindows.clear();
translatewindows.clear();
rotatewindows.clear();
arduino.digitalWrite(left, Arduino.LOW);
arduino.digitalWrite(right, Arduino.LOW);
arduino.digitalWrite(up, Arduino.LOW);
arduino.digitalWrite(down, Arduino.LOW);
t = 0;
t2 = 0;
t3 = 0;
t_temp = 0;
}
}
void Calibrate() {
frame.setLocation(0,0);
calibrator.toggle();
}
void Eraser() {
rVal = 0;
gVal = 0;
bVal = 0;
}
void Line() {
lineDrawer.reset();
drawtype = 'l';
}
*/

View file

@ -0,0 +1,56 @@
class EuglenaCounter {
int roiX, roiY, roiWidth, roiHeight, lastMillis, avgTime;
float previousAverage;
boolean averageReady;
OpenCV opencv;
ArrayList<int> counts;
EuglenaCounter(PApplet parent, int roiX, int roiY, int roiWidth, int roiHeight, int avgTime){
this.counts = new ArrayList<int>();
this.roiX = roiX;
this.roiY = roiY;
this.roiWidth = roiWidth;
this.roiHeight = roiHeight;
this.avgTime = avgTime;
this.opencv = new OpenCV(parent, roiWidth, roiHeight);
this.opencv.startBackgroundSubtraction(7, 3, .35);
this.reset();
}
void reset(){
this.lastMillis = millis();
this.counts.clear();
this.averageReady = false;
this.previousAverage = -1;
}
void update() {
pImage roiFrame = get(roiX, roiY, roiWidth, roiHeight); // Get pixels of interest and saves as image for valid image path
this.opencv.loadImage(roiFrame); // Input proper pixels into cv processing
this.opencv.updateBackground(); //Necessary for background subtraction
this.opencv.useGray(); //Create grayscale image
this.opencv.dilate(); //Clean up image
this.opencv.erode();
this.opencv.blur(3);
//dst = opencv.getOutput(); //Save computer vision as separate image path
//Find outline of moving objects - euglena
int count = opencv.findContours().size(); // Count number of outlines
this.counts.add(count);
int interval = millis() - this.lastMillis();
if (interval > this.avgTime) {
this.previousAverage = 0;
for (int c : this.counts) {
this.previousAverage = this.previousAverage + c;
}
this.previousAverage = this.previousAverage / this.counts.size();
this.averageReady = true;
this.counts.clear();
}
}
}

82
src/Presets.java Normal file
View file

@ -0,0 +1,82 @@
/*
Previously implemented programs which we need to redo using classes
case 2 : // Starts clear program
clearScreen();
break;
case 3 : // Uses reduced screen raster
// rectangularStim(64, 5);
// proto488flashraster(screenWidth - 1500, 400, screenWidth - 6*menu.width, screenHeight - 400);
// heatup();
// squareCorridor();
// LEDtest();
// colorScreen();
// clearScreen();
// circleArrayStim(screenWidth - 1500, 800, 5, 5, 20, 5);
// angleMove(screenWidth - (displayWidth-750*cos(45*PI/360)-x-menu.width), centerY, 45, 750, 0.01);
// window(20, 20);
// separate(0.1);
// merge(0.1);
// shrinkingWindow(0.01, 0, 0, 255, 10);
// translateCircle(0.1);
// gradientWindow(0,0,0,0,0,15,500);
// randomLED();
// lineRotate(50, 0.01);
break;
case 4 : // Create LED sequences or paint backgrounds to be loaded later
angleGather(screenWidth - 1400, centerY, 45, 750);
// protoGather(screenWidth - 800, 300, screenWidth - 8*menu.width, screenHeight - 500);
break;
*/
class ClearScreen {
int timeElapsed, timeCurrent, timeInitial, euglenaCountInitial, euglenaCount,
roiCornerX, roiCornerY, roiWidth, roiHeight;
float euglenaReduction, targetReduction;
// opencv = new OpenCV(this, roiWidth, roiHeight);
// opencv.startBackgroundSubtraction(7, 3, .35);
// roiFrame = new PImage(roiWidth, roiHeight);
// break;
//
// /* Identify Euglena in a certain portion of the camera feed */
// void countEuglena() {
// roiFrame = get(roiCornerX, roiCornerY, roiWidth, roiHeight); // Get pixels of interest and saves as image for valid image path
// opencv.loadImage(roiFrame); // Input proper pixels into cv processing
// opencv.updateBackground(); //Necessary for background subtraction
// opencv.useGray(); //Create grayscale image
// opencv.dilate(); //Clean up image
// opencv.erode();
// opencv.blur(3);
// dst = opencv.getOutput(); //Save computer vision as separate image path
// contours = opencv.findContours(); //Find outline of moving objects - euglena
// euglenaCount = contours.size(); // Count number of outlines
// }
//
// void reset() {
// timeInitial = millis();
// timeElapsed = 0;
// identifyEuglena();
// euglenaCountInitial = euglenaCount;
// }
//
// ClearScreen(targetReduction){
// this.reset();
// }
//
// void mouseClicked(float x, float y){
// if (!point1complete){
// lineinprogress.x1 = x;
// lineinprogress.y1 = y;
// point1complete = true;
// } else {
// lineinprogress.x2 = x;
// lineinprogress.y2 = y;
// lineinprogress.visible = true;
// lines.add(lineinprogress);
//
// lineinprogress.draw();
// this.reset();
// }
// }
//}

88
src/RectangleClass.java Normal file
View file

@ -0,0 +1,88 @@
//class RectangleDrawer {
//
// Rectangle rectangleinprogress;
//
// boolean corner1complete;
//
// void reset() {
// rectangleinprogress = new Rectangle(-1,-1,0,0);
// rectangleinprogress.visible = false;
// corner1complete = false;
//
// }
//
// RectangleDrawer(){
// this.reset();
// }
//
// void mouseClicked(float x, float y){
// if (!corner1complete){
// rectangleinprogress.corner1x = x;
// rectangleinprogress.corner1y = y;
// corner1complete = true;
//
// } else {
// rectangleinprogress.corner2x = x;
// rectangleinprogress.corner2y = y;
// rectangleinprogress.visible = true;
// rectangles.add(rectangleinprogress);
//
// rectangleinprogress.draw();
// this.reset();
// }
// }
//}
//
//class Rectangle {
//
// float corner1x, corner1y, corner2x, corner2y;
// int red, green, blue, brushSize;
// boolean visible;
//
// Rectangle(float corner1x, float corner1y, float corner2x, float corner2y) {
// this.corner1x = corner1x;
// this.corner1y = corner1y;
// this.corner2x = corner2x;
// this.corner2y = corner2y;
// this.red = rVal;
// this.green = gVal;
// this.blue = bVal;
// this.brushSize = penWidth;
// this.visible = true;
// }
//
// void draw() {
// if (visible) {
// float old_strokeWeight = g.strokeWeight;
// int old_strokeColor = g.strokeColor;
//
// rectMode(CORNERS);
// strokeWeight(brushSize);
// stroke(color(red, green, blue));
// noFill();
//
// rect(convertXCoord(corner1x), convertYCoord(corner1y), convertXCoord(corner2x), convertYCoord(corner2y));
// strokeWeight(old_strokeWeight);
// stroke(old_strokeColor);
//
// print(rVal);
// print(",");
// print(gVal);
// print(",");
// print(bVal);
// print("\n");
//
//
// /*
// print(convertXCoord(corner1x));
// print("\n");
// print(convertYCoord(corner1y));
// print("\n");
// print(convertXCoord(corner2x));
// print("\n");
// print(convertYCoord(corner2y));
// print("\n");
// */
// }
// }
//}

68
src/RotateClass.java Normal file
View file

@ -0,0 +1,68 @@
class Rotate {
RotateWindow rotateinprogress;
boolean centercomplete;
void reset() {
rotateinprogress = new RotateWindow(-1,-1,0,0);
centercomplete = false;
}
Rotate(){
centercomplete = false;
}
void mouseClicked(float x, float y){
if (!centercomplete){
rotateinprogress.centerx = x;
rotateinprogress.centery = y;
centercomplete = true;
} else {
rotateinprogress.radius = sqrt(pow(x - rotateinprogress.centerx, 2) + pow(y - rotateinprogress.centery, 2));
rotateinprogress.speed = speed;
rotateinprogress.millisInit = millis();
rotateinprogress.saveRotateRegion();
rotatewindows.add(rotateinprogress);
this.reset();
}
}
}
class RotateWindow {
float centerx, centery, radius, speed;
int timeElapsed, millisInit;
PImage rotateRegion;
RotateWindow(float centerx, float centery, float radius, float speed) {
this.centerx = centerx;
this.centery = centery;
this.radius = radius;
this.speed = speed;
}
void saveRotateRegion() {
this.rotateRegion = get(int(convertXCoord(centerx - radius)), int(convertYCoord(centery - radius)),
int(convertXDistance(2*radius)),int(convertYDistance(2*radius)));
}
void draw() {
timeElapsed = millis() - millisInit;
noFill();
noStroke();
rectMode(CENTER);
rect(convertXCoord(centerx), convertYCoord(centery),
convertXDistance(radius), convertYDistance(radius));
pushMatrix();
translate(convertXCoord(centerx), convertYCoord(centery));
rotate(radians(speed*timeElapsed/1000));
imageMode(CENTER);
image(rotateRegion, 0, 0, convertXDistance(2*radius), convertYDistance(2*radius));
popMatrix();
}
}

93
src/ShrinkClass.java Normal file
View file

@ -0,0 +1,93 @@
class Shrink {
ShrinkWindow shrinkinprogress;
boolean corner1complete;
void reset() {
shrinkinprogress = new ShrinkWindow(-1,-1,0,0,0);
corner1complete = false;
}
Shrink(){
corner1complete = false;
}
void mouseClicked(float x, float y){
if (!corner1complete){
shrinkinprogress.corner1x = x;
shrinkinprogress.corner1y = y;
corner1complete = true;
} else {
shrinkinprogress.corner2x = x;
shrinkinprogress.corner2y = y;
shrinkinprogress.speed = speed;
shrinkinprogress.millisInit = millis();
shrinkinprogress.saveShrinkRegion();
shrinkwindows.add(shrinkinprogress);
this.reset();
}
}
}
class ShrinkWindow {
float corner1x, corner1y, corner2x, corner2y, speed;
int timeElapsed, millisInit;
PImage shrinkRegion;
ShrinkWindow(float corner1x, float corner1y, float corner2x, float corner2y, float speed) {
this.corner1x = corner1x;
this.corner1y = corner1y;
this.corner2x = corner2x;
this.corner2y = corner2y;
this.speed = speed;
}
float aspectRatio() {
return abs((corner2x-corner1x)/(corner2y-corner1y));
}
float centerx() {
return (corner1x + corner2x) / 2;
}
float centery() {
return (corner1y + corner2y) / 2;
}
void saveShrinkRegion() {
this.shrinkRegion = get(int(convertXCoord(corner1x)), int(convertYCoord(corner1y)),
abs(int(convertXDistance(corner2x-corner1x))), abs(int(convertYDistance(corner2y-corner1y))));
}
void draw(){
timeElapsed = millis()-millisInit;
if(convertXDistance(corner2x-corner1x) - speed * aspectRatio() * (timeElapsed/1000) > 25) {
noFill();
noStroke();
rectMode(CORNER);
rect(convertXCoord(corner1x), convertYCoord(corner1y),
convertXDistance(corner2x - corner1x), convertYDistance(corner2y - corner1y));
imageMode(CENTER);
image(shrinkRegion, convertXCoord(this.centerx()), convertYCoord(this.centery()),
convertXDistance(corner2x - corner1x) - speed * aspectRatio() * (timeElapsed / 1000),
convertYDistance(corner2y - corner1y) - speed * (timeElapsed / 1000));
}
//
// print(convertXDistance(corner2x-corner1x) - speed * aspectRatio() * (timeElapsed/1000));
// print("\n");
// print(timeElapsed);
// print("\n");
// print(aspectRatio);
// print("\n");
}
}

99
src/TranslateClass.java Normal file
View file

@ -0,0 +1,99 @@
class Translate {
TranslateWindow translateWindowinprogress;
boolean corner1complete, corner2complete;
void reset() {
translateWindowinprogress = new TranslateWindow(-1,-1,0,0,0,0,0);
corner1complete = false;
corner2complete = false;
}
Translate(){
corner1complete = false;
corner2complete = false;
}
void mouseClicked(float x, float y){
if (!corner1complete){
translateWindowinprogress.corner1x = x;
translateWindowinprogress.corner1y = y;
corner1complete = true;
} else if (!corner2complete) {
translateWindowinprogress.corner2x = x;
translateWindowinprogress.corner2y = y;
corner2complete = true;
} else{
translateWindowinprogress.endpointx = x;
translateWindowinprogress.endpointy = y;
translateWindowinprogress.speed = speed;
translateWindowinprogress.millisInit = millis();
translateWindowinprogress.saveTranslateRegion();
translatewindows.add(translateWindowinprogress);
this.reset();
}
}
}
class TranslateWindow {
float corner1x, corner1y, corner2x, corner2y, endpointx, endpointy, speed;
int timeElapsed, millisInit;
PImage translateRegion;
TranslateWindow(float corner1x, float corner1y, float corner2x, float corner2y,
float endpointx, float endpointy, float speed) {
this.corner1x = corner1x;
this.corner1y = corner1y;
this.corner2x = corner2x;
this.corner2y = corner2y;
this.endpointx = endpointx;
this.endpointy = endpointy;
this.speed = speed;
}
// float aspectRatio() {
// return abs((corner2x - corner1x) / (corner2y - corner1y));
// }
float centerx() {
return (corner1x + corner2x) / 2;
}
float centery() {
return (corner1y + corner2y) / 2;
}
float theta() {
return (atan((endpointy-centery())/(endpointx-centerx())));
}
void saveTranslateRegion() {
this.translateRegion = get(int(convertXCoord(corner1x)), int(convertYCoord(corner1y)),
int(abs(convertXDistance(corner2x - corner1x))),int(abs(convertYDistance(corner2y - corner1y))));
}
void draw() {
timeElapsed = millis() - millisInit;
if (timeElapsed*speed/1000*cos(theta())*calibrator.magx <= endpointx - centerx()) {
noFill();
noStroke();
rectMode(CORNERS);
rect(convertXCoord(corner1x) + timeElapsed*speed/1000*cos(theta()),
convertYCoord(corner1y) + timeElapsed*speed/1000*sin(theta()),
convertXCoord(corner2x) + timeElapsed*speed/1000*cos(theta()),
convertYCoord(corner2y) + timeElapsed*speed/1000*sin(theta()));
imageMode(CENTER);
image(translateRegion, convertXCoord(this.centerx()) + timeElapsed*speed/1000*cos(theta()),
convertYCoord(this.centery()) + timeElapsed*speed/1000*sin(theta()),
convertXDistance(corner2x - corner1x), convertYDistance(corner2y - corner1y));
}
}
}

98
src/TriangleClass.java Normal file
View file

@ -0,0 +1,98 @@
//class TriangleDrawer {
//
// Triangle triangleinprogress;
//
// boolean point1complete;
// boolean point2complete;
//
// void reset() {
// triangleinprogress = new Triangle(-1,-1,0,0,1,1);
// triangleinprogress.visible = false;
// point1complete = false;
// point2complete = false;
//
// }
//
// TriangleDrawer(){
// this.reset();
// }
//
// void mouseClicked(float x, float y){
// if (!point1complete){
// triangleinprogress.point1x = x;
// triangleinprogress.point1y = y;
// point1complete = true;
//
// } else if (!point2complete) {
// triangleinprogress.point2x = x;
// triangleinprogress.point2y = y;
// point2complete = true;
//
// } else {
// triangleinprogress.point3x = x;
// triangleinprogress.point3y = y;
// triangleinprogress.visible = true;
// triangles.add(triangleinprogress);
//
// triangleinprogress.draw();
// this.reset();
// }
// }
//}
//
//class Triangle {
//
// float point1x, point1y, point2x, point2y, point3x, point3y;
// int red, green, blue, brushSize;
// boolean visible;
//
// Triangle(float point1x, float point1y, float point2x, float point2y, float point3x, float point3y) {
// this.point1x = point1x;
// this.point1y = point1y;
// this.point2x = point2x;
// this.point2y = point2y;
// this.point3x = point3x;
// this.point3y = point3y;
// this.red = rVal;
// this.green = gVal;
// this.blue = bVal;
// this.brushSize = penWidth;
// this.visible = true;
// }
//
// void draw() {
// if (visible) {
// float old_strokeWeight = g.strokeWeight;
// int old_strokeColor = g.strokeColor;
//
// strokeWeight(brushSize);
// stroke(color(red, green, blue));
// noFill();
//
// triangle(convertXCoord(point1x), convertYCoord(point1y), convertXCoord(point2x), convertYCoord(point2y),
// convertXCoord(point3x), convertYCoord(point3y));
// strokeWeight(old_strokeWeight);
// stroke(old_strokeColor);
//
// /*
// print(rVal);
// print(",");
// print(gVal);
// print(",");
// print(bVal);
// print("\n");
// */
//
// /*
// print(convertXCoord(centerx));
// print("\n");
// print(convertYCoord(centery));
// print("\n");
// print(convertXDistance(width));
// print("\n");
// print(convertYDistance(height));
// print("\n");
// */
// }
// }
//}

12
src/angleGather.java Normal file
View file

@ -0,0 +1,12 @@
void angleGather(float x, float y, float angle, float armLength) {
arduino.digitalWrite(right, arduino.HIGH);
noFill();
strokeWeight(20); // Controls thickness of blue border
stroke(color(0, 0, 127));
beginShape(); // Draws shape
vertex(convertXCoord(x + armLength*cos(angle*PI/360)), convertYCoord(y + armLength*sin(angle*PI/360)));
vertex(convertXCoord(x), convertYCoord(y));
vertex(convertXCoord(x + armLength*cos(angle*PI/360)), convertYCoord(y - armLength*sin(angle*PI/360)));
endShape();
}

26
src/angleMove.java Normal file
View file

@ -0,0 +1,26 @@
float speed;
float x_current = 0;
void angleMove(float x, float y, float angle, float armLength, float speed) {
clearDisplay();
arduino.digitalWrite(right, arduino.HIGH);
noFill();
strokeWeight(20); // Controls thickness of blue border
stroke(color(0, 0, 255));
beginShape(); // Draws shape
vertex(convertXCoord(x - x_current + armLength*cos(angle*PI/360)), convertYCoord(y + armLength*sin(angle*PI/360)));
vertex(convertXCoord(x - x_current), convertYCoord(y));
vertex(convertXCoord(x - x_current + armLength*cos(angle*PI/360)), convertYCoord(y - armLength*sin(angle*PI/360)));
endShape(CLOSE);
if (x_current < displayWidth-menu.width){
x_current = x_current + 1*speed;
} else {
x_current = 0;
}
}

10
src/circleArrayStim.java Normal file
View file

@ -0,0 +1,10 @@
void circleArrayStim(float leftCornerX, float leftCornerY, int rows, int columns, int diameter, float space){
for (int rowNum = 0; rowNum < rows; rowNum ++){
for (int colNum = 0; colNum < columns; colNum++){
fill(color(0,20,0));
ellipseMode(CENTER);
ellipse(convertXCoord(leftCornerX) + colNum*(diameter+space),
convertYCoord(leftCornerY) + rowNum*(diameter+space), diameter, diameter);
}
}
}

12
src/clearDisplay.java Normal file
View file

@ -0,0 +1,12 @@
/* Draws a black rectangle the size of the second monitor
completely covers whatever was beneath it so that it looks clear */
void clearDisplay() {
// second monitor
fill(color(bgR, bgG, bgB));
noStroke();
rectMode(CORNER);
rect(displayWidth,0,displayWidth*4,displayHeight-10);
}

79
src/clearScreen.java Normal file
View file

@ -0,0 +1,79 @@
//class ClearScreen {
//
// int timeElapsed, timeCurrent, timeInitial, euglenaCountInitial, euglenaCount, roiCornerX, roiCornerY, roiWidth, roiHeight;
// float euglenaReduction, targetReduction;
//
// opencv = new OpenCV(this, roiWidth, roiHeight);
// opencv.startBackgroundSubtraction(7, 3, .35);
// roiFrame = new PImage(roiWidth, roiHeight);
// break;
//
// /* Identify Euglena in a certain portion of the camera feed */
// void countEuglena() {
// roiFrame = get(roiCornerX, roiCornerY, roiWidth, roiHeight); // Get pixels of interest and saves as image for valid image path
// opencv.loadImage(roiFrame); // Input proper pixels into cv processing
// opencv.updateBackground(); //Necessary for background subtraction
// opencv.useGray(); //Create grayscale image
// opencv.dilate(); //Clean up image
// opencv.erode();
// opencv.blur(3);
// dst = opencv.getOutput(); //Save computer vision as separate image path
// contours = opencv.findContours(); //Find outline of moving objects - euglena
// euglenaCount = contours.size(); // Count number of outlines
// }
//
// void reset() {
// timeInitial = millis();
// timeElapsed = 0;
// identifyEuglena();
// euglenaCountInitial = euglenaCount;
// }
//
// ClearScreen(targetReduction){
// this.reset();
// }
//
// void mouseClicked(float x, float y){
// if (!point1complete){
// lineinprogress.x1 = x;
// lineinprogress.y1 = y;
// point1complete = true;
// } else {
// lineinprogress.x2 = x;
// lineinprogress.y2 = y;
// lineinprogress.visible = true;
// lines.add(lineinprogress);
//
// lineinprogress.draw();
// this.reset();
// }
// }
//}
void clearScreen(){
clearDisplay();
arduino.digitalWrite(left, arduino.HIGH);
leftArrow = 204;
noFill();
strokeWeight(15); // Controls thickness of blue border
stroke(color(0, 0, 255));
if (t<10000){
beginShape(); // Draws shape
vertex(convertXCoord(1200), convertYCoord(200));
vertex(convertXCoord(500), convertYCoord(200));
vertex(convertXCoord(500), convertYCoord(800));
vertex(convertXCoord(1200), convertYCoord(800));
endShape();
t=t+1;
} else {
beginShape();
vertex(convertXCoord(1200), convertYCoord(200));
vertex(convertXCoord(500), convertYCoord(200));
vertex(convertXCoord(500), convertYCoord(800));
vertex(convertXCoord(1200), convertYCoord(800));
endShape(CLOSE);
}
}

8
src/colorScreen.java Normal file
View file

@ -0,0 +1,8 @@
void colorScreen() {
// second monitor
fill(20,20,20);//(stimulusColor*0.7, stimulusColor*0.55,0);
noStroke();
rectMode(CORNER);
rect(displayWidth,0,displayWidth*4,displayHeight-10);
}

299
src/developer.java Normal file
View file

@ -0,0 +1,299 @@
////////////// All code below pertains to functionality that has no clear use yet. ////////////////////////////////////////////
/* Menu screen allows user to determine what type of interaction
they want with the euglena */
/*
void menu(String button1, String button2, String button3, String button4) {
strokeWeight(2);
stroke(50);
textSize(24);
//Back Button
fill(180);
ellipse ((displayWidth - menu.width)/2 - sizeButton*5.5, displayHeight/2 - sizeButton, sizeButton*2, sizeButton*2);
fill(50);
text(button1, (displayWidth - menu.width)/2 - sizeButton*5, displayHeight/2 + 10);
//ledSequence
fill(180);
ellipse((displayWidth - menu.width)/2 - sizeButton*2.5, displayHeight/2 - sizeButton, sizeButton*2, sizeButton*2);
fill(50);
text(button2, (displayWidth - menu.width)/2 - sizeButton*2.5 + sizeButton/2, displayHeight/2 + 10);
//limitedPaint
fill(180);
ellipse((displayWidth - menu.width)/2 + sizeButton/2, displayHeight/2 - sizeButton, sizeButton*2, sizeButton*2);
fill(50);
text(button3, (displayWidth - menu.width)/2 + sizeButton*1, displayHeight/2 + 10);
//levelDeveloper
fill(180);
ellipse((displayWidth - menu.width)/2 + sizeButton*3.5, displayHeight/2 -sizeButton, sizeButton*2, sizeButton*2);
fill(50);
text(button4, (displayWidth - menu.width)/2 + sizeButton*4, displayHeight/2 + 10);
}
void store(int num) {
if(startSession == 2) ledDirections.append(num);
if(startSession == 4) storedLED.append(num);
}
*/
/* Controls at what stage of LED activity the program is in */
/*
void ledSequence() {
switch(ledSession) {
case 0 : // Choose sequence
initLed();
break;
case 1 : // Turn on and off LED's in proper sequence for proper duration
runLed();
break;
case 2 :
endLed(); // Resets all variables used
break;
default : //Doodle
startSession = 5;
break;
}
}
*/
/* Allows user to choose a certain number of LED's
to run in sequence */
/*
void initLed() {
strokeWeight(2);
stroke(50);
//DOWN Button
fill(180);
ellipse((displayWidth - menu.width)/2, displayHeight/2 + sizeButton * 1.5, sizeButton, sizeButton);
fill(50);
textSize(17);
text("DOWN", (displayWidth - menu.width)/2 + 3, displayHeight/2 + sizeButton * 1.5 + sizeButton/2 + 5);
//UP Button
fill(180);
ellipse((displayWidth - menu.width)/2, displayHeight/2 - sizeButton * 1.5, sizeButton, sizeButton);
fill(50);
textSize(18);
text("UP", (displayWidth - menu.width)/2 + 18, displayHeight/2 - sizeButton * 1.5 + sizeButton/2 + 5);
//LEFT Button
fill(180);
ellipse((displayWidth - menu.width)/2 - sizeButton * 1.5, displayHeight/2, sizeButton, sizeButton);
fill(50);
textSize(18);
text("LEFT", (displayWidth - menu.width)/2 - sizeButton * 1.5 + 10, displayHeight/2 + sizeButton/2 + 5);
//RIGHT Button
fill(180);
ellipse((displayWidth - menu.width)/2 + sizeButton * 1.5, displayHeight/2, sizeButton, sizeButton);
fill(50);
textSize(18);
text("RIGHT", (displayWidth - menu.width)/2 + sizeButton * 1.5 + 5, displayHeight/2 + sizeButton/2 + 5);
if(startSession == 2) {
//Load preset Level
loadButton();
//Instructions
textSize(56);
text("Choose 3 directions to create LED sequence", 250, 100);
if (ledDirections.size() == ledLimit) { //Check to see if user has selected 3 directions
ledSession = 1;
ledTime = millis();
}
} else if (startSession == 4) {
finishButton();
}
}
*/
/* Turns on LED's for given amount of time */
/*
void runLed() {
if (load) {
ledOn(tempLED);
} else {
ledOn(ledDirections);
}
}
void ledOn(IntList LED) {
if (LED.size() > 0) {
println(LED.get(0));
arduino.digitalWrite(LED.get(0), Arduino.HIGH); // Turns on first led in sequence
if (millis() - ledTime >= ledDelay) { // checks that time on has been met
arduino.digitalWrite(LED.get(0), Arduino.LOW); // Turns of led after given amount of time
LED.remove(0);
ledTime = millis();
}
} else {
ledSession = 2; // Move to next section of activty - end
}
}
*/
/* Reset used variables for future use */
/*
void endLed() {
ledSession = 0;
startSession = 5;
load = false;
}
*/
/* Activity in which users have limited amounts of paint to accomplish goal */
/*
void limitedPaint() {
switch (paintSession) {
case 0 :
initPaint(); // Allows user option to load preset level or draw on their own
break;
case 1 :
runPaint(); // Loads preset level
break;
case 2 :
endPaint(); // Resets used variables
break;
default : // Doodle
startSession = 5;
break;
}
}
*/
/* Draws appropriate buttons on screen, free draw still allowed */
/*
void initPaint() {
if (startSession == 3) loadButton();
finishButton();
}
*/
/* Loads preset level */
/*
void runPaint() {
if(load) {
for(int i = 0; i < storedColor.size(); i++) {
stroke(colorList[storedColor.get(i)]);
strokeWeight(storedPenWidth.get(i));
point(storedXCoord.get(i), storedYCoord.get(i));
}
}
finishButton();
}
*/
/* Resets used variables */
/*
void endPaint() {
load = false;
paintLimit.clear();
clearDisplay();
paintSession = 0;
startSession = 5;
}
*/
/* Allows users to create and store doodles and LED sequences */
/*
void levelDeveloper() {
switch(levelSession) {
case 0 :
finishDeveloper(); // Resets used variables
break;
case 1 :
initLevelDeveloper(); // Choose what type of level
break;
case 2 :
createPaintLevel(); // Allows users to draw and save their doodle
break;
case 3 :
createLEDLevel(); // Allows users t select and save their led sequence
break;
default :
startSession = 5; // doodle
break;
}
}
*/
/* Two buttons for user to select what type of level to create */
/*
void initLevelDeveloper() {
storedColor.clear();
storedXCoord.clear();
storedYCoord.clear();
storedPenWidth.clear();
storedLED.clear();
strokeWeight(2);
stroke(50);
// LED level
fill(180);
ellipse((displayWidth - menu.width)/2 - sizeButton*3, displayHeight/2 - sizeButton, sizeButton*2, sizeButton*2);
fill(50);
textSize(24);
text("LED",(displayWidth - menu.width)/2 - sizeButton*2.5, displayHeight/2 + 5);
// Paint Level
fill(180);
ellipse((displayWidth - menu.width)/2 + sizeButton, displayHeight/2 - sizeButton, sizeButton*2, sizeButton*2);
fill(50);
textSize(24);
text("Paint",(displayWidth - menu.width)/2 + sizeButton*1.5, displayHeight/2 + 5);
}
*/
/* Button to indicate level creation is ifnished */
/*
void finishButton() {
fill(180);
ellipse((displayWidth - menu.width) - sizeButton - 5, 5, sizeButton, sizeButton);
fill(50);
textSize(18);
text("Finish", (displayWidth-menu.width) - sizeButton , sizeButton/2 + 10);
}
*/
/* Loads appropriate precreated level */
/*
void loadButton() {
fill(180);
ellipse((displayWidth - menu.width) - sizeButton - 5, displayHeight - sizeButton*2 , sizeButton, sizeButton);
fill(50);
textSize(18);
text("Load", (displayWidth - menu.width) - sizeButton, displayHeight - sizeButton * 1.5 + 5);
}
*/
/* Reset used variables */
/*
void finishDeveloper() {
clearDisplay();
startSession = 5;
levelSession = 1;
}
*/
/* Clears containers for new use only one level can be stored at a time */
/*
void createPaintLevel() {
initPaint();
}
*/
/* Clears containers for new use only one level can be stored at a time */
/*
void createLEDLevel() {
initLed();
}
*/

View file

@ -0,0 +1,480 @@
/* Development Version
Created By: Seung Ah Lee
Modified by: Karina Samuel-Gama
Modified by: Amy Lam
This program runs patterned light stimuli. Users choose between different stimuli which
are projected through the projector and displayed onto Euglena. A webcam records the
projections overlayed with the view of the Euglena.
Current Functionality
- Screen calibration. Users can line up the 4 colored dots with the 4 corners of the screen
using the directional keys and home, end, page up, and page down
- Allows free draw. Users can change colors and pen width to interact with the euglena.
Users can also activate the four LEDs using 'a' 'w' 'd' 's'. In free draw users can also
see the computer tracking the top right corner of the screen by hitting CTRL
- Users can input LED sequences and see the reaction of the euglena. This allows for the
user to easily draw while the sequence is running. [The code can also be saved for future
functionality]
- The User can also save LED sequences and paint drawings for future uses. The data is only saved
in the current instance of the program. NEED to integrate the program with remote database
___________________________________________________________
| | |
| | Projection |
| Display Screen | Off Screen doodle |
| visible on laptop | appears here |
| | |
| | |
|___________________________|_____________________________|
*/
import org.firmata.*;
import gab.opencv.*;
import processing.video.*;
import processing.serial.*;
import cc.arduino.*;
import controlP5.*;
Capture cam; // One camera object needed to display euglena
Arduino arduino; // One arduino to control the LEDs
ControlP5 cp5; // Library to create nicer GUI
OpenCV opencv; // One opencv object needed per region of interest with unique dimension
OpenCV opencv2;
OpenCV opencv3;
OpenCV opencv4;
OpenCV opencv5;
/* CONSTANTS */
/////////////////// Program Controls
final long ledDelay = 5000; // Duration of light from LED during LED sequence
final int recordDelay = 0; // Time delay befoe taking next xcoord in case of lag
final int paintSize = 100; // Number of xcoord taken in limited paint activity
final int ledLimit = 3; // Number of LEDs in sequence
////////////////// LED Controls
final int left = 10;
final int right = 5;
final int down = 9;
final int up = 6;
//////////////////// Image Processing for doodle exploration
final int roiWidth = 500; // Width of ROI
final int roiHeight = 500; // Height of region of interest
final int roiCornerX = 610;
final int roiCornerY = 290;
final int centerY = 540; // Center Y coordinate
final int centerX = 860; // Center X coordinate
/////////////////// Game Controls
final int goalEntrance = 150; // 250 Width of entrance of goal
final int goalDepth = 150; // 100 Depth of goal
final float totalGameTime = 45000; // Duration of game
final float scoreDelay = 100; // time to wait before score update so score display doesn't look as jumpy
final float clearTime = 100000; // Duration of clear function : 1 minute 40 seconds
final String gameInstructions = "Pulsed 488 nm light for whole screen"; // Instructions
final String game2Instructions = "Draw barriers and use a, w, d, s to change the driection to get the euglena into the green box.";
final String game3Instructions = "Draw barriers to get the eugelna into the green box. Don't let them escape. You have limited paint.";
/* Global Variables */
///////////////// Miscellaneaous Variables
int penWidth = 15; // Default width of pen
int ledPin = 5; // LED of interest
boolean load = false; // Boolean to determine if user wants to load previously saved led sequences or paint
long ledTime; // Temporary time storage used to keep LED's on for certain period of time
long paintTime; // Temporary time storage used to determine when paint "runs out"
////////////////// Image Processing Variables
boolean showcv = false; // Show image tracking during doodle mode
PImage roiFrame; // Region of interest
PImage dst; // Backend computer vision
ArrayList<Contour> contours; // Stores outlines of moving objects within region of interest
int count; // Equivalent to number of outline
///////////////////////// Color Variables
int iColor=0;//current color
int rightArrow = 0;
int downArrow = 0;
int leftArrow = 0;
int upArrow = 0;
float lagTime = 1;
int totalTime = 15000;
int presetProg;
//////////////////// Storage Variables
IntList paintLimit = new IntList(); // Stores finite limit of XCoord of points drawn. Once limit is reached "drawing" is stopped
IntList ledDirections = new IntList(); // Stores a certain number of LED pins in the order they will be turned on
IntList storedColor = new IntList(); // Stores color of each point
FloatList storedXCoord = new FloatList(); // Stores x-coordinate of each point
FloatList storedYCoord = new FloatList(); // Stores y-coordinate of each point
IntList storedPenWidth = new IntList(); // Stores stroke weight of each point
IntList storedLED = new IntList(); // Stores ledPin numbers
IntList tempLED = new IntList(); // Duplicates storedLED so the intList can be called again and again without losing any data points
////////////////////// Game Variables
// Image processing of goal regions in game
ArrayList<Contour> plusContours; // Stores outlines of moving objects
ArrayList<Contour> minusContours;
ArrayList<Contour> euglenaCount;
PImage o1; // Backend computer vision to make sure image is being processed correctly
PImage o2;
PImage o3;
PImage goal1; // Region of interest
PImage goal2;
PImage gameScreen;
PImage entireScreen;
PImage cvscreen;
// score handling
int plusScore; // Equivalent to number of outlines
int minusScore;
int totalScore;
float scoreTime; // Temporary variable to ensure score is displayed for proper length of time
float scoreUpdateTime; // Temporary variable to ensure score changes at even intervals
// Game time handling
float currentGameTime; // Temporary variable to ensure game runs for proper length of time
float secondCounter;
// screen clearing
float clearScreenTime; // Temporary variable to ensure screen clearing lasts for proper length of time
boolean cleared = false; // Keeps track of whether screen has been cleared
// LED control
int gamePin = 10; // Used to keep track of activated LED pin serves to limit user control over LED's
/////////////////////////Program Session Variables
int startSession = 0; // 0: "play" button, 1: menu, 2: ledSequence, 3: limitedPaint, 4: Level developer, 5: doodling, 6:Game Menu, 7: Level 1, 8: Level 2
int ledSession = 0; // 0: pick LED sequence, 1: run through sequence, 2: reset activity
int paintSession = 0; // 0: initialize Paint, 1: Run through paint session, 2: reset activity
int levelSession = 1; // 0: finish development, 1: Choose LED level or paint level, 2 : paint level, 3 : led level
int gameSession = 0; // 0: instructions and screen clear, 1: play level, 2: score game, 3: reset first level
int game2Session = 0; // 0: instructions and screenclear, 1: play level, 2: score game, 3: reset second level
int game3Session = 0; // 0: instructions and screenclear, 1: play level, 2: score game, 3: reset third level
int protoGameSession = 0;
int screenWidth;
int screenHeight;
int totalCount = 1;
float percentDensity;
int densityTSTime;
int densityROITime;
int displayDensityTime;
int densitySession = 0;
int gameScreenWidth = 600;
int gameScreenHeight = 600;
static float densityThreshold = 6;
boolean densityMeasured = false;
FloatList fadeXCoord = new FloatList(); // Stores x-coordinate of each point
FloatList fadeYCoord = new FloatList();
DropdownList presetsList;
ArrayList<Line> lines = new ArrayList<Line>();
ArrayList<Ellipse> ellipses = new ArrayList<Ellipse>();
ArrayList<Rectangle> rectangles = new ArrayList<Rectangle>();
ArrayList<Triangle> triangles = new ArrayList<Triangle>();
ArrayList<ShrinkWindow> shrinkwindows = new ArrayList<ShrinkWindow>();
ArrayList<ExpandWindow> expandwindows = new ArrayList<ExpandWindow>();
ArrayList<TranslateWindow> translatewindows = new ArrayList<TranslateWindow>();
ArrayList<RotateWindow> rotatewindows = new ArrayList<RotateWindow>();
EllipseDrawer ellipseDrawer = new EllipseDrawer();
LineDrawer lineDrawer = new LineDrawer();
RectangleDrawer rectangleDrawer = new RectangleDrawer();
TriangleDrawer triangleDrawer = new TriangleDrawer();
Shrink shrink = new Shrink();
Expand expand = new Expand();
Translate translate = new Translate();
Rotate rotate = new Rotate();
Calibrator calibrator = new Calibrator();
Menu menu;
char drawtype = 'd';
int preset;
void setup() {
count = 1;
totalCount = 1;
background(200);
size(displayWidth*2, displayHeight*2);
screenWidth = displayWidth;
screenHeight = displayHeight;
ellipseMode(CORNER);
smooth();
/*
// Capture cam - initialize correct camera
String[] cameras = Capture.list();
if (cameras.length == 0) {
println("There are no cameras available for capture.");
exit();
} else {
println("Available cameras:");
for(int i = 0; i < cameras.length; i++) {
println(i, cameras[i]);
}
println(cameras[37]);
cam = new Capture(this, cameras[69]); //cameras[39] : 1280x1024 fps=10, cameras[37] 1280 X 800 fps=25
cam.start();
}
// Arduino - initialize correct arduino
String[] arduinos = Arduino.list();
if (arduinos.length == 0) {
println("There are no arduinos available for use.");
exit();
} else {
println("Available arduinos:");
for(int i = 0; i < arduinos.length; i++) {
println(arduinos[i]);
}
println(arduinos[0]);
arduino = new Arduino(this, arduinos[0], 57600); // arduinos[1] : COM4
arduino.pinMode(ledPin, Arduino.OUTPUT);
}
*/
// OpenCV - initialize correct frames and images
// opencv = new OpenCV(this, roiWidth, roiHeight);
// opencv.startBackgroundSubtraction(7, 3, .35);
// roiFrame = new PImage(roiWidth, roiHeight);
menu = new Menu(this);
menu.drawBackground();
menu.drawArrows();
clearDisplay();
}
/* Runs contionous display of mouse in the background; keeps
track of what mode app is in and where mouse is on the screen */
void draw() {
// camera display - webcam feed reads into background of laptop display
if(cam.available() == true) {
cam.read();
}
imageMode(CORNER);
image(cam, 0, 0, displayWidth - menu.width, displayHeight);
if (showcv) { // Show image tracking when CTRL is pressed
identifyEuglena();
showCV();
}
recordTimelapse(lagTime, totalTime); //Note: the maximum fps is around 5
calibrator.draw();
menu.draw();
for (int i=0; i < shrinkwindows.size(); i++) {
shrinkwindows.get(i).draw();
}
for (int i=0; i < expandwindows.size(); i++) {
expandwindows.get(i).draw();
}
for (int i=0; i < translatewindows.size(); i++) {
translatewindows.get(i).draw();
}
for (int i=0; i < rotatewindows.size(); i++) {
rotatewindows.get(i).draw();
}
}
/*Uses keys to create uniform movement in the Euglena by turniing LEDs on
and off with standard directional keys. It also allows calibration of
the projectorApplet field of view */
void keyPressed() {
if (key == CODED) {
// Calibration of projectorApplet field of view
calibrator.buttonPressed(keyCode);
switch(keyCode) {
case 112: // F1 key
if (startSession == 8) { // Level 2
if(gamePin == 5) {
gamePin = 10; // Euglena move left
arduino.digitalWrite(right, Arduino.LOW);
} else {
gamePin = 5; // Euglena move right
arduino.digitalWrite(left, Arduino.LOW);
}
}
break;
case CONTROL:
if(showcv) showcv = false;
else showcv = true;
break;
default:
break;
}
} else if (startSession != 7 && startSession != 9) {
// Control LED with standard directional keys
switch(key) {
case 'd':
ledPin = right; // Forces Euglena right
rightArrow = 204;
arduino.digitalWrite(ledPin, Arduino.HIGH);
break;
case 'w':
ledPin = up; // Forces Euglena up
upArrow = 204;
arduino.digitalWrite(ledPin, Arduino.HIGH);
break;
case 's':
ledPin = down; // Forces Euglena down
downArrow = 204;
arduino.digitalWrite(ledPin, Arduino.HIGH);
break;
case 'a':
ledPin = left; //Forces Euglena left
leftArrow = 204;
arduino.digitalWrite(ledPin, Arduino.HIGH);
break;
default: // Turn off last light
arduino.digitalWrite(ledPin, Arduino.LOW);
leftArrow = rightArrow = upArrow = downArrow = 0;
break;
case ENTER: // Takes a snapshot of the FOV
snapshot();
break;
case 'r': // Toggles between recording timelapse and not recording
record = !record;
}
}
}
/* Turns off LED's that have been turned on while the app is running*/
void keyReleased() {
switch(key) {
case 'd':
ledPin = right;
rightArrow = 0;
arduino.digitalWrite(ledPin, Arduino.LOW);
break;
case 'w':
ledPin = up;
upArrow = 0;
arduino.digitalWrite(ledPin, Arduino.LOW);
break;
case 's':
ledPin = down;
downArrow = 0;
arduino.digitalWrite(ledPin, Arduino.LOW);
break;
case 'a':
ledPin = left;
leftArrow = 0;
arduino.digitalWrite(ledPin, Arduino.LOW);
break;
// case 'n':
// opencv = new OpenCV(this, roiWidth, roiHeight);
// opencv.startBackgroundSubtraction(7, 3, .35);
// roiFrame = new PImage(roiWidth, roiHeight);
// break;
default :
arduino.digitalWrite(ledPin, Arduino.LOW);
leftArrow = rightArrow = upArrow = downArrow = 0;
break;
}
}
/* Listens for user dragging mouse and draws points of appropriate
color and width on the screen */
void mouseDragged() {
if(mouseX < displayWidth-menu.width){ // Determines if mouse is in drawing area
stroke(color(rVal, gVal, bVal)); // Sets pent to current color
strokeWeight(penWidth); // Sets pen to current Width
point(convertXCoord(mouseX), convertYCoord(mouseY)); // Moves points on to second monitor with correct sizing
}
}
void mouseClicked(){
if (mouseX < displayWidth-menu.width){
switch(drawtype) {
case 'e' :
ellipseDrawer.mouseClicked(mouseX, mouseY);
break;
case 'l' :
lineDrawer.mouseClicked(mouseX, mouseY);
break;
case 'r' :
rectangleDrawer.mouseClicked(mouseX, mouseY);
break;
case 't' :
triangleDrawer.mouseClicked(mouseX, mouseY);
break;
case 's' :
shrink.mouseClicked(mouseX, mouseY);
break;
case 'x' :
expand.mouseClicked(mouseX, mouseY);
break;
case 'm' :
translate.mouseClicked(mouseX, mouseY);
break;
case 'c' :
rotate.mouseClicked(mouseX, mouseY);
break;
}
}
}
void controlEvent(ControlEvent theEvent) {
menu.controlEvent(theEvent);
}
/* Translates x coordinate of point from user screen to projection screeen */
float convertXCoord(float x) {
return (x / calibrator.magx + displayWidth * calibrator.offsetx);
}
/* Translates y coordinate of point from user screen to projection screen */
float convertYCoord(float y) {
return (y / calibrator.magy + displayHeight * calibrator.offsety);
}
/* Translates x distances on screen to projectorApplet*/
float convertXDistance(float x) {
return (x / calibrator.magx);
}
/* Translates y distances on screen to projectorApplet*/
float convertYDistance(float y) {
return (y / calibrator.magy);
}

40
src/gradientWindow.java Normal file
View file

@ -0,0 +1,40 @@
void gradientWindow(float minR, float minG, float minB, float maxR, float maxG, float maxB, float winSizeY){
float stepR = (maxR-minR)/(centerY-(winSizeY/2));
float stepG = (maxG-minG)/(centerY-(winSizeY/2));
float stepB = (maxB-minB)/(centerY-(winSizeY/2));
float winSizeX = (winSizeY/centerY)*centerX;
for (int x_pix = 0; x_pix < 2*centerX; x_pix ++){
for (int y_pix = 0; y_pix < 2*centerY; y_pix ++){
//Defines a rectagular window and gradient
if (abs(x_pix-centerX) >= abs(y_pix-centerY)) {
color c = color(0,0,round(abs(x_pix-centerX)-(winSizeX/2)*stepB));
/*color(round(abs(x_pix-centerX)-(winSizeX/2)*stepR),
round(abs(x_pix-centerX)-(winSizeX/2)*stepG),
round(abs(x_pix-centerX)-(winSizeX/2)*stepB));
*/
set(round(convertXCoord(x_pix)), round(convertYCoord(y_pix)), c);
} else {
color c = color(0,0,round(abs(y_pix-centerY)-(winSizeY/2)*stepB));
/*color(round(abs(y_pix-centerY)-(winSizeY/2)*stepR),
round(abs(y_pix-centerY)-(winSizeY/2)*stepG),
round(abs(y_pix-centerY)-(winSizeY/2)*stepB));
*/
set(round(convertXCoord(x_pix)), round(convertYCoord(y_pix)), c);
}
}
}
//Defines a circular window and gradient
}

11
src/heatup.java Normal file
View file

@ -0,0 +1,11 @@
void heatup(LEDController leds){
if (t < 60) {
leds.allOn();
} else {
leds.allOff();
}
t_temp = t_temp + 1;
t = t_temp / framerate;
}

14
src/identifyEuglena.java Normal file
View file

@ -0,0 +1,14 @@
/* Identify Euglena in a certain portion of the camera feed */
void identifyEuglena() {
roiFrame = get(610, 290, roiWidth, roiHeight); // Get pixels of interest and saves as image for valid image path
opencv.loadImage(roiFrame); // Input proper pixels into cv processing
opencv.updateBackground(); //Necessary for background subtraction
opencv.useGray(); //Create grayscale image
opencv.dilate(); //Clean up image
opencv.erode();
opencv.blur(3);
dst = opencv.getOutput(); //Save computer vision as separate image path
contours = opencv.findContours(); //Find outline of moving objects - euglena
count = contours.size(); // Count number of outlines
}

26
src/lineRotate.java Normal file
View file

@ -0,0 +1,26 @@
float rotAngle = 0;
void lineRotate(float armLength, float speed){
clearDisplay();
strokeWeight(10); // Controls thickness of line
stroke(color(0, 0, 255));
fill(0,0,0);
if ((screenWidth - menu.width)/calibrator.magx - t > 2*armLength){
ellipseMode(CENTER);
ellipse(convertXCoord(centerX), convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t);
t = t + speed;
} else {
ellipseMode(CENTER);
ellipse(convertXCoord(centerX), convertYCoord(centerY), 2*armLength, 2*armLength);
line(convertXCoord(centerX), convertYCoord(centerY),
convertXCoord(centerX) + armLength*cos(rotAngle*PI/180), convertYCoord(centerY) + armLength*sin(rotAngle*PI/180));
rotAngle = rotAngle + speed;
}
}

63
src/merge.java Normal file
View file

@ -0,0 +1,63 @@
float t3;
void merge(float speed){
if ((screenWidth - menu.width)/calibrator.magx - t > 60){
clearDisplay();
fill(0,0,0);
strokeWeight(10); // Controls thickness of line
stroke(color(0, 0, 255));
ellipseMode(CENTER);
ellipse(convertXCoord(centerX), convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t);
t = t + speed*1;
} else {
if (convertXCoord(centerX) - t2 > convertXCoord(250)){
clearDisplay();
fill(0,0,0);
strokeWeight(10); // Controls thickness of line
stroke(color(0, 0, 255));
ellipseMode(CENTER);
arc(convertXCoord(centerX) - t2, convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t,
PI/2, 3*PI/2, CHORD);
arc(convertXCoord(centerX) + t2, convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t,
-PI/2, PI/2, CHORD);
t2 = t2 + speed*0.05;
} else {
if (t2 >= t3){
clearDisplay();
fill(0,0,0);
strokeWeight(10); // Controls thickness of line
stroke(color(0, 0, 255));
ellipseMode(CENTER);
arc(convertXCoord(centerX) - t2 + t3, convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t,
PI/2, 3*PI/2, CHORD);
arc(convertXCoord(centerX) + t2 - t3, convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t,
-PI/2, PI/2, CHORD);
t3 = t3 + speed*0.05; //follow the white rabbit amy ??
} else {
ellipse(convertXCoord(centerX), convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t);
}
}
}
}

76
src/objDensity.java Normal file
View file

@ -0,0 +1,76 @@
void densityMeasure(int x, int y, int gameScreenWidth, int gameScreenHeight) {
switch (densitySession) {
case 0:
densityMeasureTotalScreen();
break;
case 1:
densityMeasureROI(x, y, gameScreenWidth, gameScreenHeight);
break;
case 2:
calculatePercentDensity();
break;
default :
startSession = 5;
break;
}
}
void densityMeasureTotalScreen() {
// text("Whole Screen", 300, 600);
if (millis() - densityTSTime <= 2000) {
entireScreen = get(0, 0, screenWidth, screenHeight); // Get pixels of interest and saves as image for valid image path
opencv5.loadImage(entireScreen); // Input proper pixels into cv processing
opencv5.updateBackground(); //Necessary for background subtraction
opencv5.useGray(); //Create grayscale image
opencv5.dilate(); //Clean up image
opencv5.erode();
opencv5.blur(3);
cvscreen = opencv5.getOutput(); //Save computer vision as separate image path
euglenaCount = opencv5.findContours(); //Find outline of moving objects - euglena
totalCount = euglenaCount.size();
} else {
densityROITime = millis();
densitySession = 1;
}
}
void densityMeasureROI(int x, int y, int gameScreenWidth, int gameScreenHeight) {
// text("Region of Interest", 300, 600);
if (millis() - densityROITime <= 2000) {
gameScreen = get(x, y, gameScreenWidth, gameScreenHeight); // Get pixels of interest and saves as image for valid image path
opencv4.loadImage(gameScreen); // Input proper pixels into cv processing
opencv4.updateBackground(); //Necessary for background subtraction
opencv4.useGray(); //Create grayscale image
opencv4.dilate(); //Clean up image
opencv4.erode();
opencv4.blur(3);
o3 = opencv4.getOutput(); //Save computer vision as separate image path
//image(o3, x - gameScreenWidth, y);
contours = opencv4.findContours(); //Find outline of moving objects - euglena
count = contours.size();
} else {
displayDensityTime = millis();
densitySession = 2;
}
}
void calculatePercentDensity() {
// if (millis() - displayDensityTime <= 4000) {
// text(count + " " + totalCount, 600, 900);
// delay(1000);
percentDensity = ((float)count/ (float)totalCount)*100;
densityMeasured = true;
// } else {
// densityTSTime = millis();
densitySession = 0;
// }
}
void displayDensity() {
if(percentDensity != 0) {
textSize(56);
fill(color(180, 0, 0));
text("% Density: " + percentDensity, 100, 100);
}
}

View file

@ -0,0 +1,43 @@
int x_f = screenWidth;
int y_f = 0;
int t_raster = 0;
int x = 0;
int y = 0;
int framerate = 30;
int num_blinks = 3;
int blinktime = 2 * framerate * num_blinks;
int xstep = 50;
int ystep = 50;
int xsize = xstep;
int ysize = ystep;
void proto488flashraster(int x_i, int y_i, int rasterWidth, int rasterHeight){
//clearDisplay();
color draw_color;
float draw_size_factor;
if ((t_raster % (2*framerate) > framerate) || (t_raster % (2*framerate) == 0)) {
draw_color = color(bgR,bgG,bgB); //Background color
draw_size_factor = 1.1;
} else {
draw_color = color(0,247,255);
draw_size_factor = 1.0;
}
fill(draw_color);
noStroke();
rectMode(CENTER);
rect(convertXCoord(x_f), convertYCoord(y_f), xsize/calibrator.magx * draw_size_factor, ysize/calibrator.magy * draw_size_factor);
t_raster = t_raster + 1;
x = x + xstep * (t_raster / blinktime);
x_f = x_i + x;
y = y + ystep * (x / rasterWidth);
y_f = y_i + y;
t_raster = t_raster % blinktime;
x = x % rasterWidth;
y = y % rasterHeight;
}

19
src/protoClear.java Normal file
View file

@ -0,0 +1,19 @@
/* ____ The area of interest is outlined is in blue and
-> / a triangle is used as border to make sure euglena
\____ are cleared out. The top coordinates of the top right
x and y and width and height can be passed as parameters
*/
void protoClear(float x, float y, float screenWidth, float screenHeight) {
noFill();
stroke(color(0, 0, 220));
strokeWeight(5);
beginShape();
vertex(convertXCoord(x + screenWidth), convertYCoord(y));
vertex(convertXCoord(x), convertYCoord(y));
vertex(convertXCoord(x - menu.width), convertYCoord((y + y + screenHeight)/2));
vertex(convertXCoord(x), convertYCoord(y + screenHeight));
vertex(convertXCoord(x + screenWidth), convertYCoord(y + screenHeight));
endShape();
arduino.digitalWrite(left, Arduino.HIGH);
}

33
src/protoGather.java Normal file
View file

@ -0,0 +1,33 @@
/*
\__ Draws shape like this and activates arduino so that
-> __| euglena stream into the opening. The top coordinates of the top right
/ x and y and width and height of containment box can be passed as parameters
After amount of time or (yet to be implemented) after number of euglena
enter the box is closed
*/
float t_temp = 0;
float t = 0;
void protoGather(float x, float y, float boxWidth, float boxHeight) {
noFill();
strokeWeight(10); // Controls thickness of blue border
stroke(color(0, 0, 220));
beginShape(); // Draws shape
vertex(convertXCoord(x - menu.width), displayHeight*calibrator.offsety+displayHeight/calibrator.magy-10);
vertex(convertXCoord(x), convertYCoord(y));
vertex(convertXCoord(x + boxWidth), convertYCoord(y));
vertex(convertXCoord(x + boxWidth), convertYCoord(y + boxHeight));
vertex(convertXCoord(x), convertYCoord(y + boxHeight));
vertex(convertXCoord(x - menu.width), displayHeight*calibrator.offsety);
endShape();
if (t < 180) {
arduino.analogWrite(down, 64); // Turns on arduino light (can make ledPin into a parameter that is passed in)
} else {
arduino.analogWrite(down, 0);
}
t_temp = t_temp + 1;
t = t_temp / framerate;
}

30
src/randomLED.java Normal file
View file

@ -0,0 +1,30 @@
void randomLED(){
float rNum = random(100);
if (rNum < 25){
arduino.digitalWrite(left, Arduino.HIGH);
arduino.digitalWrite(right, Arduino.LOW);
arduino.digitalWrite(up, Arduino.LOW);
arduino.digitalWrite(down, Arduino.LOW);
}
if (rNum >= 25 && rNum <50){
arduino.digitalWrite(left, Arduino.LOW);
arduino.digitalWrite(right, Arduino.HIGH);
arduino.digitalWrite(up, Arduino.LOW);
arduino.digitalWrite(down, Arduino.LOW);
}
if (rNum >= 50 && rNum <75){
arduino.digitalWrite(left, Arduino.LOW);
arduino.digitalWrite(right, Arduino.LOW);
arduino.digitalWrite(up, Arduino.HIGH);
arduino.digitalWrite(down, Arduino.LOW);
}
if (rNum >= 75 && rNum <100){
arduino.digitalWrite(left, Arduino.LOW);
arduino.digitalWrite(right, Arduino.LOW);
arduino.digitalWrite(up, Arduino.LOW);
arduino.digitalWrite(down, Arduino.HIGH);
}
}

28
src/recordTimelapse.java Normal file
View file

@ -0,0 +1,28 @@
int initMillis = 0;
boolean record = false;
int frameMillis = 0;
void recordTimelapse(float lagtime, float maxtime){
// checks if record state is turned off
if (record == false){
initMillis = 0;
return;
}
// records the milliseconds elapsed between program start and first frame taken
if (initMillis == 0){
initMillis = millis();
}
// automatically turns off recording if maxtime has elapsed
if (millis()-initMillis > maxtime*1000){
record = false;
return;
}
// takes snapshot if enough time has elapsed since last frame was taken
if ((millis()-frameMillis) >= lagtime*1000){
snapshot();
frameMillis = millis();
}
}

30
src/rectangularStim.java Normal file
View file

@ -0,0 +1,30 @@
int stimTime = 0;
void rectangularStim(int intensity, int stimTime) {
if (t%(4*stimTime) < stimTime) {
arduino.analogWrite(down, intensity); // Turns on arduino light (can make ledPin into a parameter that is passed in)
} else {
arduino.analogWrite(down, 0);
}
if (t%(4*stimTime) >= stimTime && t%(4*stimTime) < 2*stimTime) {
arduino.analogWrite(left, intensity);
} else {
arduino.analogWrite(left, 0);
}
if (t%(4*stimTime) >= 2*stimTime && t%(4*stimTime) < 3*stimTime){
arduino.analogWrite(up, intensity);
} else {
arduino.analogWrite(up, 0);
}
if (t%(4*stimTime) >= 3*stimTime && t%(4*stimTime) < 4*stimTime){
arduino.analogWrite(right, intensity);
} else {
arduino.analogWrite(right, 0);
}
t_temp = t_temp + 1;
t = t_temp / FrameRate;
}

38
src/separate.java Normal file
View file

@ -0,0 +1,38 @@
float t2;
void separate(float speed){
if ((screenWidth - menu.width)/calibrator.magx - t > 60){
clearDisplay();
fill(0,0,0);
strokeWeight(10); // Controls thickness of line
stroke(color(0, 0, 255));
ellipseMode(CENTER);
ellipse(convertXCoord(centerX), convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t);
t = t + speed*1;
} else {
if (convertXCoord(centerX) - t2 > convertXCoord(250)){
clearDisplay();
fill(0,0,0);
strokeWeight(10); // Controls thickness of line
stroke(color(0, 0, 255));
ellipseMode(CENTER);
arc(convertXCoord(centerX) - t2, convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t,
PI/2, 3*PI/2, CHORD);
arc(convertXCoord(centerX) + t2, convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t,
-PI/2, PI/2, CHORD);
t2 = t2 + speed*0.01;
}
}
}

24
src/showCV.java Normal file
View file

@ -0,0 +1,24 @@
/* Show backend computer vision for curious users */
void showCV() {
rectMode(CORNER);
stroke(100);
noFill();
rect(roiCornerX, roiCornerY, roiWidth, roiHeight); // Outlines region of interest
noFill();
stroke(255, 0, 0);
strokeWeight(3);
for (Contour contour : contours) {
beginShape();
for (PVector p : contour.getPoints()) {
vertex(p.x + roiCornerX, p.y + roiCornerY);
}
endShape(PConstants.CLOSE); // Draws outlines of moving objects
}
image(dst, roiCornerX + roiWidth, roiCornerY, roiWidth, roiHeight); // Displays backend cv
textSize(56);
text("Count: " + count, 300, 600); // COunts number of euglena in region of interest
}

50
src/shrinkingCircle.java Normal file
View file

@ -0,0 +1,50 @@
//class SlowConcentrate{
//
// float speed;
// int centerX, centerY, red, green, blue, brushSize, t_init, t_last;
// boolean accumulate, centerComplete;
//
// void reset(){
// centerComplete = false;
// t_init = millis();
// }
//
// SlowConcentrate(int centerX, int centerY){
//
// this.centerX = centerX;
// this.centerY = centery;
// this.speed = speedSet;
// this.red = rVal;
// this.green = gVal;
// this.blue = bVal;
// this.brushSize = penWidth;
//
// }
//
// void draw(){
//
// }
//}
int t_circ_shrink_last = 0;
int step = 0;
float radius;
void shrinkingCircle(float speed, int red, int green, int blue, int borderWidth){
clearDisplay();
radius = (screenWidth - menu.width)/calibrator.magx - step;
if (radius > 25){
if (millis() - t_circ_shrink_last > speed*1000){
step = step + 1;
noFill();
strokeWeight(borderWidth);
stroke(color(red, green, blue));
ellipseMode(CENTER);
ellipse(convertXCoord(centerX), convertYCoord(centerY), radius, radius);
t_circ_shrink_last = millis();
}
}
}

18
src/shrinkingWindow.java Normal file
View file

@ -0,0 +1,18 @@
void shrinkingWindow(float speed, int red, int green, int blue, int borderWidth){
// clearDisplay();
fill(0,0,0);
strokeWeight(borderWidth); // Controls thickness of line
stroke(color(red, green, blue));
rectMode(CENTER);
rect(convertXCoord(centerX), convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx-t, (screenHeight)/calibrator.magx-t);
if (screenHeight/calibrator.magx-t > 20){
t = t + speed*1;
} else {
t = t;
}
}

2
src/sketch.properties Normal file
View file

@ -0,0 +1,2 @@
mode.id=processing.mode.java.JavaMode
mode=Java

7
src/snapshot.java Normal file
View file

@ -0,0 +1,7 @@
void snapshot(){
PImage c = get(0, 15, screenWidth-menu.width, screenHeight-15); //Takes the FOV
c.save("Image" + str(millis()) + ".jpg"); //Saves the FOV with Image_____.jpg, where _____ is the number of milliseconds elapsed from the program start
//print(str(millis())+"\n");
}

12
src/squareCorridor.java Normal file
View file

@ -0,0 +1,12 @@
void squareCorridor() {
noFill();
strokeWeight(12); // Controls thickness of blue border
stroke(color(0, 0, 31));
rectMode(CENTER);
rect(convertXCoord(screenWidth - 1000), convertYCoord(550), xsize/calibrator.magx *15, ysize/calibrator.magy *15);
fill(color(0, 0, 255));
noStroke();
rectMode(CENTER);
rect(convertXCoord(screenWidth - 1000), convertYCoord(550), xsize/calibrator.magx *9, ysize/calibrator.magy *9);
}

11
src/testing.java Normal file
View file

@ -0,0 +1,11 @@
int rVal = 255;
int gVal = 255;
int bVal = 255;
int bgVal = 0;
int bgR = bgVal*13/10; // Red value
int bgG = bgVal*5/10; // Green value
int bgB = bgVal*4/10; // Blue value
final float stimulusColor = 180; //stimulus intensity out of 255
final float greenscale = 0.3; // scales down intensity of green
final float redscale = 0.7; // scales down intensity of red

29
src/translateCircle.java Normal file
View file

@ -0,0 +1,29 @@
void translateCircle(float speed){
if ((screenWidth - menu.width)/calibrator.magx - t > 60){
clearDisplay();
fill(0,0,0);
strokeWeight(10); // Controls thickness of line
stroke(color(0, 0, 255));
ellipseMode(CENTER);
ellipse(convertXCoord(centerX), convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t);
t = t + speed*1;
} else {
if (convertXCoord(centerX) - t2 > convertXCoord(250)){
clearDisplay();
fill(0,0,0);
strokeWeight(10); // Controls thickness of line
stroke(color(0, 0, 255));
ellipseMode(CENTER);
ellipse(convertXCoord(centerX) - t2, convertYCoord(centerY),
(screenWidth - menu.width)/calibrator.magx - t, (screenWidth - menu.width)/calibrator.magx - t);
t2 = t2 + speed*0.1;
}
}
}

18
src/unidirectionStim.java Normal file
View file

@ -0,0 +1,18 @@
/*
Holds stimulus light from screen left on for 10 seconds.
*/
float FrameRate = 30;
int intensity = 0;
void unidirectionStim(int intensity) {
if (t < 180) {
arduino.analogWrite(down, intensity); // Turns on arduino light (can make ledPin into a parameter that is passed in)
} else {
arduino.analogWrite(down, 0);
}
t_temp = t_temp + 1;
t = t_temp / FrameRate;
}

15
src/window.java Normal file
View file

@ -0,0 +1,15 @@
void window(int xsize, int ysize) {
//Outer rectangle is filled
fill(color(0, 0, 255));
noStroke();
rectMode(CENTER);
rect(convertXCoord(screenWidth - 1000), convertYCoord(centerY), screenWidth-500, screenHeight);
//Inner rectangle with no stimulus
fill(0,0,0);
strokeWeight(1);
stroke(color(0, 0, 0));
rectMode(CENTER);
rect(convertXCoord(screenWidth - 1000), convertYCoord(centerY), xsize, ysize);
}