In this chapter we will be doing the same as we did for processing in open frameworks: We want a real-time mask (Let's say we want to map a projection on people or objects that move). Masks can e.g. be black/white images, so what we do is very easy: We define a maximum and a minimum distance and use the distance information, the kinect delivers, to create a simple black/white Image, that is updated in real-time.

Below you find the complete code for creating the mask image from kinect. Find remarks inside the code. The main difference from processing is that the distances are not seen in cm but as brightness values for each pixel. So if we look at a pixel in the original depth image from kinect:

  • 0 means completely far away
  • 255 means completely near

This is important to understand how our helper variables for far and near distance Threshold nearBorder and farBorder work.

ofApp.h

#pragma once

 

#include "ofMain.h"

#include "ofxKinect.h"

#include "ofxOpenCv.h"

 

class ofApp : public ofBaseApp{

    

public:

    void setup();

    void setupKinect();

    void update();

    void draw();

    void prepareMaskImageFromKinect();

    

    void keyPressed(int key);

    

    // kinect

    ofxKinect kinect;

    // grayscale depth image

    ofxCvGrayscaleImage grayImage;

    // helper variables (which pixel shall

    // be white, depending on distances)

    int nearBorder;

    int farBorder;

    int angle;

    bool setupFlag;

 

};

ofApp.cpp

#include "ofApp.h"

 

//--------------------------------------------------------------

void ofApp::setup(){

    setupKinect();

}

 

//--------------------------------------------------------------

void ofApp::setupKinect(){

ofSetLogLevel(OF_LOG_VERBOSE);

// enable depth->video image calibration

kinect.setRegistration(true);

    

    // init kinect like this

//kinect.init();

    // OR like next line: shows infrared instead of RGB video image

//kinect.init(true);

    // OR like next line: disable video image (faster fps)

kinect.init(false, false);

    // opens first available kinect

kinect.open();

    // OR: open a kinect by id, starting with 0 (sorted by

    // serial # lexicographically))

//kinect.open(1);

    // OR: open a kinect using it's unique serial #    

//kinect.open("A00362A08602047A");

// info only: print the intrinsic IR sensor values

if(kinect.isConnected()) {

ofLogNotice() << "sensor-emitter dist: " << kinect.getSensorEmitterDistance() << "cm";

ofLogNotice() << "sensor-camera dist:  " << kinect.getSensorCameraDistance() << "cm";

ofLogNotice() << "zero plane pixel size: " << kinect.getZeroPlanePixelSize() << "mm";

ofLogNotice() << "zero plane dist: " << kinect.getZeroPlaneDistance() << "mm";

        setupFlag = true;

}

    

grayImage.allocate(kinect.width, kinect.height);

    

  nearBorder = 165;

farBorder = 143;

    

// zero the tilt on startup

angle = 0;

kinect.setCameraTiltAngle(angle);

}

 

//--------------------------------------------------------------

void ofApp::update(){

    prepareMaskImageFromKinect();    

}

 

//--------------------------------------------------------------

void ofApp::draw(){

    

ofSetColor(255, 255, 255);

    if (setupFlag) {

        kinect.drawDepth(10, 10, 400, 300);

        grayImage.draw(10, 320, 400, 300);

    }

        

    // now for some info only output

stringstream reportStream;

    

    if(kinect.hasAccelControl()) {

        reportStream << "accel is: " << ofToString(kinect.getMksAccel().x, 2) << " / "

        << ofToString(kinect.getMksAccel().y, 2) << " / "

        << ofToString(kinect.getMksAccel().z, 2) << endl;

    } else {

        reportStream << "Note: this is a newer Xbox Kinect or Kinect For Windows device," << endl

<< "motor / led / accel controls are not currently supported" << endl << endl;

    }

    

reportStream << "press p to switch between images and point cloud, rotate the point cloud with the mouse" << endl

<< "set near threshold " << nearBorder << " (press: + -)" << endl

<< "set far threshold " << farBorder << " (press: < >) "

<< ", fps: " << ofGetFrameRate() << endl

<< "press c to close the connection and o to open it again, connection is: " << kinect.isConnected() << endl;

    

    if(kinect.hasCamTiltControl()) {

    reportStream << "press UP and DOWN to change the tilt angle: " << angle << " degrees" << endl

        << "press 1-5 & 0 to change the led mode" << endl;

    }

    

ofDrawBitmapString(reportStream.str(), 20, 652);

    

    

}

 

//--------------------------------------------------------------

void ofApp::prepareMaskImageFromKinect(){

    // Here we prepare an image consisting of white or 

    // black pixels. We later use this image as a mask

    

    kinect.update();

    // there is a new frame and we are connected

    if(kinect.isFrameNew()) {

        

        // load grayscale depth image from the kinect source

        grayImage.setFromPixels(kinect.getDepthPixels(), kinect.width, kinect.height);

        

        //get a pixel map

        unsigned char * pix = grayImage.getPixels();

        // get number of all pixels

        int numPixels = grayImage.getWidth() * grayImage.getHeight();

        // run through all pixels

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

            // check the distance - if it is in beteen our borders (farBorder/nearBorder) change it to white, else black

            if(pix[i] > farBorder && pix[i] < nearBorder) {

                pix[i] = 255;

            } else {

                pix[i] = 0;

            }

        }

        

        // update the cv image

        grayImage.flagImageChanged();

        

        // now we have an image consisting of only white or black pixels. We now could blur it or the like to adapt the mask to our needs. We used ofcCv image to make this easier

        

    }

}

 

//--------------------------------------------------------------

void ofApp::keyPressed(int key){

    // chekc for keys pressed

    // use this to adjust borders (Threshold)

    switch (key) {

case '>':

case '.':

farBorder ++;

if (farBorder > 255) farBorder = 255;

break;

case '<':

case ',':

farBorder --;

if (farBorder < 0) farBorder = 0;

break;

case '+':

nearBorder ++;

if (nearBorder > 255) nearBorder = 255;

break;

case '-':

nearBorder --;

if (nearBorder < 0) nearBorder = 0;

break;

        case OF_KEY_UP:

            angle++;

            if(angle>30) angle=30;

            kinect.setCameraTiltAngle(angle);

            break;

            

        case OF_KEY_DOWN:

            angle--;

            if(angle<-30) angle=-30;

            kinect.setCameraTiltAngle(angle);

            break;            

    }

}