Example #1
0
void Noiser::EstimateNoise()
{
	cout<<"Estimating noise..."<<endl;
	Mat desv_estandar(h,w,CV_32F,Scalar(0));	
	for(int i =0;i<total;i++)
	{
		//desviacion estandar		
		Mat aux(h,w,CV_32F,Scalar(0));
		pow(cleanImage-images[i],2,aux);
		desv_estandar += aux;
	}
	desv_estandar/=total;
	sqrt(desv_estandar,desv_estandar);
	
	double ruido_promedio =  mean(desv_estandar).val[0];
	double ruido_peor;
	minMaxLoc(desv_estandar,NULL,&ruido_peor);

	Mat aux;
	meanStdDev(cleanImage,noArray(),aux);
	double signal = aux.at<double>(0);

	meanStdDev(desv_estandar,noArray(),aux);
	double noise = aux.at<double>(0);

	double SNR = 10*log10(signal/noise);

	cout<<"Ruido Promedio: "<<ruido_promedio<<endl;
	cout<<"Ruido Peor: "<<ruido_peor<<endl;
	cout<<"SNR: "<<SNR<<" db"<<endl;
	this->ready = false;
	

}
Example #2
0
std::vector<int> visionUtils::updateHSVAdaptiveSkin(std::vector<Mat> pixelPlanes, bool displayFaces)//( int, char** argv )
{
    if (displayFaces)
    {
        drawHist(pixelPlanes, 35);
    }

    Scalar b_mean, b_stdDev;

    meanStdDev(pixelPlanes[0], b_mean, b_stdDev);
    int b_min=b_mean[0] - b_stdDev[0]*3;
    int b_max=b_mean[0] + b_stdDev[0]*3;

    Scalar g_mean,g_stdDev;
    meanStdDev(pixelPlanes[1], g_mean,g_stdDev);
    int g_min=g_mean[0] - g_stdDev[0]*3;
    int g_max=g_mean[0] + g_stdDev[0]*3;

    Scalar r_mean, r_stdDev;
    meanStdDev(pixelPlanes[2], r_mean, r_stdDev);
    int r_min=r_mean[0] - r_stdDev[0]*3;
    int r_max=r_mean[0] + r_stdDev[0]*3;

    std::vector<int> hsvAdaptiveUpdated;
    hsvAdaptiveUpdated.push_back(b_min);
    hsvAdaptiveUpdated.push_back(g_min);
    hsvAdaptiveUpdated.push_back(r_min);
    hsvAdaptiveUpdated.push_back(b_max);
    hsvAdaptiveUpdated.push_back(g_max);
    hsvAdaptiveUpdated.push_back(r_max);

    return hsvAdaptiveUpdated;

}
Example #3
0
void Objectness::illustrate()
{
    Mat xP1f, xN1f;
    CV_Assert(matRead(_modelName + ".xP", xP1f) && matRead(_modelName + ".xN", xN1f));
    CV_Assert(xP1f.cols == xN1f.cols && xP1f.cols == _W*_W && xP1f.type() == CV_32F && xN1f.type() == CV_32F);
    Mat meanP,  meanN, stdDevP, stdDevN;
    meanStdDev(xP1f, meanP, stdDevP);
    meanStdDev(xN1f, meanN, stdDevN);
    Mat meanV(_W, _W*2, CV_32F), stdDev(_W, _W*2, CV_32F);
    meanP.reshape(1, _W).copyTo(meanV.colRange(0, _W));
    meanN.reshape(1, _W).copyTo(meanV.colRange(_W, _W*2));
    stdDevP.reshape(1, _W).copyTo(stdDev.colRange(0, _W));
    stdDevN.reshape(1, _W).copyTo(stdDev.colRange(_W, _W*2));
    normalize(meanV, meanV, 0, 255, NORM_MINMAX, CV_8U);
    CmShow::showTinyMat(_voc.resDir + "PosNeg.png", meanV);

    FILE* f = fopen(_S(_voc.resDir + "PosNeg.m"), "w");
    CV_Assert(f != NULL);
    fprintf(f, "figure(1);\n\n");
    PrintVector(f, getVector(meanP), "MeanP");
    PrintVector(f, getVector(meanN), "MeanN");
    PrintVector(f, getVector(stdDevP), "StdDevP");
    PrintVector(f, getVector(stdDevN), "StdDevN");
    PrintVector(f, getVector(_svmFilter), "Filter");
    fprintf(f, "hold on;\nerrorbar(MeanP, StdDevP, 'r');\nerrorbar(MeanN, StdDevN, 'g');\nhold off;");
    fclose(f);
}
Example #4
0
//Descriptor media y desviacion RGB
vector<float> RGB::extract_RGB_des(Mat img)
{
    vector<float> V_des_RGB;
    V_des_RGB.clear();

    Mat img_rgb, RGB_m;
    Scalar RGBm, RGBstdv, img_med, img_stdv;

    //----------------------------------------------------
    //V_des_RGB interprete
    //V_des_RGB[0] = media canal B
    //V_des_RGB[1] = media canal G
    //V_des_RGB[2] = media canal R
    //V_des_RGB[3] = media todos los 3 canales
    //V_des_RGB[4] = desviacion estandar de los 3 canales
    //V_des_RGB[5] = brillo //pendiente
    //----------------------------------------------------

    if(!img.empty())
    {
        cvtColor(img,img_rgb,CV_BGR2RGB,0);

        // Calculamos la media de cada canal (H, S, V) y la
        // desviacion tipica de cada canal
        meanStdDev(img_rgb, RGBm, RGBstdv);
        // RED
        V_des_RGB.push_back(RGBm[2]);
        // GREEN
        V_des_RGB.push_back(RGBm[1]);
        // BLUE
        V_des_RGB.push_back(RGBm[0]);

        RGB_m = (Mat_<double>(3,1) << RGBm[0], RGBm[1], RGBm[2]);

        // Calculamos la media de la media de los tres canales,
        // y la desviacion tipica de la media de cada canal
        meanStdDev(RGB_m, img_med, img_stdv);

#ifdef DEBUG
//        cout << "+++++++++++++++++++++++++++++++++" << endl;
//        cout << RGBm << endl;
//        cout << RGBstdv << endl;
        cout << "Media RGB: " << img_med[0] << endl;
        cout << "Desv. RGB: " << img_stdv[0] << endl;
//        cout << "+++++++++++++++++++++++++++++++++" << endl;
#endif

        V_des_RGB.push_back(img_med[0]);
        V_des_RGB.push_back(img_stdv[0]);
    }
    return V_des_RGB;
} // end extract_RGB_des
Example #5
0
double compare_float(const Mat& one, const Mat& two) {
  Scalar oMean;
  Scalar tMean;
  Scalar oSdv;
  Scalar tSdv;

  meanStdDev(one, oMean, oSdv);
  meanStdDev(two, tMean, tSdv);

  double mean = fabs(oMean.val[0] - tMean.val[0]);
  double sdv = fabs(oSdv.val[0] - tSdv.val[0]);

  return 1.0 - ((mean + sdv) / 2.0);
}
Example #6
0
Vec2f DepthMapJudge::CalculateNeighbours(Vec3f center, int cx, int cy, Mat xyz)
{
	int count = 0;
	const double max_z = 10000;
	for(int y = max(0,cy-ws); y < xyz.rows && y<=cy+ws; y++)
    {
        for(int x = max(0,cx-ws); x < xyz.cols && x<=cx+ws; x++)
        {			
			Vec3f point = xyz.at<Vec3f>(y, x);
            if(fabs(point[2] - max_z) < FLT_EPSILON || fabs(point[2]) > max_z) continue; 
			if(norm(point-center)<=radius)
			{
				points.at<float>(0,count) = point[2];
				count++;
			}
        }
    } 
	//create a mask that selects the non zero vlues in points
	Mat mask(points.rows,points.cols,CV_8U,Scalar::all(0));
	for(int i=0;i<count;i++){ mask.at<uchar>(0,i)=255;	}
	//calculate standard deviation
	Mat aux;
	meanStdDev(points,noArray(),aux,mask);
	double stdev = aux.at<double>(0);
	//clean points
	bitwise_and(points,0,points);

	return Vec2f(count,stdev);
}
void Feature::calcColorFeature()
{
    // TODO: optimize this part, reduce extra work
    
    Mat hsv;
    cvtColor(mROI, hsv, CV_BGR2HSV_FULL);
    
    Mat temp(mROI.size(), CV_8UC3), mixed;
    Mat src[] = { mROI, mGray, hsv };
    int fromTo[] = { 2,0, 3,1, 5,2 };
    mixChannels(src, 3, &temp, 1, fromTo, 3);
    temp.convertTo(mixed, CV_64F);
    
    Scalar avg, stdDev;
    meanStdDev(mixed, avg, stdDev, mMask);
    Scalar var = stdDev.mul(stdDev);
    Mat temp1 = mixed - avg;
    Mat temp2 = temp1.mul(temp1);
    Scalar sk = mean(temp1.mul(temp2), mMask) / (var.mul(stdDev));
    Scalar ku = mean(temp2.mul(temp2), mMask) / (var.mul(var));
    
    Scalar stat[] = { avg, stdDev, sk, ku };
    for (int i = 0; i < 4; i++) {
        red[i] = stat[i][0];
        gray[i] = stat[i][1];
        saturation[i] = stat[i][2];
    }
}
Example #8
0
int InterframeRegister::cvutStdDevStretch( Mat src, Mat dst)
{
	// Contrast Stretching:
	// Stretching by Standard deviation
	// A two standard deviation linear contrast stretch is applied

	Scalar mean;
	Scalar std_deviation;
	double min, max, scale, shift;

	// Computes mean and std dev of image src

	meanStdDev( src, mean, std_deviation);

	// Computes the stretch min and max
	min = mean.val[0] - 2.0 * std_deviation.val[0];
	max = mean.val[0] + 2.0 * std_deviation.val[0];

	if ( min != max )
	{
		scale = 255.0/(max - min);
		shift = -min * scale;
	}
	else
	{
		scale = 1.0;
		shift = 0.0;
	}

	// Computes:
	// image = ((image-mind)/(maxd-mind))*255;
	convertScaleAbs( src, dst, scale, shift );
	return true;
}
Example #9
0
//RETURNS THE TOP-LEFT CORNER OF THE REFLECTION OF sourceTemplate ON image
cv::Rect findBestMatchLocation( const cv::Mat& image, const cv::Rect& source_rect, 
        double* nsigma, const cv::Mat& mask )
{
    cv::Mat image_gray;
    cvtColor( image, image_gray, CV_RGB2GRAY, 1 );
    cv::Mat image_copy = image_gray.clone();
    
    // Create template.
    cv::Mat image_template_copy = image_gray.clone();
    cv::Mat sourceTemplate = image_template_copy( source_rect );
    flip( sourceTemplate, sourceTemplate, 0 );

    // Creates results matrix where the top left corner of the 
    // template is slid across each pixel of the source
    int result_cols = image.cols-sourceTemplate.cols+1;
    int result_rows = image.rows-sourceTemplate.rows+1;
    cv::Mat result;
    result.create( result_cols,result_rows, CV_32FC1 );

    // Mask image to match only in selected ROI.
    if( !mask.empty() )
    {
        cv::Mat tmp;
		image_copy.copyTo( tmp, mask );
        image_copy = tmp;
    }

    //0:CV_TM_SQDIFF
    //1:CV_TM_SQDIFF_NORMED
    //2:CV_TM_CORR
    //3:CV_TM_CCOR_NORMED
    //4:CV_TM_CCOEFF
    //5:CV_TM_CCOEFF_NORMED <----Most succesful at finding reflections
    
    int match_method = CV_TM_CCOEFF_NORMED; // 4 seemed good for stddev thresholding.

    //matchTemplate( masked_scene, sourceTemplate, result, match_method );
    matchTemplate( image_gray, sourceTemplate, result, match_method );

    double minVal, maxVal; 
    cv::Point minLoc, maxLoc, matchLoc;
    minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat() );
     
    if( match_method == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
    {
        matchLoc = minLoc;	
    }
    else 
    {
        matchLoc = maxLoc;
    }
    cv::Scalar mean, stddev;
    meanStdDev( result, mean, stddev, cv::Mat() );
    *nsigma = ( maxVal-mean[0] )/ stddev[0];
    // matchLoc is the location of the top left corner of the reflection
    // that matchTemplate found

    return cv::Rect( matchLoc, source_rect.size() );
}
Example #10
0
 virtual int filter(const Mat &src, Mat &dest) const
 {
     Scalar m,s; 
     meanStdDev(src, m, s);
     dest  = src - m[0];
     dest /= s[0];
     return 0;
 }
PatchMatcher::PatchMatcher(const Image<Vec3b> *patch, const Image<Vec3b> *output, const Image<uchar> *outputMask) :
    OffsetChooser(patch, outputMask), output(output) {

    Scalar mean, stddev;
    meanStdDev(*patch, mean, stddev);

    factor = - 1.0 / (K * pow(norm(stddev), 2) * patch->width() * patch->height());
}
Example #12
0
double getContraste(const Mat& src)
{
    Mat gray;
    cvtColor(src, gray, CV_BGR2HLS);
    Scalar mean;
    Scalar stddev;
    meanStdDev(src, mean, stddev);
    return stddev[1];
}
double GroupClassifier::operator()(vector<int> *group, vector<Region> *regions)
{
	assert(group != NULL);
	assert(group->size() > 1);
	assert(regions != NULL);

	Mat votes          ( group->size(), 1, CV_32F, 1 );
	Mat strokes     ( group->size(), 1, CV_32F, 1 );
	Mat aspect_ratios  ( group->size(), 1, CV_32F, 1 );
	Mat compactnesses  ( group->size(), 1, CV_32F, 1 );
	Mat nums_holes     ( group->size(), 1, CV_32F, 1 );
	Mat holeareas_area ( group->size(), 1, CV_32F, 1 );

	for (int i=group->size()-1; i>=0; i--)
	{
		// TODO check first if regions->at(group->at(i)).votes_ has already been calculated !!! 
		regions->at(group->at(i)).classifier_votes_ = character_classifier_->get_votes(&regions->at(group->at(i)));

		votes.at<float>(i,0) = regions->at(group->at(i)).classifier_votes_;
		strokes.at<float>(i,0) = (float)regions->at(group->at(i)).stroke_mean_;
		aspect_ratios.at<float>(i,0) = (float)min( regions->at(group->at(i)).rect_.size.width, regions->at(group->at(i)).rect_.size.height)/max( regions->at(group->at(i)).rect_.size.width, regions->at(group->at(i)).rect_.size.height);
		compactnesses.at<float>(i,0) = sqrt(regions->at(group->at(i)).area_)/regions->at(group->at(i)).perimeter_;
		nums_holes.at<float>(i,0) = (float)regions->at(group->at(i)).num_holes_;
		holeareas_area.at<float>(i,0) = (float)regions->at(group->at(i)).holes_area_/regions->at(group->at(i)).area_;
	}

        vector<float> sample;
	sample.push_back(0);
	
	Scalar mean,std;
	meanStdDev( votes, mean, std );
	sample.push_back( mean[0]);
	sample.push_back( std[0]);
	sample.push_back( std[0]/mean[0] ); 
	meanStdDev( strokes, mean, std );
	sample.push_back( mean[0]);
	sample.push_back( std[0]);
	sample.push_back( std[0]/mean[0] ); 
	meanStdDev( aspect_ratios, mean, std );
	sample.push_back( mean[0]);
	sample.push_back( std[0]);
	sample.push_back( std[0]/mean[0] ); 
	meanStdDev( compactnesses, mean, std );
	sample.push_back( mean[0]);
	sample.push_back( std[0]);
	sample.push_back( std[0]/mean[0] ); 
	meanStdDev( nums_holes, mean, std );
	sample.push_back( mean[0]);
	sample.push_back( std[0]);
	sample.push_back( std[0]/mean[0] ); 
	meanStdDev( holeareas_area, mean, std );
	sample.push_back(mean[0]);
	sample.push_back( std[0]);
	sample.push_back( std[0]/mean[0] ); 


	float votes_group = boost_.predict( Mat(sample), Mat(), Range::all(), false, true );

  return (double)1-(double)1/(1+exp(-2*votes_group));
}
Mat ZeroMeanUnitVarianceFilter::applyTo(const Mat& image, Mat& filtered) const {
	if (image.channels() > 1)
		throw invalid_argument("ZeroMeanUnitVarianceFilter: The image must have exactly one channel.");
	Scalar mean, deviation;
	meanStdDev(image, mean, deviation);
	image.convertTo(filtered, CV_32F);

	if (deviation[0] == 0)
		filtered = Scalar(0);
	else
		filtered = (filtered - mean) / deviation[0];
	return filtered;
}
Example #15
0
Mat NNClassifier::getPatch(const Mat &img32F)
{
    Mat patch;
    
    resize(img32F, patch, Size(NN_PATCH_SIZE, NN_PATCH_SIZE));
    
    Scalar mean, stddev;
    
    meanStdDev(patch, mean, stddev);
    patch -= mean.val[0];   // to reduce brightness influence

    return patch;
}
Example #16
0
// normalized value concatenation
// gray patch has problem when contrast of object patch is flipped, gradient is more robust
bool ObjPatchMatcher::ComputePatchFeat(MatFeatureSet& patches, Mat& feat) {
	feat.release();
	feat.create(0, 0, CV_32F);
	if(patches.find("gray") != patches.end()) {
		Scalar mean_, std_;
		//normalize(patches["gray"], patches["gray"], 1, 0, NORM_MINMAX);
		meanStdDev(patches["gray"], mean_, std_);
		Mat patch_ = (patches["gray"]-0);///std_.val[0];
		if(feat.empty()) patch_.reshape(1,1).copyTo(feat);
		else hconcat(patch_.reshape(1, 1), feat, feat);
	}
	if(patches.find("gradient") != patches.end()) {
		normalize(patches["gradient"], patches["gradient"], 1, 0, NORM_MINMAX);
		Scalar mean_, std_;
		meanStdDev(patches["gradient"], mean_, std_);
		Mat patch_ = (patches["gradient"]-0);///std_.val[0];
		if(feat.empty()) patch_.reshape(1,1).copyTo(feat);
		else hconcat(patch_.reshape(1, 1), feat, feat);
	}
	if(patches.find("normal") != patches.end()) {
		Scalar mean_, std_;
		meanStdDev(patches["normal"], mean_, std_);
		//Mat patch_ = (patches["normal"]-mean_.val);
		if(feat.empty()) patches["normal"].reshape(1,1).copyTo(feat);
		else hconcat(patches["normal"].reshape(1,1), feat, feat);
	}
	if(patches.find("depth") != patches.end()) {
		//if(feat.empty()) patches["normal"].reshape(1,1).copyTo(feat);
		//else 
		Scalar mean_, std_;
		//normalize(patches["depth"], patches["depth"], 1, 0, NORM_MINMAX);
		meanStdDev(patches["depth"], mean_, std_);
		Mat patch_ = (patches["depth"]-mean_.val[0]);///std_.val[0];
		hconcat(patch_.reshape(1,1), feat, feat);
	}

	return true;
}
void COpenCVInterfaceDlg::OnMorphologyConvexhull()
{
	if(mainImage.cols)
	{
		ConvexHull c;
		Mat rez=mainImage.clone();
		mainImage=Filters::gaussianFilter(mainImage,1);
		Scalar meanVal,stdval;

		meanStdDev(mainImage,meanVal,stdval);
		Canny(mainImage,mainImage,meanVal.val[0]*1/3.,meanVal.val[0]);
		//imshow("contours",mainImage);

		vector<std::vector<cv::Point>> contours;
		findContours(mainImage,contours,CV_RETR_LIST,CV_CHAIN_APPROX_NONE,Point(2,2));

		vector<Point> Points;
		//Points.resize(contours.size()*contours[0].size());
		for(int i=0;i<contours.size();i++)
		{
			for(int j=0;j<contours[i].size();j++)
			{
				Points.push_back(contours[i][j]);
			}
		}

		//for(int i=2;i<mainImage.rows-2;i++)
		//{
		//	for(int j=2;j<mainImage.cols-2;j++)
		//	{
		//		if(mainImage.at<uchar>(i,j)==255)
		//			Points.push_back(Point(i,j));
		//	}
		//}	

		std::vector<Point> chull;
		c.graham(Points, chull);

		for(int i=0;i<chull.size()-1;i++)
		{
			line(rez,chull[i],chull[i+1],Scalar(255,255,255),2);
		}

		line(rez,chull[chull.size()-1],chull[0],Scalar(255,255,255),2);
		prelImage=rez.clone();
		ShowResult(prelImage);
	}
	else
		MessageBox("No image loaded");
}
void Feature::calcAreaVar()
{
    // TODO: optimize this part
    
    if (mAreaVec.size() < MAX_AREA_VEC_SIZE) {
        areaVar = -1;
        return;
    }
    
    Scalar m, s;
    meanStdDev(mAreaVec, m, s);
    areaVar = s[0] / m[0];

#ifdef DEBUG_OUTPUT
    cout << "areaVar: " << areaVar << endl;
#endif
}
Example #19
0
File: Dip4.cpp Project: kziel1/dip
/*
img         :  input image
degradedImg :  degraded output image
filterDev   :  standard deviation of kernel for gaussian blur
snr         :  signal to noise ratio for additive gaussian noise
return      :  the used gaussian kernel
*/
Mat Dip4::degradeImage(Mat& img, Mat& degradedImg, double filterDev, double snr){

    int kSize = round(filterDev*3)*2 - 1;
   
    Mat gaussKernel = getGaussianKernel(kSize, filterDev, CV_32FC1);
    gaussKernel = gaussKernel * gaussKernel.t();
    filter2D(img, degradedImg, -1, gaussKernel);

    Mat mean, stddev;
    meanStdDev(img, mean, stddev);

    Mat noise = Mat::zeros(img.rows, img.cols, CV_32FC1);
    randn(noise, 0, stddev.at<double>(0)/snr);
    degradedImg = degradedImg + noise;
    threshold(degradedImg, degradedImg, 255, 255, CV_THRESH_TRUNC);
    threshold(degradedImg, degradedImg, 0, 0, CV_THRESH_TOZERO);

    return gaussKernel;
}
Example #20
0
  // Gets the hue/sat/val for areas that we believe are license plate characters
  // Then uses that to filter the whole image and provide a mask.
  void ColorFilter::findCharColors()
  {
    int MINIMUM_SATURATION = 45;

    if (this->debug)
      cout << "ColorFilter::findCharColors" << endl;

    //charMask.copyTo(this->colorMask);
    this->colorMask = Mat::zeros(charMask.size(), CV_8U);
    bitwise_not(this->colorMask, this->colorMask);

    Mat erodedCharMask(charMask.size(), CV_8U);
    Mat element = getStructuringElement( 1,
                                         Size( 2 + 1, 2+1 ),
                                         Point( 1, 1 ) );
    erode(charMask, erodedCharMask, element);

    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(erodedCharMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);

    vector<float> hMeans, sMeans, vMeans;
    vector<float> hStdDevs, sStdDevs, vStdDevs;

    for (unsigned int i = 0; i < contours.size(); i++)
    {
      if (hierarchy[i][3] != -1)
        continue;

      Mat singleCharMask = Mat::zeros(hsv.size(), CV_8U);

      drawContours(singleCharMask, contours,
                   i, // draw this contour
                   cv::Scalar(255,255,255), // in
                   CV_FILLED,
                   8,
                   hierarchy
                  );

      // get rid of the outline by drawing a 1 pixel width black line
      drawContours(singleCharMask, contours,
                   i, // draw this contour
                   cv::Scalar(0,0,0), // in
                   1,
                   8,
                   hierarchy
                  );

      //drawAndWait(&singleCharMask);

      Scalar mean;
      Scalar stddev;
      meanStdDev(hsv, mean, stddev, singleCharMask);

      if (this->debug)
      {
        cout << "ColorFilter " << setw(3) << i << ". Mean:  h: " << setw(7) << mean[0] << " s: " << setw(7) <<mean[1] << " v: " << setw(7) << mean[2]
             << " | Std: h: " << setw(7) <<stddev[0] << " s: " << setw(7) <<stddev[1] << " v: " << stddev[2] << endl;
      }

      if (mean[0] == 0 && mean[1] == 0 && mean[2] == 0)
        continue;

      hMeans.push_back(mean[0]);
      sMeans.push_back(mean[1]);
      vMeans.push_back(mean[2]);
      hStdDevs.push_back(stddev[0]);
      sStdDevs.push_back(stddev[1]);
      vStdDevs.push_back(stddev[2]);
    }

    if (hMeans.size() == 0)
      return;

    int bestHueIndex = this->getMajorityOpinion(hMeans, .65, 30);
    int bestSatIndex = this->getMajorityOpinion(sMeans, .65, 35);
    int bestValIndex = this->getMajorityOpinion(vMeans, .65, 30);

    if (sMeans[bestSatIndex] < MINIMUM_SATURATION)
      return;

    bool doHueFilter = false, doSatFilter = false, doValFilter = false;
    float hueMin, hueMax;
    float satMin, satMax;
    float valMin, valMax;

    if (this->debug)
      cout << "ColorFilter Winning indices:" << endl;
    if (bestHueIndex != -1)
    {
      doHueFilter = true;
      hueMin = hMeans[bestHueIndex] - (2 * hStdDevs[bestHueIndex]);
      hueMax = hMeans[bestHueIndex] + (2 * hStdDevs[bestHueIndex]);

      if (abs(hueMin - hueMax) < 20)
      {
        hueMin = hMeans[bestHueIndex] - 20;
        hueMax = hMeans[bestHueIndex] + 20;
      }

      if (hueMin < 0)
        hueMin = 0;
      if (hueMax > 180)
        hueMax = 180;

      if (this->debug)
        cout << "ColorFilter Hue: " << bestHueIndex << " : " << setw(7) << hMeans[bestHueIndex] << " -- " << hueMin << "-" << hueMax << endl;
    }
    if (bestSatIndex != -1)
    {
      doSatFilter = true;

      satMin = sMeans[bestSatIndex] - (2 * sStdDevs[bestSatIndex]);
      satMax = sMeans[bestSatIndex] + (2 * sStdDevs[bestSatIndex]);

      if (abs(satMin - satMax) < 20)
      {
        satMin = sMeans[bestSatIndex] - 20;
        satMax = sMeans[bestSatIndex] + 20;
      }

      if (satMin < 0)
        satMin = 0;
      if (satMax > 255)
        satMax = 255;

      if (this->debug)
        cout << "ColorFilter Sat: " << bestSatIndex << " : " << setw(7) << sMeans[bestSatIndex] << " -- " << satMin << "-" << satMax << endl;
    }
    if (bestValIndex != -1)
    {
      doValFilter = true;

      valMin = vMeans[bestValIndex] - (1.5 * vStdDevs[bestValIndex]);
      valMax = vMeans[bestValIndex] + (1.5 * vStdDevs[bestValIndex]);

      if (abs(valMin - valMax) < 20)
      {
        valMin = vMeans[bestValIndex] - 20;
        valMax = vMeans[bestValIndex] + 20;
      }

      if (valMin < 0)
        valMin = 0;
      if (valMax > 255)
        valMax = 255;

      if (this->debug)
        cout << "ColorFilter Val: " << bestValIndex << " : " << setw(7) << vMeans[bestValIndex] << " -- " << valMin << "-" << valMax  << endl;
    }

    Mat imgDebugHueOnly = Mat::zeros(hsv.size(), hsv.type());
    Mat imgDebug = Mat::zeros(hsv.size(), hsv.type());
    Mat imgDistanceFromCenter = Mat::zeros(hsv.size(), CV_8U);
    Mat debugMask = Mat::zeros(hsv.size(), CV_8U);
    bitwise_not(debugMask, debugMask);

    for (int row = 0; row < charMask.rows; row++)
    {
      for (int col = 0; col < charMask.cols; col++)
      {
        int h = (int) hsv.at<Vec3b>(row, col)[0];
        int s = (int) hsv.at<Vec3b>(row, col)[1];
        int v = (int) hsv.at<Vec3b>(row, col)[2];

        bool hPasses = true;
        bool sPasses = true;
        bool vPasses = true;

        int vDistance = abs(v - vMeans[bestValIndex]);

        imgDebugHueOnly.at<Vec3b>(row, col)[0] = h;
        imgDebugHueOnly.at<Vec3b>(row, col)[1] = 255;
        imgDebugHueOnly.at<Vec3b>(row, col)[2] = 255;

        imgDebug.at<Vec3b>(row, col)[0] = 255;
        imgDebug.at<Vec3b>(row, col)[1] = 255;
        imgDebug.at<Vec3b>(row, col)[2] = 255;

        if (doHueFilter && (h < hueMin || h > hueMax))
        {
          hPasses = false;
          imgDebug.at<Vec3b>(row, col)[0] = 0;
          debugMask.at<uchar>(row, col) = 0;
        }
        if (doSatFilter && (s < satMin || s > satMax))
        {
          sPasses = false;
          imgDebug.at<Vec3b>(row, col)[1] = 0;
        }
        if (doValFilter && (v < valMin || v > valMax))
        {
          vPasses = false;
          imgDebug.at<Vec3b>(row, col)[2] = 0;
        }

        //if (pixelPasses)
        //  colorMask.at<uchar>(row, col) = 255;
        //else
        //imgDebug.at<Vec3b>(row, col)[0] = hPasses & 255;
        //imgDebug.at<Vec3b>(row, col)[1] = sPasses & 255;
        //imgDebug.at<Vec3b>(row, col)[2] = vPasses & 255;

        if ((hPasses) ||  (hPasses && sPasses))//(hPasses && vPasses) || (sPasses && vPasses) ||
          this->colorMask.at<uchar>(row, col) = 255;
        else
          this->colorMask.at<uchar>(row, col) = 0;

        if ((hPasses && sPasses) || (hPasses && vPasses) || (sPasses && vPasses))
        {
          vDistance = pow(vDistance, 0.9);
        }
        else
        {
          vDistance = pow(vDistance, 1.1);
        }
        if (vDistance > 255)
          vDistance = 255;
        imgDistanceFromCenter.at<uchar>(row, col) = vDistance;
      }
    }

    vector<Mat> debugImagesSet;

    if (this->debug)
    {
      debugImagesSet.push_back(addLabel(charMask, "Charecter mask"));
      //debugImagesSet1.push_back(erodedCharMask);
      Mat maskCopy(colorMask.size(), colorMask.type());
      colorMask.copyTo(maskCopy);
      debugImagesSet.push_back(addLabel(maskCopy, "color Mask Before"));
    }

    Mat bigElement = getStructuringElement( 1,
                                            Size( 3 + 1, 3+1 ),
                                            Point( 1, 1 ) );

    Mat smallElement = getStructuringElement( 1,
                       Size( 1 + 1, 1+1 ),
                       Point( 1, 1 ) );

    morphologyEx(this->colorMask, this->colorMask, MORPH_CLOSE, bigElement);
    //dilate(this->colorMask, this->colorMask, bigElement);

    Mat combined(charMask.size(), charMask.type());
    bitwise_and(charMask, colorMask, combined);

    if (this->debug)
    {
      debugImagesSet.push_back(addLabel(colorMask, "Color Mask After"));

      debugImagesSet.push_back(addLabel(combined, "Combined"));

      //displayImage(config, "COLOR filter Mask", colorMask);
      debugImagesSet.push_back(addLabel(imgDebug, "Color filter Debug"));

      cvtColor(imgDebugHueOnly, imgDebugHueOnly, CV_HSV2BGR);
      debugImagesSet.push_back(addLabel(imgDebugHueOnly, "Color Filter Hue"));

      equalizeHist(imgDistanceFromCenter, imgDistanceFromCenter);
      debugImagesSet.push_back(addLabel(imgDistanceFromCenter, "COLOR filter Distance"));

      debugImagesSet.push_back(addLabel(debugMask, "COLOR Hues off"));

      Mat dashboard = drawImageDashboard(debugImagesSet, imgDebugHueOnly.type(), 3);
      displayImage(config, "Color Filter Images", dashboard);
    }
  }
Example #21
0
int main(int argc, char **argv) {
	bool die(false);
	string filename("snapshot");
	string suffix(".png");
	int i_snap(0),iter(0);
	
	Mat depthMat(Size(640,480),CV_16UC1);
	Mat depthf  (Size(640,480),CV_8UC1);
	Mat rgbMat(Size(640,480),CV_8UC3,Scalar(0));
	Mat ownMat(Size(640,480),CV_8UC3,Scalar(0));
	
	Freenect::Freenect<MyFreenectDevice> freenect;
	MyFreenectDevice& device = freenect.createDevice(0);
	
	device.setTiltDegrees(10.0);
	
	bool registered  = false;
	Mat blobMaskOutput = Mat::zeros(Size(640,480),CV_8UC1),outC;
	Point midBlob;
	
	int startX = 200, sizeX = 180, num_x_reps = 18, num_y_reps = 48;
	double	height_over_num_y_reps = 480/num_y_reps,
			width_over_num_x_reps = sizeX/num_x_reps;
	
	
	vector<double> _d(num_x_reps * num_y_reps); //the descriptor
	Mat descriptorMat(_d);

//	CvNormalBayesClassifier classifier;	//doesnt work
	CvKNearest classifier;
//	CvSVM classifier;	//doesnt work
//	CvBoost classifier;	//only good for 2 classes
//	CvDTree classifier;
	
	
	vector<vector<double> > training_data;
	vector<int>				label_data;
	PCA pca;
	Mat labelMat, dataMat; 
	vector<float> label_counts(4);
	
	bool trained = false, loaded = false;
 	
	device.startVideo();
	device.startDepth();
    while (!die) {
    	device.getVideo(rgbMat);
    	device.getDepth(depthMat);
//        cv::imshow("rgb", rgbMat);
    	depthMat.convertTo(depthf, CV_8UC1, 255.0/2048.0);
				
        cv::imshow("depth",depthf);
		
		//interpolation & inpainting
		{
			Mat _tmp,_tmp1; // = (depthMat - 400.0);          //minimum observed value is ~440. so shift a bit
			Mat(depthMat - 400.0).convertTo(_tmp1,CV_64FC1);
			_tmp.setTo(Scalar(2048), depthMat > 750.0);   //cut off at 600 to create a "box" where the user interacts
//			_tmp.convertTo(depthf, CV_8UC1, 255.0/1648.0);  //values are 0-2048 (11bit), account for -400 = 1648

			//quadratic interpolation
//			cv::pow(_tmp,2.0,_tmp1);
//			_tmp1 = _tmp1 * 4.0;
			
//			try {
//				cv:log(_tmp,_tmp1);
//			}
//			catch (cv::Exception e) {
//				cerr << e.what() << endl;
//				exit(0);
//			}
			
			Point minLoc; double minval,maxval;
			minMaxLoc(_tmp1, &minval, &maxval, NULL, NULL);
			_tmp1.convertTo(depthf, CV_8UC1, 255.0/maxval);
			
			Mat small_depthf; resize(depthf,small_depthf,Size(),0.2,0.2);
			cv::inpaint(small_depthf,(small_depthf == 255),_tmp1,5.0,INPAINT_TELEA);
			
			resize(_tmp1, _tmp, depthf.size());
			_tmp.copyTo(depthf, (depthf == 255));
		}

		{
//			Mat smallDepth = depthf; //cv::resize(depthf,smallDepth,Size(),0.5,0.5);
//			Mat edges; //Laplacian(smallDepth, edges, -1, 7, 1.0);
//			Sobel(smallDepth, edges, -1, 1, 1, 7);
			//medianBlur(edges, edges, 11);
//			for (int x=0; x < edges.cols; x+=20) {
//				for (int y=0; y < edges.rows; y+=20) {
//					//int nz = countNonZero(edges(Range(y,MIN(y+20,edges.rows-1)),Range(x,MIN(x+20,edges.cols-1))));
//					Mat _i = edges(Range(y,MIN(y+20,edges.rows-1)),Range(x,MIN(x+20,edges.cols-1)));
//					medianBlur(_i, _i, 7);
//					//rectangle(edges, Point(x,y), Point(x+20,y+20), Scalar(nz), CV_FILLED);
//				}
//			}
		
//			imshow("edges", edges);
		}
				
		cvtColor(depthf, outC, CV_GRAY2BGR);
		
		Mat blobMaskInput = depthf < 120; //anything not white is "real" depth, TODO: inpainting invalid data
		vector<Point> ctr,ctr2;

		//closest point to the camera
		Point minLoc; double minval,maxval;
		minMaxLoc(depthf, &minval, &maxval, &minLoc, NULL, blobMaskInput);
		circle(outC, minLoc, 5, Scalar(0,255,0), 3);
		
		blobMaskInput = depthf < (minval + 18);
		
		Scalar blb = refineSegments(Mat(),blobMaskInput,blobMaskOutput,ctr,ctr2,midBlob); //find contours in the foreground, choose biggest
//		if (blobMaskOutput.data != NULL) {
//			imshow("first", blobMaskOutput);
//		}
		/////// blb :
		//blb[0] = x, blb[1] = y, blb[2] = 1st blob size, blb[3] = 2nd blob size.
		

		
		if(blb[0]>=0 && blb[2] > 500) { //1st blob detected, and is big enough
			//cvtColor(depthf, outC, CV_GRAY2BGR);
			
			Scalar mn,stdv;
			meanStdDev(depthf,mn,stdv,blobMaskInput);
			
			//cout << "min: " << minval << ", max: " << maxval << ", mean: " << mn[0] << endl;
			
			//now refining blob by looking at the mean depth value it has...
			blobMaskInput = depthf < (mn[0] + stdv[0]);
			
			//(very simple) bias with hand color
			{
				Mat hsv; cvtColor(rgbMat, hsv, CV_RGB2HSV);
				Mat _col_p(hsv.size(),CV_32FC1);
				int jump = 5;
				for (int x=0; x < hsv.cols; x+=jump) {
					for (int y=0; y < hsv.rows; y+=jump) {
						Mat _i = hsv(Range(y,MIN(y+jump,hsv.rows-1)),Range(x,MIN(x+jump,hsv.cols-1)));
						Scalar hsv_mean = mean(_i);
						Vec2i u; u[0] = hsv_mean[0]; u[1] = hsv_mean[1];
						Vec2i v; v[0] = 120; v[1] = 110;
						rectangle(_col_p, Point(x,y), Point(x+jump,y+jump), Scalar(1.0-MIN(norm(u-v)/125.0,1.0)), CV_FILLED);
					}
				}
				//			hsv = hsv - Scalar(0,0,255);
				Mat _t = (Mat_<double>(2,3) << 1, 0, 15,    0, 1, -20);
				Mat col_p(_col_p.size(),CV_32FC1);
				warpAffine(_col_p, col_p, _t, col_p.size());
				GaussianBlur(col_p, col_p, Size(11.0,11.0), 2.5);
				imshow("hand color",col_p);
				//			imshow("rgb",rgbMat);
				Mat blobMaskInput_32FC1; blobMaskInput.convertTo(blobMaskInput_32FC1, CV_32FC1, 1.0/255.0);
				blobMaskInput_32FC1 = blobMaskInput_32FC1.mul(col_p, 1.0);
				blobMaskInput_32FC1.convertTo(blobMaskInput, CV_8UC1, 255.0);
				
				blobMaskInput = blobMaskInput > 128;
				
				imshow("blob bias", blobMaskInput);
			}
			
			
			blb = refineSegments(Mat(),blobMaskInput,blobMaskOutput,ctr,ctr2,midBlob);
			
			imshow("blob", blobMaskOutput);
			
			if(blb[0] >= 0 && blb[2] > 300) {
				//draw contour
				Scalar color(0,0,255);
				for (int idx=0; idx<ctr.size()-1; idx++)
					line(outC, ctr[idx], ctr[idx+1], color, 1);
				line(outC, ctr[ctr.size()-1], ctr[0], color, 1);
				
				if(ctr2.size() > 0) {	//second blob detected
					Scalar color2(255,0,255);
					for (int idx=0; idx<ctr2.size()-1; idx++)
						line(outC, ctr2[idx], ctr2[idx+1], color2, 2);
					line(outC, ctr2[ctr2.size()-1], ctr2[0], color2, 2);
				}
								
				//blob center
				circle(outC, Point(blb[0],blb[1]), 50, Scalar(255,0,0), 3);
				
				{
					Mat hsv; cvtColor(rgbMat, hsv, CV_RGB2HSV);
					Scalar hsv_mean,hsv_stddev; meanStdDev(hsv, hsv_mean, hsv_stddev, blobMaskOutput);
					stringstream ss; ss << hsv_mean[0] << "," << hsv_mean[1] << "," << hsv_mean[2];
					putText(outC, ss.str(), Point(blb[0],blb[1]), CV_FONT_HERSHEY_PLAIN, 1.0, Scalar(0,255,255));
				}
				
				
				Mat blobDepth,blobEdge; 
				depthf.copyTo(blobDepth,blobMaskOutput);
				Laplacian(blobDepth, blobEdge, 8);
//				equalizeHist(blobEdge, blobEdge);//just for visualization
				
				Mat logPolar(depthf.size(),CV_8UC1);
				cvLogPolar(&((IplImage)blobEdge), &((IplImage)logPolar), Point2f(blb[0],blb[1]), 80.0);
				
//				for (int i=0; i<num_x_reps+1; i++) {
//					//verical lines
//					line(logPolar, Point(startX+i*width_over_num_x_reps, 0), Point(startX+i*width_over_num_x_reps,479), Scalar(255), 1);
//				}
//				for(int i=0; i<num_y_reps+1; i++) {			
//					//horizontal
//					line(logPolar, Point(startX, i*height_over_num_y_reps), Point(startX+sizeX,i*height_over_num_y_reps), Scalar(255), 1);
//				}
				
				double total = 0.0;
				
				//histogram
				for (int i=0; i<num_x_reps; i++) {
					for(int j=0; j<num_y_reps; j++) {
						Mat part = logPolar(
										Range(j*height_over_num_y_reps,(j+1)*height_over_num_y_reps),
										 Range(startX+i*width_over_num_x_reps,startX+(i+1)*width_over_num_x_reps)
										 );
						
//						int count = countNonZero(part); //TODO: use calcHist
//						_d[i*num_x_reps + j] = count;

						Scalar mn = mean(part);						
//						part.setTo(Scalar(mn[0])); //for debug: show the value in the image
						_d[i*num_x_reps + j] = mn[0];
						
						
						total += mn[0];
					}
				}
				
				descriptorMat = descriptorMat / total;
				
				/*
				Mat images[1] = {logPolar(Range(0,30),Range(0,30))};
				int nimages = 1;
				int channels[1] = {0};
				int dims = 1;
				float range_0[]={0,256};
				float* ranges[] = { range_0 };
				int histSize[1] = { 5 };
				
				calcHist(, <#int nimages#>, <#const int *channels#>, <#const Mat mask#>, <#MatND hist#>, <#int dims#>, <#const int *histSize#>, <#const float **ranges#>, <#bool uniform#>, <#bool accumulate#>)
				*/
				
//				Mat _tmp(logPolar.size(),CV_8UC1);
//				cvLogPolar(&((IplImage)logPolar), &((IplImage)_tmp),Point2f(blb[0],blb[1]), 80.0, CV_WARP_INVERSE_MAP);
//				imshow("descriptor", _tmp);
//				imshow("logpolar", logPolar);
			}
		}
		
		if(trained) {
			Mat results(1,1,CV_32FC1);
			Mat samples; Mat(Mat(_d).t()).convertTo(samples,CV_32FC1);
			
			Mat samplesAfterPCA = samples; //pca.project(samples);
			
			classifier.find_nearest(&((CvMat)samplesAfterPCA), 1, &((CvMat)results));
//			((float*)results.data)[0] = classifier.predict(&((CvMat)samples))->value;
			
			Mat lc(label_counts); lc *= 0.9;
			
//			label_counts[(int)((float*)results.data)[0]] *= 0.9;
			label_counts[(int)((float*)results.data)[0]] += 0.1;
			Point maxLoc;
			minMaxLoc(lc, NULL, NULL, NULL, &maxLoc);
			int res = maxLoc.y;
			
			stringstream ss; ss << "prediction: ";
			if (res == LABEL_OPEN) {
				ss << "Open hand";
			}
			if (res == LABEL_FIST) {
				ss << "Fist";
			}
			if (res == LABEL_THUMB) {
				ss << "Thumb";
			}
			if (res == LABEL_GARBAGE) {
				ss << "Garbage";
			}
			putText(outC, ss.str(), Point(20,50), CV_FONT_HERSHEY_PLAIN, 3.0, Scalar(0,0,255), 2);
		}
		
		stringstream ss; ss << "samples: " << training_data.size();
		putText(outC, ss.str(), Point(30,outC.rows - 30), CV_FONT_HERSHEY_PLAIN, 2.0, Scalar(0,0,255), 1);
		
		imshow("blobs", outC);
		
		char k = cvWaitKey(5);
		if( k == 27 ){
			break;
		}
		if( k == 8 ) {
			std::ostringstream file;
			file << filename << i_snap << suffix;
			cv::imwrite(file.str(),rgbMat);
			i_snap++;
		}
		if (k == 'g') {
			//put into training as 'garbage'
			training_data.push_back(_d);
			label_data.push_back(LABEL_GARBAGE);
			cout << "learn grabage" << endl;
		}
		if(k == 'o') {
				//put into training as 'open'
			training_data.push_back(_d);
			label_data.push_back(LABEL_OPEN);
			cout << "learn open" << endl;
		}
		if(k == 'f') {
			//put into training as 'fist'
			training_data.push_back(_d);
			label_data.push_back(LABEL_FIST);
			cout << "learn fist" << endl;
		}
		if(k == 'h') {
			//put into training as 'thumb'
			training_data.push_back(_d);
			label_data.push_back(LABEL_THUMB);
			cout << "learn thumb" << endl;
		}
		if (k=='t') {
			//train model
			cout << "train model" << endl;
			if(loaded != true) {
				dataMat = Mat(training_data.size(),_d.size(),CV_32FC1);	//descriptors as matrix rows
				for (uint i=0; i<training_data.size(); i++) {
					Mat v = dataMat(Range(i,i+1),Range::all());
					Mat(Mat(training_data[i]).t()).convertTo(v,CV_32FC1,1.0);
				}
				Mat(label_data).convertTo(labelMat,CV_32FC1);
			}
			
//			pca = pca(dataMat,Mat(),CV_PCA_DATA_AS_ROW,15);
			Mat dataAfterPCA = dataMat;
//			pca.project(dataMat,dataAfterPCA);
			
			classifier.train(&((CvMat)dataAfterPCA), &((CvMat)labelMat));
			
			trained = true;
		}
//		if(k=='p' && trained) {
//			//predict
//			Mat results(1,1,CV_32FC1);
//			Mat samples(1,64,CV_32FC1); Mat(Mat(_d).t()).convertTo(samples,CV_32FC1);
//			classifier.find_nearest(&((CvMat)samples), 1, &((CvMat)results));
//			cout << "prediction: " << ((float*)results.data)[0] << endl;
//		}
		if(k=='s') {
			cout << "save training data" << endl;
//			classifier.save("knn-classifier-open-fist-thumb.yaml"); //not implemented
			dataMat = Mat(training_data.size(),_d.size(),CV_32FC1);	//descriptors as matrix rows
			for (uint i=0; i<training_data.size(); i++) {
				Mat v = dataMat(Range(i,i+1),Range::all());
				Mat(Mat(training_data[i]).t()).convertTo(v,CV_32FC1,1.0);
			}
			Mat(label_data).convertTo(labelMat,CV_32FC1);

			FileStorage fs;
			fs.open("data-samples-labels.yaml", CV_STORAGE_WRITE);
			if (fs.isOpened()) {
				fs << "samples" << dataMat;
				fs << "labels" << labelMat;

				fs << "startX" << startX;
				fs << "sizeX" << sizeX;
				fs << "num_x_reps" << num_x_reps;
				fs << "num_y_reps" << num_y_reps;
				
				loaded = true;
				fs.release();
			} else {
				cerr << "can't open saved data" << endl;
			}
		}
		if(k=='l') {
			cout << "try to load training data" << endl;
			FileStorage fs;
			fs.open("data-samples-labels.yaml", CV_STORAGE_READ);
			if (fs.isOpened()) {
				fs["samples"] >> dataMat;
				fs["labels"] >> labelMat;
				fs["startX"] >> startX;
				fs["sizeX"] >> sizeX;
				fs["num_x_reps"] >> num_x_reps;
				fs["num_y_reps"] >> num_y_reps;
				height_over_num_y_reps = 480/num_y_reps;
				width_over_num_x_reps = sizeX/num_x_reps;
				
				loaded = true;
				fs.release();			
			} else {
Example #22
0
int Judgement::JudgementYON(Mat &image)
{
	int success = 0;
	MatND dstHist;
	Mat histoImg = image.clone();
	calcHist(&histoImg, 1, &channels, Mat(), dstHist, 1, &size, ranges);
	Mat dstImg(256, 256, CV_8U, Scalar(0));//画直方图
	double minValue = 0;
	double maxValue = 0;
	Point maxloc;
	minMaxLoc(dstHist, &minValue, &maxValue, NULL, &maxloc);
	//cout << "	     " << n << "." << m << "	     " << maxValue << endl;
	int hpt = saturate_cast<int>(0.9 * 256);
	vector<int> Boundnum;
	for (int j = 0; j < 256; j++)
	{
		float binValue = dstHist.at<float>(j);
		int realValue = saturate_cast<int>(binValue * hpt / maxValue);
		if (realValue != 0)
		{
			rectangle(dstImg, Point(j, 255), Point(j, 256 - realValue), Scalar(255));
			Boundnum.push_back(j);
		}

	}
	int  maxdata = *max_element(Boundnum.begin(), Boundnum.end());
	int  mindata = *min_element(Boundnum.begin(), Boundnum.end());//寻找直方图动态范围

	Rect recttemp;
	recttemp.x = maxloc.x;
	recttemp.y = maxloc.y - int((maxdata - mindata)*0.15);
	recttemp.width = 1;
	recttemp.height = int((maxdata - mindata)*0.3);
	rectangle(dstHist, recttemp, Scalar(0), -1);
	minMaxLoc(dstHist, &minValue, &maxValue, NULL, &maxloc);
	int anoThres = maxloc.y;//寻找次峰值

	Scalar avgnum;
	Mat StdDevImg;
	meanStdDev(histoImg, avgnum, StdDevImg);
	double Stdnum = StdDevImg.at<double>(Point(0, 0));

	int ThreStep = maxdata - mindata;
	int StepNum = 30;
	int OrStep = mindata + int(ThreStep / 10);
	int Dstep = int(ThreStep / 30.0 + 0.5);
	if (Dstep == 0)
	{
		Dstep = 1;
		StepNum = ThreStep;
	}
	Mat TempImg;
	histoImg.copyTo(TempImg);
	vector<vector<Point>> contours;
	vector<Vec4i> hierarchy;
	Point pointSN, maxPoint = Point(0, 0);
	int Marknumone = 0;
	int Marknumtwo = 0;
	int Marknumthree = 0;
	for (int i = 0; i < StepNum; i++)
	{
		vector<Point> SN;
		OrStep = OrStep + Dstep;
		threshold(histoImg, TempImg, OrStep, 255, CV_THRESH_BINARY);


		/*Mat element = getStructuringElement(MORPH_RECT,Size(2,2));
		erode(TempImg, TempImg, cv::Mat());
		dilate(TempImg, TempImg, cv::Mat());*/
		TempImg = ~TempImg;


		/*stringstream strstrone;
		strstrone << "水渍动态图" << i << ".jpg";
		imwrite(strstrone.str(), TempImg);*/

		Mat BoundImg(TempImg.rows, TempImg.cols, CV_8UC1, Scalar(255));
		Rect Wrect;
		Wrect.x = 1;
		Wrect.y = 1;
		Wrect.width = BoundImg.cols - 2;
		Wrect.height = BoundImg.rows - 2;
		rectangle(BoundImg, Wrect, Scalar(0), -1);

		Mat PlusImg(TempImg.rows + 2, TempImg.cols + 2, CV_8UC1, Scalar(255));
		Mat PlusROI = PlusImg(Rect(1, 1, TempImg.cols, TempImg.rows));
		TempImg.copyTo(PlusROI);
		Mat ContoursImg = PlusImg.clone();

		findContours(ContoursImg, contours, hierarchy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
		for (size_t j = 0; j < contours.size(); j++)
		{
			double area = cv::contourArea(contours[j]);
			pointSN.x = int(area);
			pointSN.y = j;
			SN.push_back(pointSN);
		}

		if (contours.size() != 0)
		{
			sort(SN.begin(), SN.end(), SortByM2);
			maxPoint = SN.back();
			if (OrStep > anoThres - 5 && OrStep<anoThres + 20)
				Dstep = 1;
			else
			{
				Dstep = int(ThreStep / 30.0 + 0.5);
			}
			if (Dstep == 0)
				Dstep = 1;
			int k = maxPoint.y;


			Mat MarkImg(TempImg.rows, TempImg.cols, CV_8UC1, Scalar(0));
			drawContours(MarkImg, contours, k, Scalar(255), -1);
			bitwise_and(BoundImg, MarkImg, MarkImg);
			int Mbound = 0;//判断轮廓是否到边界
			Mbound = countNonZero(MarkImg);
			if (Mbound>0.5*(histoImg.cols))
				break;
			if (contours[k].size() <= 4)
				continue;
			int son = hierarchy[k][2];
			Point gravitycore = barycenter(contours[k]);//寻找轮廓重心

			Rect maxcontours = boundingRect(contours[k]);
			int wValue = maxcontours.width / 12;
			gravitycore = gravitycore + Point(wValue - 1, wValue - 1);

			Mat gravityImg(TempImg.rows + 2 * wValue, TempImg.cols + 2 * wValue, CV_8UC1, Scalar(0));
			Mat gravityImgROI = gravityImg(Rect(wValue, wValue, TempImg.cols, TempImg.rows));
			TempImg.copyTo(gravityImgROI);


			Rect gravityrect = Rect(gravitycore - Point(1, 1), gravitycore + Point(2 * wValue, 2 * wValue) - Point(2, 2));//画出重心周围(2 * wValue)*(2 * wValue)的矩形区域
			if (gravityrect.x < 0 || gravityrect.y < 0)
				continue;

			int avnum = countNonZero(gravityImg(Rect(gravityrect)));
			vector<Point> hull;
			convexHull(contours[k], hull, false);
			double promark = (contourArea(contours[k])) / (contourArea(hull));

			if (son >= 0)//判断是否为父轮廓
			{
				int sonarea = 0;
				for (size_t j = 0; j < contours.size(); j++)
				{
					if (hierarchy[j][3] == k&&contourArea(contours[j])>4.0)
						sonarea = sonarea + contourArea(contours[j]);
				}
				if (50 * sonarea>maxPoint.x)//此处忽略一些偶然出现的中空点
					Marknumone++;
			}
			if (avnum < double(0.5 * gravityrect.width*gravityrect.width))//在重心区域中的白色点的数量是否过半
				Marknumtwo++;
			if (promark < 0.6)
				Marknumthree++;
		}

	}

	if (Marknumone > 2 || Marknumtwo >= 2 || Marknumthree > 3)//缺陷点也可能偶然出现包含
	{
		/*cout << "该点是水渍2" << endl;*/

	}
	else
	{
		/*cout << "该点是缺陷2" << endl;*/
		success++;
	}
	return success;
}
Example #23
0
int main(int argc, char **argv)
{
  int res;

  try {
    socket.bind ("tcp://*:14444");
    s_sendmore (socket, "event");
        s_send (socket, "{type:\"up\"}");
  }
  catch (zmq::error_t e) {
    cerr << "Cannot bind to socket: " <<e.what() << endl;
    return -1;
  }

  //  printf("Kinect camera test\n");
  //
  //  int i;
  //  for (i=0; i<2048; i++) {
  //    float v = i/2048.0;
  //    v = powf(v, 3)* 6;
  //    t_gamma[i] = v*6*256;
  //  }
  //
  //  g_argc = argc;
  //  g_argv = argv;
  //
  //  //setup Freenect...
  //  if (freenect_init(&f_ctx, NULL) < 0) {
  //    printf("freenect_init() failed\n");
  //    return 1;
  //  }
  //
  //  freenect_set_log_level(f_ctx, FREENECT_LOG_ERROR);
  //
  //  int nr_devices = freenect_num_devices (f_ctx);
  //  printf ("Number of devices found: %d\n", nr_devices);
  //
  //  int user_device_number = 0;
  //  if (argc > 1)
  //    user_device_number = atoi(argv[1]);
  //
  //  if (nr_devices < 1)
  //    return 1;
  //
  //  if (freenect_open_device(f_ctx, &f_dev, user_device_number) < 0) {
  //    printf("Could not open device\n");
  //    return 1;
  //  }
  //
  //  freenect_set_tilt_degs(f_dev,freenect_angle);
  //  freenect_set_led(f_dev,LED_RED);
  //  freenect_set_depth_callback(f_dev, depth_cb);
  //  freenect_set_video_callback(f_dev, rgb_cb);
  //  freenect_set_video_format(f_dev, FREENECT_VIDEO_RGB);
  //  freenect_set_depth_format(f_dev, FREENECT_DEPTH_11BIT);
  //
  //  freenect_start_depth(f_dev);
  //  freenect_start_video(f_dev);

  initFreenect();

  //start the freenect thread to poll for events
  res = pthread_create(&ocv_thread, NULL, freenect_threadfunc, NULL);
  if (res) {
    printf("pthread_create failed\n");
    return 1;
  }

  Mat depthf;

  Mat frameMat(rgbMat);
  Mat blobMaskOutput(frameMat.size(),CV_8UC1),
  outC(frameMat.size(),CV_8UC3);
  Mat prevImg(frameMat.size(),CV_8UC1),
  nextImg(frameMat.size(),CV_8UC1),
  prevDepth(depthMat.size(),CV_8UC1);
  vector<Point2f> prevPts,nextPts;
  vector<uchar> statusv;
  vector<float> errv;
  Rect cursor(frameMat.cols/2,frameMat.rows/2,10,10);
  bool update_bg_model = true;
  int fr = 1;
  int register_ctr = 0,register_secondbloc_ctr = 0;
  bool registered = false;

  Point2i appear(-1,-1); double appearTS = -1;

  Point2i midBlob(-1,-1);
  Point2i lastMove(-1,-1);

  int hcr_ctr = -1;
  vector<int> hc_stack(20); int hc_stack_ptr = 0;

  while (!die) {
    fr++;

    //    imshow("rgb", rgbMat);
    pthread_mutex_lock(&buf_mutex);

    //Linear interpolation
    {
      Mat _tmp = (depthMat - 400.0);          //minimum observed value is ~440. so shift a bit
      _tmp.setTo(Scalar(2048), depthMat > ((!registered) ? 700.0 : 750.0));   //cut off at 600 to create a "box" where the user interacts
      _tmp.convertTo(depthf, CV_8UC1, 255.0/1648.0);  //values are 0-2048 (11bit), account for -400 = 1648
    }

    {
      Mat _tmp;
      depthMat.convertTo(_tmp, CV_8UC1, 255.0/2048.0);
      cvtColor(_tmp, outC, CV_GRAY2BGR);
    }

    pthread_mutex_unlock(&buf_mutex);

    //    { //saving the frames to files for debug
    //      stringstream ss; ss << "depth_"<<fr<<".png";
    //      imwrite(ss.str(), depthf);
    //    }

    //Logarithm interpolation - try it!, It should be more "sensitive" for closer depths
    //    {
    //      Mat tmp,tmp1;
    //      depthMat.convertTo(tmp, CV_32FC1);
    //      log(tmp,tmp1);
    //      tmp1.convertTo(depthf, CV_8UC1, 255.0/7.6246189861593985);
    //    }
    //    imshow("depth",depthf);


    Mat blobMaskInput = depthf < 255; //anything not white is "real" depth
    vector<Point> ctr,ctr2;


    Scalar blb = refineSegments(Mat(),blobMaskInput,blobMaskOutput,ctr,ctr2,midBlob); //find contours in the foreground, choose biggest
    imshow("first", blobMaskOutput);
    /////// blb :
    //blb[0] = x, blb[1] = y, blb[2] = 1st blob size, blb[3] = 2nd blob size.

    //    uint mode_counters[3] = {0};

    if(blb[0]>=0 && blb[2] > 500) { //1st blob detected, and is big enough
      //cvtColor(depthf, outC, CV_GRAY2BGR);

      //closest point to the camera
      Point minLoc; double minval,maxval;
      minMaxLoc(depthf, &minval, &maxval, &minLoc, NULL, blobMaskInput);
      circle(outC, minLoc, 5, Scalar(0,255,0), 3);

      Scalar mn,stdv;
      meanStdDev(depthf,mn,stdv,blobMaskInput);

      //cout << "min: " << minval << ", max: " << maxval << ", mean: " << mn[0] << endl;

      blobMaskInput = depthf < (mn[0] + stdv[0]*.5);

      blb = refineSegments(Mat(),blobMaskInput,blobMaskOutput,ctr,ctr2,midBlob);

      imshow("second", blobMaskOutput);

      if(blb[0] >= 0 && blb[2] > 300) {
        //draw contour
        Scalar color(0,0,255);
        for (int idx=0; idx<ctr.size()-1; idx++)
          line(outC, ctr[idx], ctr[idx+1], color, 1);
        line(outC, ctr[ctr.size()-1], ctr[0], color, 1);

        if(ctr2.size() > 0) {
          Scalar color2(255,0,255);
          for (int idx=0; idx<ctr2.size()-1; idx++)
            line(outC, ctr2[idx], ctr2[idx+1], color2, 2);
          line(outC, ctr2[ctr2.size()-1], ctr2[0], color2, 2);
        }

        //draw "major axis"
        //      Vec4f _line;
        Mat curve(ctr);
        //      fitLine(curve, _line, CV_DIST_L2, 0, 0.01, 0.01);
        //      line(outC, Point(blb[0]-_line[0]*70,blb[1]-_line[1]*70),
        //            Point(blb[0]+_line[0]*70,blb[1]+_line[1]*70),
        //            Scalar(255,255,0), 1);

        //blob center
        circle(outC, Point(blb[0],blb[1]), 50, Scalar(255,0,0), 3);


        //      cout << "min depth " << minval << endl;

        register_ctr = MIN((register_ctr + 1),60);

        if(blb[3] > 5000)
          register_secondbloc_ctr = MIN((register_secondbloc_ctr + 1),60);

        if (register_ctr > 30 && !registered) {
          registered = true;
          appear.x = -1;
          update_bg_model = false;
          lastMove.x = blb[0]; lastMove.y = blb[1];

          cout << "blob size " << blb[2] << endl;

          if(register_secondbloc_ctr < 30) {
            if(blb[2] > 10000) {
              cout << "register panner" << endl;
              send_event("Register", "\"mode\":\"openhand\"");
            } else {
              cout << "register pointer" << endl;
              send_event("Register", "\"mode\":\"theforce\"");
            }
          } else {
            cout << "register tab swithcer" << endl;
            send_event("Register", "\"mode\":\"twohands\"");
          }
        }

        if(registered) {
          stringstream ss;
          ss  << "\"x\":"  << (int)floor(blb[0]*100.0/640.0)
            << ",\"y\":" << (int)floor(blb[1]*100.0/480.0)
            << ",\"z\":" << (int)(mn[0] * 2.0);
          //cout << "move: " << ss.str() << endl;
          send_event("Move", ss.str());

          //---------------------- fist detection ---------------------
          //calc laplacian of curve
          vector<Point> approxCurve;  //approximate curve
          approxPolyDP(curve, approxCurve, 10.0, true);
          Mat approxCurveM(approxCurve);

          Mat curve_lap;
          calc_laplacian(approxCurveM, curve_lap);  //calc laplacian

          hcr_ctr = 0;
          for (int i=0; i<approxCurve.size(); i++) {
            double n = norm(((Point2d*)(curve_lap.data))[i]);
            if (n > 10.0) {
              //high curvature point
              circle(outC, approxCurve[i], 3, Scalar(50,155,255), 2);
              hcr_ctr++;
            }
          }

          hc_stack.at(hc_stack_ptr) = hcr_ctr;
          hc_stack_ptr = (hc_stack_ptr + 1) % hc_stack.size();

          Scalar _avg = mean(Mat(hc_stack));
          if (abs(_avg[0] - (double)hcr_ctr) > 5.0) { //a big change in curvature = hand fisted/opened?
            cout << "Hand click!" << endl;
            send_event("HandClick", "");
          }

          if (mode_state == MODE_NONE) {

          }

          //        imshow("out",out);
          //doHist(depthf,out);

          { //some debug on screen..
            stringstream ss; ss << "high curve pts " << hcr_ctr << ", avg " << _avg[0];
            putText(outC, ss.str(), Point(50,50), CV_FONT_HERSHEY_PLAIN, 2.0,Scalar(0,0,255), 2);
          }
        } else {
          //not registered, look for gestures
          if(appear.x<0) {
            //first appearence of blob
            appear = midBlob;
            //          update_bg_model = false;
            appearTS = getTickCount();
            cout << "appear ("<<appearTS<<") " << appear.x << "," << appear.y << endl;
          } else {
            //blob was seen before, how much time passed
            double timediff = ((double)getTickCount()-appearTS)/getTickFrequency();
            if (timediff > .2 && timediff < 1.0) {
              //enough time passed from appearence
              line(outC, appear, Point(blb[0],blb[1]), Scalar(0,0,255), 3);
              if (appear.x - blb[0] > 100) {
                cout << "right"<<endl; appear.x = -1;
                send_event("SwipeRight", "");
                update_bg_model = true;
                register_ctr = 0;
              } else if (appear.x - blb[0] < -100) {
                cout << "left" <<endl; appear.x = -1;
                send_event("SwipeLeft", "");
                update_bg_model = true;
                register_ctr = 0;
              } else if (appear.y - blb[1] > 100) {
                cout << "up" << endl; appear.x = -1;
                send_event("SwipeUp", "");
                update_bg_model = true;
                register_ctr = 0;
              } else if (appear.y - blb[1] < -100) {
                cout << "down" << endl; appear.x = -1;
                send_event("SwipeDown", "");
                update_bg_model = true;
                register_ctr = 0;
              }
            }
            if(timediff >= 1.0) {
              cout << "a ghost..."<<endl;
              update_bg_model = true;
              //a second passed from appearence - reset 1st appear
              appear.x = -1;
              appearTS = -1;
              midBlob.x = midBlob.y = -1;
            }
          }
        }
        send_image(outC);
      }
    } else {
      send_image(depthf);
      register_ctr = MAX((register_ctr - 1),0);
      register_secondbloc_ctr = MAX((register_secondbloc_ctr - 1),0);
    }
    imshow("blob",outC);

    if (register_ctr <= 15 && registered) {
      midBlob.x = midBlob.y = -1;
      registered = false;
      mode_state = MODE_NONE;
      update_bg_model = true;
      cout << "unregister" << endl;
      send_event("Unregister", "");
    }

        char k = cvWaitKey(5);
        if( k == 27 ) break;
        if( k == ' ' )
            update_bg_model = !update_bg_model;
    if (k=='s') {
      cout << "send test event" << endl;
      send_event("TestEvent", "");
    }
  }

  printf("-- done!\n");

  pthread_join(ocv_thread, NULL);
  pthread_exit(NULL);
  return 0;
}
void LaneDetection::AlgoFilterLanes(ntuple_list line_out)
{
	//fout_2.open("pairs.txt");
	unsigned int dim = line_out->dim;
	int n_size = line_out->size;
	
	Mat lines_candidats = Mat::zeros(processGrayImage.size(), CV_32SC1);

	for (int i = 0; i < n_size; i++)
	{
		const Point2d p1(line_out->values[i * dim + 0], line_out->values[i * dim + 1]);
		const Point2d p2(line_out->values[i * dim + 2], line_out->values[i * dim + 3]);
		Segment2d p12 = Segment2d(p1, p2);//p1.y < p2.y

		for (int j = 0; j < n_size; j++)
		{
			if (j == i) continue;
			Point2d seg1(line_out->values[j * dim + 0], line_out->values[j * dim + 1]);
			Point2d seg2(line_out->values[j * dim + 2], line_out->values[j * dim + 3]);
			Segment2d seg(seg1, seg2);
			
			if (seg.getLength() > p12.getLength())
			{
				continue;
			}

			//simple check
			if (!p12.isNeighbor(seg))
			{
				continue;
			}

			//slope difference?
			if (abs(atan(p12.getSlope()) - atan(seg.getSlope())) > 15 * CV_PI / 180)
			{
				//fout_2 << p1 << p2 << seg1 << seg2 << p12.getSlope() << "," << seg.getSlope() << endl;
				//fout_2 << "continue in abs(atan(p12.getSlope()) - atan(seg.getSlope())) > 10 * CV_PI / 180" << endl;
				continue;
			}

			vector<Segment2d> v = p12.getValidPoly(seg, processGrayImage.rows);
			//valid?
			if (v.empty())
			{
				//fout_2 << p1 << p2 << seg1 << seg2 << endl;
				//fout_2 << "continue in v.empty()" << endl;
				continue;
			}

			//color compare
			Point2d translation[3];
			translation[0] = Point2d(0, 0);
			translation[1] = v[0].p1 - v[1].p1;
			translation[2] = -translation[1];

			vector<uchar> vec_color[3];
			double mean_color[3];
			double stdDev_color[3];
			

			for (int _trans = 0; _trans < 3; _trans++)
			{
				Rect box = getBoundingBox(v[0].p1 + translation[_trans], v[0].p2 + translation[_trans],
					v[1].p1 + translation[_trans], v[1].p2 + translation[_trans]);
				for (int _y = box.y; _y < box.y + box.height; _y++)
				{
					if (_y >= processImage.rows || _y < 0) continue;
					uchar* ptr_row_processImage = processGrayImage.ptr<uchar>(_y);
					for (int _x = box.x; _x < box.x + box.width; _x++)
					{
						if (_x >= processImage.cols || _x < 0) continue;
						Point2d p(_x, _y);
						int direc = cross(p, v[0].p1 + translation[_trans], v[0].p2 + translation[_trans]) > -0.0 ? 1 : -1;

						if (direc != (cross(p, v[0].p2 + translation[_trans], v[1].p2 + translation[_trans]) > -0.0 ? 1 : -1))
							continue;
						if (direc != (cross(p, v[1].p2 + translation[_trans], v[1].p1 + translation[_trans]) > -0.0 ? 1 : -1))
							continue;
						if (direc != (cross(p, v[1].p1 + translation[_trans], v[0].p1 + translation[_trans]) > -0.0 ? 1 : -1))
							continue;

						vec_color[_trans].push_back(ptr_row_processImage[_x]);
					}
				}
				if (vec_color[_trans].empty())
					;
				else
				{
					Mat mean, stdDev;
					meanStdDev(vec_color[_trans], mean, stdDev);
					mean_color[_trans] = mean.at<double>(0);
					stdDev_color[_trans] = stdDev.at<double>(0);
				}
			}

			bool color_matched = (mean_color[0] > mean_color[1] + 10) && (mean_color[0] > mean_color[2] + 10)
				&& stdDev_color[0] < 50;

			if (!color_matched)
			{
				//fout_2 << p1 << p2 << seg1 << seg2 << mean_color[0] << "," << mean_color[1] << "," << mean_color[2];
				//fout_2 << "," << stdDev_color[0] << endl;
				//fout_2 << "continue in color_matched" << endl;

				continue;
			}

			//fout_2 << p1 << p2 << seg1 << seg2 << endl;
			//fout_2 << "Paired!!!!!!" << endl;

			line(processImage, p1, p2, Scalar(0, 0, 255));
			line(processImage, seg1, seg2, Scalar(0, 255, 0));
			//imshow("step1", processImage);
			//waitKey();
			//break;
		}//end for j

	}


	//fout_2 << "-------------------" << endl;
	//fout_2.close();
}
Example #25
0
void RGB::obtainDescriptors (int nGroups)
{
    // Grupos en los que se dividen las imagenes
    int grup10 = nGroups;
    int ix_vec = -1;
    int sizepng = _fileList.size();

    Mat img;
    QString namePng;
    string namePngPath;

    // RGB variables
    vector<float> V_des_RGB;
    vector<float> V_des_mRGB_10;
    vector<float> V_des_mB_10;
    vector<float> V_des_mG_10;
    vector<float> V_des_mR_10;
    vector<float> V_des_sdv_10;
    vector<float> V_des_RGB_10;

    Scalar med_medBlue;
    Scalar med_medGreen;
    Scalar med_medRed;
    Scalar med_medRGB;
    Scalar med_svd;

    Scalar desvi_med_medBlue;
    Scalar desvi_med_medGreen;
    Scalar desvi_med_medRed;
    Scalar desvi_med_medRGB;
    Scalar desvi_med_svd;

    for(int cont = 0; cont < sizepng; ++cont)
    {
        namePng = _fileList.at(cont);
        namePngPath = this->getImagesPath() + namePng.toStdString();

#ifdef DEBUG
        cout << "name image: " << namePng.toStdString() << endl;
        cout << "path image: " << namePngPath << endl;
#endif
        img = imread(namePngPath);

        if(img.empty())
        {
            cout<<"Imagen no leida"<< endl;
        }

        if(!img.empty())
        {
#ifdef DEBUG
            char key;
            imshow("img_in",img);

            key = waitKey(10);
            if(key == 'q' || key == 'c' || key == 'Q' || key == 'C')
            {
                break;
            }
#endif
            grup10 = grup10 - 1;
            // Se calcula el descriptor de la media y la desviacion estandar del RGB
            V_des_RGB = this->extract_RGB_des(img);
            // Almacenamos todos los valores de media y desviacion estandar de cada
            // imagen en el vector _VV_des_RGB
            _VV_des_RGB.push_back(V_des_RGB);

            //Agrupando en grupos de 10
            if(grup10 <= nGroups)
            {
                ix_vec = ix_vec + 1;

                _orden << (Mat)_VV_des_RGB[ix_vec] << " ----> " << namePngPath << "\n";

                // ALMACENAMOS LOS DESCRIPTORES: MEDIA B, G, R, RGB Y DESVIACION ESTANDAR RGB
                V_des_mB_10.push_back(V_des_RGB[0]);
                V_des_mG_10.push_back(V_des_RGB[1]);
                V_des_mR_10.push_back(V_des_RGB[2]);
                V_des_mRGB_10.push_back(V_des_RGB[3]);
                V_des_sdv_10.push_back(V_des_RGB[4]);
            }

            if(grup10 == 0)
            {
                grup10 = nGroups;

                // Calculamos la media R, G, B Y RGB,y la desv tipica de la media RGB para grupos de 10
                meanStdDev((Mat)V_des_mB_10, med_medBlue, desvi_med_medBlue);
                _orden << "med_medBlue : "  << med_medBlue[0]  << " \t desv :  " << desvi_med_medBlue[0] << "\n";

                meanStdDev((Mat)V_des_mG_10, med_medGreen, desvi_med_medGreen);
                _orden << "med_medGreen : " << med_medGreen[0] << " \t desv :  " << desvi_med_medGreen[0] << "\n";

                meanStdDev((Mat)V_des_mR_10, med_medRed, desvi_med_medRed);
                _orden << "med_medRed : "   << med_medRed[0]   << " \t desv :  " << desvi_med_medRed[0] << "\n";

                meanStdDev((Mat)V_des_mRGB_10, med_medRGB, desvi_med_medRGB);
                _orden << "med_medRGB : "   << med_medRGB[0]   << " \t desv :  " << desvi_med_medRGB[0] << "\n";

                meanStdDev((Mat)V_des_sdv_10, med_svd, desvi_med_svd);
                _orden << "med_svd : "      << med_svd[0]      << " \t desv :  " << desvi_med_svd[0] << "\n";

                //Almacenando los descriptores
                _medBlue  << med_medBlue[0]  << " " << desvi_med_medBlue[0]  << "\n";
                _medGreen << med_medGreen[0] << " " << desvi_med_medGreen[0] << "\n";
                _medRed   << med_medRed[0]   << " " << desvi_med_medRed[0]   << "\n";
                _medRGB   << med_medRGB[0]   << " " << desvi_med_medRGB[0]   << "\n";
                _svd      << med_svd[0]      << " " << desvi_med_svd[0]      << "\n";

                // Creamos dos Mat con 1 columna y nfilas de imagenes
                _V_des_RGB_10_SVDmedBlue.push_back(desvi_med_medBlue[0]);
                _V_des_RGB_10_SVDmedGreen.push_back(desvi_med_medGreen[0]);
                _V_des_RGB_10_SVDmedRed.push_back(desvi_med_medRed[0]);
                _V_des_RGB_10_SVDmedRGB.push_back(desvi_med_medRGB[0]);
                _V_des_RGB_10_SVDmedSVD.push_back(desvi_med_svd[0]);

                _V_des_RGB_10_MEDmedBlue.push_back(med_medBlue[0]);
                _V_des_RGB_10_MEDmedGreen.push_back(med_medGreen[0]);
                _V_des_RGB_10_MEDmedRed.push_back(med_medRed[0]);
                _V_des_RGB_10_MEDmedRGB.push_back(med_medRGB[0]);
                _V_des_RGB_10_MEDmedSVD.push_back(med_svd[0]);

                // Almacenamos todos los valores de media y desviacion estandar de cada
                // grupo de imagenes en el vector _VV_des_RGB_10
                V_des_RGB_10.push_back(med_medBlue[0]);
                V_des_RGB_10.push_back(med_medGreen[0]);
                V_des_RGB_10.push_back(med_medRed[0]);
                V_des_RGB_10.push_back(med_medRGB[0]);
                V_des_RGB_10.push_back(med_svd[0]);
                _VV_des_RGB_10.push_back(V_des_RGB_10);

                V_des_RGB_10.clear();
                V_des_mB_10.clear();
                V_des_mG_10.clear();
                V_des_mR_10.clear();
                V_des_mRGB_10.clear();
                V_des_sdv_10.clear();
                _orden << "======================================================" <<"\n" ;
            }
        } // si img no esta vacia
    } // del for cont
    // Cerramos la escritura de los ficheros

    _medBlue.close();
    _medGreen.close();
    _medRed.close();
    _medRGB.close();
    _svd.close();
    _orden.close();
}
void TargetExtractor::regionGrow(int threshold)
{
    Mat gray;
    cvtColor(mFrame, gray, CV_BGR2GRAY);

    Mat temp;
    mMask.copyTo(temp);

    vector<vector<Point> > contours;
    findContours(temp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

    int maxQueueSize = mFrame.rows * mFrame.cols / 4;
    static int direction[8][2] = {
        { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 },
        { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 }
    };

    for (int i = 0; i < contours.size(); i++) {
        Rect rect = boundingRect(Mat(contours[i]));
        Mat mask = Mat::zeros(gray.size(), CV_8U);
        drawContours(mask, contours, i, Scalar::all(255), CV_FILLED);
        int size = sum(mask(rect))[0] / 255;
        Scalar m, s;
        meanStdDev(gray(rect), m, s, mask(rect));
        double mean = m[0], stdDev = s[0];

        Mat temp;
        mMask.copyTo(temp);
        int origSize = size;

        queue<Point> pointQueue;
        for (int j = 0; j < contours[i].size(); j++) {
            uchar pixel = gray.at<uchar>(contours[i][j]);
            if (abs(pixel - mean) < 1.0 * stdDev) {
                pointQueue.push(contours[i][j]);
            }
        }

        Point cur, pop;
        while (!pointQueue.empty() && pointQueue.size() < maxQueueSize) {

            pop = pointQueue.front();
            pointQueue.pop();
            uchar pixel = gray.at<uchar>(pop);

            for (int k = 0; k < 8; k++) {
                cur.x = pop.x + direction[k][0];
                cur.y = pop.y + direction[k][1];

                if (cur.x < 0 || cur.x > gray.cols - 1 || cur.y < 0 || cur.y > gray.rows - 1) {
                    continue;
                }

                if (temp.at<uchar>(cur) != 255) {
                    uchar curPixel = gray.at<uchar>(cur);

                    if (abs(curPixel - pixel) < threshold &&
                            abs(curPixel - mean) < 1.0 * stdDev) {

                        temp.at<uchar>(cur) = 255;

                        double diff = curPixel - mean;
                        double learningRate = 1.0 / (++size);
                        mean = (1 - learningRate) * mean + learningRate * curPixel;
                        stdDev = sqrt((1 - learningRate) * stdDev * stdDev + learningRate * diff * diff);

                        pointQueue.push(cur);
                    }
                }
            }
        }

        if (pointQueue.empty()) {
            int incSize = size - origSize;
            if (incSize < mFrame.rows * mFrame.cols / 6 && incSize / origSize < 5) {
                mMask = temp;
            }
        }
    }
}
//bool Depth_and_Disparity::calc_disperity(int desiredPhase, Mat in_left_clr, Mat in_right_clr, 
bool Depth_and_Disparity::calc_disperity(int desiredPhase, Mat left_im_gray, Mat right_im_gray, 
											Mat BgMask , Target *previousTarget,
											Mat *disperity_out, double *min_depth_of_ROI)
{
	double		max_disperity;
	const double allowed_disp_delta_between_cycles = 0.1 ; //10[%]

	if ( ! (desiredPhase==2) )		//calculate the new disparity for new inputs
	{
		// delivers new input , when the process is waiting (not in calculation process)
		set_disparity_input(right_im_gray,left_im_gray, /*myStereoCams.GetFrameCycleCounter()*/ 1 );  

		// waiting trial : 
		while (! get_rectified_and_disparity(last_result_of_disparity, last_result_of_disparity_struct) )  
		{
		}

		if ((desiredPhase==1))
		{
			*disperity_out = last_result_of_disparity.clone() ;
			return true;
		}
	}
	// continue to give the filtered disparity (for the new or the last calculated)

	/* if output is ready from disparity calculation , it returns true */
	//if ( localDisp.get_rectified_and_disparity(disp_temporary, disperity_struct) )  
	{
		/* calculate average depth for the ROI of the target */ 
		Mat tmpma = last_result_of_disparity;
		if ( ! BgMask.empty() )
		{
			filtered_disparity =	Mat();
			last_result_of_disparity.copyTo(filtered_disparity , BgMask);
			threshold (filtered_disparity , filtered_disparity ,	minDisparityToCut ,	255,THRESH_TOZERO);	
		}
		else 
			/* no additional mask */
			if ((*previousTarget).target_object_prop.relevant_disparity > -999)
			{
				threshold (last_result_of_disparity , filtered_disparity ,	
					(*previousTarget).target_object_prop.relevant_disparity * (1-allowed_disp_delta_between_cycles) ,	
					(*previousTarget).target_object_prop.relevant_disparity * (1+allowed_disp_delta_between_cycles),
					THRESH_TOZERO);	//.15??	
			}
			else
			/* loose the far away objects (small disparities) */
			threshold (last_result_of_disparity , filtered_disparity ,	minDisparityToCut ,	255,THRESH_TOZERO);	

		int an=1;	//an=1->kernel of 3
		Mat element = getStructuringElement(MORPH_RECT, Size(an*2+1, an*2+1), Point(an, an) );
		medianBlur	(filtered_disparity,	filtered_disparity,	an*3);
		erode		(filtered_disparity ,	filtered_disparity, element);									
		dilate		(filtered_disparity,	filtered_disparity, element); 

		//max disperity into avg_disp var
	//	minMaxLoc(filtered_disparity, 0, &max_disperity ); 
	//	convert_disperity_value_to_depth(max_disperity , *min_depth_of_ROI);	
	//	last_disparity_min_depth	= *min_depth_of_ROI;


		Scalar     mean;
		Scalar     stddev;
		Rect tmp = boundingRect(filtered_disparity);
		Mat  tmpMask = filtered_disparity;
		///meanStdDev ( filtered_disparity, mean, stddev );
		///meanStdDev ( filtered_disparity(tmp), mean, stddev );
		meanStdDev ( filtered_disparity, mean, stddev , tmpMask);
		//uchar       mean_pxl = mean.val[0];
		int         mean_val = mean.val[0];
		//uchar       stddev_pxl = stddev.val[0];
		int         stddev_val = stddev.val[0];

		int minDispToTake = mean_val - stddev_val * 1 ;
		if (minDispToTake > mean_val * (1-allowed_disp_delta_between_cycles/2.) ) 
			minDispToTake = mean_val * (1-allowed_disp_delta_between_cycles/2.) ; //minimum for case of ~zero std ;	// furthest object
		//int maxDispToTake = max_disperity ;						// closest  object

		convert_disperity_value_to_depth(mean_val , *min_depth_of_ROI);	
		last_disparity_depth	= *min_depth_of_ROI;

		/* filter far or close objects then the target itself (mean) */
		threshold (filtered_disparity , filtered_disparity ,	minDispToTake ,	255/*max_disperity*/,THRESH_TOZERO);
		/* set partial data for current target */
		(*previousTarget).target_object_prop.relevant_disparity = mean_val;
	}
	
	*disperity_out = filtered_disparity.clone() ;
	
	return true;	// TODO: set as SUCCESS system enum
}
Example #28
0
/*
 * 1. CALCULATE RANGE FROM MEAN AND STANDARD DEVIATION
 * 2. CREATE A MASK FROM THE RANGE
 * 3. SMOOTH STUFF USING MORPHOLOGY
 * 4. DETECT THE CIRCLES
 */
vector<ILAC_Sphere>
ILAC_SphereFinder::findSpheres ( ILAC_Square &square, Mat &img,
                                 const size_t pixSphDiam )
{
  /* 1. CALCULATE RANGE FROM MEAN AND STANDARD DEVIATION */
  Mat mean, stddev;
  {/* Isolate the Hue */
    Mat tmpImg;
    vector<Mat> tmp_dim;
    cvtColor ( square.getImg(), tmpImg, CV_BGR2HSV_FULL );
    split( tmpImg, tmp_dim );
    tmpImg = tmp_dim[0];
    meanStdDev ( tmpImg, mean, stddev );
  }

  /*
   * Range will be -+ 1 standard deviation. This has aprox 68% of the data
   * (http://en.wikipedia.org/wiki/Standard_deviation)
   */
  Mat lowerb = mean - stddev;
  Mat upperb = mean + stddev;

  /* 2. CREATE A MASK FROM THE RANGE */
  Mat himg;
  {
    Mat tmpImg;
    vector<Mat> tmp_dim;
    cvtColor ( img, tmpImg, CV_BGR2HSV_FULL );
    split ( tmpImg, tmp_dim );
    himg = tmp_dim[0];
  }

  Mat mask = Mat::ones(img.rows, img.cols, CV_8UC1);
  inRange(himg, lowerb, upperb, mask);

  /* 3. SMOOTH STUFF USING MORPHOLOGY */
  {
    /*
     * Morphological open is 1.Erode and 2.Dilate. We use 1/4 of the sphere
     * diameter in the hope that its big enough to clean the noise, but not big
     * enough to remove the big sphere blob.
     */
    int openSize = pixSphDiam/4;
    Mat se = getStructuringElement ( MORPH_ELLIPSE, Size(openSize,openSize) );
    morphologyEx ( mask, mask, MORPH_OPEN, se );


    /*
     * We dilate with half of the sphere diameter and hope for a blob
     * that is approx double the radius of the original blob. The edges are more
     * roundy this way.
     */
    int dilateSize = pixSphDiam/2;
    se = getStructuringElement ( MORPH_ELLIPSE,
                                 Size(dilateSize,dilateSize) );
    dilate ( mask, mask, se );
  }

  /* 4. DETECT THE CIRCLES */
  /* Play with the arguments for HoughCircles. */
  vector<Vec3f> circles;
  vector<ILAC_Sphere> spheres;
  int minCircDist = 3*pixSphDiam/2;

  GaussianBlur ( mask, mask, Size(15, 15), 2, 2 );
  HoughCircles ( mask, circles, CV_HOUGH_GRADIENT, 2, minCircDist, 100, 40);

  for( size_t i = 0; i < circles.size(); i++ )
  {
    Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
    int radius = cvRound(circles[i][2]);
    ILAC_Sphere temp ( &img, center, radius );
    spheres.push_back(temp);

    for ( int j = i ;
         j > 0 && spheres[j].getRadius() < spheres[j-1].getRadius() ; j-- )
      std::swap( spheres[j], spheres[j-1] );
  }

  if ( spheres.size() < 3 )
    throw ILACExLessThanThreeSpheres ();

  return spheres;
}
Example #29
0
    void run( Mat& image,
              string& out_sequence,
              vector<Rect>* component_rects,
              vector<string>* component_texts,
              vector<float>* component_confidences,
              int component_level)
    {

        CV_Assert( (image.type() == CV_8UC1) || (image.type() == CV_8UC3) );
        CV_Assert( (image.cols > 0) && (image.rows > 0) );
        CV_Assert( component_level == OCR_LEVEL_WORD );

        out_sequence.clear();
        if (component_rects != NULL)
            component_rects->clear();
        if (component_texts != NULL)
            component_texts->clear();
        if (component_confidences != NULL)
            component_confidences->clear();

        // First we split a line into words
        vector<Mat> words_mask;
        vector<Rect> words_rect;

        /// Find contours
        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;
        Mat tmp;
        image.copyTo(tmp);
        findContours( tmp, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0) );
        if (contours.size() < 6)
        {
            //do not split lines with less than 6 characters
            words_mask.push_back(image);
            words_rect.push_back(Rect(0,0,image.cols,image.rows));
        }
        else
        {

            Mat_<float> vector_w((int)image.cols,1);
            reduce(image, vector_w, 0, REDUCE_SUM, -1);

            vector<int> spaces;
            vector<int> spaces_start;
            vector<int> spaces_end;
            int space_count=0;
            int last_one_idx;

            int s_init = 0, s_end=vector_w.cols;
            for (int s=0; s<vector_w.cols; s++)
            {
                if (vector_w.at<float>(0,s) == 0)
                    s_init = s+1;
                else
                    break;
            }
            for (int s=vector_w.cols-1; s>=0; s--)
            {
                if (vector_w.at<float>(0,s) == 0)
                    s_end = s;
                else
                    break;
            }

            for (int s=s_init; s<s_end; s++)
            {
                if (vector_w.at<float>(0,s) == 0)
                {
                    space_count++;
                } else {
                    if (space_count!=0)
                    {
                        spaces.push_back(space_count);
                        spaces_start.push_back(last_one_idx);
                        spaces_end.push_back(s-1);
                    }
                    space_count = 0;
                    last_one_idx = s;
                }
            }
            Scalar mean_space,std_space;
            meanStdDev(Mat(spaces),mean_space,std_space);
            int num_word_spaces = 0;
            int last_word_space_end = 0;
            for (int s=0; s<(int)spaces.size(); s++)
            {
                if (spaces_end.at(s)-spaces_start.at(s) > mean_space[0]+(mean_space[0]*1.1)) //this 1.1 is a param?
                {
                    if (num_word_spaces == 0)
                    {
                        //cout << " we have a word from  0  to " << spaces_start.at(s) << endl;
                        Mat word_mask;
                        Rect word_rect = Rect(0,0,spaces_start.at(s),image.rows);
                        image(word_rect).copyTo(word_mask);

                        words_mask.push_back(word_mask);
                        words_rect.push_back(word_rect);
                    }
                    else
                    {
                        //cout << " we have a word from " << last_word_space_end << " to " << spaces_start.at(s) << endl;
                        Mat word_mask;
                        Rect word_rect = Rect(last_word_space_end,0,spaces_start.at(s)-last_word_space_end,image.rows);
                        image(word_rect).copyTo(word_mask);

                        words_mask.push_back(word_mask);
                        words_rect.push_back(word_rect);
                    }
                    num_word_spaces++;
                    last_word_space_end = spaces_end.at(s);
                }
            }
            //cout << " we have a word from " << last_word_space_end << " to " << vector_w.cols << endl << endl << endl;
            Mat word_mask;
            Rect word_rect = Rect(last_word_space_end,0,vector_w.cols-last_word_space_end,image.rows);
            image(word_rect).copyTo(word_mask);

            words_mask.push_back(word_mask);
            words_rect.push_back(word_rect);

        }

        for (int w=0; w<(int)words_mask.size(); w++)
        {

            vector< vector<int> > observations;
            vector< vector<double> > confidences;
            vector<int> obs;
            // First find contours and sort by x coordinate of bbox
            words_mask[w].copyTo(tmp);
            if (tmp.empty())
                continue;
            contours.clear();
            hierarchy.clear();
            /// Find contours
            findContours( tmp, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0) );
            vector<Rect> contours_rect;
            for (int i=0; i<(int)contours.size(); i++)
            {
                contours_rect.push_back(boundingRect(contours[i]));
            }

            sort(contours_rect.begin(), contours_rect.end(), sort_rect_horiz);

            // Do character recognition foreach contour
            for (int i=0; i<(int)contours.size(); i++)
            {
                Mat tmp_mask;
                words_mask[w](contours_rect.at(i)).copyTo(tmp_mask);

                vector<int> out_class;
                vector<double> out_conf;
                classifier->eval(tmp_mask,out_class,out_conf);
                if (!out_class.empty())
                    obs.push_back(out_class[0]);
                observations.push_back(out_class);
                confidences.push_back(out_conf);
            }


            //This must be extracted from dictionary, or just assumed to be equal for all characters
            vector<double> start_p(vocabulary.size());
            for (int i=0; i<(int)vocabulary.size(); i++)
                start_p[i] = 1.0/vocabulary.size();


            Mat V = Mat::zeros((int)observations.size(),(int)vocabulary.size(),CV_64FC1);
            vector<string> path(vocabulary.size());

            // Initialize base cases (t == 0)
            for (int i=0; i<(int)vocabulary.size(); i++)
            {
                for (int j=0; j<(int)observations[0].size(); j++)
                {
                    emission_p.at<double>(observations[0][j],obs[0]) = confidences[0][j];
                }
                V.at<double>(0,i) = start_p[i] * emission_p.at<double>(i,obs[0]);
                path[i] = vocabulary.at(i);
            }


            // Run Viterbi for t > 0
            for (int t=1; t<(int)obs.size(); t++)
            {

                //Dude this has to be done each time!!
                emission_p = Mat::eye(62,62,CV_64FC1);
                for (int e=0; e<(int)observations[t].size(); e++)
                {
                    emission_p.at<double>(observations[t][e],obs[t]) = confidences[t][e];
                }

                vector<string> newpath(vocabulary.size());

                for (int i=0; i<(int)vocabulary.size(); i++)
                {
                    double max_prob = 0;
                    int best_idx = 0;
                    for (int j=0; j<(int)vocabulary.size(); j++)
                    {
                        double prob = V.at<double>(t-1,j) * transition_p.at<double>(j,i) * emission_p.at<double>(i,obs[t]);
                        if ( prob > max_prob)
                        {
                            max_prob = prob;
                            best_idx = j;
                        }
                    }

                    V.at<double>(t,i) = max_prob;
                    newpath[i] = path[best_idx] + vocabulary.at(i);
                }

                // Don't need to remember the old paths
                path.swap(newpath);
            }

            double max_prob = 0;
            int best_idx = 0;
            for (int i=0; i<(int)vocabulary.size(); i++)
            {
                double prob = V.at<double>((int)obs.size()-1,i);
                if ( prob > max_prob)
                {
                    max_prob = prob;
                    best_idx = i;
                }
            }

            //cout << path[best_idx] << endl;
            out_sequence = out_sequence+" "+path[best_idx];

            if (component_rects != NULL)
                component_rects->push_back(words_rect[w]);
            if (component_texts != NULL)
                component_texts->push_back(path[best_idx]);
            if (component_confidences != NULL)
                component_confidences->push_back((float)max_prob);

        }

        return;
    }
    double score_segmentation( vector<int> &segmentation, string& outstring )
    {

        // Score Heuristics:
        // No need to use Viterbi to know a given segmentation is bad
        // e.g.: in some cases we discard a segmentation because it includes a very large character
        //       in other cases we do it because the overlapping between two chars is too large
        // TODO  Add more heuristics (e.g. penalize large inter-character variance)

        Mat interdist ((int)segmentation.size()-1, 1, CV_32F, 1);
        for (size_t i=0; i<segmentation.size()-1; i++)
        {
          interdist.at<float>((int)i,0) = (float)oversegmentation[segmentation[(int)i+1]]*step_size
                                          - (float)oversegmentation[segmentation[(int)i]]*step_size;
          if ((float)interdist.at<float>((int)i,0)/win_size > 2.25) // TODO explain how did you set this thrs
          {
             return -DBL_MAX;
          }
          if ((float)interdist.at<float>((int)i,0)/win_size < 0.15) // TODO explain how did you set this thrs
          {
             return -DBL_MAX;
          }
        }
        Scalar m, std;
        meanStdDev(interdist, m, std);
        //double interdist_std = std[0];

        //TODO Extracting start probs from lexicon (if we have it) may boost accuracy!
        vector<double> start_p(vocabulary.size());
        for (int i=0; i<(int)vocabulary.size(); i++)
            start_p[i] = log(1.0/vocabulary.size());


        Mat V = Mat::ones((int)segmentation.size(),(int)vocabulary.size(),CV_64FC1);
        V = V * -DBL_MAX;
        vector<string> path(vocabulary.size());

        // Initialize base cases (t == 0)
        for (int i=0; i<(int)vocabulary.size(); i++)
        {
            V.at<double>(0,i) = start_p[i] + recognition_probabilities[segmentation[0]][i];
            path[i] = vocabulary.at(i);
        }


        // Run Viterbi for t > 0
        for (int t=1; t<(int)segmentation.size(); t++)
        {

            vector<string> newpath(vocabulary.size());

            for (int i=0; i<(int)vocabulary.size(); i++)
            {
                double max_prob = -DBL_MAX;
                int best_idx = 0;
                for (int j=0; j<(int)vocabulary.size(); j++)
                {
                    double prob = V.at<double>(t-1,j) + transition_p.at<double>(j,i) + recognition_probabilities[segmentation[t]][i];
                    if ( prob > max_prob)
                    {
                        max_prob = prob;
                        best_idx = j;
                    }
                }

                V.at<double>(t,i) = max_prob;
                newpath[i] = path[best_idx] + vocabulary.at(i);
            }

            // Don't need to remember the old paths
            path.swap(newpath);
        }

        double max_prob = -DBL_MAX;
        int best_idx = 0;
        for (int i=0; i<(int)vocabulary.size(); i++)
        {
            double prob = V.at<double>((int)segmentation.size()-1,i);
            if ( prob > max_prob)
            {
                max_prob = prob;
                best_idx = i;
            }
        }

        outstring = path[best_idx];
        return (max_prob / (segmentation.size()-1));
    }