Tuesday, November 6, 2012

Drawing with a Kinect


Using OpenFramewoks, the challenge for this assignment was to find the 'fore point' from the Kinect's Depth Image and treating it as the tip of a pencil.
I've merged the ribbon example by James Jorge with the Kinect point cloud example by Kyle McDonald.

Hand drawing with a Kinect from Federico Zannier on Vimeo.



testApp.cpp:

 #include "testApp.h"
 const float FovX = 1.0144686707507438;
 const float FovY = 0.78980943449644714;
 const float XtoZ = tanf(FovX / 2) * 2;
 const float YtoZ = tanf(FovY / 2) * 2;
 const unsigned int Xres = 1024;
 const unsigned int Yres = 768;
 bool bOverflow = false;
 ofVec3f pClosest;
 ofVec3f ConvertProjectiveToRealWorld(float x, float y, float z) {
      return ofVec3f((x / Xres - .5f) * z * XtoZ,
                                          (y / Yres - .5f) * z * YtoZ,
                                          z);
 }
 void testApp::setup() {
   ofSetFrameRate(60);
      ofSetVerticalSync(true);
   kinect.init();
      kinect.setRegistration(true);
      kinect.setDepthClipping(500, 1000);
      kinect.open();
   imGrayScale.allocate(1024,768,OF_IMAGE_GRAYSCALE);
   imWhite.allocate(640,480,OF_IMAGE_GRAYSCALE);
   for(int i=0; i < imWhite.width;i++)
     for(int j=0; j < imWhite.height;j++)
       imWhite.setColor(i, j, 255);
      useProjective = true;
   bCamera = false;
   ofColor c;
   c.set(10,10,10);
   colors.push_back(c);
 }
 void testApp::update()
 {
      kinect.update();
   ofVec3f sumOfAllPoints(0,0,0);
   if(!bCamera)
   {
     if(kinect.isFrameNew())
     {
       int width = kinect.getWidth();
       int height = kinect.getHeight();
       float* distancePixels = kinect.getDistancePixels();
       float fClosest = 10000;
       for(int y = 0; y < height; y++) {
         for(int x = 0; x < width; x++) {
           int i = y * width + x;
           float z = distancePixels[i];
           if(z < fClosest && z!=0)
           {
             pClosest.x =x; pClosest.y = y;
             pClosest.x = (Xres * pClosest.x)/width; pClosest.y = (Yres * pClosest.y)/height;
             pClosest.z = 0;
             fClosest = z;
           }
         }
       }
       points.push_back(pClosest);
       ofColor c = colors[points.size()-1];
       if(c.r < 255 && bOverflow == false)
         c.lerp(c+5,0.5);
       else
       {
         bOverflow = true;
         c.lerp(c-5,0.5);
         if(c.r < 5)
           bOverflow = false;
       }
       colors.push_back(colors[points.size()-1]+1);
     }
     for(int i = 0; i < points.size(); i++)
     {
       points[i].z -= 4;
       sumOfAllPoints += points[i];
     }
     center = sumOfAllPoints / points.size();
   }
 }
 void testApp::draw() {
   imGrayScale.setFromPixels(kinect.getDepthPixels(), 640, 480, OF_IMAGE_GRAYSCALE);
   ofxCv::subtract(imWhite,imGrayScale,imGrayScale);
   imGrayScale.draw(0,0,1024,768);
   ofSetLineWidth(30);
   if(bCamera)
     camera.begin();
   ofMesh meshDrawing;
      meshDrawing.setMode(OF_PRIMITIVE_LINE_STRIP);
      for(int i = 1; i < points.size(); i++){
           ofVec3f thisPoint = points[i-1];
           ofVec3f nextPoint = points[i];
           ofVec3f direction = (nextPoint - thisPoint);
           float distance = direction.length();
           ofVec3f unitDirection = direction.normalized();
           ofVec3f toTheLeft = unitDirection.getRotated(-90, ofVec3f(0,0,1));
           ofVec3f toTheRight = unitDirection.getRotated(90, ofVec3f(0,0,1));
           float thickness = ofMap(distance, 0, 60, 1, 4, true);
           ofVec3f leftPoint = thisPoint+toTheLeft*thickness;
           ofVec3f rightPoint = thisPoint+toTheRight*thickness;
           meshDrawing.addColor(colors[i]);
     meshDrawing.addVertex(ofVec3f(leftPoint.x, leftPoint.y, leftPoint.z));
     meshDrawing.addVertex(ofVec3f(rightPoint.x, rightPoint.y, rightPoint.z));
      }
      meshDrawing.draw();
   if(bCamera)
     camera.end();
 }
 void testApp::exit() {
      kinect.close();
 }
 void testApp::keyPressed(int key)
 {
   if(key == 'a')
   {
     points.clear();
   }
   if(key == 'c')
   {
     bCamera = !bCamera;
   }
 }
 void testApp::mouseMoved(int x, int y ){
   if(bCamera){
     float rotateAmount = ofMap(ofGetMouseX(), 0, ofGetWidth(), 0, 360);
           ofVec3f furthestPoint = points[0];
     ofVec3f directionToFurthestPoint = (furthestPoint - center);
     ofVec3f directionToFurthestPointRotated = directionToFurthestPoint.rotated(rotateAmount, ofVec3f(0,1,0));
     camera.setPosition(center + directionToFurthestPointRotated);
     camera.lookAt(center);
   }
 }

testApp.h:

 #pragma once  
 #include "ofMain.h"  
 #include "ofxOpenCv.h"  
 #include "ofxKinect.h"  
 #include "ofxCv.h"  
 class testApp : public ofBaseApp {  
 public:  
      void setup();  
      void update();  
      void draw();  
      void exit();  
   void keyPressed (int key);  
   void keyReleased(int key);  
   void mouseMoved(int x, int y );  
   void mouseDragged(int x, int y, int button);  
   void mousePressed(int x, int y, int button);  
   void mouseReleased(int x, int y, int button);  
   void windowResized(int w, int h);  
   void dragEvent(ofDragInfo dragInfo);  
   void gotMessage(ofMessage msg);  
      ofxKinect kinect;  
      ofCamera camera;  
      bool useProjective;  
   bool bCamera;  
   //this holds all of our points  
   vector<ofVec3f> points;  
   //this keeps track of the center of all the points  
   ofVec3f center;  
   ofImage imWhite;  
   ofImage imGrayScale;  
   vector<ofColor> colors;  
 };  

No comments:

Post a Comment