Calibrate works?
This commit is contained in:
parent
26e34f7671
commit
cc711c6343
1104 changed files with 636510 additions and 75 deletions
121
src/Calibrator.java
Normal file
121
src/Calibrator.java
Normal 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
99
src/EllipseClass.java
Normal 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
84
src/ExpandClass.java
Normal 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));
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
79
src/LineClass.java
Normal 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
313
src/Menu.java
Normal 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';
|
||||
}
|
||||
*/
|
||||
56
src/ObjectRecognition.java
Normal file
56
src/ObjectRecognition.java
Normal 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
82
src/Presets.java
Normal 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
88
src/RectangleClass.java
Normal 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
68
src/RotateClass.java
Normal 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
93
src/ShrinkClass.java
Normal 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
99
src/TranslateClass.java
Normal 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
98
src/TriangleClass.java
Normal 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
12
src/angleGather.java
Normal 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
26
src/angleMove.java
Normal 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
10
src/circleArrayStim.java
Normal 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
12
src/clearDisplay.java
Normal 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
79
src/clearScreen.java
Normal 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
8
src/colorScreen.java
Normal 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
299
src/developer.java
Normal 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();
|
||||
}
|
||||
*/
|
||||
480
src/euglena_basic_stimuli.java
Normal file
480
src/euglena_basic_stimuli.java
Normal 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
40
src/gradientWindow.java
Normal 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
11
src/heatup.java
Normal 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
14
src/identifyEuglena.java
Normal 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
26
src/lineRotate.java
Normal 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
63
src/merge.java
Normal 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
76
src/objDensity.java
Normal 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);
|
||||
}
|
||||
}
|
||||
43
src/proto488flashraster.java
Normal file
43
src/proto488flashraster.java
Normal 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
19
src/protoClear.java
Normal 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
33
src/protoGather.java
Normal 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
30
src/randomLED.java
Normal 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
28
src/recordTimelapse.java
Normal 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
30
src/rectangularStim.java
Normal 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
38
src/separate.java
Normal 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
24
src/showCV.java
Normal 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
50
src/shrinkingCircle.java
Normal 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
18
src/shrinkingWindow.java
Normal 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
2
src/sketch.properties
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
mode.id=processing.mode.java.JavaMode
|
||||
mode=Java
|
||||
7
src/snapshot.java
Normal file
7
src/snapshot.java
Normal 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
12
src/squareCorridor.java
Normal 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
11
src/testing.java
Normal 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
29
src/translateCircle.java
Normal 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
18
src/unidirectionStim.java
Normal 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
15
src/window.java
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue