Created
February 3, 2012 11:11
-
-
Save frederickk/1729700 to your computer and use it in GitHub Desktop.
A collection of classes used for my lightBrush http://kenfrederick.blogspot.com/2009/08/lightbrush.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* LightBrushColorduino receiver 1.0 | |
* | |
* Ken Frederick | |
* ken.frederick@gmx.de | |
* | |
* http://cargocollective.com/kenfrederick/ | |
* http://kenfrederick.blogspot.com/ | |
* | |
* Arduino code for receiving Serial messages from SerialPixelSender.pde | |
* | |
*/ | |
//----------------------------------------------------------------------------- | |
// includes | |
//----------------------------------------------------------------------------- | |
#include <Colorduino.h> | |
//----------------------------------------------------------------------------- | |
// constants | |
//----------------------------------------------------------------------------- | |
/** | |
* these must match what is being sent | |
* from the host app | |
*/ | |
#define ARDUINO_BAUD_RATE 115200 // must be exactly the same in the arduino sketch | |
// data packet constants | |
#define BUFFER_SIZE 64 // 8*8 | |
#define START_BYTE 42 // 42 = * | |
#define DELIMITER 44 // 44 = , | |
#define END_BYTE 35 // 35 = # | |
#define MODE_BYTE 63 // 32 = ? | |
#define DRAW_BYTE 124 // 124 = | | |
#define SEND_BYTE 95 // 95 = _ | |
//----------------------------------------------------------------------------- | |
// properties | |
//----------------------------------------------------------------------------- | |
//int bufferPacket[BUFFER_SIZE][5]; | |
int bufferPacket[BUFFER_SIZE][3]; | |
unsigned char red, green, blue; | |
int pos, index; | |
bool bDraw = false; | |
bool bMode = true; | |
//----------------------------------------------------------------------------- | |
// methods | |
//----------------------------------------------------------------------------- | |
void setup() { | |
// serial | |
Serial.begin(ARDUINO_BAUD_RATE); | |
red = green = blue = 0; | |
pos = 0; | |
index = 0; | |
// colorduino | |
Colorduino.Init(); | |
/** | |
* compensate for relative intensity differences in R/G/B brightness | |
* array of 6-bit base values for RGB (0~63) | |
* whiteBalVal[0] = red | |
* whiteBalVal[1] = green | |
* whiteBalVal[2] = blue | |
*/ | |
unsigned char whiteBalVal[3] = { 10,25,25 }; | |
Colorduino.SetWhiteBal(whiteBalVal); | |
} | |
//----------------------------------------------------------------------------- | |
void update() { | |
while (Serial.available()) { | |
byte serialBuffer = Serial.read(); | |
switch(serialBuffer) { | |
case START_BYTE: | |
pos = 0; | |
//Serial.flush(); | |
continue; | |
break; | |
case DELIMITER: | |
pos++; | |
break; | |
case DRAW_BYTE: | |
bDraw = !bDraw; | |
//continue; | |
break; | |
case MODE_BYTE: | |
bMode = !bMode; | |
//continue; | |
break; | |
case END_BYTE: | |
//Serial.print(SEND_BYTE); | |
Serial.flush(); | |
//continue; | |
break; | |
} // end switch serialBuffer | |
/** | |
* how many values are we sending at once? | |
* switch between to load the proper variables | |
*/ | |
switch(pos) { | |
case 0: | |
red = serialBuffer; | |
break; | |
case 1: | |
green = serialBuffer; | |
break; | |
case 2: | |
blue = serialBuffer; | |
break; | |
case 3: | |
index = serialBuffer; | |
// push to bufferPacker | |
bufferPacket[index][0] = red; | |
bufferPacket[index][1] = green; | |
bufferPacket[index][2] = blue; | |
/* | |
unsigned int x = index / ColorduinoScreenWidth; | |
unsigned int y = index % ColorduinoScreenHeight; | |
bufferPacket[index][3] = x; | |
bufferPacket[index][4] = y; | |
*/ | |
break; | |
} | |
} // end while | |
} | |
//----------------------------------------------------------------------------- | |
void loop() { | |
update(); | |
/** | |
* process color | |
*/ | |
if(bDraw) { | |
if(bMode) { | |
ColorFill(bufferPacket[0][0], bufferPacket[0][1], bufferPacket[0][2]); | |
} else if(!bMode) { | |
ColorFrame(bufferPacket); | |
/* | |
for(int i=0; i<BUFFER_SIZE; i++) { | |
ColorPoint(bufferPacket[i][0], bufferPacket[i][1], bufferPacket[i][2], i); | |
} | |
*/ | |
} | |
} | |
Colorduino.FlipPage(); | |
} | |
//----------------------------------------------------------------------------- | |
void ColorFrame(int buffer[BUFFER_SIZE][3]) { | |
ColorRGB *p = Colorduino.curWriteFrame; | |
int pindex = 0; | |
for(unsigned char y=0; y<ColorduinoScreenWidth; y++) { | |
for(unsigned char x=0; x<ColorduinoScreenHeight; x++) { | |
// p->r = bufferPacket[pindex][0]; | |
// p->g = bufferPacket[pindex][1]; | |
// p->b = bufferPacket[pindex][2]; | |
p->r = buffer[pindex][0]; | |
p->g = buffer[pindex][1]; | |
p->b = buffer[pindex][2]; | |
pindex++; | |
p++; | |
} | |
} | |
} | |
//----------------------------------------------------------------------------- | |
void ColorPoint(unsigned char R,unsigned char G,unsigned char B, unsigned int _index) { | |
ColorRGB *p = Colorduino.curWriteFrame; | |
p[index].r = R; | |
p[index].g = G; | |
p[index].b = B; | |
//Colorduino.FlipPage(); | |
} | |
void ColorPoint(unsigned int x, unsigned int y, unsigned char R,unsigned char G,unsigned char B) { | |
ColorRGB *p = Colorduino.GetPixel(x,y); | |
p->r = R; | |
p->g = G; | |
p->b = B; | |
//Colorduino.SetPixel(x,y, R,G,B); | |
//Colorduino.FlipPage(); | |
} | |
//----------------------------------------------------------------------------- | |
void ColorFill(unsigned char R,unsigned char G,unsigned char B) { | |
ColorRGB *p = Colorduino.GetPixel(0,0); | |
for(unsigned char y=0; y<ColorduinoScreenWidth; y++) { | |
for(unsigned char x=0; x<ColorduinoScreenHeight; x++) { | |
p->r = R; | |
p->g = G; | |
p->b = B; | |
p++; | |
} | |
} | |
//Colorduino.FlipPage(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* OpenCVTracker.pde | |
* | |
* Ken Frederick | |
* ken.frederick@gmx.de | |
* | |
* http://cargocollective.com/kenfrederick/ | |
* http://kenfrederick.blogspot.com/ | |
* | |
*/ | |
//----------------------------------------------------------------------------- | |
// libraries | |
//----------------------------------------------------------------------------- | |
import codeanticode.gsvideo.*; | |
import hypermedia.video.*; | |
public class OpenCVTracker extends Thread { | |
//----------------------------------------------------------------------------- | |
// properties | |
//----------------------------------------------------------------------------- | |
private PApplet papplet; | |
private PGraphics imageBuff; | |
boolean bRunning = false; | |
// video | |
private GSCapture video; | |
// openCV | |
private OpenCV opencv; | |
private Blob[] blobs; | |
private int cvBrightness; | |
private int cvContrast; | |
private int cvThresh; | |
// points | |
float avgWeight = 0.5; | |
//----------------------------------------------------------------------------- | |
// constructor | |
//----------------------------------------------------------------------------- | |
public OpenCVTracker(PApplet _papplet, int _width, int _height) { | |
papplet = _papplet; | |
imageBuff = createGraphics(_width,_height, P2D); | |
// setup video | |
video = new GSCapture(_papplet, _width, _height); | |
video.play(); | |
// setup openCV | |
opencv = new OpenCV(_papplet); | |
opencv.allocate(_width, _height); | |
setBrightness(0); | |
setContrast(0); | |
setThreshold(0); | |
} | |
//----------------------------------------------------------------------------- | |
// methods | |
//----------------------------------------------------------------------------- | |
public void start() { | |
bRunning = true; | |
super.start(); | |
} | |
//----------------------------------------------------------------------------- | |
public void run() { | |
while(bRunning) { | |
update(); | |
try { | |
} catch (Exception e) { | |
} | |
} | |
} | |
//----------------------------------------------------------------------------- | |
public void update() { | |
// open cv | |
opencv.copy(video); | |
opencv.convert(GRAY); | |
opencv.brightness(cvBrightness); | |
opencv.contrast(cvContrast); | |
opencv.threshold(cvThresh); | |
blobs = opencv.blobs(10, video.width*video.height/2, 4, false, 1); //OpenCV.MAX_VERTICES*4 ); | |
// video | |
if (video.available()) { | |
video.read(); | |
//video.loadPixels(); | |
} | |
} | |
//----------------------------------------------------------------------------- | |
public void draw(int _x, int _y, boolean bVideo) { | |
draw(_x,_y, video.width,video.height, bVideo); | |
} | |
public void draw(int _x, int _y, int _width, int _height, boolean bVideo) { | |
pushMatrix(); | |
translate(_x,_y); | |
PVector videoSize = new PVector(video.width, video.height, 0); | |
PVector avg = getAvg().get(); | |
avg.mult(videoSize); | |
imageBuff.beginDraw(); | |
imageBuff.background(0); | |
imageBuff.noFill(); | |
if(bVideo) { | |
imageBuff.image(video, 0,0, video.width,video.height); | |
} else { | |
imageBuff.image(opencv.image(), 0,0, video.width,video.height); | |
//imageBuff.image(opencv.image(), 0,0+video.height, video.width,video.height); | |
//imageBuff.image(opencv.image(), 0+video.width,0, video.width,video.height); | |
} | |
// draw blobs | |
imageBuff.stroke(255,0,255, 255*0.6); | |
imageBuff.beginShape(); | |
for(int i=0; i<blobs.length; i++) { | |
for(int j=0; j<blobs[i].points.length; j++ ) { | |
//imageBuff.ellipse(blobs[i].points[j].x, blobs[i].points[j].y, 9,9); | |
imageBuff.line(blobs[i].points[j].x-4.5,blobs[i].points[j].y, blobs[i].points[j].x+4.5,blobs[i].points[j].y); | |
imageBuff.line(blobs[i].points[j].x,blobs[i].points[j].y-4.5, blobs[i].points[j].x,blobs[i].points[j].y+4.5); | |
imageBuff.vertex(blobs[i].points[j].x, blobs[i].points[j].y); | |
} | |
imageBuff.vertex(avg.x,avg.y); | |
} | |
imageBuff.endShape(); | |
// averaged blob point | |
//imageBuff.fill(0,255,255, 255*0.6); | |
//imageBuff.ellipse(getAvg().x,getAvg().y, 9,9); | |
imageBuff.strokeWeight(3); | |
imageBuff.stroke(0,255,255, 255*0.7); | |
imageBuff.line(avg.x-4.5,avg.y, avg.x+4.5,avg.y); | |
imageBuff.line(avg.x,avg.y-4.5, avg.x,avg.y+4.5); | |
imageBuff.ellipse(avg.x,avg.y, 12,12); | |
imageBuff.endDraw(); | |
image(imageBuff, 0,0, _width,_height); | |
popMatrix(); | |
} | |
//----------------------------------------------------------------------------- | |
/** | |
* filter the current result using a weighted average filter: | |
* http://web.archive.org/web/20070224180400/http://www.tigoe.net/pcomp/code/archives/arduino/000710.shtml | |
*/ | |
private float filter(float rawValue, float weight, float lastValue) { | |
float fValue = 0.0f; | |
float x = weight; // is a value between 0 and 1 | |
//int x = 0; | |
//x = weight/102; // convert the weight number to a value between 0 and 1: | |
fValue = (x * rawValue + (10-x)*lastValue)/10; // run the filter: | |
return fValue; | |
} | |
//----------------------------------------------------------------------------- | |
public void quit() { | |
bRunning = false; | |
opencv.stop(); | |
papplet.stop(); | |
interrupt(); | |
} | |
//----------------------------------------------------------------------------- | |
// public void stop() { | |
// quit(); | |
// opencv.stop(); | |
// papplet.stop(); | |
// } | |
//----------------------------------------------------------------------------- | |
// sets | |
//----------------------------------------------------------------------------- | |
public void setBrightness(int val) { | |
cvBrightness = val; | |
} | |
public void setContrast(int val) { | |
cvContrast = val; | |
} | |
public void setThreshold(int val) { | |
cvThresh = val; | |
} | |
//----------------------------------------------------------------------------- | |
public void setAvgWeight(float val) { | |
avgWeight = val; | |
} | |
//----------------------------------------------------------------------------- | |
// gets | |
//----------------------------------------------------------------------------- | |
public boolean getRunning() { | |
return bRunning; | |
} | |
//----------------------------------------------------------------------------- | |
public PVector getCoord(int num) { | |
PVector v = new PVector(); | |
if( blobs.length != 0) { | |
int c = constrain(num, 0,blobs.length); | |
v.set( norm(blobs[c].points[0].x, 0,video.width), norm(blobs[c].points[0].y, 0,video.height), 0); | |
} | |
return v; | |
} | |
//----------------------------------------------------------------------------- | |
PVector pv = new PVector(); | |
public PVector getAvg() { | |
PVector v = new PVector(); | |
int count = 0; | |
for(int i=0; i<blobs.length; i++) { | |
v.x += getCoord(i).x; | |
v.y += getCoord(i).y; | |
v.z += getCoord(i).z; | |
count++; | |
} | |
v.x /= count; | |
v.y /= count; | |
v.z /= count; | |
v.x = filter(v.x, avgWeight, pv.x); | |
v.y = filter(v.y, avgWeight, pv.y); | |
v.z = filter(v.z, avgWeight, pv.z); | |
pv = v.get(); | |
return v; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* SerialPixelSender.pde | |
* | |
* Ken Frederick | |
* ken.frederick@gmx.de | |
* | |
* http://cargocollective.com/kenfrederick/ | |
* http://kenfrederick.blogspot.com/ | |
* | |
* threaded code for sending data from processing to arduino | |
* | |
*/ | |
//----------------------------------------------------------------------------- | |
// libraries | |
//----------------------------------------------------------------------------- | |
import processing.serial.*; | |
public class SerialPixelSender extends Thread { | |
//----------------------------------------------------------------------------- | |
// constants | |
//----------------------------------------------------------------------------- | |
private int ARDUINO_BAUD_RATE = 115200; // must be exactly the same in the arduino sketch | |
private final int ARDUINO_TIMEOUT = 0; // milliseconds | |
private final char START_BYTE = 42; // 42 = * | |
private final char DELIMITER = 44; // 44 = , | |
private final char END_BYTE = 35; // 35 = # | |
private final char MODE_BYTE = 63; // 32 = ? | |
private final char DRAW_BYTE = 124; // 124 = | | |
private final char SEND_BYTE = 95; // 95 = _ | |
//----------------------------------------------------------------------------- | |
// properties | |
//----------------------------------------------------------------------------- | |
// application | |
private PApplet papplet; | |
private boolean bMode = false; | |
private boolean bRunning = false; | |
private boolean bSendMessage = false; | |
// serial | |
private Serial arduino; | |
private boolean bConnected = false; | |
// image | |
private PImage src; | |
//----------------------------------------------------------------------------- | |
// constructor | |
//----------------------------------------------------------------------------- | |
public SerialPixelSender() { | |
} | |
public SerialPixelSender(PApplet _papplet) { | |
// application | |
papplet = _papplet; | |
// serial | |
println( Serial.list() ); | |
String portName = Serial.list()[0]; | |
arduino = new Serial(papplet, portName, ARDUINO_BAUD_RATE); | |
arduino.bufferUntil( END_BYTE ); // lf == line feed, ASCII 10; the line ending from arduino | |
// image | |
//PImage src = new PImage(8,8, RGB); | |
} | |
public SerialPixelSender(PApplet _papplet, int _ARDUINO_BAUD_RATE) { | |
// application | |
papplet = _papplet; | |
// serial | |
println( Serial.list() ); | |
String portName = Serial.list()[0]; | |
ARDUINO_BAUD_RATE = _ARDUINO_BAUD_RATE; | |
arduino = new Serial(papplet, portName, ARDUINO_BAUD_RATE); | |
arduino.bufferUntil( END_BYTE ); // lf == line feed, ASCII 10; the line ending from arduino | |
// image | |
//PImage src = new PImage(8,8, RGB); | |
} | |
//----------------------------------------------------------------------------- | |
// methods | |
//----------------------------------------------------------------------------- | |
public void start() { | |
bRunning = true; | |
super.start(); | |
} | |
//----------------------------------------------------------------------------- | |
public void run() { | |
while(bRunning) { | |
update(); | |
try { | |
//sleep( (long)(ARDUINO_TIMEOUT) ); | |
} catch (Exception e) { | |
} | |
} | |
} | |
//----------------------------------------------------------------------------- | |
public void update() { | |
if(bSendMessage) { | |
sendImage(src); | |
} | |
} | |
//----------------------------------------------------------------------------- | |
private void sendImage(PImage _src) { | |
toggleDraw(); | |
try { | |
//img.resize(8,8); | |
PImage img = new PImage(8,8, RGB); | |
if(_src.width > 7 || _src.height > 7) { | |
img = setImage(_src); | |
/* | |
img.copy(_src, 0,0,_src.width,_src.height, 0,0,8,8); | |
img.loadPixels(); | |
*/ | |
} else { | |
img = _src; | |
} | |
for(int index=0; index<img.pixels.length; index++) { | |
int col = img.pixels[index]; | |
int r = (int) ((col >> 16) & 0xFF); | |
int g = (int) ((col >> 8) & 0xFF); | |
int b = (int) (col & 0xFF); | |
sendRGB(r,g,b, index); | |
} | |
} catch(Exception e) { | |
} | |
toggleDraw(); | |
} | |
//----------------------------------------------------------------------------- | |
private void sendRGB(int R, int G, int B, int index) { | |
arduino.write( START_BYTE ); | |
//R | |
arduino.write(R); | |
arduino.write( DELIMITER ); | |
//G | |
arduino.write(G); | |
arduino.write( DELIMITER ); | |
//B | |
arduino.write(B); | |
arduino.write( DELIMITER ); | |
//INDEX | |
arduino.write( index ); | |
arduino.write( END_BYTE ); | |
arduino.clear(); // dumps buffer before asking for next data point | |
} | |
//----------------------------------------------------------------------------- | |
private void toggleDraw() { | |
arduino.write( START_BYTE ); | |
arduino.write( DRAW_BYTE ); | |
arduino.write( END_BYTE ); | |
arduino.clear(); // dumps buffer before asking for next data point | |
} | |
//----------------------------------------------------------------------------- | |
private void toggleMode() { | |
arduino.write( START_BYTE ); | |
arduino.write( MODE_BYTE ); | |
arduino.write( END_BYTE ); | |
arduino.clear(); // dumps buffer before asking for next data point | |
} | |
//----------------------------------------------------------------------------- | |
public void quit() { | |
bRunning = false; | |
interrupt(); | |
arduino.clear(); | |
arduino.stop(); | |
} | |
//----------------------------------------------------------------------------- | |
// sets | |
//----------------------------------------------------------------------------- | |
public void send() { | |
bSendMessage = true; | |
} | |
//----------------------------------------------------------------------------- | |
public void set(int[] colors, int colorsNum) { | |
PImage img = new PImage(8,8, RGB); | |
//img.loadPixels(); | |
for(int i=0; i<colors.length; i++) { | |
img.pixels[i] = colors[i]; | |
} | |
setImage(img); | |
} | |
//----------------------------------------------------------------------------- | |
public PImage setImage(PImage _src) { | |
src = _src; | |
PImage temp = new PImage(8,8, RGB); | |
temp.copy(src, 0,0,src.width,src.height, 0,0,8,8); | |
temp.loadPixels(); | |
return src; | |
} | |
//----------------------------------------------------------------------------- | |
// gets | |
//----------------------------------------------------------------------------- | |
public boolean getRunning() { | |
return bRunning; | |
} | |
//----------------------------------------------------------------------------- | |
PImage getImage() { | |
return src; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment