void dispRefinement::boundaryDetect(Mat& src, Mat& guid, Mat& dest, Mat& mask)
{
	int d = 2*r+1;
	Size kernel = Size(d,d);

	Mat trimap = Mat::zeros(src.size(),CV_8U);
	Mat trimask = Mat::zeros(src.size(),CV_8U);

	Mat dmax,dmin;
	maxFilter(src,dmax,kernel);
	minFilter(src,dmin,kernel);

	for(int i = 0; i < src.size().area(); i++)
	{
		uchar maxdiff = dmax.data[i] - src.data[i];
		uchar mindiff = src.data[i] - dmin.data[i];
		if(dmax.data[i]-dmin.data[i]<th)
		{
			// non boudnary region
			trimap.data[i] = 128;
			trimask.data[i] = 255;
		}
		else // boundary region
		{
			if(abs(src.data[i]-dmax.data[i])<abs(src.data[i]-dmin.data[i]))
			{
				trimap.data[i]=255; // foreground region
			}
			else
			{
				trimap.data[i]=0; // background region
			}
		}
	}

	Mat trimax, trimin;
	for(int i=0;i<iter_ex;i++)
	{
		maxFilter(trimap,trimax,Size(3,3));
		compare(trimap,0,mask,CMP_NE);
		trimax.copyTo(trimap,mask);

		minFilter(trimap,trimin,Size(3,3));
		compare(trimap,255,mask,CMP_NE);
		trimin.copyTo(trimap,mask);
	}

	trimap.copyTo(dest);
	trimask.copyTo(mask);
}
void dispRefinement::dispRefine(Mat& src, Mat& guid, Mat& guid_mask, Mat& alpha)
{
	Mat guid_;guid.copyTo(guid_);
	Mat tmp;
	compare(alpha,255.0*((double)th_r/100.0),tmp,CMP_GT);
	guid_.setTo(255,tmp);
	compare(alpha,255.0*((double)th_r/100.0),tmp,CMP_LT);
	guid_.setTo(0,tmp);
	guid_.setTo(128,guid_mask);

	int d = 2*r_flip+1;
	Size kernel = Size(d,d);

	Mat dmax, dmin;
	maxFilter(src,dmax,kernel);
	minFilter(src,dmin,kernel);

		for(int i=0;i<guid.size().area();i++)
	{
		if(guid.data[i]!=128)
		{
			if(guid.data[i]==0 && guid_.data[i]==255)
			{
				src.data[i] = dmax.data[i];
			}
			else if(guid.data[i]==255 && guid_.data[i]==0)
			{
				src.data[i] = dmin.data[i];
			}
		}
	}
}
void mattingMethod::getAmap(Mat& img)
{
	Mat mask;
	Mat trimax;
	Mat trimin;
	for(int i=0;i<iter;i++)
	{
		maxFilter(trimap,trimax,Size(3,3));
		compare(trimap,0,mask,CMP_NE);
		trimax.copyTo(trimap,mask);

		minFilter(trimap,trimin,Size(3,3));
		compare(trimap,255,mask,CMP_NE);
		trimin.copyTo(trimap,mask);
	}
	
	Mat tmp;
	Mat imgG;cvtColor(img,imgG,CV_BGR2GRAY);
	for(int i=0;i<iter_g;i++)
	{
		guidedFilter(trimap,imgG,tmp,r_g,eps_g/100.0f);
		tmp.copyTo(trimap);
	}

}
void mattingMethod::boundaryDetect(Mat& disp)
{
	int d = 2*r+1;
	Size kernel = Size(d,d);

	Mat dmax;
	Mat dmin;
	maxFilter(disp,dmax,kernel);
	minFilter(disp,dmin,kernel);

	for(int i=0;i<disp.size().area();i++)
	{
		uchar maxdiff = dmax.data[i] - disp.data[i];
		uchar mindiff = disp.data[i] - dmin.data[i];

		if(dmax.data[i]-dmin.data[i] < th)
		{
			trimap.data[i] = 128;
			trimask.data[i] = 255;
		}
		else
		{
			if(abs(disp.data[i]-dmax.data[i])<abs(disp.data[i]-dmin.data[i]))
			{
				trimap.data[i] = 255;
			}
			else
			{
				trimap.data[i] = 0;
			}
		}
	}

}
int CDataset::extractFeatures(const CConfig& conf){

    int imgRow = this->img.at(0)->rows, imgCol = this->img.at(0)->cols;
    cv::Mat *integralMat;

    if(conf.learningMode != 1){
        if(conf.rgbFeature == 1){ // if got rgb image only, calc hog feature
            feature.clear();
            feature.resize(32);
            for(int i = 0; i < 32; ++i)
                feature.at(i) = new cv::Mat(imgRow, imgCol, CV_8UC1);

            cv::cvtColor(*img.at(0), *(feature.at(0)), CV_RGB2GRAY);

            cv::Mat I_x(imgRow, imgCol, CV_16SC1);
            cv::Mat I_y(imgRow, imgCol, CV_16SC1);


            cv::Sobel(*(feature.at(0)), I_x, CV_16S, 1, 0);
            cv::Sobel(*(feature.at(0)), I_y, CV_16S, 0, 1);

            cv::convertScaleAbs(I_x, *(feature[3]), 0.25);
            cv::convertScaleAbs(I_y, *(feature[4]), 0.25);

            // Orientation of gradients
            for(int  y = 0; y < img.at(0)->rows; y++)
                for(int  x = 0; x < img.at(0)->cols; x++) {
                    // Avoid division by zero
                    float tx = (float)I_x.at<short>(y, x) + (float)copysign(0.000001f, I_x.at<short>(y, x));
                    // Scaling [-pi/2 pi/2] -> [0 80*pi]
                    feature.at(1)->at<uchar>(y, x) = (uchar)(( atan((float)I_y.at<short>(y, x) / tx) + 3.14159265f / 2.0f ) * 80);
                    //std::cout << "scaling" << std::endl;
                    feature.at(2)->at<uchar>(y, x) = (uchar)sqrt((float)I_x.at<short>(y, x)* (float)I_x.at<short>(y, x) + (float)I_y.at<short>(y, x) * (float)I_y.at<short>(y, x));
                }

            // Magunitude of gradients
            for(int y = 0; y < img.at(0)->rows; y++)
                for(int x = 0; x < img.at(0)->cols; x++ ) {
                    feature.at(2)->at<uchar>(y, x) = (uchar)sqrt(I_x.at<short>(y, x)*I_x.at<short>(y, x) + I_y.at<short>(y, x) * I_y.at<short>(y, x));
                }

            hog.extractOBin(feature[1], feature[2], feature, 7);

            // calc I_xx I_yy
            cv::Sobel(*(feature.at(0)), I_x, CV_16S, 2, 0);
            cv::Sobel(*(feature.at(0)), I_y, CV_16S, 0, 2);

            cv::convertScaleAbs(I_x, *(feature[5]), 0.25);
            cv::convertScaleAbs(I_y, *(feature[6]), 0.25);

            cv::Mat img_Lab;
            cv::cvtColor(*img.at(0), img_Lab, CV_RGB2Lab);
            cv::vector<cv::Mat> tempfeature(3);

            cv::split(img_Lab, tempfeature);

            for(int i = 0; i < 3; ++i)
                tempfeature.at(i).copyTo(*(feature.at(i)));

            // min max filter
            for(int c = 0; c < 16; ++c)
                minFilter(feature[c], feature[c + 16], 5);
            for(int c = 0; c < 16; ++c)
                maxFilter(feature[c], feature[c], 5);

        }else{
            feature.clear();

            // calc gray integral image
            cv::Mat grayImg(imgRow + 1, imgCol, CV_8U);
            cv::cvtColor(*img.at(0), grayImg, CV_RGB2GRAY);
            integralMat = new cv::Mat(imgRow + 1, imgCol + 1, CV_64F);
            cv::integral(grayImg, *integralMat, CV_64F);
            feature.push_back(integralMat);

            // calc r g b integral image
            std::vector<cv::Mat> splittedRgb;
            cv::split(*img.at(0), splittedRgb);
            for(int i = 0; i < splittedRgb.size(); ++i){
                integralMat = new cv::Mat(imgRow + 1, imgCol + 1, CV_64F);
                cv::integral(splittedRgb.at(i), *integralMat, CV_64F);
                feature.push_back(integralMat);
            }



            featureFlag = 1;
        }
    }

    if(img.size() > 1){
        cv::Mat tempDepth = cv::Mat(img.at(0)->rows, img.at(0)->cols, CV_8U);// = *img.at(1);

        if(img.at(1)->type() != CV_8U)
            img.at(1)->convertTo(tempDepth, CV_8U, 255.0 / (double)(conf.maxdist - conf.mindist));
        else
            tempDepth = *img.at(1);
        integralMat = new cv::Mat(imgRow + 1, imgCol + 1, CV_64F);
        cv::integral(tempDepth, *integralMat, CV_64F);
        feature.push_back(integralMat);

        featureFlag  = 1;
    }

    return 0;
}
	void maxFilter(InputArray src, OutputArray dest, int radius)
	{
		maxFilter(src, dest, Size(2 * radius + 1, 2 * radius + 1));
	}