#include <limits.h> #include "BlobOperators.h" /*************************************************************************** Implementation of the helper classes to perform operations on blobs ***************************************************************************/ /** - FUNCTION: moment - FUNCTIONALITY: Calculates the pq moment of the blob - PARAMETERS: - RESULT: - returns the pq moment or 0 if the moment it is not implemented - RESTRICTIONS: - Currently, implemented moments up to 3 - AUTHOR: Ricard Borràs - CREATION DATE: 20-07-2004. - MODIFICATION: Date. Author. Description. */ double BlobGetMoment::operator()(Blob& blob) { return blob.moment(m_p, m_q); } /** - FUNCTION: BlobGetHullPerimeter - FUNCTIONALITY: Calculates the convex hull perimeter of the blob - PARAMETERS: - RESULT: - returns the convex hull perimeter of the blob or the perimeter if the blob edges could not be retrieved - RESTRICTIONS: - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetHullPerimeter::operator()(Blob& blob) { Contours convexHull; blob.getConvexHull(convexHull); double perimeter; if (convexHull.size() != 0) { perimeter = fabs(arcLength(convexHull[0], true)); } else { return 0; } return perimeter; } double BlobGetHullArea::operator()(Blob& blob) { Contours convexHull; blob.getConvexHull(convexHull); double area; if (convexHull.size() == 0) { area = fabs(contourArea(convexHull[0], true)); } else { return 0; } return area; } /** - FUNCTION: BlobGetMinXatMinY - FUNCTIONALITY: Calculates the minimum X on the minimum Y - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetMinXatMinY::operator()(Blob& blob) { double result = static_cast<double>(LONG_MAX); //CvSeqReader reader; //CvPoint actualPoint; PointList externalContour; externalContour = blob.getExternalContour()->getContourPoints(); if (externalContour.size()==0) return result; PointList::iterator it = externalContour.begin(), en = externalContour.end(); for (; it != en; ++it) { cv::Point &actualPoint = *it; if ((actualPoint.y == blob.minY()) && (actualPoint.x < result)) { result = actualPoint.x; } } return result; } /** - FUNCTION: BlobGetMinXatMinY - FUNCTIONALITY: Calculates the minimum Y on the maximum X - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetMinYatMaxX::operator()(Blob& blob) { double result = static_cast<double>(LONG_MAX); //CvSeqReader reader; //CvPoint actualPoint; PointList externalContour; externalContour = blob.getExternalContour()->getContourPoints(); if (externalContour.size() == 0) { return result; } PointList::iterator it = externalContour.begin(), en = externalContour.end(); for (; it != en; ++it) { cv::Point actualPoint = *it; if ((actualPoint.x == blob.maxX()) && (actualPoint.y < result)) { result = actualPoint.y; } } return result; } /** - FUNCTION: BlobGetMaxXatMaxY - FUNCTIONALITY: Calculates the maximum X on the maximum Y - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetMaxXatMaxY::operator()(Blob& blob) { double result = LONG_MIN; //CvSeqReader reader; //CvPoint actualPoint; PointList externalContour; externalContour = blob.getExternalContour()->getContourPoints(); if (externalContour.size() == 0) { return result; } PointList::iterator it = externalContour.begin(), en = externalContour.end(); for (; it != en; ++it) { cv::Point &actualPoint = *it; if ((actualPoint.y == blob.maxY()) && (actualPoint.x > result)) { result = actualPoint.x; } } return result; } /** - FUNCTION: BlobGetMaxYatMinX - FUNCTIONALITY: Calculates the maximum Y on the minimum X - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetMaxYatMinX::operator()(Blob& blob) { double result = LONG_MIN; //CvSeqReader reader; //CvPoint actualPoint; PointList externalContour; externalContour = blob.getExternalContour()->getContourPoints(); if (externalContour.size() == 0) { return result; } PointList::iterator it = externalContour.begin(), en = externalContour.end(); for (; it != en; ++it) { cv::Point &actualPoint = *it; if ((actualPoint.x == blob.minX()) && (actualPoint.y > result)) { result = actualPoint.y; } } return result; } /** - FUNCTION: BlobGetElongation - FUNCTIONALITY: Calculates the elongation of the blob (length/breadth) - PARAMETERS: - RESULT: - RESTRICTIONS: - See below to see how the lenght and the breadth are aproximated - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetElongation::operator()(Blob& blob) { double widthC, lengthC, width, length; double tmp; tmp = blob.perimeter()*blob.perimeter() - 16 * blob.area(); if (tmp > 0.0) { widthC = (double) (blob.perimeter() + sqrt(tmp)) / 4; // error intrínsec en els càlculs de l'àrea i el perímetre } else { widthC = (double) (blob.perimeter()) / 4; } if (widthC <= 0.0) { return 0; } lengthC = (double) blob.area() / widthC; length = MAX(lengthC, widthC); width = MIN(lengthC, widthC); return (double) length/width; } /** - FUNCTION: BlobGetCompactness - FUNCTIONALITY: Calculates the compactness of the blob (maximum for circle shaped blobs, minimum for the rest) - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetCompactness::operator()(Blob& blob) { if (blob.area() != 0.0) { return (double) pow(blob.perimeter(), 2)/(4 * CV_PI * blob.area()); } else { return 0.0; } } /** - FUNCTION: BlobGetRoughness - FUNCTIONALITY: Calculates the roughness of the blob (ratio between perimeter and convex hull perimeter) - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetRoughness::operator()(Blob& blob) { BlobGetHullPerimeter getHullPerimeter = BlobGetHullPerimeter(); double hullPerimeter = getHullPerimeter(blob); if (hullPerimeter != 0.0) { return blob.perimeter() / hullPerimeter;//HullPerimeter(); } return 0.0; } /** - FUNCTION: BlobGetLength - FUNCTIONALITY: Calculates the lenght of the blob (the biggest axis of the blob) - PARAMETERS: - RESULT: - RESTRICTIONS: - The lenght is an aproximation to the real lenght - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetLength::operator()(Blob& blob) { double widthC, lengthC; double tmp; tmp = blob.perimeter() * blob.perimeter() - 16 * blob.area(); if (tmp > 0.0) { widthC = (double) (blob.perimeter() + sqrt(tmp)) / 4; // error intrínsec en els càlculs de l'àrea i el perímetre } else { widthC = (double) (blob.perimeter()) / 4; } if (widthC <= 0.0) { return 0; } lengthC = (double) blob.area() / widthC; return MAX(lengthC , widthC); } /** - FUNCTION: BlobGetBreadth - FUNCTIONALITY: Calculates the breadth of the blob (the smallest axis of the blob) - PARAMETERS: - RESULT: - RESTRICTIONS: - The breadth is an aproximation to the real breadth - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetBreadth::operator()(Blob& blob) { double widthC, lengthC; double tmp; tmp = blob.perimeter() * blob.perimeter() - 16 * blob.area(); if (tmp > 0.0) { widthC = (double) (blob.perimeter() + sqrt(tmp)) / 4; // error intrínsec en els càlculs de l'àrea i el perímetre } else { widthC = (double) (blob.perimeter()) / 4; } if (widthC <= 0.0) { return 0; } lengthC = (double) blob.area() / widthC; return MIN(lengthC , widthC); } /** - FUNCTION: BlobGetDistanceFromPoint - FUNCTIONALITY: Calculates the euclidean distance between the blob center and the point specified in the constructor - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borràs - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ double BlobGetDistanceFromPoint::operator()(Blob& blob) { BlobGetXCenter getXCenter; BlobGetYCenter getYCenter; double deltaX = m_x - getXCenter(blob); double deltaY = m_y - getYCenter(blob); return sqrt((deltaX * deltaX) + (deltaY * deltaY)); } /** - FUNCTION: BlobGetXYInside - FUNCTIONALITY: Calculates whether a point is inside the rectangular bounding box of a blob - PARAMETERS: - RESULT: - returns 1 if it is inside; o if not - RESTRICTIONS: - AUTHOR: Francesc Pinyol Margalef - CREATION DATE: 16-01-2006. - MODIFICATION: Date. Author. Description. */ double BlobGetXYInside::operator()(Blob& blob) { const PointList &contourPoints = blob.getExternalContour()->getContourPoints(); if (contourPoints.size() == 0) { return pointPolygonTest(contourPoints, m_p, false) >= 0; } return 0; } #ifdef BLOB_OBJECT_FACTORY /** - FUNCTION: RegisterAll Operators - FUNCTIONALITY: Register all operators defined in blob.h - PARAMETERS: - fabricaOperadorsBlob: factory where the operators will be registered - RESULT: - Modifies the manufacturesOperatorsBlob object - RESTRICTIONS: - Only blob.h operators will be registered. If you want to add them, you need to add them with the Register method of the factory. - AUTHOR: trees - DATE OF CREATION: 2006/05/18 - MODIFICATION: Date. Author. Description. */ void RegistraTotsOperadors(t_OperadorBlobFactory &fabricaOperadorsBlob) { // blob shape fabricaOperadorsBlob.Register(BlobGetArea().name(), Type2Type<BlobGetArea>()); fabricaOperadorsBlob.Register(BlobGetBreadth().name(), Type2Type<BlobGetBreadth>()); fabricaOperadorsBlob.Register(BlobGetCompactness().name(), Type2Type<BlobGetCompactness>()); fabricaOperadorsBlob.Register(BlobGetElongation().name(), Type2Type<BlobGetElongation>()); fabricaOperadorsBlob.Register(BlobGetExterior().name(), Type2Type<BlobGetExterior>()); fabricaOperadorsBlob.Register(BlobGetLength().name(), Type2Type<BlobGetLength>()); fabricaOperadorsBlob.Register(BlobGetPerimeter().name(), Type2Type<BlobGetPerimeter>()); fabricaOperadorsBlob.Register(BlobGetRoughness().name(), Type2Type<BlobGetRoughness>()); // blob color fabricaOperadorsBlob.Register(BlobGetMean(NULL).name(), Type2Type<BlobGetMean>()); fabricaOperadorsBlob.Register(BlobGetStdDev(NULL).name(), Type2Type<BlobGetStdDev>()); // external pixels fabricaOperadorsBlob.Register(BlobGetExternalPerimeterRatio().name(), Type2Type<BlobGetExternalPerimeterRatio>()); fabricaOperadorsBlob.Register(BlobGetExternalHullPerimeterRatio().name(), Type2Type<BlobGetExternalHullPerimeterRatio>()); fabricaOperadorsBlob.Register(BlobGetExternalPerimeter().name(), Type2Type<BlobGetExternalPerimeter>()); // hull fabricaOperadorsBlob.Register(BlobGetHullPerimeter().name(), Type2Type<BlobGetHullPerimeter>()); fabricaOperadorsBlob.Register(BlobGetHullArea().name(), Type2Type<BlobGetHullArea>()); // elipse info fabricaOperadorsBlob.Register(BlobGetMajorAxisLength().name(), Type2Type<BlobGetMajorAxisLength>()); fabricaOperadorsBlob.Register(BlobGetMinorAxisLength().name(), Type2Type<BlobGetMinorAxisLength>()); fabricaOperadorsBlob.Register(BlobGetAxisRatio().name(), Type2Type<BlobGetAxisRatio>()); fabricaOperadorsBlob.Register(BlobGetOrientation().name(), Type2Type<BlobGetOrientation>()); fabricaOperadorsBlob.Register(BlobGetOrientationCos().name(), Type2Type<BlobGetOrientationCos>()); fabricaOperadorsBlob.Register(BlobGetAreaElipseRatio().name(), Type2Type<BlobGetAreaElipseRatio>()); // min an max fabricaOperadorsBlob.Register(BlobGetMaxX().name(), Type2Type<BlobGetMaxX>()); fabricaOperadorsBlob.Register(BlobGetMaxY().name(), Type2Type<BlobGetMaxY>()); fabricaOperadorsBlob.Register(BlobGetMinX().name(), Type2Type<BlobGetMinX>()); fabricaOperadorsBlob.Register(BlobGetMinY().name(), Type2Type<BlobGetMinY>()); fabricaOperadorsBlob.Register(BlobGetMaxXatMaxY().name(), Type2Type<BlobGetMaxXatMaxY>()); fabricaOperadorsBlob.Register(BlobGetMaxYatMinX().name(), Type2Type<BlobGetMaxYatMinX>()); fabricaOperadorsBlob.Register(BlobGetMinXatMinY().name(), Type2Type<BlobGetMinXatMinY>()); fabricaOperadorsBlob.Register(BlobGetMinYatMaxX().name(), Type2Type<BlobGetMinYatMaxX>()); // coordinate info fabricaOperadorsBlob.Register(BlobGetXYInside().name(), Type2Type<BlobGetXYInside>()); fabricaOperadorsBlob.Register(BlobGetDiffY().name(), Type2Type<BlobGetDiffY>()); fabricaOperadorsBlob.Register(CBlobGetDiffX().name(), Type2Type<CBlobGetDiffX>()); fabricaOperadorsBlob.Register(BlobGetXCenter().name(), Type2Type<BlobGetXCenter>()); fabricaOperadorsBlob.Register(BlobGetYCenter().name(), Type2Type<BlobGetYCenter>()); fabricaOperadorsBlob.Register(BlobGetDistanceFromPoint().name(), Type2Type<BlobGetDistanceFromPoint>()); // moments fabricaOperadorsBlob.Register(BlobGetMoment().name(), Type2Type<BlobGetMoment>()); } #endif //BLOB_OBJECT_FACTORY