nim_duilib/examples/contour/blob/BlobOperators.cpp
2025-03-16 16:42:44 +08:00

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