This weeks assignment for Computational Cameras includes using the Kinect, and also proposing a project for our midterm. Since my midterm project is an offshoot of my Kinect project for this week, I will start with my proposal:
Kinect Midterm Proposal: Conducting the Sunrise / Sunset
In the children’s book The Phantom Tollbooth, there is a character named Chroma the Great who is responsible for conducting the conditions of the sky (Sunrise, Sunset, Thunderstorms, etc).
In short, I would like to create a Kinect/Processing/Java sketch to enable the user to “conduct” the sunrise or sunset similarly to Chroma, without the use of a baton . I plan to keep track of where the user has his or her hands, and then time how long it takes them to move between locations on the screen to determine how the sky changes / what sounds are played.
I am still undecided on the exact way to map the movement onto the sound component. One possibility has the tempo of a piece of music related to the difference in time between they will be mapped to the tempo of a song playing, with longer times between motions equate to a slower tempo of music. Another possibility is to have a sequence of notes and progress through the sequence based on which zones are hit in a specific order.
What I have for this week for my Kinect project assignment is the color sequencing. As of now, the color changes once the user enters a certain zone (two zones are mapped to blue, and one each to red and green). The individual color component is increased each time the zone is breached, but is a discrete color increase rather than a continuous one. As the user waves their arms in a somewhat conductor-like pattern, the color slowly gets closer to the toggled skylight setting (RGB values were selected for both complete sunrise and sunset).
I’m still working on the placement of the triggering zones so that it encourages a more natural conductor motion, but also allows the user to play freely with the transition from day to night and back again.
Again, note to self…better screen capture software (taking recommendations):
And the code (starting to appreciate Java for the ability to hide functions..makes everything so much smaller)
package kinecting;
import org.openkinect.processing.Kinect;
import processing.core.PApplet;
import processing.core.PImage;
public class sunrise1 extends PApplet {
/* This sketch is meant to mimic Chroma the Great from The Phantom Tollbooth
* in that the user controls the state of the sky. By waving his or her arms in
* a consistent pattern, the sky will slowly fade to darkness, or blaze to light
* mimicking a sunset or sunrise (respectively)
*/
Kinect kinect;
float deg; //deg at which the camera is set
int w = 640;
int h = 480;
int limitr, limitg, limitb; //limits of the RGB spectrum for the sky color, change with
//sunrise vs sunset
int r, g, b, a; //color variables
boolean sunset; //determines the color scheme changes (setting or rising)
boolean ready; //determines if the sky has changed already from touching the box or not
int threshold = 650; //in front of the threshold the sketch looks for the closest point
int rx; // length/width of square zone
int ybottom; //setting the top of the observed zones (bottom 3) , top is one length down, in the middle
public void setup() {
size(w*2, h);
kinect = new Kinect(this);
kinect.start();
kinect.enableDepth(true);
kinect.processDepthImage(true);
ellipseMode(CENTER);
deg = 20;
rx = 100;
ybottom = 250;
r = 25;
g = 25;
b = 112;
sunset = false;
limitr = 135;
limitg = 206;
limitb= 250;
a = 80;
ready = true;
}
public void draw() {
sunlimit(sunset);
PImage img = kinect.getDepthImage();
image(img, 0, 0);
int[] depth = kinect.getRawDepth();
int allX = 0;
int allY = 0;
int all = 0;
int locX = 0;
int locY = 0;
fill(255, 0, 0, 25);
rect(w/2 - rx/2, rx, rx, rx); //top rectangle
rect(w/2 - rx/2, ybottom, rx, rx); //bottom middle rectangle
rect(3 * w/4 - rx, ybottom, rx, rx); //bottom right rectangle
rect(w/4, ybottom, rx, rx); //bottom left rectangle
for (int x = 0; x < w; x ++) {
for (int y = 0; y < h; y ++) {
int offset = x + y * w;
int rawDepth = depth[offset];
if (depth == null) return;
if (rawDepth < threshold) {
allX += x;
allY += y;
all++;
}
}
}
if (all != 0){
locX = allX/all;
locY = allY/all;
int check = intersect(locX, locY);
colorchange(check);
if (check > 0){
fill(0, 255, 0);
}
else {
fill(255, 0, 0);
}
ellipse(locX, locY, 20, 20);
}
fill(r, g, b, a);
//used formerly to change the color based on where on the screen the hand was
// r = (int) map(locX, 0, w, 25, 135);
// g = (int) map(locY, 0, h, 25, 206);
// b = (int) map(locY, 0, h, 112, 250);
rect(w, 0, w * 2, h);
kinect.tilt(deg);
}
public void keyPressed(){
if (key == '+'){
deg++;
}
else if (key== '-'){
deg--;
}
else if (key == 'w'){
sunset =!sunset;
println(sunset);
}
else if (key == 'i'){
threshold--;
}
else if (key == 'o'){
threshold++;
}
else if (key == 'f'){
println(frameRate);
}
else if (key == 'c'){
println(r + " " + g + " " + b);
}
}
public int intersect(int tempX, int tempY){
if (rx+ybottom > tempY && tempY > ybottom){
if (((w/4 + rx) > tempX) && (tempX > (w/4)) ||
((3 * w/4) > tempX) && (tempX > (3 * w/4 - rx))){
return 1; //if touching a blue box, return a 1
}
else if (((w/2 + rx/2) > tempX) && (tempX > (w/2 - rx/2))){
return 2; //if touching the green box, return a 2
}
else{
return 0; //not touching any box
}
}
else if ((2 * rx > tempY) && (tempY > rx)){
if (((w/2 + rx/2) > tempX) && (tempX > (w/2 - rx/2))){
return 3; //if touching the red box, return a 3
}
else{
return 0; //not touching a box
}
}
else{
return 0; //not touching a box
}
}
public void colorchange(int tempX){
int bincrease = 15;
int gincrease = 15;
int rincrease = 15;
if (tempX > 0){
if (ready){
if (tempX == 1){
if (!sunset){
if (b < limitb){ b += bincrease; ready = false; } else { b = limitb; } } else { if (b > limitb) {
b -= bincrease;
ready = false;
}
else{
b = limitb;
}
}
}
else if (tempX == 2){
if (!sunset){
if(g < limitg){ g += gincrease; ready = false; } else{ g = limitg; } } else{ if (g > limitg){
g -= gincrease;
ready = false;
}
else{
g = limitg;
}
}
}
else if (tempX == 3){
if (!sunset){
if (r < limitr){ r += rincrease; ready = false; } else{ r = limitr; } } else { if (r > limitr){
r -= rincrease;
ready = false;
}
else {
r = limitr;
}
}
}
}
}
else if (tempX == 0){
ready = true;
}
}
public void sunlimit(boolean checksun){ //sunrise or sunset
if (!checksun){
limitr = 135;
limitg = 206;
limitb = 250;
}
else{
limitr = 25;
limitg = 25;
limitb = 112;
}
}
public void stop(){
kinect.quit();
super.stop();
}
}