top of page

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

 

 

 

© 2046 by Heart

bottom of page