/** * 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 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; }