
PROCESS
PROCESS
Processing
createByHeart.pde
import processing.serial.*;
import processing.video.*;
import java.awt.*;
/*------from the lecture note------*/
Serial myPort; // Create object from Serial class
/*------from the processing libraries------*/
import gab.opencv.*;
OpenCV opencv;
Capture capture;
/*-------Button variables--------*/
String val="n"; // button value of changing shapes
String save="q"; // value of save button
/*-------Camera function--------*/
boolean backgroundCaptured = false; // this variable show the functionality
PImage samplingImage; // this is the image that is used to check the differences with the live image
/*-------Data of pulse sensor--------*/
int Sensor; // HOLDS PULSE SENSOR DATA FROM ARDUINO
int IBI; // HOLDS TIME BETWEN HEARTBEATS FROM ARDUINO
int BPM; // HOLDS HEART RATE VALUE FROM ARDUINO
boolean beat = false;
/*-------paint function--------*/
float j = 0; // j is the value fed into sine functions
float speedPaint = 0; // speedPaint is mapped to mouse x and added into j per frame
float z = 0; // used to oscilate ring thickness using sine(j)
float size = 196; // used to translate shapes downwards in the for loop to make ring rather than circle
float col; // makes the shapes glow white when they get to center using sin
/*-------boolean switches--------*/
boolean shape = true; // if true then use circles, otherwise rectanges
boolean play = true; // if false then pause the animation
void setup() {
size(960, 960);
myPort=new Serial(this, "COM3", 115200); // set port
myPort.clear();
myPort.bufferUntil('\n'); // set buffer full flag on receipt of carriage return
colorMode(HSB, 360); // uses hue, saturation and brightness colour mode
smooth(); // smooth dem lines
frameRate(225);
String[] cameras = Capture.list();
samplingImage = createImage(320, 240, RGB); // create a new blank image to define its dimensions
capture = new Capture(this, 320, 240, cameras[0]);
// here begins a new sessions of capturing of the images from the webcam
capture.start();
opencv = new OpenCV(this, 320, 240);
opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); // It is used for face detection
}
void captureEvent (Capture myCapture) {
capture.read();
}
void draw() {
background(360); // some shade of grey that works visually
cam();// call cam function
BPM = min(BPM, 200);
paint(width/2, height/2, IBI*0.2, BPM, -IBI, -BPM, 100, 100, 30, 58, 86, 75, 20, 75, 200, 320);
if (Sensor == 0) {
play=!play;
}
savef();
}
// camera function with face detection
void cam() {
if (capture.available()==true)
capture.read();
opencv.loadImage(capture);
Rectangle[] faces = opencv.detect();
image( capture, 0, -50); //show the live webcam image in different positions
set(0, -50, capture);
image( capture, 320, -50); //show the live webcam image in different positions
set(320, -50, capture);
// when the cam detected the face, image will build out and follow your face position
if (faces.length>0) {
for ( int i=0; i<faces.length; i++)
{
paint(faces[i].x-10+faces[i].width/2, faces[i].y+this.height/2+faces[i].height/2, IBI*0.4, BPM, -IBI, -BPM, 10, 10, 30, 58, 86, 75, 20, 75, 100, 120);
}
}
image( capture, 640, -50); // show the live webcam image in different positions
set(640, -50, capture);
image( capture, 0, 770); // show the live webcam image in different positions
set(0, 770, capture);
image( capture, 320, 770); // show the live webcam image in different positions
set(320, 770, capture);
// when the cam detected the face, image will build out and follow your face position
if (faces.length>0) {
for ( int i=0; i<faces.length; i++)
{
paint(faces[i].x+640+faces[i].width/2, faces[i].y+this.height/2+faces[i].height/2, IBI*0.4, BPM, -IBI, -BPM, 10, 10, 30, 58, 86, 75, 20, 75, 100, 120);
}
}
image( capture, 640, 770); // show the live webcam image in different positions
set(640, 770, capture);
}
void changeShape() {
shape = !shape;
}
/*------reference from https://processing.org/reference/saveFrame_.html ------*/
// screen capture to png file
void savef() {
if (save.charAt(0)!='q') {
saveFrame("image/artwork-####.png");
} else {
}
}
paint.pde
/*-------Paint Pattern--------*/
void paint(float tranx, float trany, float circlex, float circley, float rectx, float recty, float sizex, float sizey, float tx1, float tx2, float tx3, float ty1, float ty2, float ty3, float s1, float s2) {
// speed of animation is directly linked to BPM
speedPaint = map(BPM, 0, 200, -0.01, 0.01);
// size of the pattern
size = map(sin(j*4), -1, 1, 0, s1);
// this fades in the white glow when all the shapes meet in middle
col = map(sin(j*4), -1, -0.8, 0, s2);
if (play) {
// speed up/slowdown/reverse sine functions according to BPM
j += speedPaint;
// change thickness
z = map(sin(j), -1, 1, -0.5, 1.5);
}
// brings all shapes down centre
// reference from https://processing.org/reference/pushMatrix_.html
pushMatrix();
translate(tranx, trany);
//rotate everything backwars or forwards depending on j val
rotate(j*4);
// loop 360, allows me to make a circle
for (int degree = 0; degree < 360; degree++) {
pushMatrix();
rotate(radians(degree));
//change the size
translate(0, size);
// sin scale the wave form, z makes it thicker and thiner
scale(map(sin(radians(degree*5.5)), -1, 1, 0.5, z), map(sin(radians(degree*11)), -1, 1, 0.5, z));
noFill();
// hue changes as it goes round circle, col changes according to sin
stroke(degree, col, 360);
strokeWeight(0.2);
// determine the shape
if (shape) {
ellipse(circlex, circley, sizex, sizey);
rect(rectx*0.15, recty, sizex*0.5, sizey*0.3);
} else {
rect(rectx*0.15, recty, sizex, sizey*0.5);
rect(rectx*0.5, recty, sizex*0.1, sizey*0.5);
triangle(tx1, ty1, tx2, ty2, tx3, ty3);
}
// changing shape
if (val.charAt(0)=='c') {
println("yes");
shape = !shape;
} else if (val.charAt(0)=='w') {
}
// reference from https://processing.org/reference/popMatrix_.html
// reset the transformation
popMatrix();
}
popMatrix();
}
serialEvent.pde
/*------reference from http://pulsesensor.com/------*/
/*-------Handle data from arduino--------*/
void serialEvent(Serial port) {
String inData = port.readStringUntil('\n');
if (inData == null) { //return if we didn't get anything
return;
}
if (inData.isEmpty()) { //return if we got an empty line
return;
}
inData = trim(inData); // cut off white space (carriage return)
if (inData.length() <= 0) { // return if there's nothing there
return;
}
if (inData.charAt(0) == 'S') { // leading 'S' for sensor data
inData = inData.substring(1); // cut off the leading 'S'
Sensor = int(inData); // convert the string to usable int
}
if (inData.charAt(0) == 'B') { // leading 'B' for BPM data
inData = inData.substring(1); // cut off the leading 'B'
BPM = int(inData); // convert the string to usable int
}
if (inData.charAt(0) == 'Q') { // leading 'Q' means IBI data
inData = inData.substring(1); // cut off the leading 'Q'
IBI = int(inData); // convert the string to usable int
}
if (inData.charAt(0) == 'c') { // leading 'c' means value of changing shape button
val = inData; // store the value
}
if (inData.charAt(0) == 'w') { // leading 'w' means the wrong value of changing shape button
val = inData; // store the value
}
if (inData.charAt(0) == 'v') { // leading 'v' means data of save button
save = inData; // store the value
}
}
Reference
-
Capture https://processing.org/reference/libraries/video/Capture.html
-
popMatrix() https://processing.org/reference/popMatrix_.html
-
pushMatrix() https://processing.org/reference/pushMatrix_.html
-
Serial from the lecture note
-
Pulse Sensor http://pulsesensor.com/