/************************************************************************** Definition of classes to perform operations on blobs Helper classes to perform operations on blobs **************************************************************************/ #ifndef BLOB_OPERATORS_H_INCLUDED #define BLOB_OPERATORS_H_INCLUDED #include "blob.h" //! Degree to radian conversion factor #define DEGREE2RAD (CV_PI / 180.0) //! Interface to derive all blob operations class OperatorBlob { public: virtual ~OperatorBlob() {}; //! Apply operator to blob virtual double operator()(Blob& blob) = 0; //! Get operator name virtual const char *name() = 0; operator OperatorBlob*() { return (OperatorBlob*)this; } }; typedef OperatorBlob BlobOperator; #ifdef BLOB_OBJECT_FACTORY /** Function to compare two identifiers within the COperadorBlobs factory */ struct functorComparacioIdOperador { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } }; //! Definition of Object factory type for OperatorBlob objects typedef ObjectFactory t_OperadorBlobFactory; //! Global function to register all operators defined in blob.h void RegistraTotsOperadors(t_OperadorBlobFactory &fabricaOperadorsBlob); #endif //! Class to get ID of a blob class BlobGetID : public OperatorBlob { public: double operator()(Blob& blob) { return blob.getID(); } const char *name() { return "BlobGetID"; } }; //! Class to get bool m_toBeDeleted class BlobGetTBDeleted : public OperatorBlob { public: double operator()(Blob& blob) { return blob.m_toBeDeleted; } const char *name() { return "BlobGetTBDeleted"; } }; //! Class to get the area of a blob class BlobGetArea : public OperatorBlob { public: double operator()(Blob& blob) { return blob.area(); } const char *name() { return "BlobGetArea"; } }; //! Class to get the perimeter of a blob class BlobGetPerimeter : public OperatorBlob { public: double operator()(Blob& blob) { return blob.perimeter(); } const char *name() { return "BlobGetPerimeter"; } }; //! Class to get the external flag of a blob class BlobGetExterior : public OperatorBlob { public: BlobGetExterior() { m_mask = NULL; m_xBorder = true; m_yBorder = true; } BlobGetExterior(IplImage* mask, bool xBorder = true, bool yBorder = true) { m_mask = mask; m_xBorder = xBorder; m_yBorder = yBorder; } double operator()(Blob& blob) { return blob.exterior(m_mask, m_xBorder, m_yBorder); } const char *name() { return "BlobGetExterior"; } private: IplImage* m_mask; bool m_xBorder, m_yBorder; }; //! Class to get the mean grey level of a blob class BlobGetMean : public OperatorBlob { public: BlobGetMean() { m_image = NULL; } BlobGetMean(IplImage* image) { m_image = image; }; double operator()(Blob& blob) { return blob.mean(m_image); } const char *name() { return "BlobGetMean"; } private: IplImage* m_image; }; //! Class to get the standard deviation of the grey level values of a blob class BlobGetStdDev : public OperatorBlob { public: BlobGetStdDev() { m_image = NULL; } BlobGetStdDev(IplImage* image) { m_image = image; }; double operator()(Blob& blob) { return blob.stdDev(m_image); } const char *name() { return "BlobGetStdDev"; } private: IplImage* m_image; }; //! Class to calculate the compactness of a blob class BlobGetCompactness : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetCompactness"; } }; //! Class to calculate the length of a blob class BlobGetLength : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetLength"; } }; //! Class to calculate the breadth of a blob class BlobGetBreadth : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetBreadth"; } }; //! Class to calculate the difference in X of the blob class CBlobGetDiffX : public OperatorBlob { public: double operator()(Blob& blob) { return blob.getBoundingBox().width; } const char *name() { return "CBlobGetDiffX"; } }; //! Class to calculate the difference in X of the blob class BlobGetDiffY : public OperatorBlob { public: double operator()(Blob& blob) { return blob.getBoundingBox().height; } const char *name() { return "BlobGetDiffY"; } }; //! Class to calculate the P, Q moment of a blob class BlobGetMoment : public OperatorBlob { public: //! Standard constructor (gets the 00 moment) BlobGetMoment() { m_p = m_q = 0; } //! Constructor: gets the P, Q moment BlobGetMoment(int p, int q) { m_p = p; m_q = q; }; double operator()(Blob& blob); const char *name() { return "BlobGetMoment"; } private: //! moment que volem calcular int m_p, m_q; }; //! Class to calculate the convex hull perimeter of a blob class BlobGetHullPerimeter : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetHullPerimeter"; } }; //! Class to calculate the convex hull area of a blob class BlobGetHullArea : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetHullArea"; } }; //! Class to calculate the minimum x on the minimum y class BlobGetMinXatMinY : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetMinXatMinY"; } }; //! Class to calculate the minimum y on the maximum x class BlobGetMinYatMaxX : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetMinYatMaxX"; } }; //! Class to calculate the maximum x on the maximum y class BlobGetMaxXatMaxY : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetMaxXatMaxY"; } }; //! Class to calculate the maximum y on the minimum y class BlobGetMaxYatMinX : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetMaxYatMinX"; } }; //! Class to get the minimum x class BlobGetMinX : public OperatorBlob { public: double operator()(Blob& blob) { return blob.minX(); } const char *name() { return "BlobGetMinX"; } }; //! Class to get the maximum x class BlobGetMaxX : public OperatorBlob { public: double operator()(Blob& blob) { return blob.maxX(); } const char *name() { return "BlobGetMaxX"; } }; //! Class to get the minimum y class BlobGetMinY : public OperatorBlob { public: double operator()(Blob& blob) { return blob.minY(); } const char *name() { return "BlobGetMinY"; } }; //! Class to get the maximum y class BlobGetMaxY : public OperatorBlob { public: double operator()(Blob& blob) { return blob.maxY(); } const char *name() { return "BlobGetMaxY"; } }; //! Class to calculate the elongation of the blob class BlobGetElongation : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetElongation"; } }; //! Class to calculate the roughness of the blob class BlobGetRoughness : public OperatorBlob { public: double operator()(Blob& blob); const char *name() { return "BlobGetRoughness"; } }; //! Class to calculate the euclidean distance between the center of a blob and a given point class BlobGetDistanceFromPoint : public OperatorBlob { public: //! Standard constructor (distance to point 0,0) BlobGetDistanceFromPoint() { m_x = m_y = 0.0; } //! Constructor (distance to point x,y) BlobGetDistanceFromPoint(const double x, const double y) { m_x = x; m_y = y; } double operator()(Blob& blob); const char *name() { return "BlobGetDistanceFromPoint"; } private: // coordinates of the point where we want to calculate the distance double m_x, m_y; }; //! Class to get the number of external pixels of a blob class BlobGetExternalPerimeter : public OperatorBlob { public: BlobGetExternalPerimeter() { m_mask = NULL; m_xBorder = true; m_yBorder = true; } BlobGetExternalPerimeter(IplImage* mask, bool xBorder = true, bool yBorder = true) { m_mask = mask; m_xBorder = xBorder; m_yBorder = yBorder; } double operator()(Blob& blob) { return blob.externalPerimeter(m_mask, m_xBorder, m_yBorder); } const char *name() { return "BlobGetExternalPerimeter"; } private: IplImage* m_mask; bool m_xBorder, m_yBorder; }; //! Class to calculate the ratio between the perimeter and number of external pixels //! values close to 0 indicate that most of the blob is internal //! values close to 1 indicate that most of the blob is external //! Class to calculate the ratio between the perimeter and the number of external pixels class BlobGetExternalPerimeterRatio : public OperatorBlob { public: BlobGetExternalPerimeterRatio() { m_mask = NULL; m_xBorder = false; m_yBorder = false; } BlobGetExternalPerimeterRatio(IplImage* mask, bool xBorder = true, bool yBorder = true) { m_mask = mask; m_xBorder = xBorder; m_yBorder = yBorder; } double operator()(Blob& blob) { if (blob.perimeter() != 0) { return blob.externalPerimeter(m_mask, m_xBorder, m_yBorder) / blob.perimeter(); } else { return blob.externalPerimeter(m_mask, m_xBorder, m_yBorder); } } const char *name() { return "BlobGetExternalPerimeterRatio"; } private: IplImage* m_mask; bool m_xBorder, m_yBorder; }; //! Class to calculate the ratio between the convex perimeter and the number of external pixels //! values close to 0 indicate that most of the blob is internal blob //! values close to 1 indicate that most of the blob is external //! Class to calculate the ratio between the perimeter and the number of external pixels class BlobGetExternalHullPerimeterRatio : public OperatorBlob { public: BlobGetExternalHullPerimeterRatio() { m_mask = NULL; m_xBorder = false; m_yBorder = false; } BlobGetExternalHullPerimeterRatio(IplImage* mask, bool xBorder = true, bool yBorder = true) { m_mask = mask; m_xBorder = xBorder; m_yBorder = yBorder; } double operator()(Blob& blob) { BlobGetHullPerimeter getHullPerimeter; double hullPerimeter; if ((hullPerimeter = getHullPerimeter(blob)) != 0) { return blob.externalPerimeter(m_mask, m_xBorder, m_yBorder) / hullPerimeter; } else { return blob.externalPerimeter(m_mask, m_xBorder, m_yBorder); } } const char *name() { return "BlobGetExternalHullPerimeterRatio"; } private: IplImage* m_mask; bool m_xBorder, m_yBorder; }; //! Class to calculate the center in the X direction class BlobGetXCenter : public OperatorBlob { public: double operator()(Blob& blob) { return blob.minX() + ((blob.maxX() - blob.minX()) / 2.0); } const char *name() { return "BlobGetXCenter"; } }; //! Class to calculate the center in the Y direction class BlobGetYCenter : public OperatorBlob { public: double operator()(Blob& blob) { return blob.minY() + ((blob.maxY() - blob.minY()) / 2.0); } const char *name() { return "BlobGetYCenter"; } }; //! Class to calculate the length of the major axis of the ellipse that fits the blob edges class BlobGetMajorAxisLength : public OperatorBlob { public: double operator()(Blob& blob) { cv::RotatedRect elipse = blob.getEllipse(); return elipse.size.width; } const char *name() { return "BlobGetMajorAxisLength"; } }; //! Class to calculate the ratio between the area of the ellipse and that of the spot class BlobGetAreaElipseRatio : public OperatorBlob { public: double operator()(Blob& blob) { if (blob.area() == 0.0) { return 0.0; } cv::RotatedRect elipse = blob.getEllipse(); double ratioAreaElipseAreaTaca = ((elipse.size.width/2.0) * (elipse.size.height/2.0) * CV_PI) / blob.area(); return ratioAreaElipseAreaTaca; } const char *name() { return "BlobGetAreaElipseRatio"; } }; //! Class to calculate the length of the minor axis of the ellipse that fits the blob edges class BlobGetMinorAxisLength : public OperatorBlob { public: double operator()(Blob& blob) { cv::RotatedRect elipse = blob.getEllipse(); return elipse.size.height; } const char *name() { return "BlobGetMinorAxisLength"; } }; //! Class to calculate the orientation of the ellipse that fits the blob edges in radians class BlobGetOrientation : public OperatorBlob { public: double operator()(Blob& blob) { cv::RotatedRect elipse = blob.getEllipse(); /* if (elipse.angle > 180.0) return ((elipse.angle - 180.0)* DEGREE2RAD); else return (elipse.angle * DEGREE2RAD); */ return elipse.angle; } const char *name() { return "BlobGetOrientation"; } }; //! Class to calculate the cosinus of the orientation of the ellipse that fits the blob edges class BlobGetOrientationCos : public OperatorBlob { public: double operator()(Blob& blob) { BlobGetOrientation getOrientation; return fabs(cos(getOrientation(blob)*DEGREE2RAD)); } const char *name() { return "BlobGetOrientationCos"; } }; //! Class to calculate the ratio between both axes of the ellipse class BlobGetAxisRatio : public OperatorBlob { public: double operator()(Blob& blob) { double major,minor; BlobGetMajorAxisLength getMajor; BlobGetMinorAxisLength getMinor; major = getMajor(blob); minor = getMinor(blob); if (major != 0) { return minor / major; } else { return 0; } } const char *name() { return "BlobGetAxisRatio"; } }; //! Class to calculate whether a point is inside a blob class BlobGetXYInside : public OperatorBlob { public: //! Standard constructor BlobGetXYInside() { m_p.x = 0; m_p.y = 0; } //! Constructor: sets the point BlobGetXYInside(cv::Point2f p) { m_p = p; }; double operator()(Blob& blob); const char *name() { return "BlobGetXYInside"; } private: //! point to be considered cv::Point2f m_p; }; #endif //!BLOB_OPERATORS_H_INCLUDED