Skip to content

Instantly share code, notes, and snippets.

@BurakDev
Forked from spartonia/kinectproject.cpp
Created December 30, 2017 15:05
Show Gist options
  • Select an option

  • Save BurakDev/0f4bac3361bc45d5fcac3e0f8a4b5231 to your computer and use it in GitHub Desktop.

Select an option

Save BurakDev/0f4bac3361bc45d5fcac3e0f8a4b5231 to your computer and use it in GitHub Desktop.

Revisions

  1. @spartonia spartonia created this gist Nov 7, 2015.
    938 changes: 938 additions & 0 deletions kinectproject.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,938 @@

    #include <Windows.h>
    #include <Ole2.h>
    #include <iostream>
    #include <fstream>
    #include <sstream>
    #include <WinBase.h>

    // Kinect
    #include <NuiApi.h>
    #include <NuiImageCamera.h>
    #include <NuiSensor.h>

    // Opencv
    #include <cv.h>
    #include <cxcore.h>
    #include <highgui.h>
    #include <core.hpp>
    #include <opencv2\contrib\contrib.hpp>
    #include <opencv2\highgui\highgui.hpp>
    #include <opencv2\imgproc\imgproc.hpp>
    #include <opencv2\objdetect\objdetect.hpp>
    #include <opencv2\core\core.hpp>

    using namespace cv;
    using namespace std;

    #define pictureMode false // true: take pictures for training
    #define cropMode false // true: crop the faces in the images
    #define pictureOwner "Lady_Big2" // name the picture owner
    /* Image setting */
    #define imgWidth 640
    #define imgHeight 480
    #define imgWidthBig 1280
    #define imgHeightBig 960

    #define useExistingModel true // train new face rec. model or load existing.
    #define recognizerThreshold 125.0
    #define writeToVideo false // true: record the operation
    bool useBigPic = true; // true: use 1280x960 images for better accuracy. false: 640x480

    string modelName = "fisher"; // name the face rec. model

    // Kinect variables
    HANDLE rgbStream;
    HANDLE skeletonStream;
    INuiSensor* sensor;
    NUI_SKELETON_FRAME* nextSkeletonFrame;
    bool *m_bArrSkeletonsTracked;



    // Program variables
    IplImage* kinectColorImage = cvCreateImage(cvSize(imgWidth, imgHeight), IPL_DEPTH_8U, 4);
    IplImage* kinectColorImageBig = cvCreateImage(cvSize(1280, 960), IPL_DEPTH_8U, 4);
    IplImage* kinectColorImageTiny = cvCreateImage(cvSize(320, 240), IPL_DEPTH_8U, 4);

    string output_folder = "Images";//"C:/attFaces/frec"; //for face recog only
    string fn_csv = "croppedImagesBig/frecAll.txt"; //path to the csv file.
    //string fn_csv = "Images/BigImages.txt"; //path to the csv file.
    string fn_haar = "C:\\opencv243\\data\\haarcascades\\haarcascade_frontalface_alt.xml"; //.._default.xml";
    string fn_lbp = "C:\\opencv243\\data\\lbpcascades\\lbpcascade_frontalface.xml"; //.._profileface.xml, lbpcascade_frontalface.xml
    string eye_cascade_name = "C:/opencv243/data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";//haarcascade_mcs_eyepair_small";//haarcascade_eye_tree_eyeglasses.xml";


    vector<Mat> images;//These vectors hold the images and corresponding labels.
    vector<int> labels;

    int training_im_width; // for video face recog.
    int training_im_height;
    bool showResult = false; // true: show the eigenvalues, eigenvectors, etc, false: save resuts in files

    Ptr<FaceRecognizer> model; // Face recognizer model for eigenfaces.
    CascadeClassifier haar_cascade; // cascade classifier (to detect faces, or what in needed)
    CascadeClassifier eye_cascade; // Eye detector

    int *sklBelongsToFaceId;
    bool *skeletonHasFaceId;


    /*
    Initialize the kinect.
    */
    bool initKinect() {
    //get a working kinect sensor
    int numSensors;
    if (NuiGetSensorCount(&numSensors) < 0 || numSensors < 1) return false;
    if (NuiCreateSensorByIndex(0, &sensor) < 0) return false;

    nextSkeletonFrame = new NUI_SKELETON_FRAME;
    m_bArrSkeletonsTracked = new bool[NUI_SKELETON_COUNT];

    // init face data holder
    skeletonHasFaceId = new bool [NUI_SKELETON_COUNT];
    sklBelongsToFaceId = new int [NUI_SKELETON_COUNT]; // for each skeleton, a face label will be assigned, if mathched.

    for (int i = 0; i < NUI_SKELETON_COUNT; ++i )
    {
    m_bArrSkeletonsTracked[i] = false;
    skeletonHasFaceId[i] = false;
    sklBelongsToFaceId[i] = -1;
    }


    // Initialize sensor
    DWORD nuiFlags = NUI_INITIALIZE_FLAG_USES_DEPTH | NUI_INITIALIZE_FLAG_USES_COLOR | NUI_INITIALIZE_FLAG_USES_SKELETON;
    sensor->NuiInitialize(nuiFlags);
    NUI_IMAGE_RESOLUTION kinect_resolution;
    useBigPic? kinect_resolution = NUI_IMAGE_RESOLUTION_1280x960 : kinect_resolution = NUI_IMAGE_RESOLUTION_640x480;
    // Get Color Data
    sensor->NuiImageStreamOpen(NUI_IMAGE_TYPE_COLOR, // Depth camera or rgb camera ?
    kinect_resolution ,//NUI_IMAGE_RESOLUTION_640x480, // Image resolution
    0, // Image stream flags, e.g. near mode
    2, // Number of frames to buffer
    NULL, // Event Handle
    &rgbStream);
    // Get Skeleton Data
    sensor->NuiImageStreamOpen(
    HasSkeletalEngine(sensor) ? NUI_IMAGE_TYPE_DEPTH_AND_PLAYER_INDEX : NUI_IMAGE_TYPE_DEPTH,
    NUI_IMAGE_RESOLUTION_640x480, // Change? to 640x480 later.
    0,
    2,
    NULL,
    &skeletonStream);
    cout <<"Kinect initialized!\n";
    return sensor;
    }

    /*
    Retrieves the RGB image of the kinect.
    */
    void getKinectColorData(IplImage* dest) {
    NUI_IMAGE_FRAME imageFrame;
    NUI_LOCKED_RECT lockedRect;
    if (sensor->NuiImageStreamGetNextFrame(rgbStream,0, &imageFrame) < 0) return;
    INuiFrameTexture* texture = imageFrame.pFrameTexture;
    texture->LockRect(0, &lockedRect, NULL, 0);
    if (lockedRect.Pitch != 0)
    {
    cvSetData(dest, static_cast<BYTE *>(lockedRect.pBits),
    dest->widthStep);
    }
    texture->UnlockRect(0);
    sensor->NuiImageStreamReleaseFrame(rgbStream, &imageFrame);
    }

    /*
    Retrieves the kinect's skeleton data
    */
    void getKinectSkeletalData() {

    bool bFoundSkeleton = false;
    float fClosestDistance = 0;

    if (SUCCEEDED(sensor->NuiSkeletonGetNextFrame(0, nextSkeletonFrame))) {
    for (int i = 0; i < NUI_SKELETON_COUNT; i++) {
    if (nextSkeletonFrame->SkeletonData[i].eTrackingState == NUI_SKELETON_TRACKED) // might need revision : && m_bAppTracking is ommited
    {
    if ( !m_bArrSkeletonsTracked[i] )
    {
    cout << " * Skeleton " << i << " found at " << nextSkeletonFrame->SkeletonData[i].Position.z
    << " meters from camera, " << (int) (clock() / CLOCKS_PER_SEC) << " seconds after startup.\n\n";
    if (fClosestDistance == 0 || fClosestDistance > nextSkeletonFrame->SkeletonData[i].Position.z )
    {
    fClosestDistance = nextSkeletonFrame->SkeletonData[i].Position.z;
    }
    m_bArrSkeletonsTracked[i] = true;

    }
    bFoundSkeleton = true;
    }
    else if (m_bArrSkeletonsTracked[i]) {
    cout << " * Skeleton " << i << " lost.\n\n";
    m_bArrSkeletonsTracked[i] = false;
    skeletonHasFaceId[i] = false;
    }
    }

    }

    // no skeletons!
    if ( !bFoundSkeleton) {
    return;
    }

    // smooth out the skeleton
    sensor->NuiTransformSmooth(nextSkeletonFrame, NULL);

    }

    /*
    Scales the skeleton's 20 joints to the corresponding actual points in the RGB image.
    */
    void scaleTo(Vector4 aPoint, int *x, int *y) {

    float fx = 0, fy = 0;
    NuiTransformSkeletonToDepthImage(aPoint, &fx, &fy);
    long l_x =0, l_y = 0;
    NuiImageGetColorPixelCoordinatesFromDepthPixel(NUI_IMAGE_RESOLUTION_640x480,
    NULL,
    (long) fx,
    (long) fy,
    NULL,
    &l_x,
    &l_y);
    *x = (int) l_x;
    *y = (int) l_y;

    }

    /*
    Capture and save the images in a folder with th same name as the picture owner.
    These pictures will be used to crop faces to train the face recog. model.
    */
    void saveImages(string person){
    //create a folder named person
    //
    cout <<
    "*************************************************\n" <<
    "* Saving images for training purpose.\n"<<
    "* Face to the camera and ";

    system("pause");
    string image_folder = "Images/";
    image_folder.append(person.c_str());
    // create destination dir for images
    CreateDirectory(image_folder.c_str(), NULL);

    //IplImage* kinectImg = cvCreateImage(cvSize(imgWidth,imgHeight), IPL_DEPTH_8U, 4);
    IplImage* kinectImgBig = cvCreateImage(cvSize(imgWidthBig,imgHeightBig), IPL_DEPTH_8U, 4);

    for (int i = 0; i < 150 ; i++) {
    getKinectColorData(kinectImgBig);
    Mat image(kinectImgBig);
    if (image.empty()) continue;

    string fname = format("%s/%s/%s_%d.jpg", output_folder.c_str(), person.c_str(), person.c_str(), i);
    //cout << "appended "<< fname<<endl;
    //imwrite(fname, image);
    imwrite(fname, image);
    namedWindow(fname, CV_WINDOW_AUTOSIZE);
    imshow(fname, image);
    cout << "Image " << i<< " saved. Press a key to continue, Escape to end." << endl;
    char key = (char)waitKey(0);
    if (key == 27)
    return;
    destroyWindow(fname);
    }

    //cvReleaseImage(&kinectImgBig);
    return;
    }

    /*
    Finds and crops the faces from the captured images. These cropped faces will be used in model training.
    */
    Mat CropFaces( Mat frame )
    {
    Mat tFrame = frame.clone();
    std::vector<Rect> faces;
    Mat frame_gray;
    Mat cropped;

    cvtColor(frame, frame_gray, CV_BGR2GRAY );
    equalizeHist( frame_gray, frame_gray);

    // detect faces
    haar_cascade.detectMultiScale(frame_gray, faces, 1.1, 2,
    0|CV_HAAR_SCALE_IMAGE, Size(30,30) );

    for (int i = 0; i < faces.size(); i++ )
    {
    Point center(faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5);
    ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360,
    Scalar(255, 0, 255), 4, 8, 0);
    cropped = tFrame (faces[i] );
    }
    //show the crooped face
    imshow("Face", frame);
    waitKey(0);
    return cropped;
    }

    /*
    Histogram normalize the image.
    */
    static Mat norm_0_255(InputArray _src){
    Mat src = _src.getMat();
    //create and return normalized image:
    Mat dst;
    switch(src.channels()){
    case 1:
    cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
    break;
    case 3:
    cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
    break;
    default:
    src.copyTo(dst);
    break;
    }
    return dst;
    }
    //
    // Calculates the TanTriggs Preprocessing as described in:
    //
    // Tan, X., and Triggs, B. "Enhanced local texture feature sets for face
    // recognition under difficult lighting conditions.". IEEE Transactions
    // on Image Processing 19 (2010), 1635\96650.
    //
    // Default parameters are taken from the paper.
    //
    Mat tan_triggs_preprocessing(InputArray src,
    float alpha = 0.1, float tau = 10.0, float gamma = 0.2, int sigma0 = 1,
    int sigma1 = 2) {

    // Convert to floating point:
    Mat X = src.getMat();
    X.convertTo(X, CV_32FC1);
    // Start preprocessing:
    Mat I;
    pow(X, gamma, I);
    // Calculate the DOG Image:
    {
    Mat gaussian0, gaussian1;
    // Kernel Size:
    int kernel_sz0 = (3*sigma0);
    int kernel_sz1 = (3*sigma1);
    // Make them odd for OpenCV:
    kernel_sz0 += ((kernel_sz0 % 2) == 0) ? 1 : 0;
    kernel_sz1 += ((kernel_sz1 % 2) == 0) ? 1 : 0;
    GaussianBlur(I, gaussian0, Size(kernel_sz0,kernel_sz0), sigma0, sigma0, BORDER_CONSTANT);
    GaussianBlur(I, gaussian1, Size(kernel_sz1,kernel_sz1), sigma1, sigma1, BORDER_CONSTANT);
    subtract(gaussian0, gaussian1, I);
    }

    {
    double meanI = 0.0;
    {
    Mat tmp;
    pow(abs(I), alpha, tmp);
    meanI = mean(tmp).val[0];

    }
    I = I / pow(meanI, 1.0/alpha);
    }

    {
    double meanI = 0.0;
    {
    Mat tmp;
    pow(min(abs(I), tau), alpha, tmp);
    meanI = mean(tmp).val[0];
    }
    I = I / pow(meanI, 1.0/alpha);
    }

    // Squash into the tanh:
    {
    for(int r = 0; r < I.rows; r++) {
    for(int c = 0; c < I.cols; c++) {
    I.at<float>(r,c) = tanh(I.at<float>(r,c) / tau);
    }
    }
    I = tau * I;
    }
    return I;
    }

    /*
    Reads a csv file containing training images as well as corresponding labels.
    */

    static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';'){
    std::ifstream file(filename.c_str(), ifstream::in);
    if (!file) {
    string error_message = "No valid input file was given, please check the given file name";
    CV_Error(CV_StsBadArg, error_message);
    }
    string line, path, classlabel;
    while (getline(file, line)) {
    stringstream liness(line);
    getline(liness, path, separator);
    getline(liness, classlabel);
    if (!path.empty() && !classlabel.empty()) {
    Mat img = imread(path,0);
    //imshow("Image", img);
    //waitKey(0);
    //Mat processed = tan_triggs_preprocessing(img);
    //processed = norm_0_255(processed);
    images.push_back(img);
    labels.push_back(atoi(classlabel.c_str()));
    }
    }

    }


    /*
    Returns true if the skeleton with specified ID is available.
    */
    bool skeletonAvailable(int skltnId)
    {
    return m_bArrSkeletonsTracked[skltnId];
    }

    /*
    Checks if a face label is associated with the specified skeleton.
    */
    bool skeletonHasFaceLabel(int skeletonId)
    {
    return skeletonHasFaceId[skeletonId];
    }

    /*
    Returns the label associated to the skeleton.
    */
    int getSkeletonFaceLabel(int skeletonId)
    {
    return sklBelongsToFaceId[skeletonId];
    }

    /*
    Draws the given skeleton joints on the given Mat image dest. If drawLabel == true, also shows the associated label along with a circle on the head position.
    */
    void drawSkeletonByID(int id, Mat *dest, bool drawLabel)
    {
    /*
    - id : skeleton id
    - *dest : destination image joints to be drawn
    - drawLabel : true ? show assigned skltn label : do not show label
    */
    CvPoint jointPos = cvPoint(200,200);
    int xs = 0, ys = 0;
    for (int i = 0; i < NUI_SKELETON_COUNT; ++i) {
    if ( i == id ){ // draw selected skeleton only
    if (nextSkeletonFrame->SkeletonData[i].eTrackingState == NUI_SKELETON_TRACKED) {
    if ( !drawLabel ) { //show all joints
    for (int j = 0; j < NUI_SKELETON_POSITION_COUNT; ++j) {
    scaleTo(nextSkeletonFrame->SkeletonData[i].SkeletonPositions[j], &xs, &ys);
    jointPos.x = xs;
    jointPos.y = ys;
    circle(*dest, jointPos, 10, CV_RGB(235,30,0),-1);
    }
    }
    else // Draw head joint only with its label
    {
    scaleTo(nextSkeletonFrame->SkeletonData[i].SkeletonPositions[NUI_SKELETON_POSITION_HEAD], &xs, &ys);
    jointPos.x = xs;
    jointPos.y = ys;
    circle(*dest, jointPos, 30, CV_RGB(235,30,220),2);
    int predictedLabel = getSkeletonFaceLabel(i);
    if ( predictedLabel == -1 ) // face not detected
    return;
    // Create the text we will annotate the face with
    string box_text = format("SID=%d", predictedLabel);
    //calculate the position of the annotated text:
    int pos_x = std::max(xs - 40, 0);
    int pos_y = std::max(ys - 40, 0);
    // Put the text in the image
    putText(*dest, box_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(235,30,0), 2.0);
    }
    }
    }
    }
    }


    /*
    Assigns the given label to the corresponding head position in the skeleton data.
    */
    void assignFaceToSkeleton(Point headPoint, int fLabel)
    {
    int x1 = 0 ,y1 = 0;

    for (int i = 0 ; i < NUI_SKELETON_COUNT; i++ )
    {
    float dThreshold = 15; // distance :50
    if (m_bArrSkeletonsTracked[i] && !skeletonHasFaceLabel(i)) // if skeleton is tracked, and not has label yet:
    {
    // obtain the head joint position coordiates
    x1 = (int) nextSkeletonFrame->SkeletonData[i].SkeletonPositions[NUI_SKELETON_POSITION_HEAD].x;
    y1 = (int) nextSkeletonFrame->SkeletonData[i].SkeletonPositions[NUI_SKELETON_POSITION_HEAD].y;
    // see if any of detected face coordinates mathes(close enough)
    float dist = sqrt ((float) ((x1 - headPoint.x)^2 + (y1 - headPoint.y)^2));
    if (dist <= dThreshold)
    {
    dThreshold = dist;
    skeletonHasFaceId[i] = true;
    sklBelongsToFaceId[i] = fLabel;
    }

    }
    }
    return;
    }

    /*
    Performs a face detection in the given image and finds the faces.
    */
    void detecFaces(Mat *original)
    {
    /* Recognition */
    //convert current image to grayscale
    Mat gray;
    cvtColor(*original, gray, CV_BGR2GRAY);

    //find the faces in the frame
    vector< Rect_<int> > faces;
    CvPoint faceCenter = cvPoint(0,0); // Detected face coordinates in RGB image.

    /* To speed up: */
    //1. reduce the size of the gray image before feeding to haar_cascade if the faces are much larger than 24x24 pixels:
    //find:small_image at http://www710.univ-lyon1.fr/~bouakaz/OpenCV-0.9.5/docs/ref/OpenCVRef_Experimental.htm
    int downgradeScale = 2; // subject to change to 4? if using 1280x960 resolution.
    Mat small_gray;
    // Downscale the image:
    pyrDown(gray, small_gray, cvSize(gray.cols/downgradeScale, gray.rows/downgradeScale));

    // Search the faces in downscaled gray image:
    if (modelName == "LBPH" || modelName == "lbph") {
    haar_cascade.detectMultiScale(small_gray, faces, 1.2, 3, CV_HAAR_DO_CANNY_PRUNING, Size(50,50));
    } else {
    haar_cascade.detectMultiScale(small_gray, faces, 1.2, 3, CV_HAAR_DO_ROUGH_SEARCH | CV_HAAR_DO_CANNY_PRUNING |
    CV_HAAR_SCALE_IMAGE, Size(40, 40)); // , Size(150,150): max size
    }

    // At this point we have the position of faces in faces.
    // Now, we;ll get the faces, make a prediction and annotate
    // it in the video. Coooooool!


    for (int i = 0; i < faces.size(); i++) {
    // Process face by face
    // scale up then crop
    Rect face_i;
    face_i.x = faces[i].x * downgradeScale;
    face_i.width = faces[i].width * downgradeScale;
    face_i.y = faces[i].y * downgradeScale;
    face_i.height = faces[i].height * downgradeScale;
    //Crop the face from the image, so simple with opencv
    Mat face = gray(face_i);
    // Return the image to the original size? and then feed to the prediction.


    int prediction = -1;
    double confidence = 0.0;
    if (modelName == "LBPH" || modelName == "lbph") {
    //prediction = model->predict(face);
    model->predict(face, prediction, confidence);
    }
    else
    {
    // FOR FISHER and EIGEN MODEL
    // Resizing the face is necessary for Fisgerfaces and Eigrnfaces, but not
    // for Local Binary Pattern Histograms. So this part depends on the algorithm used.
    Mat face_resized;

    ///********* forget: (corrected: seems legit?)Probelmatic!? ONLY RESIZE THE FACE NOT HOLE IMAGE:Size(training_im_width, training_im_height)
    cv::resize(face, face_resized,Size(training_im_width, training_im_height), 1.0, 1.0, INTER_CUBIC);
    // Now perform the prediction
    //prediction = model->predict(face_resized);
    model->predict(face_resized, prediction, confidence);
    face_resized.release();
    }

    cout << modelName <<" -> Predicted: "<< prediction<< " with confidence: "<< confidence << endl;
    // And finally write all we;ve found to the original image.
    // First, draw a green rectangle arud the detected face:

    CvPoint faceRectP1 = cvPoint(face_i.x, face_i.y);
    CvPoint faceRectP2 = cvPoint((face_i.x+face_i.width),
    (face_i.y+face_i.height));
    Rect fRect = Rect(faceRectP1, faceRectP2);

    rectangle(*original, faceRectP1, faceRectP2, CV_RGB(0,255,0), 3);

    // get the face center
    faceCenter.x = ( faceRectP1.x + faceRectP2.x ) / 2;
    faceCenter.y = ( faceRectP2.y + faceRectP2.y ) /2;

    // Create the text we will annotate the face with
    string box_text = format("P=%d", prediction);

    //calculate the position of the annotated text:
    int pos_x = std::max(face_i.tl().x - 10, 0);
    int pos_y = std::max(face_i.tl().y - 10, 0);

    // Put the text in the image
    putText(*original, box_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 2.0, CV_RGB(0,255,0), 3.0);
    //cout << " Face Position of RGB Image " << i << " at : (" << faceCenter.x << ", " << faceCenter.y << ")\n";

    /* Detect eyes*/
    /*
    vector<Rect> eyes;
    eye_cascade.detectMultiScale(face, eyes, 1.1, 2,
    0|CV_HAAR_SCALE_IMAGE, Size(5,5) );
    for ( int j = 0; j < eyes.size(); j++ )
    {
    Point center ( faces[i].x + eyes[j].x + eyes[j].width*0.5,
    faces[i].y + eyes[j].y + eyes[j].height*0.5);
    int radius = cvRound( (eyes[j].width + eyes[j].height*0.25));
    circle(*original,center, radius, Scalar(30, 150, 220), 4, 8, 0);
    }
    */
    //assign face to a skeleton
    assignFaceToSkeleton(Point(pos_x, pos_y), prediction);

    face.release();
    }
    }

    /*
    Draws all of the available skeletons.
    */
    void drawAllSkeletons (Mat *anImage)
    {
    for (int i = 0; i < NUI_SKELETON_COUNT; i++ )
    {
    drawSkeletonByID(i, anImage, false);
    }
    }

    /*
    Check if a file already exists with the given name.
    */
    bool fileExist(string filename)
    {
    GetFileAttributes(filename.c_str());
    if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(filename.c_str()) && GetLastError() == ERROR_FILE_NOT_FOUND)
    return false;
    return true;
    }


    int main() {

    if (!initKinect()) return 1;
    Sleep(1000); // Wait for initialization

    // if we are taking the images for traing purpose, enter to the picture mode.
    // The program terminates once the operation is done. To start over change the
    // status to "pictureMode = false".
    if (pictureMode)
    {
    saveImages(pictureOwner);
    //cout << "Finished saving images." << endl;
    //system("pause");
    exit(0);
    }
    // Load images and corresponding labels:
    try {
    read_csv(fn_csv, images, labels);
    } catch(cv::Exception& e) {
    cerr <<"Error opening file \""<<fn_csv << "\". Reason: " <<e.msg << endl;
    system("pause");
    exit(1);
    }

    //Quit if there are not enough images for training.
    if (images.size() <= 1) {
    string error_message = "This demo needs at least 2 images to work. Please add more images.";
    CV_Error(CV_StsError, error_message);
    system("pause");
    }

    //get the hight from first image. We'll need this later in code to reshape
    // the incoming images to their original size:
    training_im_width = images[0].cols;
    training_im_height = images[0].rows;

    // To save or load the model with name
    //string modelStr = format("%s-model.yml", modelName);
    string modelStr = modelName + "_model.yml";
    /***********************************************************************************/
    if ( modelName == "Fisher" || modelName == "fisher")
    model = createFisherFaceRecognizer();
    else if (modelName == "Eigen" || modelName == "eigen")
    model = createEigenFaceRecognizer();
    else if (modelName == "LBPH" || modelName == "lbph")
    model = createLBPHFaceRecognizer();
    else {
    cout << "Please provide a valid recognizer type:" << endl;
    cout << "\"Fisher\", \"Eigen\" or \"LBPH\"" << endl;
    system("pause");
    exit(1);
    }


    // Now we are going to use the haar cascade you have specified in the command line
    if (modelName == "LBPH" || modelName == "lbph") {
    haar_cascade.load(fn_lbp);
    } else {
    haar_cascade.load(fn_haar);
    }
    if( !eye_cascade.load(eye_cascade_name)) {printf(" Error loading eye cascade"); return -1;}
    if ( cropMode )
    {
    Mat frame = images[images.size() - 1];
    images.pop_back();

    imshow("Poped Image", frame);
    waitKey(10);
    Mat cropped = CropFaces(frame);
    //imshow("cropped", cropped);
    waitKey(0);

    exit(1);
    }
    // Training Phase
    if (!useExistingModel) {
    // train a new model
    cout << "Training a new recognizer of type " << modelName << " model." << endl;
    // Train the model
    model->train(images, labels);
    // Save the trained madel
    model->save(modelStr);
    } else {
    // load the existing model
    cout << "Loading the existing recognizer of type " << modelName<< " model." << endl;
    model->load(modelStr);
    cout << "Loading finished.\n";
    }

    // requirements for recording the video
    VideoWriter vid_unlabeled, vid_labeled, vid_skeleton;
    Size vidSize = Size(imgWidth, imgWidth);
    int codec = CV_FOURCC('F', 'L', 'V', '1');//CV_FOURCC('M', 'J', 'P', 'G');
    int fps = 4;

    /**************************************/
    // Go!

    // If video recording is on, prepare ..
    if ( writeToVideo )
    {
    string pname = "oldLady"; // name of the person who is acting in the kitchen
    string vidName_unlabeled = format("%s_unlabeledVideo.avi",pname.c_str());
    string vidName_labeled = format("%s_LabeledVideo.avi", pname.c_str());
    string vidName_skeleton = format("%s_skeletonVideo.avi", pname.c_str());

    // check that the video file name not already exists.
    if ( fileExist( vidName_labeled.c_str()) || fileExist(vidName_skeleton.c_str()) || fileExist(vidName_unlabeled.c_str()) )
    {
    cout << "Error! Avi file already exist! Change the file name and ";
    system("pause");
    return -8;
    }

    vid_unlabeled.open(vidName_unlabeled, codec , fps, vidSize, true);
    if ( !vid_unlabeled.isOpened())
    {
    cout << "Error opening "<<vidName_unlabeled << " ";
    system("pause"); return -1;
    }

    vid_labeled.open(vidName_labeled, codec, fps, vidSize, true);
    if ( !vid_labeled.isOpened())
    {
    cout << "Error opening "<<vidName_labeled << " ";
    system("pause"); return -1;
    }
    vid_skeleton.open(vidName_skeleton, codec, fps, vidSize, true);
    if ( !vid_skeleton.isOpened())
    {
    cout << "Error opening "<<vidName_skeleton << " ";
    system("pause"); return -1;
    }

    }



    for (;;) {
    int tic = (int) (clock()); // start time
    if ( useBigPic)
    {
    getKinectSkeletalData();
    getKinectColorData(kinectColorImageBig);
    Mat originalBig(kinectColorImageBig);
    Mat rs;
    resize(originalBig, rs, Size(imgWidth, imgHeight));


    Mat imSkeleton = rs.clone();
    Mat rgbImage = originalBig.clone();

    detecFaces(&rgbImage);
    drawAllSkeletons(&imSkeleton);
    Mat rgb_rsz;
    resize(rgbImage, rgb_rsz, Size(imgWidth, imgHeight));
    for ( int i = 0; i < NUI_SKELETON_COUNT; i++ )
    {
    if ( skeletonAvailable(i) && skeletonHasFaceLabel(i) )
    drawSkeletonByID( i , &rgb_rsz, true);
    }
    /*Mat rgb_rsz;
    resize(rgbImage, rgb_rsz, Size(640,480));*/


    /* Write to video files */


    // Get the elapsed time
    int t_elapsed = clock() / CLOCKS_PER_SEC;
    string t_string = format("Elapsed time: %d", t_elapsed);
    putText(rgb_rsz, t_string, Point(300, 100), CV_FONT_HERSHEY_PLAIN, 2.0, Scalar(255, 0, 0), 2);


    if ( writeToVideo )
    {
    Mat aFrame;
    // convert the color, otherwise videowriter does not work.
    cvtColor(rs, aFrame, CV_RGB2BGR);
    // conver back again to retain the original colors
    cvtColor(aFrame, aFrame, CV_BGR2RGB);
    resize(aFrame, aFrame, vidSize);
    //imshow("aFrame", aFrame);
    //waitKey(10);

    vid_unlabeled << aFrame;
    vid_unlabeled << aFrame;
    vid_unlabeled << aFrame;
    vid_unlabeled << aFrame;

    Mat sFrame;
    cvtColor(imSkeleton, sFrame, CV_RGB2BGR);
    cvtColor(sFrame, sFrame, CV_BGR2RGB);
    // resize the image to be square (height = width), otherwise videowriter doesnt work.
    resize(sFrame, sFrame, vidSize);
    vid_skeleton << sFrame;
    vid_skeleton << sFrame;
    vid_skeleton << sFrame;
    vid_skeleton << sFrame;
    //waitKey(30);

    Mat rgb_vid;
    resize(rgb_rsz, rgb_vid, vidSize);
    cvtColor(rgb_vid, rgb_vid, CV_RGB2BGR);
    cvtColor(rgb_vid, rgb_vid, CV_BGR2RGB);
    vid_labeled << rgb_vid;
    vid_labeled << rgb_vid;
    vid_labeled << rgb_vid;
    vid_labeled << rgb_vid;
    //waitKey(30);

    }
    //imshow("Face recognizer(Esc to exit)", rgb_rsz);
    // put images together
    //
    //Mat twoImages = Mat::zeros(Size(imgWidth*2+3, imgHeight), rgb_rsz.type());
    //Rect roi = Rect(0,0, imgWidth, imgHeight);
    //Mat roiImage = twoImages(roi);
    //rs.copyTo(roiImage);
    //// move roi
    //roi.x = roi.x + imgWidth+2;
    //roiImage = twoImages(roi);
    //rgb_rsz.copyTo(roiImage);
    //namedWindow("Skeleton Joints(Esc to exit)", CV_WINDOW_AUTOSIZE);
    //imshow("Skeleton Joints(Esc to exit)", twoImages);
    //

    namedWindow("Skeleton Joints(Esc to exit)", CV_WINDOW_AUTOSIZE);
    resize(imSkeleton, imSkeleton, Size(320, 240));
    imshow("Skeleton Joints(Esc to exit)", imSkeleton);
    namedWindow("Face recognizer(Esc to exit)", CV_WINDOW_AUTOSIZE);
    imshow("Face recognizer(Esc to exit)",rgb_rsz);


    //cout << t_elapsed << endl;

    // convert the RGB image to BGR, otherwise videowriter won't work!!


    char key = (char) waitKey(30);
    // Exit the loop on escape:
    if (key == 27)
    {
    vid_unlabeled.release();
    vid_labeled.release();
    vid_skeleton.release();
    break;
    }


    //clean-up
    originalBig.release();
    imSkeleton.release();
    //rgb_rsz.release();
    rs.release();

    int toc = (int) (clock()); // end time
    cout << " One cycle done in "<< toc - tic << " miliseconds" << endl;


    }
    else // normal size images
    {
    getKinectSkeletalData();
    getKinectColorData(kinectColorImage);
    Mat original(kinectColorImage);

    Mat imSkeleton = original.clone();
    Mat rgbImage = original.clone();

    detecFaces(&rgbImage);
    drawAllSkeletons(&imSkeleton);

    for ( int i = 0; i < NUI_SKELETON_COUNT; i++ )
    {
    if ( skeletonAvailable(i) && skeletonHasFaceLabel(i) )
    drawSkeletonByID( i , &rgbImage, true);
    }


    // Show the result
    namedWindow("Skeleton Joints(Esc to exit)", CV_WINDOW_AUTOSIZE);
    imshow("Skeleton Joints(Esc to exit)", imSkeleton);
    namedWindow("Face recognizer(Esc to exit)", CV_WINDOW_AUTOSIZE);
    imshow("Face recognizer(Esc to exit)", rgbImage);

    char key = (char) waitKey(10);
    // Exit the loop on escape:
    if (key == 27)
    break;

    //clean-up
    original.release();
    imSkeleton.release();
    rgbImage.release();
    }
    //vid_unlabeled.release();
    //vid_labeled.release();
    }

    return 0;
    }