457 lines
14 KiB
C++
457 lines
14 KiB
C++
#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
|