John Brieger — Face OSC

by John Brieger @ 6:49 am 24 January 2012

[vimeo=35562537 w=605&h=400]

Uses Face_OSC to do facial recognition, smiling and mouth movement to control an array of LED’s that respond in real time to facial features. Raising your eyebrows flashes the lights on the back of the collar in rapid succession, letting everyone around know if you are surprised or angry.

The dress itself is part of a fashion collaboration between myself and Alanna Fusaro. You can see our full line here.

Sorry for the rendering issues in the video.

Processing Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// John Brieger
// IACD 2012
//
//
//
// Facetracking through:
// Kyle McDonald's FaceOSC https://github.com/kylemcdonald/ofxFaceTracker
//
// this example includes a class to abstract the Face data
//
// 2012 Dan Wilcox danomatika.com
// for the IACD Spring 2012 class at the CMU School of Art
//
// adapted from from Greg Borenstein's 2011 example
// http://www.gregborenstein.com/
// https://gist.github.com/1603230
 
import oscP5.*;
import processing.serial.*;
Serial port = null;
OscP5 oscP5;
 
// our FaceOSC tracked face dat
Face face = new Face();
 
void setup() {
  size(600, 720);
  frameRate(30);
 
  //setup serial connection to Arduino
  println("Available serial ports:");
  String[] serialList =Serial.list();
  println(serialList);
  if(serialList.length != 0)
  {
  port = new Serial(this, serialList[0], 9600);
  }
  else
    println("No Available Serial Ports!");
  oscP5 = new OscP5(this, 8338);
}
 
void draw() {  
  background(255);
  stroke(0);
  if (port == null)
  {
     //check for available serial ports
     String[] serialList =Serial.list();
     if(serialList.length != 0)
      {
       println("Found Serial Port!");
       println(serialList);
       println("\n");
      port = new Serial(this, serialList[0], 9600);
      }
  }
  if (face.found > 0)
  {
   // write data out to port
    if(port != null)
    {
    port.write('Y');
    float browHeightAvg = (face.eyebrowLeft + face.eyebrowRight) /2.0;
    if(browHeightAvg >= 8.0)    {
        print("Brow Raised!");
        port.write('^');
    }
    else   {
      port.write('_');  
    }
    port.write('B');
 
    //mouth is a formula based off sqrt of area
    float mouthArea= face.mouthWidth * face.mouthHeight;
    float sqr = sqrt(mouthArea);
    byte mouthSend = (byte)((int)sqr);
    port.write(mouthSend);
    println("Mouth Sent: "+mouthSend);
    port.write('M');
    }
  print(face.toString());
  }
  else
  {
    //no face
    if(port != null)
    {
    port.write('N');
    }
  }
}
 
// OSC CALLBACK FUNCTIONS
 
void oscEvent(OscMessage m) {
  face.parseOSC(m);
}

Arduino Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
int currentPattern;
const int DEFAULTPATTERN = 0;
const int FACEPATTERN = 1;
int ledArray[14];
int currentLED;      // the number of the LED pin
int index;
int updown= 1;
long previousMillis = 0;        // will store last time LED was updated
long interval = 125;           // interval at which to blink (milliseconds)
 
int noFaceCount = 0;
int noRaiseCount = 0;
 
char buff[]= "0000000000";  //charbuff for serial
boolean browRaise = false;
int mouthPin = 3;
int browPin = 10;
boolean brow = false;
int mouth = 12;
void setup() {
  // set the digital pins as output:
  pinMode(0, OUTPUT);  
  pinMode(1, OUTPUT);  
  pinMode(2, OUTPUT);      
  pinMode(3, OUTPUT);      
  pinMode(4, OUTPUT);      
  pinMode(5, OUTPUT);      
  pinMode(6, OUTPUT);      
  pinMode(7, OUTPUT);      
  pinMode(8, OUTPUT);  
  pinMode(9, OUTPUT);     
  pinMode(10, OUTPUT);   
  pinMode(11, OUTPUT);   
  pinMode(12, OUTPUT);   
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  updown = 1;
  index = 0;
  currentLED =0;
  currentPattern = DEFAULTPATTERN;
}
 
void loop()
{
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   
    while( Serial.available() > 0)
    {
      for (int i=0; i= 10)
          {
            browRaise = false; 
          }
        }
        break;
      case 'M':
        mouthPin = (int)(buff[9]);
        if (mouthPin>9){
           mouthPin = 9; 
        }
        break;
      case 'Y':
        if(currentPattern == DEFAULTPATTERN)
        {
          for(int i = 0; i = 40){
          //turn all off;
          if(currentPattern == FACEPATTERN)
          {
            for(int i = 0; i <=13; i++)
            {
              digitalWrite(i, LOW); 
            }
            updown = 1;
            currentLED = 0;
            index = 0;
          }
          currentPattern = DEFAULTPATTERN;
        }
        break;       
      }
 
    }
 
    //HERE BE PATTERNS!
    //PATTERNTASTIC!
    if(currentPattern == DEFAULTPATTERN)
    {
      if(updown == 1)   {
        if(currentLED != 0)     {
          digitalWrite(currentLED-1, LOW);
        }
        index++;
        if(index == 13)     {
          updown = -1;
        }
      }
      else
      {
        if(currentLED != 13)    {
          digitalWrite(currentLED+1, LOW);
        }
        index--;
        if(index == 0)    {
          updown = 1;
        }
      }
      //currentLED= ledArray[index];
      currentLED=index;
      // set the LED with the ledArraytate of the variable:
      digitalWrite(currentLED, HIGH);
      delay(125);
    }
 
    //YAY FACES
    else if(currentPattern == FACEPATTERN){
      for(int i = 0; i<= mouthPin; i++){
        digitalWrite(i, HIGH); 
      }
      for( int i =mouthPin+1; i<10;i++)
      {
       digitalWrite(i,LOW); 
      }
      if(browRaise)     {
        digitalWrite(currentLED, LOW);
        if(updown == 1)   {        
          index++;
          if(index == 13)  {
            updown = -1;
          }
        }
        else      {
          index--;
          if(index == 10) {
            updown = 1;
          }
        }
        currentLED = index;
        digitalWrite(currentLED, HIGH);        
      }
      else{
       digitalWrite(11, LOW);
       digitalWrite(12, LOW);
       digitalWrite(13, LOW);
       digitalWrite(10, HIGH);
      }
    }
  }
}

Duncan Boehle – FaceOSC

by duncan @ 6:27 am

[youtube=https://www.youtube.com/watch?v=MIyjMMm55Xo]

 

For this project, I adapted a previously-existing game (a couple friends and I made it during a 24-hour game jam) to handle controls using FaceOSC.

The game is based around manipulating gravity in order to jump on platforms and push blocks to reach the end of each puzzle room. The character is controlled using the arrow keys, and if the player wants to change the direction of gravity, he/she must first pause the game, then select the direction with an arrow key. In order to prevent the second use of arrow keys and the delay, I use FaceOSC to detect the orientation of the player’s face in order to determine what direction they want gravity to pull.

Unfortunately, there are some puzzles that require precise timing, and rotating the head can easily lose FaceOSC’s tracking, which can only be reacquired if the face isn’t rotated. I found that during testing, it did help players to have the pause feature so they could avoid rapidly tilting their head, so in keeping with the FaceOSC theme, I pause gravity if the player raises his/her eyebrows. FaceOSC tracks eyebrows surprisingly quickly and accurately, so this gives the player much more precise control.

The game works fairly well with the face tracking, but unfortunately Flash cannot directly communicate with FaceOSC. Because Flash doesn’t accept the UDP traffic that OSC is based on, I needed to set up an intermediate server (in Java: http://benchun.net/flosc/) to receive the UDP packets from FaceOSC and send them along to Flash via TCP on an XMLSocket. This ultimately means that I would need to distribute both FaceOSC and the Java server to players, make sure their Flash networking security settings are correct, and make sure they can run the command line Java server. For the moment, it remains mostly experimental, but a project trying to achieve this mechanic with a better distribution model would be better off statically linking with OpenCV’s face detection.

Go here to play the original version of the game (without face tracking).

Sarah Keeling; FaceOSC

by sarah @ 5:04 am

For my FaceOSC project I wanted to do something that interacted with video. I thought it could be an interesting experience if while you were watching a movie, your facial reactions in response to the movie affected how it played. My version is a bit glitchy and there are some parts commented out that I would really have liked to get working. So far what I have is: the location of the “face” controls the speed and direction which the video is played back, opening the mouth draws a rectangle of color over the entire screen from a pixel from the movie file and by raising the eyebrows the movie is paused. (Unfortunately this is really hard to see on the video but it does work!) I found a really interesting piece of code on the Processing Forums that was using incoming video stream and mousePressed to ripple the video and was hoping to get this same effect by blinking the eyes, but I’m still working on getting this part running. Also, I was trying to get other clips to works such as the the famous shower scene from “Psycho”, but I’m still working on them too.

Sorry, the second link is a bit long (and crappy) but it shows the mouth variables.

//SarahKeeling's FaceOSC project for Golan Levin's IACD, CMU Spring 2012
// a template for receiving face tracking osc messages from
// Kyle McDonald's FaceOSC https://github.com/kylemcdonald/ofxFaceTracker
//
// this example includes a class to abstract the Face data
//
// 2012 Dan Wilcox danomatika.com
// for the IACD Spring 2012 class at the CMU School of Art
//
// adapted from from Greg Borenstein's 2011 example
// http://www.gregborenstein.com/
// https://gist.github.com/1603230
//

import processing.video.*;
Movie myMovie;

import oscP5.*;
OscP5 oscP5;

// our FaceOSC tracked face dat
Face face = new Face();

void setup() {
  size(600, 600);
  frameRate(30);

  oscP5 = new OscP5(this, 8338);

  //myMovie =new Movie (this, "lenlye_colourbox.mov");
  //myMovie =new Movie (this, "testVid.mov");
  //myMovie =new Movie (this, "psycho_showerscene_evensmaller.mov");
  //myMovie =new Movie (this, "vimeo_abstract_sm.mov");
  //myMovie =new Movie (this, "NotWhatIPaidFor.mov");

  myMovie.play ();

  loadPixels ();
  myMovie.loadPixels ();
}

void draw() {  
  background(255);

  image (myMovie, 0, 0);

  float newSpeed = map (face.posePosition.x, 0, 600, -1.0, 2.0);

  myMovie.speed (newSpeed);

  if (face.eyebrowLeft > 8.4) {
    myMovie.pause ();
  }
  else {
    myMovie.play ();
  }

  if (face.mouthHeight > 2) {
    int col;
    col = myMovie.get (50, 50);
    noStroke ();
    fill (col);
    rect (20, 20, myMovie.width, myMovie.height);
  }


  /*
  if(face.found > 0) {
   translate(face.posePosition.x, face.posePosition.y);
   scale(face.poseScale);
   noFill();
   ellipse(-20, face.eyeLeft * -9, 20, 7);
   ellipse(20, face.eyeRight * -9, 20, 7);
   ellipse(0, 20, face.mouthWidth* 3, face.mouthHeight * 3);
   ellipse(-5, face.nostrils * -1, 7, 3);
   ellipse(5, face.nostrils * -1, 7, 3);
   rectMode(CENTER);
   fill(0);
   rect(-20, face.eyebrowLeft * -5, 25, 5);
   rect(20, face.eyebrowRight * -5, 25, 5);
   */
  print(face.toString());
}


// OSC CALLBACK FUNCTIONS

void oscEvent(OscMessage m) {
  face.parseOSC(m);
}

void movieEvent (Movie m) {
  m.read ();
}

Ju Young Park – FaceOSC

by ju @ 5:03 am

For this project, I have created Face Turntable using Processing and FaceOSC. In this program, processing reads face signals from FaceOSC and use them to mix sound through changing playing rates and volumes as if a user is a DJ who plays a song with turn table. For instance, a user’s mouth width and height control the speeding rates of playing sound, and a user’s eyebrow left and eyebrow right control the volume of playing sound.

For a demo, I chose a random electronic song, called La Musica Electronica. I personally do not know the DJ who made this song, and I got this song from youtube.

<Still Image>

 

<Video Demo>

[youtube=https://www.youtube.com/watch?v=oBlDh7AajwE]

 

Duncan Boehle – 13-9-65

by duncan @ 4:59 am

This is my attempt at generating pieces of art that follow the convents of Frieder Nake’s work 13/9/65. Press any key to continually generate more random versions.

//
// Duncan Boehle
// Emulation of 13/9/65 - Nake
//
 
int minCols = 6;
int maxCols = 8;
int minRows = 8;
int maxRows = 12;
int minCircles = 4;
int maxCircles = 8;
int minRadius = 3;
int maxRadius = 50;
float vertProb = 0.25f;
float crossProb = 0.35f;
int sideSize = 550;
int sideBuffer = 8;
 
ArrayList heightRows;
 
// ArrayList of rows, which is length "rows", and each
// element is an ArrayList of length "cols"
// each element of this inner ArrayList is a Box
Box[][] boxes;
 
int numRows;
int numCols;
int[] colMinXs;
int[] rowStartYs;
 
ArrayList circles;
 
void setup() {
  size(566, 566);
  smooth();
  stroke(0);
  strokeWeight(1.5);
  noFill();
 
  drawNake();
}
 
public void drawNake() {
 
  background(255);
 
  heightRows = new ArrayList();
  numRows = int(random(minRows, maxRows));
  numCols = int(random(minCols, maxCols));
  boxes = new Box[numRows][numCols];
 
  colMinXs = makePosArray(numCols, sideBuffer, sideSize + sideBuffer, 1.0f, 3.0f);
  rowStartYs = makePosArray(numRows, sideBuffer, sideSize + sideBuffer, 1.0f, 2.5f);
 
  for (int y = 0; y &lt;= numRows; y++) {
    ArrayList row = new ArrayList();
    int rowHeight = y &lt; numRows ? rowStartYs[y] : (sideSize + sideBuffer);
    row.add(rowHeight);
    for (int x = 0; x  0 &amp;&amp; y &lt; numRows) {
        rowHeight += int(random(-12, 12));
      }
      row.add(rowHeight);
    }
 
    heightRows.add(row);
  }
 
  rect(sideBuffer, sideBuffer, sideSize, sideSize);
 
  for (int y = 0; y &lt; numRows; y++) {
    ArrayList topRowHeightRow = (ArrayList)heightRows.get(y);
    ArrayList botRowHeightRow = (ArrayList)heightRows.get(y + 1);
    for (int x = 0; x &lt; numCols; x++) {
      int minX = colMinXs[x];
      int maxX = (x &lt; numCols - 1) ? colMinXs[x + 1] : (sideSize + sideBuffer);
      int ulY = (Integer)topRowHeightRow.get(x);
      int urY = (Integer)topRowHeightRow.get(x + 1);
      int blY = (Integer)botRowHeightRow.get(x);
      int brY = (Integer)botRowHeightRow.get(x + 1);
 
      line(minX, ulY, maxX, urY);
      //line(minX, ulY, minX, blY);
      //line(maxX, urY, maxX, brY);
      line(minX, blY, maxX, brY);
 
      float rand = random(0.0f, 1.0f);
      int type = Box.TYPE_EMPTY;
      if (rand &lt; vertProb)
        type = Box.TYPE_VERTICAL;
      else if (rand  0) {
        Box boxAbove = boxes[y - 1][x];
        if (type == Box.TYPE_VERTICAL &amp;&amp; boxAbove.type == Box.TYPE_VERTICAL) {
          newBox = boxAbove;
        }
      }
 
      if (newBox == null) {
        newBox = new Box(type, int(random(1, 5)));
      }
      newBox.draw(minX, maxX, ulY, urY, blY, brY);
      boxes[y][x] = newBox;
    }
  }
 
  int numCircles = int(random(minCircles, maxCircles));
  circles = new ArrayList();
  for (int i = 0; i &lt; numCircles; i++) {
    int rad = int(random(minRadius, maxRadius));
    int x = int(random(2 * sideBuffer + rad, sideSize - rad));
    int y = int(random(2 * sideBuffer + rad, sideSize - rad));
    Circle circle = new Circle(x, y, rad);
 
    boolean intersects = false;
    for (int c = 0; c &lt; circles.size(); c++) {
      Circle otherCircle = (Circle)circles.get(c);
      if (circle.intersects(otherCircle)) {
        intersects = true;
        break;
      }
    }
 
    if (!intersects) {
      circles.add(circle);
      ellipse(x, y, rad * 2, rad * 2);
    }
  }
}
 
public int[] makePosArray(int num, int minN, int maxN, float minRat, float maxRat) {
  float[] ratioList = new float[num];
  float totalRat = 0.0f;
  for (int i = 0; i &lt; num; i++) {
    float ratio = random(minRat, maxRat);
    ratioList[i] = ratio;
    totalRat += ratio;
  }
 
  int curN = minN;
  int[] pixelList = new int[num];
  for (int i = 0; i &lt; num; i++) {
    pixelList[i] = curN;
    float ratio = ratioList[i];
    ratio /= totalRat;
    curN += ratio * (maxN - minN);
  }
 
  return pixelList;
}
 
void draw() {
  if (keyPressed) {
    drawNake();
  }
}
 
class Box {
 
  public static final int TYPE_EMPTY = 0;
  public static final int TYPE_VERTICAL = 1;
  public static final int TYPE_CROSSED = 2;
 
  public int type;
  public int maxDegree;
  public ArrayList topRow;
  public ArrayList bottomRow;
 
  public Box(int type, int maxDegree) {
    this.type = type;
    this.maxDegree = maxDegree;
    topRow = new ArrayList();
    bottomRow = new ArrayList();
 
    switch (type) {
      case TYPE_EMPTY:
        break;
      case TYPE_VERTICAL:
        fillRow(topRow, 2, 16);
        break;
      case TYPE_CROSSED:
        fillRow(topRow, 2, 16);
        fillRow(bottomRow, 2, 16);
        break;
      default:
        break;
    }
  }
 
  public void draw(int minX, int maxX, int ulY, int urY, int blY, int brY) {
 
    switch (type) {
      case TYPE_EMPTY:
        break;
      case TYPE_VERTICAL:
        // for each point along the line, draw a vertical line to the bottom
        for (int i = 0; i &lt; topRow.size(); i++) {
          float n = (Float)topRow.get(i);
          float x = lerp(minX, maxX, n);
          float topY = lerp(ulY, urY, n);
          float bottomY = lerp(blY, brY, n);
          line(x, topY, x, bottomY);
        }
        break;
      case TYPE_CROSSED:
        // for each point along the top row, draw a random number of lines
        // to points in the bottom row
        for (int i = 0; i &lt; topRow.size(); i++) {
          float topN = (Float)topRow.get(i);
          float topX = lerp(minX, maxX, topN);
          float topY = lerp(ulY, urY, topN);
 
          int outDegree = int(random(1, maxDegree));
          for (int j = 0; j &lt; outDegree; j++) {
            int randIndex = int(random(0, bottomRow.size()));
            float botN = (Float)bottomRow.get(randIndex);
            float botX = lerp(minX, maxX, botN);
            float botY = lerp(blY, brY, botN);
            line(topX, topY, botX, botY);
          }
        }
        break;
      default:
        break;
    }
 
  }
 
  public void fillRow(ArrayList inList, int minEls, int maxEls) {
    int numEls = (int)random(minEls, maxEls);
    inList.clear();
 
    for (int i = 0; i &lt; numEls; i++) {
      inList.add(random(0.0f, 1.0f));
    }
 
    return;
  }
}
 
class Circle {
  public int x;
  public int y;
  public int rad;
 
  public Circle(int x, int y, int rad) {
    this.x = x;
    this.y = y;
    this.rad = rad;
  }
 
  public boolean intersects(Circle other) {
    int xdiff = other.x - x;
    int ydiff = other.y - y;
    float distance = sqrt(xdiff * xdiff + ydiff * ydiff);
 
    return distance &lt; (other.rad + rad);
  }
}

Sarah Keeling; 13-9-65

by sarah @ 4:55 am

gauntlet_part1_try5

Click to generate different variations.
 

 

//Sarah Keeling's reproduction of Frieder Nake's 13/9/65 
//for Golan Levin's IACD at Carnegie Mellon University, Spring 2012

PVector line0 [];
PVector line1 [];
PVector line2 [];
PVector line3 [];
PVector line4 [];
PVector line5 [];
PVector line6 [];
PVector line7 [];
PVector line8 [];
PVector line9 [];

void setup() {
  size(600, 600);
  strokeWeight( 2 );
  smooth();
  background (255);
  frameRate (10);
}

void mousePressed() {
  loop();
}

void draw () {

  line0 = drawHLine( -20 ); 
  drawDiagonalLines( line0, line1, 4);

  line1 = drawHLine( 40 ); 
  drawVerticalLines( line1, line2, (int) random (3, 4) ); 
  drawDiagonalLines( line1, line2, 1 ); 
  drawDiagonalLines( line1, line2, (int) random (3) );
  drawDiagonalLines( line1, line2, (int) random (3, 5)); 

  line2 = drawHLine( 120 ); 
  drawVerticalLines( line2, line3, 1 ); 
  drawVerticalLines( line2, line3, (int)random (2, 4) ); 
  drawDiagonalLines( line2, line3, (int) random (3, 4)); 

  line3 = drawHLine( 220 ); 
  drawVerticalLines( line3, line4, (int) random (1)); 
  drawDiagonalLines( line3, line4, (int) random(2));
  drawDiagonalLines( line3, line4, (int) random(3, 5));

  line4 = drawHLine( 268 );
  drawVerticalLines( line4, line5, 1 ); 
  drawDiagonalLines( line4, line5, (int) random(2));
  drawDiagonalLines( line4, line5, (int) random(3, 5));

  line5 = drawHLine( 340 );
  drawVerticalLines( line5, line6, (int) random (3)); 
  drawVerticalLines( line5, line6, 3); 
  drawDiagonalLines( line5, line6, (int) random(1));
  drawDiagonalLines( line5, line6, (int)random (3, 4));

  line6 = drawHLine( 390 );
  drawVerticalLines( line6, line7, 2); 
  drawDiagonalLines( line6, line7, (int)random (4));

  line7 = drawHLine( 460 );
  drawVerticalLines( line7, line8, (int) random (2, 4)); 
  drawDiagonalLines( line7, line8, (int)random (2));
  drawDiagonalLines( line7, line8, 0 );

  line8 = drawHLine( 560 );
  drawDiagonalLines( line8, line9, (int)random(2, 4));

  line9 = drawHLine( 650 );


  circles ( 60, 3);
  circles ( 120, 5);

  noLoop();
}

void drawVerticalLines( PVector[] top, PVector[] bottom, int segment) {

  PVector left = top[segment];
  PVector right = top[segment+1];

  noStroke();
  // fill( #FF0000 );
  //ellipse( left.x, left.y, 8, 8);

  int numberOfLines = 20;

  strokeWeight( 1);
  stroke( #000000 ); 
  for ( int i = 0; i< numberOfLines; i++ ) {
    PVector temp = new PVector( (right.x - left.x), (right.y - left.y) );

    float whereItGoes = random(1);    
    line( (temp.x * whereItGoes + left.x), (temp.y * whereItGoes + left.y), 
    (temp.x * whereItGoes + left.x), (temp.y * whereItGoes + left.y) + 200 );
  }
}

void drawDiagonalLines( PVector[] top, PVector[] bottom, int segment) {

  PVector left = top[segment];
  PVector right = top[segment+1];

  noStroke();

  int numberOfLines = 20;

  strokeWeight( 1);
  stroke( #000000 ); 
  for ( int i = 0; i< numberOfLines; i++ ) {
    PVector temp = new PVector( (right.x - left.x), (right.y - left.y) );

    float whereItGoes = random(1);
    line( (temp.x * whereItGoes + left.x), (temp.y * whereItGoes + left.y), 
    (temp.x * (1-whereItGoes + random(.5)) + left.x), (temp.y * whereItGoes +
      left.y) + 150 );
  }
}


PVector[] drawHLine( int yStart ) {

  stroke (0);
  PVector [] tempLine = new PVector[9];
  PVector start = new PVector( 0, yStart );
  tempLine[0] = start;

  fill(255);
  beginShape();
  for ( int i = 0; i< 8; i++ ) {
    PVector next = new PVector( start.x + (int)random( 200 )+50, start.y +
      (int)random(30) - 20);     
    tempLine[i+1] = next ;

    if (i==0) {
      vertex (start.x, start.y);
    } 
    vertex (next.x, next.y );

    start = next;
  }

  vertex (600, 600);
  vertex (0, 600);
  endShape();

  return tempLine;
}

void circles ( int circleSize, int numCircles ) {
  int tempsize;
  stroke (0);
  strokeWeight (1);

  noFill ();
  strokeWeight (1);
  stroke (0);

  for ( int i = 0; i< numCircles; i++ ) {

    tempsize = (int) random ( 10, circleSize );

    if (tempsize/2 < width- tempsize/2) {
      
      ellipse( random( 0, width ), random( 0, height), tempsize, tempsize);
    }
  }
}



Ju Young Park – 13-9-65

by ju @ 4:47 am

As a practice for this course, I have tried to reproduce the image  “13-9-65” exactly same as much as possible by utilizing Processing.

 

Nir Rachmel | FaceOSC

by nir @ 4:30 am

In the following project, we were asked to do something “cool” with FaseOSC and Processing. I designed an interaction that allows the user to use his face to search for queries on twitter.

Once the user starts, he is presented with two pairs of opposite terms and the word “myself” in the middle. The pairs of words always change and are randomly selected. But the user can always look for tweets that have the word “myself”. Moving the user’s head, moves the cursor on the screen. The further the face goes, the bigger the pointer gets.

In order to select a word (“click”), the user has to open his mouth. Then he is transferred to another screen where he sees that query result. Hope you enjoy it!

[vimeo https://vimeo.com/35558848]

MahvishNagda-FaceOSC

by mahvish @ 3:59 am

 

 

I wanted to use FaceOsc and Processing to create something playful. So I decided to use the data I get from FaceOsc to simulate window fog. The intention was to simulate what happens when you blow on your car window on a cold day. The window fogs up when you open up your mouth (using the ratio of your mouth height to width) and the dimensions of the fogging are controlled by your distance to the camera. I then wanted to draw on the fog, so I used touchOsc’s xy-pad on my iPad. When you’re not blowing on the window, the fog and lines fade away.

A lot of the simulation of the fogging (aka randomness) is inspired from Matt Pearson’s 100 Abandoned Art project: http://abandonedart.org/ . As you open your mouth, the application draws a circle on top of the previous circle. Each circle is actually drawn as a shape with each point on the circle connected by smoothed lines. To create a more realistic effect, I randomized each x-y points around the circle. Figuring out the right parameters for the randomization and the right values took a little bit of time: making it look frosty but not too frosty. It took a little bit of time to also tweak the rate at which shapes were drawn and faded away. The biggest challenge was fading the fog away gracefully. Since layers/shapes are stacked on top of each other, when the combined opacity level for multiple of the shapes reach 255, they all merge into one. When that “255” layer fades away, the effect is of one big blob disappearing. To work around that, I first tried collecting all the shapes I had drawn and redrawing all of them at each frame. This was computationally intensive and too slow. Instead, I finally figured out that I could simulate the effect by just overlaying the shapes that I had collected during the fade, which works well enough.

EliRosen – FaceOSC

by eli @ 3:29 am

[youtube https://www.youtube.com/watch?v=LCVDSafRvH8&w=600&h=437]
I used the FaceOSC data to animate a simple puppet of an old man. I put the puppet together in photoshop from an image I found on google images. The old man’s glasses move up and down in response to the user moving his eyebrows. The user also controls the old mans mouth. When the puppet opens its mouth it spews colorful balls towards the screen.

// A puppet by Eli Rosen based on
// a template for receiving face tracking osc messages from
// Kyle McDonald's FaceOSC https://github.com/kylemcdonald/ofxFaceTracker
//
// 2012 Dan Wilcox danomatika.com
// for the IACD Spring 2012 class at the CMU School of Art
//
// adapted from from Greg Borenstein's 2011 example
// http://www.gregborenstein.com/
// https://gist.github.com/1603230
//
import oscP5.*;
OscP5 oscP5;
 
// num faces found
int found;
 
// pose
float poseScale;
PVector posePosition = new PVector();
PVector poseOrientation = new PVector();
 
// gesture
float mouthHeight;
float mouthWidth;
float eyeLeft;
float eyeRight;
float eyebrowLeft;
float eyebrowRight;
float jaw;
float nostrils;
//variables for puppet images
PImage face;
PImage glasses;
PImage chin;
 
//variable to store last eyebrow value (for reducing jitter)
float eyebrowLast = eyebrowRight;
 
//array of particle positions
PVector[] pArray = new PVector[1];
//array of particle sizes
float[] pSize = new float[1];
//particle color array
color[] pColor = new color[1];
 
void setup() {
  size(640, 480);
  frameRate(30);
  oscP5 = new OscP5(this, 8338);
  oscP5.plug(this, "found", "/found");
  oscP5.plug(this, "poseScale", "/pose/scale");
  oscP5.plug(this, "posePosition", "/pose/position");
  oscP5.plug(this, "poseOrientation", "/pose/orientation");
  oscP5.plug(this, "mouthWidthReceived", "/gesture/mouth/width");
  oscP5.plug(this, "mouthHeightReceived", "/gesture/mouth/height");
  oscP5.plug(this, "eyeLeftReceived", "/gesture/eye/left");
  oscP5.plug(this, "eyeRightReceived", "/gesture/eye/right");
  oscP5.plug(this, "eyebrowLeftReceived", "/gesture/eyebrow/left");
  oscP5.plug(this, "eyebrowRightReceived", "/gesture/eyebrow/right");
  oscP5.plug(this, "jawReceived", "/gesture/jaw");
  oscP5.plug(this, "nostrilsReceived", "/gesture/nostrils");
  //load the puppet images
  face = loadImage("face.png");
  glasses = loadImage("glasses.png");
  chin = loadImage("chin.png");
  //set color mode to HSB
  colorMode(HSB, 255);
  smooth();
 
}
 
void draw() {  
  background(255);  
  if(found &gt; 0) {
    //center and scale the elements
    translate(posePosition.x, posePosition.y);
    scale(poseScale*.8);
    //draw the face
    image(face, -45, -65,face.width*.25, face.height*.25);
    //save the new eyebrow position
    float eyebrowNew = eyebrowRight;
    //get the difference between the old eyebrow position and the new one
    float eyebrowDif = eyebrowNew - eyebrowLast;
    // check if the eyebrow moved beyond a certain threshold
    if(Math.abs(eyebrowDif) &gt; .35)
    {
      //if it did then draw it with the new position
      image(glasses, -29, /*-10*/(eyebrowNew*-4)+22,glasses.width*.25, glasses.height*.25);
      //update the last eyebrow variable
      eyebrowLast = eyebrowNew;
    }
    // if eyebrows did not move enough redraw the glasses in the same position as last time
    else
    {
      image(glasses, -29, /*-10*/(eyebrowLast*-4)+22,glasses.width*.25, glasses.height*.25);
    }
    // draw the chin based on jaw position
    image(chin, -14, jaw*1.6,chin.width*.25, chin.height*.25);
 
    // check if the jaw is open
    if(jaw &gt; 22)
    {
      //generate a random hue number
      int randomHue = int(random(0,256));
      // get a random x and y that fall within the mouth area
      float xPos = random(-2,14);
      float yPos = random(36,40);
      // use the random hue to create a color
      color fillColor = color(randomHue,200,40);
      // create a new pVector and store the random x and y
      PVector p = new PVector(xPos, yPos);
      // create temporary arrays for copying the current arrays
      PVector[] tempArray = new PVector[pArray.length+1];
      float[] tempArray2 = new float[pSize.length+1];
      color[] tempArray3 = new color[pColor.length+1];
      // copy the current particle attribute arrays
      for (int i = 0; i &lt; pArray.length; i++)
      {
        tempArray[i] = pArray[i];
        tempArray2[i] = pSize[i];
        tempArray3[i] = pColor[i];
      }
      // set the global arrays to be the new updated arrays
      pArray = tempArray;
      pSize = tempArray2;
      pColor = tempArray3;
      // add the new Pvector to the pvector array
      pArray[pArray.length-1] = p;
      // add the new color to the color array
      pColor[pColor.length-1] = fillColor;
      // set the drawing style for the new particle
      noStroke();
      fill(fillColor);
      // set the size of the new particle
      float newSize = 2;
      // add the new particle size to the particle size array
      pSize[pSize.length-1]=newSize;
      // draw the new particle
      ellipse(p.x,p.y,newSize,newSize);
    }
 
    // loop through all particles
    for(int i=1; i &lt; pArray.length; i++)
    {
      // move the particles y positions down
      pArray[i].y =  pArray[i].y + random(1,3);
      // get the particles distance from the center of the face
      float xDif = Math.abs(pArray[i].x - 6);
      // if the particle is to the left of center move it further left
      if(pArray[i].x &lt;=6)
      {
        // base magnitude of move on distance from center
        pArray[i].x =  pArray[i].x - random(1,3)*.05*xDif;
      }
      // if particle is to the right of center move it further right
      else
      {
        // base magnitude of move on distance from center
        pArray[i].x =  pArray[i].x + random(1,3)*.05*xDif;
      }
      // increase the size of the particle
      pSize[i]= pSize[i]+random(0,1);
      // brighten the particle
      float tempH = hue(pColor[i]);
      float tempS = saturation(pColor[i]);
      float tempB = brightness(pColor[i])+13;
      pColor[i] = color(tempH, tempS, tempB);
      // set fill color to new brighter color 
      fill(pColor[i]);
      // draw the particle with all updated attributes
      ellipse(pArray[i].x, pArray[i].y, pSize[i], pSize[i]);
    }
  }
}
 
// OSC CALLBACK FUNCTIONS
 
public void found(int i) {
  println("found: " + i);
  found = i;
}
 
public void poseScale(float s) {
  println("scale: " + s);
  poseScale = s;
}
 
public void posePosition(float x, float y) {
  println("pose position\tX: " + x + " Y: " + y );
  posePosition.set(x, y, 0);
}
 
public void poseOrientation(float x, float y, float z) {
  println("pose orientation\tX: " + x + " Y: " + y + " Z: " + z);
  poseOrientation.set(x, y, z);
}
 
public void mouthWidthReceived(float w) {
  println("mouth Width: " + w);
  mouthWidth = w;
}
 
public void mouthHeightReceived(float h) {
  println("mouth height: " + h);
  mouthHeight = h;
}
 
public void eyeLeftReceived(float f) {
  println("eye left: " + f);
  eyeLeft = f;
}
 
public void eyeRightReceived(float f) {
  println("eye right: " + f);
  eyeRight = f;
}
 
public void eyebrowLeftReceived(float f) {
  println("eyebrow left: " + f);
  eyebrowLeft = f;
}
 
public void eyebrowRightReceived(float f) {
  println("eyebrow right: " + f);
  eyebrowRight = f;
}
 
public void jawReceived(float f) {
  println("jaw: " + f);
  jaw = f;
}
 
public void nostrilsReceived(float f) {
  println("nostrils: " + f);
  nostrils = f;
}
 
// all other OSC messages end up here
void oscEvent(OscMessage m) {
  if(m.isPlugged() == false) {
    println("UNPLUGGED: " + m);
  }
}
« Previous PageNext Page »
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2023 Interactive Art and Computational Design, Spring 2012 | powered by WordPress with Barecity