3D Drawing
Our first OpenFrameworks-based assignment for 3D Sensing and Visualization was to create a program that finds the forepoint of a person/object (i.e. the point closest to the Kinect camera) and use it to draw a line in space. Kyle gave us an example that draws a point cloud of the objects in front of the camera, so I tweaked this code to find which point in the cloud was the closest. Then I had it add points to a mesh that will ultimately form the drawn line.
This is what it looks like when I run the program:
The main application code is below. Read the rest of the code on Github.
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 | #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 = 640; const unsigned int Yres = 480; ofVec3f ConvertProjectiveToRealWorld(float x, float y, float z) { return ofVec3f((x / Xres - .5f) * z * XtoZ, (y / Yres - .5f) * z * YtoZ, z); } void testApp::setup() { ofSetVerticalSync(true); kinect.init(false, false); // disable infrared/rgb video iamge (faster fps) kinect.open(); useProjective = true; mesh.setMode(OF_PRIMITIVE_LINE_STRIP); } void testApp::update() { kinect.update(); } void testApp::draw() { ofBackground(0); ofSetColor(255); kinect.drawDepth(0, 0, 320, 240); easyCam.begin(); int width = kinect.getWidth(); int height = kinect.getHeight(); ofScale(1, -1, -1); // orient the point cloud properly if(useProjective) { ofTranslate(-width / 2, -height / 2); // center the projective point cloud } else { ofTranslate(0, 0, -1500); // rotate about z = 1500 mm } float* distancePixels = kinect.getDistancePixels(); // distance in millimeters ofMesh cloud; cloud.setMode(OF_PRIMITIVE_POINTS); // float minZ = 20000; // float foreX = 0; // float foreY = 0; forePt.z = 20000; 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 < minZ && z != 0) { // minZ = z; // foreX = x; // foreY = y; // mesh.addVertex(ofVec3f(foreX, foreY, minZ)); if(z != 0) { // ignore empty depth pixels if(useProjective) { cloud.addVertex(ofVec3f(x, y, z)); if(z < forePt.z){ forePt = ofVec3f(x, y, z); } } else { cloud.addVertex(ConvertProjectiveToRealWorld(x, y, z)); if(z < forePt.z){ forePt = ConvertProjectiveToRealWorld(x,y,z); } } } } } mesh.addVertex(ofVec3f(forePt.x, forePt.y, forePt.z)); cloud.drawVertices(); // ofTranslate(foreX, foreY, minZ); // ofTranslate(forePt.x, forePt.y, forePt.z); ofSetColor(255, 0, 0); ofSphere(forePt.x, forePt.y, forePt.z, 10); ofSetColor(0, 255, 255); ofSetLineWidth(5); mesh.draw(); // easyCam.end(); ofSetColor(255); ofDrawBitmapString(useProjective ? "projective point cloud" : "real world point cloud", 10, 20); easyCam.end(); } void testApp::exit() { kinect.close(); } void testApp::keyPressed(int key) { if(key == ' ') { useProjective = !useProjective; } } |