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

269 lines
8.1 KiB
C++

/************************************************************************
Blob.h
FUNCTIONALITY: Definition of the Blob class and some helper classes to perform
some calculations on it
AUTHOR: Inspecta S.L.
MODIFICATIONS (Modification, Author, Date):
**************************************************************************/
//! Disable warnings referred to 255 character truncation for the std:map
//#pragma warning(disable : 4786)
#ifndef CBLOB_INSPECTA_INCLUDED
#define CBLOB_INSPECTA_INCLUDED
class Blob;
#include "opencv2/core/core_c.h"
#include "opencv2/opencv.hpp"
#include "BlobLibraryConfiguration.h"
#include "BlobContour.h"
#include <deque>
#include <list>
#ifdef BLOB_OBJECT_FACTORY
//! Object factory pattern implementation
#include "..\inspecta\DesignPatterns\ObjectFactory.h"
#endif
//! Type of labelled images
typedef unsigned int LabelID;
typedef std::list<Blob*> BlobList;
typedef std::list<BlobContour*> BlobContourList;
enum AreaMode {GREEN, PIXELWISE};
//! Blob class
class Blob
{
friend class CompLabeler;
public:
Blob();
Blob(LabelID id, const cv::Point& startPoint, const cv::Size& originalImageSize);
~Blob();
//! Copy constructor
Blob(const Blob& src);
Blob(const Blob* src);
//! Assigment operator
Blob& operator=(const Blob& src);
//! Adds a new internal contour to the blob
void addInternalContour(const BlobContour& newContour);
//! Retrieves contour in Freeman's chain code
BlobContour* getExternalContour() {
return &m_externalContour;
}
BlobContourList& getInternalContours() {
return m_internalContours;
}
//! Bool to permit deletion with filter function
double m_toBeDeleted;
//! Get label ID
LabelID getID() {
return m_id;
}
void setID(LabelID newID) {
m_id = newID;
}
//! > 0 for external blobs, 0 if not
int exterior(IplImage* mask, bool xBorder = true, bool yBorder = true);
//! opencv2 Interface
int exterior(const cv::Mat& mask, bool xBorder = true, bool yBorder = true);
//! Computes the area of the blob.
//! areaCompMode defines which way to compute the areas:
//! - Using green's formula (not exact result, probably faster)
//! - Counting the pixels (probably slower)
double area(AreaMode areaCompMode = GREEN);
//! Compute blob's perimeter
double perimeter();
//! Compute blob's moment (p,q up to MAX_CALCULATED_MOMENTS)
//! if intContours = false, internal contours do not count for moment computation (i.e. the blob is considered without holes).
double moment(int p, int q, bool intContours = true);
//! Compute external perimeter
double externalPerimeter(IplImage* mask, bool xBorder = true, bool yBorder = true);
//! opencv2 interface
double externalPerimeter(const cv::Mat& mask, bool xBorder = true, bool yBorder = true);
//! Get mean grey color
//(Warning: use meanStdDev for simultaneous computation of mean and std. dev, and for RGB images).
double mean(IplImage *image);
//! opencv2 interface
//(Warning: use meanStdDev for simultaneous computation of mean and std. dev, and for RGB images).
double mean(const cv::Mat& image);
//! Get standard deviation grey color
//(Warning: use meanStdDev for simultaneous computation of mean and std. dev, and for RGB images).
double stdDev(IplImage *image);
//! opencv2 interface
//(Warning: use meanStdDev for simultaneous computation of mean and std. dev, and for RGB images).
double stdDev(const cv::Mat& image);
//! Computes mean and standard deviation of image, which can be in any opencv format
//! Since mean and standard deviation are computed with the same function call, this results quicker than
//! calling separately mean and standard deviation.
void meanStdDev(const cv::Mat& image, cv::Scalar& mean, cv::Scalar& stddev);
//void meanStdDev(Mat image, double *mean, double *stddev);
//! Shows if the blob has associated information
bool isEmpty();
//! Calculates the convex hull of the blob
void getConvexHull(Contours& hull);
//! Paints the blob in an image
//! intContours - determines wheter to draw the holes of the blob (true) or not (false)
//! srcImage - image from where to copy the holes contents. If unassigned and intContours is true, the internal pixels will be set to black.
void fillBlob(IplImage *image, cv::Scalar color, int offsetX = 0, int offsetY = 0, bool intContours = false, const IplImage* srcImage = NULL);
void fillBlob(const cv::Mat& image, cv::Scalar color, int offsetX = 0, int offsetY = 0, bool intContours = false, const cv::Mat& srcImage = cv::Mat());
//! Joins a blob to current one
//! NOTE: All the data is copied, a new blob is created and joined to the caller one.
void joinBlob(Blob* blob);
//! Get bounding box
cv::Rect getBoundingBox();
//! Get bounding ellipse
cv::RotatedRect getEllipse();
//! Minimun X
double minX() {
return getBoundingBox().x;
}
//! Minimun Y
double minY() {
return getBoundingBox().y;
}
//! Maximun X
double maxX() {
return getBoundingBox().x + getBoundingBox().width;
}
//! Maximun Y
double maxY() {
return getBoundingBox().y + getBoundingBox().height;
}
/**
Computes extremes for the contour (i.e. 4 points, respectively with max X, max Y, min X, minY)
In case of perfect rectangular shapes, the code will return the vertexes in counterclockwise order.
TODO: Extend function to joined blobs
*/
void getExtremes(cv::Point& xmax, cv::Point& xmin, cv::Point& ymax, cv::Point& ymin);
//! Shifts the blob by (x,y)
void shiftBlob(int x, int y);
//! Returns the number of overlapping pixels between the caller blob and blob.
//! A preliminary check is performed with respect to the bounding boxes in order to avoid unnecessary computations
int overlappingPixels(Blob* blob);
//! Computes the density of the blob, i.e. the ratio (blob Area) / (ConvexHullArea)
//! areaCalculationMode defines which way to compute the areas:
//! - Using green's formula (not exact result, probably faster)
//! - Counting the pixels
double density(AreaMode areaCalculationMode);
//! Returns blob center in pixels (integers).
cv::Point getCenter();
//! Return blob centroid
cv::Point2f getCentroid(bool useInternalContours);
/*
* Border: 0 = top, 1 = right, 2 = bottom, 3 = left
*/
/*Contours getPointsTouchingBorder(int border);*/
//! For joined blobs, return the number of sub-blobs.
int getNumJoinedBlobs();
cv::Size originalImageSize() const { return m_originalImageSize; }
void originalImageSize(int width, int height) { m_originalImageSize.width = width; m_originalImageSize.height = height; }
private:
void requestDeletion(Blob* blob);
//! Deallocates all contours
void clearContours();
private:
//! Just for multithread joining routine;
bool m_startPassed;
bool m_isJoined;
BlobList m_joinedBlobs;
Blob* m_deleteRequestOwnerBlob;
//////////////////////////////////////////////////////////////////////////
// Blob contours
//////////////////////////////////////////////////////////////////////////
//! External contour of the blob (crack codes)
BlobContour m_externalContour;
//! Internal contours (crack codes)
BlobContourList m_internalContours;
//////////////////////////////////////////////////////////////////////////
// Blob features
//////////////////////////////////////////////////////////////////////////
//! Label number
LabelID m_id;
//! Area
double m_area;
//! Perimeter
double m_perimeter;
//! external perimeter from blob
double m_externalPerimeter;
//! mean gray color
double m_meanGray;
//! Standard deviation from gray color blob distribution
double m_stdDevGray;
//! Bounding box
cv::Rect m_boundingBox;
//! Bounding ellipse
cv::RotatedRect m_ellipse;
//! Sizes from image where blob is extracted
cv::Size m_originalImageSize;
friend class BlobGroup;
};
#endif //CBLOB_INSPECTA_INCLUDED