732 lines
15 KiB
C++
732 lines
15 KiB
C++
/**************************************************************************
|
|
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<OperatorBlob, const char *, functorComparacioIdOperador > 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
|