#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
#include "GCoptimization.h"

#include "opencv/cv.h"
#include "opencv/highgui.h"
#include "opencv/ml.h"

using namespace cv;

#include <vector>
#include <iostream>
#include <limits>

using namespace std;

#define __PI 3.14159265

void graphcut(Mat& featureVec, Mat& im, int num_lables) {
    Mat lables, centers;
    cout << "Kmeans: #centers = " << num_lables << ",#tries = 2...";
    kmeans(featureVec,
        num_lables,
        lables,
        TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 200, 0.0001),
        2,
        KMEANS_PP_CENTERS,centers);
    cout << "Done" << endl;

    for (int i = 0; i<num_lables; i++) {
        cout << "center " << i << ": ";
        for (int j = 0; j<centers.cols; j++) cout << centers.at<float>(i, j) << ",";
        cout << endl;
    }

#ifdef BTM_DEBUG
    {
        Mat _tmp = lables.reshape(1, im.rows);
        Mat _tmpUC;
        _tmp.convertTo(_tmpUC, CV_8UC1, 255.0 / (double)num_lables);
        imshow("tmp", _tmpUC);
        waitKey();
    }
#endif

    GCoptimizationGridGraph *gc = new GCoptimizationGridGraph(im.cols, im.rows, num_lables);

    Mat _d(featureVec.size(), CV_32FC1);

    for (int center = 0; center < num_lables; center++) {
        _d.setTo(Scalar(0));
        int count = 0;
        for (int i = 0, ii = 0; i<featureVec.rows; i++) {
            if (((int*)lables.data)[i] == center) {
                float* dptr = (float*)(_d.data + _d.step * (ii++));
                float* fptr = (float*)(featureVec.data + featureVec.step * i);

                for (int j = 0; j<featureVec.cols; j++) {
                    dptr[j] = fptr[j];
                }

                count++;
            }
        }

        Mat d = _d(Rect(0, 0, _d.cols, count));

        Mat covar;
        calcCovarMatrix(d, covar, Mat(), CV_COVAR_NORMAL + CV_COVAR_ROWS, CV_32F);

        Mat icv = covar.inv();
        Mat centerRepeat;
        repeat(centers(Rect(0, center, centers.cols, 1)), featureVec.rows, 1, centerRepeat);
        Mat diff = featureVec - centerRepeat; //difference between each pixel's value and it's center's value

        Mat A = (diff*icv).mul(diff) * 0.5f;
        for (int i = 0; i<A.rows; i++) {
            float* _ptr = (float*)(A.data + A.step * i);
            float cost = 0;

            for (int j = 0; j<A.cols; j++) {
                cost += _ptr[j];
            }

            int icost = MAX(0, (int)floor(-log(cost)));
            gc->setDataCost(i, center + 1, icost);
        }
    }

    //int *smooth = new int[num_lables*num_lables];
    //int cost;
    //for ( int l1 = 0; l1 < num_lables; l1++ )
    //  for (int l2 = 0; l2 < num_lables; l2++ ){
    //      cost = (l1-l2)*(l1-l2) <= 4  ? (l1-l2)*(l1-l2):4;
    //      //Mat _a = centers(Rect(0,l1,centers.cols,1)) - centers(Rect(0,l2,centers.cols,1));
    //      //float n = (float)norm(_a);
    //      //if(n==0)  cost = 0;
    //      //else      cost = (int)ceil(-log(n));
    //      smooth[l1+l2*num_lables] = cost;
    //  }


    //Mat gk = getGaussianKernel(3,-1,CV_32F);
    //gk = gk * gk.t();
    //cv::Sobel(gk,gk,-1,1,0);
    Mat gray; cvtColor(im, gray, CV_RGB2GRAY);
    //imshow("tmp",gray); waitKey();
    gray.convertTo(gray, CV_32FC1, 1.0f / 255.0f);
    //imshow("tmp",gray); waitKey();

    Mat grayInt, grayInt1;
    {
        Mat _tmp;
        //filter2D(gray,_tmp,CV_32F,gk);
        Sobel(gray, _tmp, -1, 1, 0);    //sobel for dx
        //Canny(gray,_tmp,50.0,150.0);
        _tmp = abs(_tmp);
#ifdef BTM_DEBUG
        imshow("tmp", _tmp); waitKey();
#endif
        double maxVal, minVal;
        minMaxLoc(_tmp, &minVal, &maxVal);
        cv::log((_tmp - minVal) / (maxVal - minVal), _tmp);
        _tmp = -_tmp * 0.35;

        _tmp.convertTo(grayInt, CV_32SC1);

        //grayInt = grayInt * 5;

        //filter2D(gray,_tmp,CV_32F,gk.t());
        Sobel(gray, _tmp, -1, 0, 1);    //sobel for dy
        //Canny(gray,_tmp,50.0,150.0);
        _tmp = abs(_tmp);
#ifdef BTM_DEBUG
        imshow("tmp", _tmp); waitKey();
#endif
        minMaxLoc(_tmp, &minVal, &maxVal);
        cv::log((_tmp - minVal) / (maxVal - minVal), _tmp);
        _tmp = -_tmp * 0.35;
        _tmp.convertTo(grayInt1, CV_32SC1);

        //grayInt1 = grayInt1 * 5;
    }

    //// next set up spatially varying arrays V and H
    //int *V = new int[featureVec.rows];
    //int *H = new int[featureVec.rows];

    //
    //for ( int i = 0; i < featureVec.rows; i++ ){
    //  //H[i] = i+(i+1)%im.rows;
    //  //V[i] = i*(i+im.cols)%im.cols;
    //  H[i] = 1;
    //  V[i] = 1;
    //}

    Mat Sc = 10 * (Mat::ones(num_lables, num_lables, CV_32SC1) - Mat::eye(num_lables, num_lables, CV_32SC1));

    gc->setSmoothCostVH((double*)(Sc.data), (double*)grayInt.data, (double*)grayInt1.data);
    //gc->setSmoothCost((int*)(Sc.data));

    while (true) {
        printf("\nBefore optimization energy is %d", gc->compute_energy());
        gc->expansion(1);// run expansion for 2 iterations. For swap use gc->swap(num_iterations);
        printf("\nAfter optimization energy is %d", gc->compute_energy());

        for (int i = 0; i < featureVec.rows; i++)
            ((int*)(lables.data + lables.step * i))[0] = gc->whatLabel(i);

        {
            Mat _tmp = lables.reshape(1, im.rows);
#ifdef BTM_DEBUG
            {
                Mat _tmpUC;
                _tmp.convertTo(_tmpUC, CV_8UC1, 255.0 / (double)num_lables);
                vector<Mat> chns; split(im, chns);
                for (unsigned int ch = 0; ch<chns.size(); ch++)
                {
                    chns[ch] = /*chns[ch] + */(_tmp == ch)/**0.5*/;
                }
                cv::merge(chns, _tmpUC);
                imshow("tmp", _tmpUC);
                int c = waitKey();
                if (c == 'q') break;
            }
#endif
        }
    }

    delete gc;
    //delete[] smooth;
    //delete[] V;
    //delete[] H;

    //printf("%d\n",reshaped.rows);
}


void graphcut1(Mat& im, Mat& probs, Mat& dx, Mat& dy, int num_lables, Mat& lables = Mat()) {
    GCoptimizationGridGraph gc(im.cols, im.rows, num_lables);

    int N = im.cols*im.rows;
    //probs = probs.reshape(1,N);
    double log2 = log(1.3);
    for (int i = 0; i<N; i++) {
        double* ppt = probs.ptr<double>(i);
        for (int l = 0; l<num_lables; l++) {
            int icost = MAX(0, (int)floor(-log(ppt[l]) / log2));
            gc.setDataCost(i, l, icost);
        }
    }

    Mat Sc = 5 * (Mat::ones(num_lables, num_lables, CV_32SC1) - Mat::eye(num_lables, num_lables, CV_32SC1));
    //int score[9] = {0,50,50,
    //              50,0,50,
    //              50,50,0};
    gc.setSmoothCostVH((double*)(/*score*/Sc.data), (double*)dx.data, (double*)dy.data);

    lables.create(N, 1, CV_8UC1);

    while (true) {
        printf("\nBefore optimization energy is %d\n", gc.compute_energy());
        gc.expansion(1);// run expansion for 2 iterations. For swap use gc->swap(num_iterations);
        printf("\nAfter optimization energy is %d\n", gc.compute_energy());

        for (int i = 0; i < N; i++)
            ((uchar*)(lables.data + lables.step * i))[0] = gc.whatLabel(i);

        {
            Mat _tmp = lables.reshape(1, im.rows);
            {
                vector<Mat> chns(3);
                for (unsigned int ch = 0; ch<chns.size(); ch++) chns[ch] = (_tmp == ch);
                Mat _tmpUC; cv::merge(chns, _tmpUC);
                imshow("tmp", _tmpUC);
                cout << "Press 'q' to finish GC iterations" << endl;
                int c = waitKey();
                if (c == 'q') break;
            }
        }
    }


}

int selectedRange = 0;
Range rs[6] = { Range(40, 164), Range(56, 149), Range(192, 241), Range(32, 185), Range(16, 169), Range(163, 206) };
bool draw = false;

void on_mouse(int event, int x, int y, int flags, void* param)
{
    Mat* pm = (Mat*)param;
    switch (event)
    {
    case CV_EVENT_LBUTTONDOWN:
    {
        rs[selectedRange * 2].start = min(max(0, y), pm->cols - 1);
        rs[selectedRange * 2 + 1].start = min(max(0, x), pm->rows - 1);
        cout << "Begin " << x << "," << y << endl;
        draw = true;
    }
        break;
    case CV_EVENT_RBUTTONDOWN:

        break;
    case CV_EVENT_LBUTTONUP:
    {
        rs[selectedRange * 2].end = min(max(0, y), pm->cols - 1);
        rs[selectedRange * 2 + 1].end = min(max(0, x), pm->rows - 1);
        cout << "End " << x << "," << y << endl;
        draw = false;
    }
        break;
    case CV_EVENT_RBUTTONUP:

        break;
    case CV_EVENT_MOUSEMOVE:
        if (draw) {
            Mat _tmp; (*((Mat*)param)).copyTo(_tmp);
            if (selectedRange != 0)
                rectangle(_tmp, Point(rs[1].start, rs[0].start), Point(rs[1].end, rs[0].end), Scalar(255, 0, 0), 2);
            else
                rectangle(_tmp, Point(rs[1].start, rs[0].start), Point(x, y), Scalar(255, 0, 0), 2);
            if (selectedRange != 1)
                rectangle(_tmp, Point(rs[3].start, rs[2].start), Point(rs[3].end, rs[2].end), Scalar(0, 255, 0), 2);
            else
                rectangle(_tmp, Point(rs[3].start, rs[2].start), Point(x, y), Scalar(0, 255, 0), 2);
            imshow("tmp1", _tmp);
        }
        break;
    }
}

void getEdges(Mat& gray, Mat& grayInt, Mat& grayInt1) {
    Mat _tmp, _tmp1, gray32f, res;

    gray.convertTo(gray32f, CV_32FC1, 1.0 / 255.0);

    GaussianBlur(gray32f, gray32f, Size(11, 11), 0.75);

    Sobel(gray32f, _tmp, -1, 1, 0, 3);  //sobel for dx
    //Sobel(gray32f,_tmp1,-1,1,0,3,-1.0);   //sobel for -dx
    //_tmp = abs(_tmp) + abs(_tmp1);
    //_tmp.copyTo(_tmp,(_tmp > 0.0));
    //_tmp1.copyTo(_tmp1,(_tmp1 > 0.0));
    _tmp1 = abs(_tmp); // + (_tmp1 == 0.0);
    _tmp1.copyTo(res, (_tmp1 > 0.2));
    //res = -res + 1.0;

    imshow("tmp", res);

    double maxVal, minVal;
    minMaxLoc(_tmp, &minVal, &maxVal);
    cv::log(/*(_tmp - minVal) / (maxVal - minVal)*/res, _tmp);
    _tmp = -_tmp * 0.17;
    _tmp.convertTo(grayInt1, CV_32SC1);

    Sobel(gray32f, _tmp, -1, 0, 1, 3);  //sobel for dy
    //Sobel(gray32f,_tmp1,-1,0,2,3,-1.0);   //sobel for -dy
    //_tmp = abs(_tmp) + abs(_tmp1);
    //_tmp = (_tmp + _tmp1 + 2.0) / 4.0;
    _tmp1 = abs(_tmp);
    res.setTo(Scalar(0));
    _tmp1.copyTo(res, (_tmp1 > 0.2));
    //res = -res+1.0;

    imshow("tmp1", res); waitKey();

    minMaxLoc(_tmp, &minVal, &maxVal);
    cv::log(/*(_tmp - minVal) / (maxVal - minVal)*/res, _tmp);
    _tmp = -_tmp * 0.17;
    _tmp.convertTo(grayInt, CV_32SC1);

}

void doEM3D(Mat& _im, Mat& probs, int num_models = 2, int num_gaussians = 3, bool useRanges = true) {
    Mat im = _im;
    vector<CvEM> model(num_models);
    CvEMParams  ps(num_gaussians);

    imshow("tmp1", im);

    vector<Mat> samples(num_models);
    while (true) {
        if (useRanges) {
            cout << "Define ranges (press <space> to continue)" << endl;
            while (true) {
                int c = waitKey();
                if (c == ' ') break;
                else selectedRange = c - '1';
                cout << "Selected range: " << selectedRange << endl;
            }

            vector<Mat> splitted;
            for (int i = 0; i<num_models; i++) {
                Mat _tmp; im(rs[i * 2], rs[i * 2 + 1]).copyTo(_tmp);
                _tmp.reshape(1, _tmp.rows*_tmp.cols).convertTo(samples[i], CV_32FC1, 1.0 / 255.0);
            }
        }

        for (int i = 0; i<num_models; i++) {
            model[i].clear();
            model[i].train(samples[i], Mat(), ps, NULL);

            cout << "Model " << i << " means: ";
            const CvMat* m = model[i].get_means();
            for (int g = 0; g<num_gaussians; g++) {
                for (int c = 0; c<3; c++) cout << m->data.db[g * 3 + c] << ", ";
                cout << endl;
            }
            cout << endl;
        }

        Mat out_lables(im.size(), CV_32FC1);
        float _s[3];
        Mat sample(1, 3, CV_32FC1, &_s);

        probs = Mat(im.rows*im.cols, num_models, CV_64FC1);
        {
            Mat _tmp(1, 2, CV_64FC1);
            for (int y = 0; y<im.rows; y++) {
                uchar* imp = im.ptr<uchar>(y);
                float* outl_ptr = out_lables.ptr<float>(y);
                int probs_mult = y*im.cols;
                for (int x = 0; x<im.cols; x++) {
                    float _label, maxv = std::numeric_limits<float>::min();
                    double p;
                    int probs_mult1 = x*num_models;
                    for (int i = 0; i<num_models; i++) {
                        float ps[3];
                        for (int c = 0; c<3; c++) {
                            _s[c] = ((float)imp[c + x * 3]) / 255.0f;
                        }

                        Mat X; sample.copyTo(X);
                        Mat xprob;
                        model[i].predict(X, &xprob);
                        double* w = model[i].get_weights()->data.db;
                        p = std::numeric_limits<double>::min();
                        for (int g = 0; g<num_gaussians; g++) p = max(p, w[g] * (double)(((float*)xprob.data)[g]));

                        probs.at<double>(probs_mult + x, i) = p;
                        if (p>maxv) { maxv = p; _label = (float)i; }
                    }
                    outl_ptr[x] = _label;
                }
            }
        }

        {
            Mat _tmp(im.size(), CV_8UC1);
            out_lables.convertTo(_tmp, CV_8UC1);
            vector<Mat> vm(3); for (int i = 0; i<3; i++) vm[i] = (_tmp == i);
            Mat out; merge(vm, out);
            imshow("tmp", out);

            if (num_models == 3)
                imshow("tmp2", probs.reshape(num_models, im.rows));
        }

        cout << "Press any key for another round or 'q' to finish" << endl;
        int c = waitKey();
        if (c == 'q') break;
    }
}

/**
* if useRanges is true, use the mouse to define ranges, else use the labeling from lables
* to train the GMM
*/
void doEM1D(Mat& _im, Mat& probs, int num_models = 2, bool useRanges = true, Mat& lables = Mat()) {
    //Mat im; cvtColor(_im,im,CV_RGB2HSV);
    Mat im = _im;
    vector<vector<CvEM>> model(num_models);
    for (int i = 0; i<num_models; i++) {
        model[i] = vector<CvEM>(3);
    }
    double CvEMParams;
    double ps(1);

    imshow("tmp1", im);

    vector<vector<Mat>> samples(num_models);
    for (int i = 0; i<num_models; i++) samples[i] = vector<Mat>(3);
    while (true) {
        if (useRanges) {
            cout << "Define ranges (press <space> to continue)" << endl;
            while (true) {
                int c = waitKey();
                if (c == ' ') break;
                else selectedRange = c - '1';
                cout << "Selected range: " << selectedRange << endl;
            }

            vector<Mat> splitted;
            for (int i = 0; i<num_models; i++) {
                int cnt = 0;
                Mat _tmp; im(rs[i * 2], rs[i * 2 + 1]).copyTo(_tmp);
                //Mat __tmp = _tmp.reshape(1,_tmp.rows*_tmp.cols);
                split(_tmp, splitted);
                for (int c = 0; c<3; c++)
                    splitted[c].reshape(1, _tmp.rows*_tmp.cols).convertTo(samples[i][c], CV_32FC1, 1.0 / 255.0);
            }
        }

        for (int i = 0; i<num_models; i++) {
            for (int c = 0; c<3; c++) {
                model[i][c].clear();
                model[i][c].train(samples[i][c], Mat(), ps, NULL);
                //m_probs[i] = model[i].get_probs();
            }

            cout << "Model " << i << " means: ";
            for (int c = 0; c<3; c++) cout << model[i][c].get_means()->data.db[0] << ", ";
            cout << endl;
        }

        Mat out_lables(im.size(), CV_32FC1);
        float _s;
        Mat sample(1, 1, CV_32FC1, &_s);

        probs = Mat(im.rows*im.cols, num_models, CV_64FC1);
        {
            Mat _tmp(1, 2, CV_64FC1);
            for (int y = 0; y<im.rows; y++) {
                uchar* imp = im.ptr<uchar>(y);
                float* outl_ptr = out_lables.ptr<float>(y);
                int probs_mult = y*im.cols;
                for (int x = 0; x<im.cols; x++) {
                    float _label, p, maxv = std::numeric_limits<float>::min();
                    int probs_mult1 = x*num_models;
                    for (int i = 0; i<num_models; i++) {
                        float ps[3];
                        for (int c = 0; c<3; c++) {
                            _s = ((float)imp[c + x * 3]) / 255.0f;
                            //model[i][c].predict(sample,&_tmp);
                            double mu = model[i][c].get_means()->data.db[0];
                            double x = (double)_s;
                            double sigma_sq = model[i][c].get_covs()[0]->data.db[0];
                            double _p = (1 / sqrt(2 * __PI*sigma_sq))*exp(-((x - mu)*(x - mu)) / (2 * sigma_sq));
                            ps[c] = (float)_p; //((double*)_tmp.data)[0];
                        }
                        p = ps[0] * ps[1] * ps[2];
                        //((double*)probs.data + probs_mult + probs_mult1 + i)[0] = p;
                        probs.at<double>(probs_mult + x, i) = p;
                        if (p>maxv) { maxv = p; _label = (float)i; }
                    }
                    outl_ptr[x] = _label;
                }
            }
        }

        {
            Mat _tmp(im.size(), CV_8UC1);
            out_lables.convertTo(_tmp, CV_8UC1);
            vector<Mat> vm(3); for (int i = 0; i<3; i++) vm[i] = (_tmp == i);
            Mat out; merge(vm, out);
            imshow("tmp", out);

            if (num_models == 3)
                imshow("tmp2", probs.reshape(num_models, im.rows));
        }

        cout << "Press any key for another round or 'q' to finish" << endl;
        int c = waitKey();
        if (c == 'q') break;
    }
}

int main(int argc, char** argv) {
    Mat _im = imread("40406598_fd4e74d51c_d.jpg");
    Mat im;
    resize(_im, im, Size(_im.cols / 2, _im.rows / 2));

    rs[4] = Range(0, im.rows - 1);
    rs[5] = Range(0, im.cols - 1);

    namedWindow("tmp");
    namedWindow("tmp1");
    cvSetMouseCallback("tmp1", on_mouse, &im);
    namedWindow("tmp2");

    Mat gray;
    cvtColor(im, gray, CV_RGB2GRAY);

    Mat probs;
    Mat hsv_im; cvtColor(im, hsv_im, CV_BGR2HSV);
    vector<Mat> v; split(hsv_im, v);

    {
        Mat gray32f; gray.convertTo(gray32f, CV_32FC1, 1.0 / 255.0);
        Mat _tmp; Sobel(gray32f, _tmp, -1, 1, 1, 3);
        Mat _tmp1; Sobel(gray32f, _tmp1, -1, 1, 1, 3, -1.0);
        Mat(abs(_tmp) + abs(_tmp1)).convertTo(v[2], CV_8UC1, 255.0);
    }

    Mat combined; cv::merge(v, combined);
    doEM3D(combined, probs, 3);

    Mat dx, dy;
    getEdges(gray, dx, dy);

    Mat lables;
    graphcut1(im, probs, dx, dy, 3, lables);

    char* winnm[3] = { "tmp", "tmp1", "tmp2" };
    for (int i = 0; i<3; i++)
    {
        Mat _tmp; im.copyTo(_tmp, lables == i);
        imshow(string(winnm[i]), _tmp);
    }
    waitKey();

    {
        Mat _tmpLabels = lables.reshape(1, im.rows);
        //find connected components in hair and face masks
        vector<vector<Point>> contours;
        for (int itr = 0; itr<2; itr++) {
            Mat mask = (_tmpLabels == itr);

            contours.clear();
            cv::findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

            //compute areas
            vector<double> areas(contours.size());
            for (unsigned int ai = 0; ai<contours.size(); ai++) {
                Mat _pts(contours[ai]);
                Scalar mp = mean(_pts);

                //bias score according to distance from center face
                areas[ai] = contourArea(Mat(contours[ai]))/* * bias.at<double>(mp.val[1],mp.val[0])*/;
            }

            //find largest connected component
            double max; Point maxLoc;
            minMaxLoc(Mat(areas), 0, &max, 0, &maxLoc);

            //draw back on mask
            _tmpLabels.setTo(Scalar(3), mask);  //all unassigned pixels will have value of 3, later we'll use it

            mask.setTo(Scalar(0)); //clear...
            drawContours(mask, contours, maxLoc.y, Scalar(255), CV_FILLED);

            _tmpLabels.setTo(Scalar(itr), mask);
        }

        lables.setTo(Scalar(2), lables == 3);  //all 3's should be the "other label"
    }

    for (int i = 0; i<3; i++)
    {
        Mat _tmp; im.copyTo(_tmp, lables == i);
        imshow(string(winnm[i]), _tmp);
    }
    waitKey();

    return 0;
}

Error 1 error C2065: 'CvEM': undeclared identifier c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 341 1 ConsoleApplication3 
Error 2 error C2923: 'std :: vector': 'CvEM' is not a valid type template argument for parameter '_Ty' c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 341 1 ConsoleApplication3 
Error 3 error C2514: 'std :: vector': class has no constructor c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 341 1 ConsoleApplication3 
Error 4 error C2678: '[' binary: no operator found which takes a left operand of type 'std :: vector' (or there is no acceptable conversion) c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 365 1 consoleApplication3 
Error 5 error C2228: left of '.clear' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 365 1 ConsoleApplication3 
Error 6 error C2678: '[' binary: no operator found which takes a left operand of type 'std :: vector' (or there is no acceptable conversion) c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 366 1 consoleApplication3 
Error 7 error C2228: left of '.train' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 366 1 ConsoleApplication3 
Error 8 error C2678: '[' binary: no operator found which takes a left operand of type 'std :: vector' (or there is no acceptable conversion) c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 369 1 consoleApplication3 
Error 9 error C2228: left of '.get_means' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 369 1 ConsoleApplication3 
Error 10 error C2678: '[' binary: no operator found which takes a left operand of type 'std :: vector' (or there is no acceptable conversion) c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 400 1 consoleApplication3 
Error 11 error C2228: left of '.predict' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 400 1 ConsoleApplication3 
Error 12 error C2678: '[' binary: no operator found which takes a left operand of type 'std :: vector' (or there is no acceptable conversion) c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 401 1 consoleApplication3 
Error 13 error C2228: left of '.get_weights' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 401 1 ConsoleApplication3 
Error 14 error C2227: left of the party '-> data' must point to a class / struct / union / generic c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 401 1 ConsoleApplication3 
Error 15 error C2228: left of '.db' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 401 1 ConsoleApplication3 
Warning 16 warning C4244: '=': conversion from 'double' to 'float', possible loss of data c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 406 1 ConsoleApplication3 
Error 17 error C2065: 'CvEM': undeclared identifier c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 437 1 ConsoleApplication3 
Error 18 error C2923: 'std :: vector': 'CvEM' is not a valid type template argument for parameter '_Ty' c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 437 1 ConsoleApplication3 
Error 19 error C3203: 'vector': Model unskilled class can not be used as a template argument for the template parameter _Ty; actual expected type c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 437 1 ConsoleApplication3 
Error 20 error C2065: 'CvEM': undeclared identifier c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 439 1 ConsoleApplication3 
Error 21 error C2923: 'std :: vector': 'CvEM' is not a valid type template argument for parameter '_Ty' c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 439 1 ConsoleApplication3 
Error 22 error C2955: 'std :: vector': use of class template requires template argument list c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 439 1 ConsoleApplication3 
Error 23 error C2109: an index requires an array or pointer type c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 471 1 ConsoleApplication3 
Error 24 error C2228: left of '.clear' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 471 1 ConsoleApplication3 
Error 25 error C2109: an index requires an array or pointer type c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 472 1 ConsoleApplication3 
Error 26 error C2228: left of '.train' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 472 1 ConsoleApplication3 
Error 27 error C2109: an index requires an array or pointer type c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 477 1 ConsoleApplication3 
Error 28 error C2228: left of '.get_means' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 477 1 ConsoleApplication3 
Error 29 error C2227: left of the party '-> data' must point to a class / struct / union / generic c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 477 1 ConsoleApplication3 
Error 30 error C2228: left of '.db' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 477 1 ConsoleApplication3 
Error 31 error C2109: an index requires an array or pointer type c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 500 1 ConsoleApplication3 
Error 32 error C2228: left of '.get_means' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 500 1 ConsoleApplication3 
Error 33 error C2227: left of the '-> data' must point to a class / struct / union / generic c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 500 1 ConsoleApplication3 
Error 34 error C2228: left of '.db' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 500 1 ConsoleApplication3 
Error 35 error C2109: an index requires an array or pointer type c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 502 1 ConsoleApplication3 
Error 36 error C2228: left of '.get_covs' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 502 1 ConsoleApplication3 
Error 37 error C2227: left of the party '-> data' must point to a class / struct / union / generic c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 502 1 ConsoleApplication3 
Error 38 error C2228: left of '.db' must have class / struct / union c: \ users \ s \ documents \ visual studio 2013 \ projects \ consoleapplication3 \ consoleapplication3 \ graphcut.cpp 502 1 ConsoleApplication3 
39 IntelliSense: identifier "CvEM" undefined c: \ Users \ s \ Documents \ Visual Studio 2013 \ Projects \ ConsoleApplication3 \ ConsoleApplication3 \ graphcut.cpp 341 9 ConsoleApplication3 
40 IntelliSense: identifier "CvEM" undefined c: \ Users \ s \ Documents \ Visual Studio 2013 \ Projects \ ConsoleApplication3 \ ConsoleApplication3 \ graphcut.cpp 437 16 ConsoleApplication3 
41 IntelliSense: identifier "CvEM" undefined c: \ Users \ s \ Documents \ Visual Studio 2013 \ Projects \ ConsoleApplication3 \ ConsoleApplication3 \ graphcut.cpp 439 21 ConsoleApplication3

`

Most of these error messages seem to stem from the lack of a declaration for the CvEM class, either directly or indirectly. Are you certain you have all of the headers included that you need?