/**
* Compute the granulometric function on a given image using the naive algorithm (see the report)
*
* @param image The input image 
*
* @param granuloImage The image where we store the granulometric function values
*/
unsigned int buildNaiveGranulo(myLittleImage& image, myLittleImage& granuloImage)
{
	PointPredicate predicate(image,0);
	DTL2 dtL2(image.domain(), predicate, l2Metric);
	unsigned int nbPoints = 0;
	for (myLittleImage::Domain::ConstIterator it = granuloImage.domain().begin(); it != granuloImage.domain().end(); ++it)
		if (dtL2(*it) > 0) // inside the image
		{
			nbPoints++;
			// Build a sphere inside the object of radius dtL2(*it)
			unsigned int radius = static_cast<unsigned int>(dtL2(*it));
			RealPoint center = *it;
			ImplicitBall<Space> ball(center,radius);
			// To iterate on the sphere, we build a tangent bounding box around it and iterate into the box
			Point top = center + Point::diagonal(radius +1);
			Point bottom = center - Point::diagonal(radius +1);
			Domain sphereDomain(bottom,top);
			for (Domain::ConstIterator ite = sphereDomain.begin(); ite != sphereDomain.end(); ++ite)
			{
				if ((granuloImage.domain().isInside(*ite)) // Point inside the image
					&& (ball(*ite) > 0)					   // Point inside the ball
					&& (granuloImage(*ite) < radius)) 	   // Granulometric value has to be updated
				{
					granuloImage.setValue(*ite,radius);
				}
			}
		}
	trace.info() << "Granulometric function computed with " << nbPoints << " balls" << endl;
	return nbPoints;
}
/**
* Compute the histogram of a granulometric image and save it in a file
*
* @param granuloImage The image containing the granulometric values
*
* @param maxGranulo The maximum of the granulometric values
*
* @param pas The number of bins of the histogram
*
* @param nbPoints The number of points inside the object contained in granuloImage
*
* @param fileName The filename where we store the histogram
*/
void buildHistogram(myLittleImage& granuloImage, unsigned int maxGranulo, unsigned int pas, unsigned int nbPoints, string fileName)
{
	vector<double> histo(pas+1,0.0);
	double cast_max = static_cast<double>(maxGranulo);
	double cast_pas = static_cast<double>(pas);
	double cast_nbPoints = static_cast<double>(nbPoints);
	for (myLittleImage::Domain::ConstIterator it = granuloImage.domain().begin(); it != granuloImage.domain().end(); ++it)
	{
		if (granuloImage.domain().isInside(*it)) // inside the image
		{
			unsigned int normalizedValue = static_cast<unsigned int>(static_cast<double>(granuloImage(*it)) / cast_max * cast_pas);
			histo[normalizedValue]++;
		}
	}
	ofstream file(fileName.c_str());
    if (file.is_open())
	{
		// for (unsigned int i = 0; i <= pas; ++i)
		// it seems that the points that doesn't belong to the object are considering in
		// DT are in fact in the histogram... Just not consider them before close the problem
		// Another advantage of this is that we use a kind a filter of "bad" balls which can
		// appear in the border
		for (unsigned int i= 1; i <= pas; ++i)
			file << i << " " << histo[i] / cast_nbPoints << endl;
	}
}
/**
* Test the speed of any algorithm which computes the granulometric function (used in testEfficiency.cpp)
*
* @param granulo The granulometric algorithm used
*
* @param image The input image of the algorithm
*/
void testSpeed(function<unsigned int(myLittleImage&, myLittleImage&)> &granulo, myLittleImage& image)
{
	trace.beginBlock ("Test");

	myLittleImage granuloImage (image.domain());
	unsigned int nbBalls = granulo(image,granuloImage);
	trace.endBlock();
	return;
}
示例#4
0
void testSpeed(function<unsigned int(myLittleImage&, myLittleImage&)> &granulo, myLittleImage& image, const char* inputFile)
{
	trace.beginBlock ("Test");

	myLittleImage granuloImage (image.domain());
	unsigned int nbBalls = granulo(image,granuloImage);
	trace.info() << "Granulometric function computed with " << nbBalls << " balls" << endl;
	trace.endBlock();
	return;
}
/**
* Compute the histogram of a granulometric image, as previously, but return it
*
* @param granuloImage The image containing the granulometric values
*
* @param maxGranulo The maximum of the granulometric values
*
* @param pas The number of bins of the histogram
*
* @param nbPoints The number of points inside the object contained in granuloImage
*
* @return The histogram as a vector of doubles
*/
vector<double> buildHistogram(myLittleImage& granuloImage, unsigned int maxGranulo, unsigned int pas, unsigned int compteur)
{
	vector<double> histo(pas+1,0.0);
	double cast_max = static_cast<double>(maxGranulo);
	double cast_pas = static_cast<double>(pas);
	double cast_compteur = static_cast<double>(compteur);
	for (myLittleImage::Domain::ConstIterator it = granuloImage.domain().begin(); it != granuloImage.domain().end(); ++it)
	{
		if (granuloImage.domain().isInside(*it)) // inside the image
		{
			unsigned int normalizedValue = static_cast<unsigned int>(static_cast<double>(granuloImage(*it)) / cast_max * cast_pas);
			histo[normalizedValue]++;
		}
	}

	for(size_t i=0; i<histo.size(); ++i)
        histo[i] /= cast_compteur;

    histo.erase(histo.begin());

	return histo;
}
/**
* Compute the granulometric function with a smarter algorithm that uses the medial axis (see report for more details)
*
* @param image The input image 
*
* @param granuloImage The image where we store the granulometric function values
*/
unsigned int granuloWithMedialAxis(myLittleImage& image, myLittleImage& granuloImage)
{
	PointPredicate predicate(image,0);
	Z2i::L2PowerMetric l2power;
	unsigned int nbBalls = 0;
	unsigned int nbPoints = 0;
	DTL2 dtL2(image.domain(), predicate, l2Metric);
    Map power(image.domain(), dtL2, l2power);
	RMA::Type rma = RMA::getReducedMedialAxisFromPowerMap(power);
	for (myLittleImage::Domain::ConstIterator it = granuloImage.domain().begin(); it != granuloImage.domain().end(); ++it)
	{
		if (dtL2(*it) > 0) // Inside the image
			nbPoints++;

		if (rma(*it) > 0) // Center of a ball
		{
			nbBalls++;
			unsigned int radius = static_cast<unsigned int>(dtL2(*it));
			RealPoint center = *it;
			ImplicitBall<Space> ball(center,radius);
			// To iterate on the sphere, we build a tangent bounding box around it and iterate into the box
			Point top = center + Point::diagonal(radius +1);
			Point bottom = center - Point::diagonal(radius +1);
			Domain sphereDomain(bottom,top);
			for (Domain::ConstIterator ite = sphereDomain.begin(); ite != sphereDomain.end(); ++ite)
			{
				if ((granuloImage.domain().isInside(*ite)) // Point inside the image
					&& (ball(*ite) > 0)					  // Point inside the ball
					&& (granuloImage(*ite) < radius)) 	  // Granulometric value has to be updated
				{
					granuloImage.setValue(*ite,radius);
				}
			}
		}
	}
	trace.info() << "Granulometric function computed with " << nbBalls << " balls" << endl;
	return nbPoints;
}
/**
* Save the granometric function values stored in an image into an EPS file
*
* @param granuloImage The image containing the granulometric function values
*
* @param maxGranulo The maximum value of the granulometric function
*
* @param fileName A string containing the filename where we store the image
*/
void saveGranulo(myLittleImage& granuloImage, unsigned int maxGranulo, string fileName)
{
	Board2D board;
	HueTwice colorMap(1,maxGranulo+1);
	Point O(0,0);
	string specificStyle =  O.className() + "/Paving";
	Color white(255,255,255);
    board << SetMode(granuloImage.domain().className(), "Paving")
      	  << granuloImage.domain()
          << SetMode(O.className(), "Paving");

   	for (myLittleImage::Domain::ConstIterator it = granuloImage.domain().begin(); it != granuloImage.domain().end(); ++it)
    {
    	if (granuloImage(*it) > 0)
		{
			Color c = colorMap(granuloImage(*it));
       		board << CustomStyle(specificStyle, new CustomColors(c,c)) << *it;
		}
		else
			board << CustomStyle(specificStyle, new  CustomColors(white,white)) << *it;
    }
    board.saveEPS(fileName.c_str());
}