In this project, I tracked my right hand detected by kinect to create an abstract structure. In the tracking process, the trajectory of the movement of my right hand will be saved in an array list. Besides, I want the thickness of the trajectory to be decided by the speed of my movement. If I move really slow, around my hand, there will be more points drawn randomly, and the range of the randomness will grow as I move really slow. And I used line() and bezier() to connect those points. To enhance the effect, I used the dist() to calculate the distance between the current position of the newest point and several points I draw before. If the result is less than a certain threshold, these the newest point and a previously drawn point will be connect by line. This time the difference in thickness can be really obvious. Besides, I set an sphere in the screen as an switch to turn the drawing processing on and off and a reference object when I move my hand.
Code: Select all
/********************************************************
* MAT265 PROJ.2 Depth Project *
* *
* Junxiang Yao *
* *
* *
* *
* Press S to show / hide the skeleton. *
* *
* Press B to show / hide the reference sphere. *
* *
* Press O to turn on / off the rotation mode. *
* *
* Press R to show / hide the righthand tracking point. *
* *
********************************************************/
import peasy.*;
import peasy.org.apache.commons.math.*;
import peasy.org.apache.commons.math.geometry.*;
import peasy.test.*;
PeasyCam cam;
import processing.opengl.*;
import SimpleOpenNI.*;
SimpleOpenNI kinect;
ArrayList <ArrayList<PVector>> dots = new ArrayList <ArrayList<PVector>> ();
PVector rightHand;
PVector pRightHand;
float pMouseX, pMouseY;
ArrayList <PVector> test = new ArrayList <PVector>();
int frameNum = 0;
ArrayList <PVector> position = new ArrayList <PVector>();
PVector speedChecker;
int tubeWidth = 8;
boolean connect = true;
boolean skeleton = true;
boolean start = false;
boolean isInSphere = false;
boolean ball = true;
boolean left = false;
boolean right = true;
boolean rotate = true;
int r = 150;
int spherePos = 1500;
float angle = 0;
ArrayList <PVector> spherePoints = new ArrayList <PVector>();
int boxSize = 150;
PVector boxCenter = new PVector(0, 0, 1000);
// this will be used for zooming
// start at normal
void setup() {
size(1024, 768, OPENGL);
kinect = new SimpleOpenNI(this);
kinect.enableDepth();
kinect.setMirror(true);
cam = new PeasyCam(this, 4000);
cam.setMinimumDistance(200);
cam.setMaximumDistance(5000);
kinect.enableUser();
rightHand = new PVector(0, 0, 0);
pRightHand = new PVector(0, 0, 0);
}
void draw() {
background(0);
kinect.update();
rotateX(radians(180));
if (rotate) {
if (start) {
rotateY(angle);
angle+= 0.01;
if (angle > TWO_PI) {
angle = 0;
}
}
if (!start&&angle != 0) {
if (angle>PI) {
if (angle>TWO_PI-0.05) {
angle = 0;
rotateY(angle);
} else {
angle+= 0.2;
rotateY(angle);
}
}
if (angle<=PI) {
if (angle<0.05) {
angle = 0;
rotateY(angle);
} else {
angle-= 0.2;
rotateY(angle);
}
}
}
}
// bumped up the translation
// so that scale is better centered
translate(0, 0, 0);
IntVector userList = new IntVector();
kinect.getUsers(userList);
if (ball) {
pushMatrix();
translate(0, 0, spherePos);
noStroke();
fill(255);
if (start) {
fill(200);
}
sphere(r);
popMatrix();
}
//// float boxAlpha = map(depthPointsInBox, 0, 1000, 0, 255);
// translate(boxCenter.x, boxCenter.y, boxCenter.z);
//// fill(255, 0, 0, boxAlpha);
// stroke(255, 0, 0);
// box(boxSize);
//user__________________________________________
if (userList.size() > 0) {
// get the first user
int userId = userList.get(0);
// if we’re successfully calibrated
if ( kinect.isTrackingSkeleton(userId)) {
if (skeleton) {
drawSkeleton(userId);
}
PVector rightHand = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_RIGHT_HAND,
rightHand);
PVector leftHand = new PVector();
kinect.getJointPositionSkeleton(userId,
SimpleOpenNI.SKEL_LEFT_HAND,
leftHand);
stroke(255, 0, 0);
strokeWeight(10);
if (right) {
point(rightHand.x, rightHand.y, rightHand.z);
}
stroke(0, 255, 0);
if (left) {
point(leftHand.x, leftHand.y, leftHand.z);
}
if (dist(rightHand.x, rightHand.y, rightHand.z, leftHand.x, leftHand.y, leftHand.z)<20) {
start = !start;
}
if (dist(rightHand.x, rightHand.y, rightHand.z, 0, 0, spherePos)<r*2-20&&!isInSphere) {
start = !start;
isInSphere = true;
print("switch!");
}
if (dist(rightHand.x, rightHand.y, rightHand.z, 0, 0, spherePos)>=r*2-20) {
isInSphere = false;
}
if (start) {
if (rightHand.x != pRightHand.x || rightHand.y != pRightHand.y || rightHand.z != pRightHand.z) {
// PVector p = new PVector(mouseX, mouseY);
//position.add(p);
float d = dist(rightHand.x, rightHand.y, rightHand.z,
pRightHand.x, pRightHand.y, pRightHand.z);
if (d >= 0 && d < tubeWidth) {
for (int i = 0; i < tubeWidth - d; i+=3) {
position.add(new PVector(rightHand.x+pow(random(d-2*tubeWidth, 2*tubeWidth-d), 1),
rightHand.y+pow(random(d-2*tubeWidth, 2*tubeWidth-d), 1),
rightHand.z+pow(random(d-2*tubeWidth, 2*tubeWidth-d), 1)));
}
}
pRightHand.x = rightHand.x;
pRightHand.y = rightHand.y;
pRightHand.z = rightHand.z;
frameNum = frameCount;
dots.add(position);
position = new ArrayList <PVector>();
}
if (rightHand.x == pRightHand.x && rightHand.y == pRightHand.y && rightHand.z == pRightHand.z) {
position.add(new PVector(rightHand.x+random(-(frameCount-frameNum), (frameCount-frameNum)),
rightHand.y+random(-(frameCount-frameNum), (frameCount-frameNum)),
rightHand.z+random(-(frameCount-frameNum), (frameCount-frameNum))));
}
}
for (int i = 0; i < dots.size (); i++) {
for (int j = 0; j < dots.get (i).size(); j++) {
stroke(255);
point(dots.get(i).get(j).x, dots.get(i).get(j).y, dots.get(i).get(j).z);
float c = dist(dots.get(i).get(j).x, dots.get(i).get(j).y, dots.get(i).get(j).z, 0, 0, spherePos);
if (c < 240) {
if (!connect) {
stroke(0);
}
line(dots.get(i).get(j).x, dots.get(i).get(j).y, dots.get(i).get(j).z, 0, 0, spherePos);
}
if (i<240) {
for (int k = 0; k < i; k+=4) {
for (int l = 0; l < dots.get (k).size(); l+=2) {
PVector p = (PVector) dots.get(k).get(l);
float d = dist(dots.get(i).get(j).x, dots.get(i).get(j).y, dots.get(i).get(j).z, p.x, p.y, p.z);
strokeWeight(1);
if (d < 200) {
if (!connect) {
stroke(0);
}
//if (random(10) < 5) // Skip some lines randomly
line(dots.get(i).get(j).x, dots.get(i).get(j).y, dots.get(i).get(j).z, p.x, p.y, p.z);
}
}
}
} else {
for (int k = i-240; k < i; k+=4) {
for (int l = 0; l < dots.get (k).size(); l+=2) {
PVector p = (PVector) dots.get(k).get(l);
float d = dist(dots.get(i).get(j).x, dots.get(i).get(j).y, dots.get(i).get(j).z, p.x, p.y, p.z);
strokeWeight(1);
stroke(255, 100);
if (d < 200) {
if (!connect) {
stroke(0);
}
//if (random(10) < 5) // Skip some lines randomly
line(dots.get(i).get(j).x, dots.get(i).get(j).y, dots.get(i).get(j).z, p.x, p.y, p.z);
}
}
}
}
}
}
strokeWeight(1.5);
stroke(255, 0);
for (int i = 0; i < dots.size (); i++) {
if (i>4) {
if (dots.get(i).size()>=dots.get(i-1).size()) {
for (int j = 0; j < dots.get (i).size(); j++) {
stroke(255);
noFill();
bezier(dots.get(i).get(j).x, dots.get(i).get(j).y, dots.get(i).get(j).z,
dots.get(i-1).get(j%dots.get(i-1).size()).x,
dots.get(i-1).get(j%dots.get(i-1).size()).y,
dots.get(i-1).get(j%dots.get(i-1).size()).z,
dots.get(i-2).get(j%dots.get(i-2).size()).x,
dots.get(i-2).get(j%dots.get(i-2).size()).y,
dots.get(i-2).get(j%dots.get(i-2).size()).z,
dots.get(i-3).get(j%dots.get(i-3).size()).x,
dots.get(i-3).get(j%dots.get(i-3).size()).y,
dots.get(i-3).get(j%dots.get(i-3).size()).z);
}
} else {
for (int j = 0; j < dots.get (i-3).size(); j++) {
stroke(255);
bezier(dots.get(i-3).get(j).x, dots.get(i-3).get(j).y, dots.get(i-3).get(j).z,
dots.get(i-2).get(j%dots.get(i-2).size()).x,
dots.get(i-2).get(j%dots.get(i-2).size()).y,
dots.get(i-2).get(j%dots.get(i-2).size()).z,
dots.get(i-1).get(j%dots.get(i-1).size()).x,
dots.get(i-1).get(j%dots.get(i-1).size()).y,
dots.get(i-1).get(j%dots.get(i-1).size()).z,
dots.get(i).get(j%dots.get(i).size()).x,
dots.get(i).get(j%dots.get(i).size()).y,
dots.get(i).get(j%dots.get(i).size()).z);
}
}
}
}
}
}
}
void keyPressed() {
if (key == 'n' || key == 'N') {
connect = ! connect;
}
if (key == 's' || key == 'S') {
skeleton = ! skeleton;
}
if (key == 'b' || key == 'B') {
ball = ! ball;
}
if (key == 'r' || key == 'R') {
right = ! right;
}
if (key == 'l' || key == 'L') {
left = ! left;
}
if (key == 'o' || key == 'O') {
rotate = ! rotate;
}
}
void drawSkeleton(int userId)
{
strokeWeight(3);
// to get the 3d joint data
drawLimb(userId, SimpleOpenNI.SKEL_HEAD, SimpleOpenNI.SKEL_NECK);
drawLimb(userId, SimpleOpenNI.SKEL_NECK, SimpleOpenNI.SKEL_LEFT_SHOULDER);
drawLimb(userId, SimpleOpenNI.SKEL_LEFT_SHOULDER, SimpleOpenNI.SKEL_LEFT_ELBOW);
drawLimb(userId, SimpleOpenNI.SKEL_LEFT_ELBOW, SimpleOpenNI.SKEL_LEFT_HAND);
drawLimb(userId, SimpleOpenNI.SKEL_NECK, SimpleOpenNI.SKEL_RIGHT_SHOULDER);
drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_SHOULDER, SimpleOpenNI.SKEL_RIGHT_ELBOW);
drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_ELBOW, SimpleOpenNI.SKEL_RIGHT_HAND);
drawLimb(userId, SimpleOpenNI.SKEL_LEFT_SHOULDER, SimpleOpenNI.SKEL_TORSO);
drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_SHOULDER, SimpleOpenNI.SKEL_TORSO);
drawLimb(userId, SimpleOpenNI.SKEL_TORSO, SimpleOpenNI.SKEL_LEFT_HIP);
drawLimb(userId, SimpleOpenNI.SKEL_LEFT_HIP, SimpleOpenNI.SKEL_LEFT_KNEE);
drawLimb(userId, SimpleOpenNI.SKEL_LEFT_KNEE, SimpleOpenNI.SKEL_LEFT_FOOT);
drawLimb(userId, SimpleOpenNI.SKEL_TORSO, SimpleOpenNI.SKEL_RIGHT_HIP);
drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_HIP, SimpleOpenNI.SKEL_RIGHT_KNEE);
drawLimb(userId, SimpleOpenNI.SKEL_RIGHT_KNEE, SimpleOpenNI.SKEL_RIGHT_FOOT);
stroke(255, 200, 200);
strokeWeight(1);
}
void drawLimb(int userId, int jointType1, int jointType2)
{
PVector jointPos1 = new PVector();
PVector jointPos2 = new PVector();
float confidence;
// draw the joint position
confidence = kinect.getJointPositionSkeleton(userId, jointType1, jointPos1);
confidence = kinect.getJointPositionSkeleton(userId, jointType2, jointPos2);
stroke(255, 0, 0, confidence * 200 + 55);
line(jointPos1.x, jointPos1.y, jointPos1.z,
jointPos2.x, jointPos2.y, jointPos2.z);
drawJointOrientation(userId, jointType1, jointPos1, 50);
}
void drawJointOrientation(int userId, int jointType, PVector pos, float length)
{
// draw the joint orientation
PMatrix3D orientation = new PMatrix3D();
float confidence = kinect.getJointOrientationSkeleton(userId, jointType, orientation);
if (confidence < 0.001f)
// nothing to draw, orientation data is useless
return;
pushMatrix();
translate(pos.x, pos.y, pos.z);
// set the local coordsys
applyMatrix(orientation);
// coordsys lines are 100mm long
// x - r
stroke(255, 0, 0, confidence * 200 + 55);
line(0, 0, 0,
length, 0, 0);
// y - g
stroke(0, 255, 0, confidence * 200 + 55);
line(0, 0, 0,
0, length, 0);
// z - b
stroke(0, 0, 255, confidence * 200 + 55);
line(0, 0, 0,
0, 0, length);
popMatrix();
}
// SimpleOpenNI user events
void onNewUser(SimpleOpenNI curContext, int userId)
{
println("onNewUser - userId: " + userId);
println("\tstart tracking skeleton");
kinect.startTrackingSkeleton(userId);
}
void onLostUser(SimpleOpenNI curContext, int userId)
{
println("onLostUser - userId: " + userId);
}
void onVisibleUser(SimpleOpenNI curContext, int userId)
{
//println("onVisibleUser - userId: " + userId);
}