Quantcast
Channel: beginners - openFrameworks
Viewing all articles
Browse latest Browse all 4929

Kinect Drawing Extra Vertices/Indices

$
0
0

@Nedelstein wrote:

Hi All,

I am working on an OF kinect project to essentially draw people covered in fur. I’m creating a mesh and getting the normals, and then drawing the vertices and indices to create the fur effect. However, it seems to be drawing extra vertices/indices around the bodies it detects. Does anyone know why this is? Been struggling with this for a few days now. Here are some pictures to show what is being drawn:

As you can see, there is this weird extra layer of lines around my body. Anyone have an idea about how to get rid of these?

Also - the background of this project is a video but I’ve excluded that for the sake of simplicity for this post.

Code here:
ofApp.h:

#pragma once

#include "ofMain.h"
#include "ofxKinect.h"
#include "ofxOpenCv.h"
#include "ofxCv.h"

using namespace cv;
using namespace ofxCv;

class ofApp : public ofBaseApp {

	public:
		void setup();
		void update();
		void draw();
    
    void updateNormals();

		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 mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
    
    ofxKinect kinect;
    
    ofVideoPlayer backgroundLoop;
    ofVideoPlayer backgroundDetect;
    
    ofSoundPlayer backgroundSound;
    
    bool blobDetected;
    
    ofMesh mesh;
    ofMesh normalLines;
    
    ofxCv::ContourFinder contourFinder;

    ofxCvGrayscaleImage grayImage;
    
    ofEasyCam cam;
    
    float nearThresh, farThresh;
    float grayFarThresh, grayNearThresh;
    float normalLength;
    int angle;
    int skip = 2;
    
    glm::vec3 getTriangleCenter(glm::vec3 a, glm::vec3 b, glm::vec3 c);
		
    ofTrueTypeFont myfont;
};

ofApp.cpp:

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(0);
    
    myfont.load("arial.ttf", 32);
    
    //    ofSetFrameRate(30);
    
    //ambient background video
    backgroundLoop.load("backgroundLoop.mp4");
    backgroundLoop.setLoopState(OF_LOOP_PALINDROME);
    //    backgroundLoop.play();
    
    //triggered background video
    backgroundDetect.load("backgroundDetect.mp4");
    backgroundDetect.setLoopState(OF_LOOP_NONE);
    
    //background sound
    backgroundSound.load("backgroundNoise.mp3");
    backgroundSound.play();
    backgroundSound.setLoop(true);
    
    blobDetected = false;

    
    kinect.setRegistration(true);
    kinect.init();
    kinect.open();
    
    grayImage.allocate(kinect.width, kinect.height);
    
    angle = 20;
    kinect.setCameraTiltAngle(angle);
    
    
    grayFarThresh = 145;
    grayNearThresh = 255;
    
    farThresh = -800;
    nearThresh = 1000;
    
//    farThresh = 800;
//    nearThresh = 500;
    
    contourFinder.setMinArea(50);
    contourFinder.setThreshold(30);
    contourFinder.getTracker().setPersistence(10);


//    farThresh = 1000;
//    nearThresh = 50;
}

//--------------------------------------------------------------
void ofApp::update(){
    mesh.setMode(OF_PRIMITIVE_TRIANGLES);
    kinect.update();
    
    backgroundLoop.update();
    if(blobDetected == true){
        backgroundDetect.update();
    }
    
    if(kinect.isFrameNew()){
        mesh.clear();
        grayImage.setFromPixels(kinect.getDepthPixels());
        ofPixels & pix = grayImage.getPixels();
        int numPixels = pix.size();
        for(int i=0; i<numPixels; i++){
            if(pix[i] < grayNearThresh && pix[i] > grayFarThresh){
                pix[i] = 255;
            } else{
                pix[i] = 0;
            }
        }
        
        //update the cv images
        grayImage.flagImageChanged();
        
        // find contours which are between the size of 20 pixels and 1/3 the w*h pixels.
        // also, find holes is set to true so we will get interior contours as well...
//        contourFinder.findContours(grayImage, 50, (kinect.width*kinect.height)/2, 5, false);
//         cout << "number of blobs: " << contourFinder.nBlobs << endl;
        
        contourFinder.findContours(grayImage);
        
        int width = kinect.width/skip;
        int height = kinect.height/skip;
        for(int y=0; y<height; y++){
            for(int x=0; x<width; x++){
//                if(kinect.getDistanceAt(x, y) > 0){
                glm::vec3 vertex = kinect.getWorldCoordinateAt(x *skip, y*skip);
                ofColor kinCol = kinect.getColorAt(x*skip, y*skip);
                glm::vec3 normal = glm::vec3(0,0,0);
              
                vertex.z *= -1;
                vertex.z += 1000;
                
                if(vertex.z > nearThresh || vertex.z <farThresh){
                    kinCol.a = 0;
                }
                
                    mesh.addVertex(vertex);
                    mesh.addNormal(normal);
                    mesh.addColor(kinCol);
//        }
        }
        }
    for(int y = 0; y<height-1; y++){
        for(int x = 0; x<width-1; x++){
            
            mesh.addIndex(x+y*width);         // 0
            mesh.addIndex((x+1)+y*width);     // 1
            mesh.addIndex(x+(y+1)*width);     // 10
            
            mesh.addIndex((x+1)+y*width);     // 1
            mesh.addIndex((x+1)+(y+1)*width); // 11
            mesh.addIndex(x+(y+1)*width);     // 10
        }
    }
        
    }

    updateNormals();
    
}

//--------------------------------------------------------------
void ofApp::draw(){
    
    if(blobDetected == false){
        backgroundDetect.setPaused(true);
        backgroundLoop.play();
        backgroundLoop.draw(0, 0, ofGetWidth(), ofGetHeight());
    }
    else if(blobDetected == true){
        //        backgroundLoop.setPaused(true);
        backgroundLoop.stop();
        backgroundDetect.play();
        backgroundDetect.draw(0,0, ofGetWidth(), ofGetHeight());
        if(backgroundDetect.getIsMovieDone()){
            backgroundDetect.setPaused(true);
        }
    }
    ofBackground(0);
    
//    ofPushStyle();
//    ofBackground(0, 0, 0);
//    grayImage.draw(10, 320, 400, 300);
//    ofScale(-1,-1,1);
//    contourFinder.draw(0, 0, ofGetWidth(), ofGetHeight());
//    ofPopStyle();

    ofPushMatrix();
    ofPushStyle();
    cam.begin();
    ofEnableDepthTest();
    ofTranslate(0, 0, 0);
    ofScale(-1,-1, 1);
//    mesh.drawFaces();
    
    //dark brown
    ofSetColor(78, 54, 41);
    
    //forest green
//    ofSetColor(33, 68, 2);

    if (contourFinder.size() > 0){
        blobDetected = true;
    }
    else{
        blobDetected = false;
    }
    
//    for(int j = 0; j< contourFinder.size(); j++){
//        int id = contourFinder.getLabel(j);
//        ofPushStyle();
//        ofSetColor(0);
//        ofFill();
//        mesh.drawFaces();
//        ofPopStyle();
//        normalLines.draw();
//    }
    
    if (contourFinder.size()){
        normalLines.draw();
    }
    
    ofPopStyle();
    cam.end();
    ofDisableDepthTest();
    ofPopMatrix();
    
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    switch(key){
        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;
    }
    
    if(key == 'f'){
        ofToggleFullscreen();
    }
    
    //threshold values
    if(key == 'q'){
        farThresh +=50;
    }
    else    if(key == 'w'){
        farThresh -=50;
    }
    
    else    if(key == 'e'){
        nearThresh +=50;
    }
    
    else    if(key == 'r'){
        nearThresh -=50;
    }
    
    cout<<nearThresh<<endl;
    cout<<farThresh<<endl;
    

}

//--------------------------------------------------------------
void ofApp::updateNormals(){
    
    
    auto& verts = mesh.getVertices();
    normalLines.clear();
    normalLines.setMode(OF_PRIMITIVE_LINES);
    int normalIndex = 0;
    
    
    //generate vertex normals:
    //based on ofxMeshUtils addon:
    // https://github.com/ofZach/ofxMeshUtils/blob/master/src/ofxMeshUtils.cpp#L32-L58
  
    
    // reset current normals
    mesh.clearNormals();
    mesh.addNormals( vector<glm::vec3>(verts.size()) );
    // 1 normal per vertex
    
    // loop through the triangles
    for( int i=0; i+2 < mesh.getIndices().size(); i+=3 )
    {
        // 3 vertices per triangle
        const int va = mesh.getIndices()[i];
        const int vb = mesh.getIndices()[i+1];
        const int vc = mesh.getIndices()[i+2];
    
        ofFloatColor ca = mesh.getColors()[va];
        ofFloatColor cb = mesh.getColors()[vb];
        ofFloatColor cc = mesh.getColors()[vc];
        
        if (ca.a > 0 && ca.a > 0 && ca.a > 0){
 
        // calculate triangle face normal:
        // cross product of two edges
        glm::vec3 e1 = verts[va] - verts[vb];
        glm::vec3 e2 = verts[vc] - verts[vb];
        glm::vec3 nml = glm::normalize(glm::cross(e2,e1));
    
    
        // depending on your clockwise / winding order, you might want to reverse the e2 / e1 above if your normals are flipped.
        
        // distribute face normal to 3 vertex normals:
        mesh.getNormals()[va] += nml;    // *add* face normal
        mesh.getNormals()[vb] += nml;    // to each vertex -
        mesh.getNormals()[vc] += nml;    // averages faces
    
        // extra --
        // store the face normal as a line
        // in normalLines mesh for drawing
        // -- normalLines mesh uses OF_PRIMITIVE_LINES mode
        
        glm::vec3 faceCenter = getTriangleCenter(verts[va],verts[vb],verts[vc]);
        
        normalLength = ofRandom(10,40);
        glm::vec3 normalEnd = faceCenter + nml * normalLength;
       
        // 1 line = 2 vertices, 2 indices
        normalLines.addVertex(faceCenter);
        normalLines.addVertex(normalEnd);
        
        normalLines.addIndex(normalIndex);
        normalLines.addIndex(normalIndex+1);
            
        normalIndex += 2;   // increment
        
        }
    }
}
//--------------------------------------------------------------

glm::vec3 ofApp::getTriangleCenter(glm::vec3 a, glm::vec3 b, glm::vec3 c)
{
    // center of a triangle:
    // 2/3 from point to center of opposite edge
    glm::vec3 edgePt = (b + c) * 0.5;     // middle b_c edge
    return a * .333f + edgePt * .667f;    // lerp 2/3 a --> edgePt
}

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

void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y ){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 

}

Posts: 1

Participants: 1

Read full topic


Viewing all articles
Browse latest Browse all 4929

Trending Articles