/************************************************************************ Blob.cpp - FUNCIONALITAT: Implementaciķ de la classe CBlob - AUTOR: Inspecta S.L. MODIFICACIONS (Modificaciķ, Autor, Data): FUNCTIONALITY: Implementation of the CBlob class and some helper classes to perform some calculations on it AUTHOR: Inspecta S.L. MODIFICATIONS (Modification, Author, Date): **************************************************************************/ #include #include "Blob.h" /** - FUNCIĶ: CBlob - FUNCIONALITAT: Constructor estāndard - PARĀMETRES: - RESULTAT: - inicialitzaciķ de totes les variables internes i de l'storage i la sequencia per a les cantonades del blob - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CBlob - FUNCTIONALITY: Standard constructor - PARAMETERS: - RESULT: - memory allocation for the blob edges and initialization of member variables - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ CBlob::CBlob() { etiqueta = -1; // Flag indicates null region exterior = 0; area = 0.0f; perimeter = 0.0f; parent = -1; minx = LONG_MAX; maxx = 0; miny = LONG_MAX; maxy = 0; sumx = 0; sumy = 0; sumxx = 0; sumyy = 0; sumxy = 0; mean = 0; stddev = 0; externPerimeter = 0; m_storage = cvCreateMemStorage(0); edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour), sizeof(CvPoint),m_storage); } /** - FUNCIĶ: CBlob - FUNCIONALITAT: Constructor de cōpia - PARĀMETRES: - RESULTAT: - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CBlob - FUNCTIONALITY: Copy constructor - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ CBlob::CBlob( const CBlob &src ) { // copiem les propietats del blob origen a l'actual etiqueta = src.etiqueta; exterior = src.exterior; area = src.Area(); perimeter = src.Perimeter(); parent = src.parent; minx = src.minx; maxx = src.maxx; miny = src.miny; maxy = src.maxy; sumx = src.sumx; sumy = src.sumy; sumxx = src.sumxx; sumyy = src.sumyy; sumxy = src.sumxy; mean = src.mean; stddev = src.stddev; externPerimeter = src.externPerimeter; // copiem els edges del blob origen a l'actual CvSeqReader reader; CvSeqWriter writer; CvPoint edgeactual; // creem una sequencia buida per als edges m_storage = cvCreateMemStorage(0); edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour), sizeof(CvPoint),m_storage); cvStartReadSeq( src.Edges(), &reader); cvStartAppendToSeq( edges, &writer ); for( int i=0; i< src.Edges()->total; i++) { CV_READ_SEQ_ELEM( edgeactual ,reader); CV_WRITE_SEQ_ELEM( edgeactual , writer ); } cvEndWriteSeq( &writer ); } CBlob::CBlob( const CBlob *src ) { // copiem les propietats del blob origen a l'actual etiqueta = src->etiqueta; exterior = src->exterior; area = src->Area(); perimeter = src->Perimeter(); parent = src->parent; minx = src->minx; maxx = src->maxx; miny = src->miny; maxy = src->maxy; sumx = src->sumx; sumy = src->sumy; sumxx = src->sumxx; sumyy = src->sumyy; sumxy = src->sumxy; mean = src->mean; stddev = src->stddev; externPerimeter = src->externPerimeter; // copiem els edges del blob origen a l'actual CvSeqReader reader; CvSeqWriter writer; CvPoint edgeactual; // creem una sequencia buida per als edges m_storage = cvCreateMemStorage(0); edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour), sizeof(CvPoint),m_storage); cvStartReadSeq( src->Edges(), &reader); cvStartAppendToSeq( edges, &writer ); for( int i=0; i< src->Edges()->total; i++) { CV_READ_SEQ_ELEM( edgeactual ,reader); CV_WRITE_SEQ_ELEM( edgeactual , writer ); } cvEndWriteSeq( &writer ); } /** - FUNCIĶ: ~CBlob - FUNCIONALITAT: Destructor estāndard - PARĀMETRES: - RESULTAT: - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CBlob - FUNCTIONALITY: Standard destructor - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ CBlob::~CBlob() { // Eliminar včrtexs del blob cvClearSeq(edges); // i la zona de memōria on sķn cvReleaseMemStorage( &m_storage ); } /** - FUNCIĶ: operator= - FUNCIONALITAT: Operador d'assignaciķ - PARĀMETRES: - src: blob a assignar a l'actual - RESULTAT: - Substitueix el blob actual per el src - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: Assigment operator - FUNCTIONALITY: Assigns a blob to the current - PARAMETERS: - src: blob to assign - RESULT: - the current blob is replaced by the src blob - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ CBlob& CBlob::operator=(const CBlob &src ) { // si ja sķn el mateix, no cal fer res if (this != &src) { // Eliminar včrtexs del blob cvClearSeq(edges); // i la zona de memōria on sķn cvReleaseMemStorage( &m_storage ); // creem una sequencia buida per als edges m_storage = cvCreateMemStorage(0); edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2, sizeof(CvContour), sizeof(CvPoint),m_storage); // copiem les propietats del blob origen a l'actual etiqueta = src.etiqueta; exterior = src.exterior; area = src.Area(); perimeter = src.Perimeter(); parent = src.parent; minx = src.minx; maxx = src.maxx; miny = src.miny; maxy = src.maxy; sumx = src.sumx; sumy = src.sumy; sumxx = src.sumxx; sumyy = src.sumyy; sumxy = src.sumxy; mean = src.mean; stddev = src.stddev; externPerimeter = src.externPerimeter; // copiem els edges del blob origen a l'actual CvSeqReader reader; CvSeqWriter writer; CvPoint edgeactual; cvStartReadSeq( src.Edges(), &reader); cvStartAppendToSeq( edges, &writer ); for( int i=0; i< src.Edges()->total; i++) { CV_READ_SEQ_ELEM( edgeactual ,reader); CV_WRITE_SEQ_ELEM( edgeactual , writer ); } cvEndWriteSeq( &writer ); } return *this; } /** - FUNCIĶ: FillBlob - FUNCIONALITAT: Pinta l'interior d'un blob amb el color especificat - PARĀMETRES: - imatge: imatge on es vol pintar el el blob - color: color amb que es vol pintar el blob - RESULTAT: - retorna la imatge d'entrada amb el blob pintat - RESTRICCIONS: - AUTOR: - Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: FillBlob - FUNCTIONALITY: - Fills the blob with a specified colour - PARAMETERS: - imatge: where to paint - color: colour to paint the blob - RESULT: - modifies input image and returns the seed point used to fill the blob - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ void CBlob::FillBlob( IplImage *imatge, CvScalar color, int offsetX /*=0*/, int offsetY /*=0*/) const { //verifiquem que existeixi el blob i que tingui cantonades if( edges == NULL || edges->total == 0 ) return; CvPoint edgeactual, pt1, pt2; CvSeqReader reader; vectorPunts vectorEdges = vectorPunts( edges->total ); vectorPunts::iterator itEdges, itEdgesSeguent; bool dinsBlob; int yActual; // passem els punts del blob a un vector de punts de les STL cvStartReadSeq( edges, &reader); itEdges = vectorEdges.begin(); while( itEdges != vectorEdges.end() ) { CV_READ_SEQ_ELEM( edgeactual ,reader); *itEdges = edgeactual; itEdges++; } // ordenem el vector per les Y's i les X's d'esquerra a dreta std::sort( vectorEdges.begin(), vectorEdges.end(), comparaCvPoint() ); // recorrem el vector ordenat i fem linies entre punts consecutius itEdges = vectorEdges.begin(); itEdgesSeguent = vectorEdges.begin() + 1; dinsBlob = true; while( itEdges != (vectorEdges.end() - 1)) { yActual = (*itEdges).y; if( ( (*itEdges).x != (*itEdgesSeguent).x ) && ( (*itEdgesSeguent).y == yActual ) ) { if( dinsBlob ) { pt1 = *itEdges; pt1.x += offsetX; pt1.y += offsetY; pt2 = *itEdgesSeguent; pt2.x += offsetX; pt2.y += offsetY; cvLine( imatge, pt1, pt2, color ); } dinsBlob =! dinsBlob; } itEdges++; itEdgesSeguent++; if( (*itEdges).y != yActual ) dinsBlob = true; } vectorEdges.clear(); } /** - FUNCIĶ: CopyEdges - FUNCIONALITAT: Afegeix els včrtexs del blob al blob destination - PARĀMETRES: - destination: blob al que volem afegir els včrtexs - RESULTAT: - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CopyEdges - FUNCTIONALITY: Adds the blob edges to destination - PARAMETERS: - destination: where to add the edges - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ void CBlob::CopyEdges( CBlob &destination ) const { CvSeqReader reader; CvSeqWriter writer; CvPoint edgeactual; cvStartReadSeq( edges, &reader); cvStartAppendToSeq( destination.Edges(), &writer ); for( int i=0; itotal; i++) { CV_READ_SEQ_ELEM( edgeactual ,reader); CV_WRITE_SEQ_ELEM( edgeactual , writer ); } cvEndWriteSeq( &writer ); } /** - FUNCIĶ: ClearEdges - FUNCIONALITAT: Elimina els včrtexs del blob - PARĀMETRES: - RESULTAT: - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: ClearEdges - FUNCTIONALITY: Delete current blob edges - PARAMETERS: - RESULT: - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ void CBlob::ClearEdges() { // Eliminar včrtexs del blob eliminat cvClearSeq( edges ); } /** - FUNCIĶ: GetConvexHull - FUNCIONALITAT: Retorna el poligon convex del blob - PARĀMETRES: - dst: sequencia on desarem el resultat (no ha d'estar inicialitzada) - RESULTAT: - true si tot ha anat bé - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: GetConvexHull - FUNCTIONALITY: Calculates the convex hull polygon of the blob - PARAMETERS: - dst: where to store the result - RESULT: - true if no error ocurred - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ bool CBlob::GetConvexHull( CvSeq **dst ) const { if( edges != NULL && edges->total > 0) { *dst = cvConvexHull2( edges, 0, CV_CLOCKWISE, 0 ); return true; } return false; } /** - FUNCIĶ: GetEllipse - FUNCIONALITAT: Retorna l'ellipse que s'ajusta millor a les cantonades del blob - PARĀMETRES: - RESULTAT: - estructura amb l'ellipse - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 25-05-2005. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: GetEllipse - FUNCTIONALITY: Calculates the ellipse that best fits the edges of the blob - PARAMETERS: - RESULT: - CvBox2D struct with the calculated ellipse - RESTRICTIONS: - AUTHOR: Ricard Borrās - CREATION DATE: 25-05-2005. - MODIFICATION: Date. Author. Description. */ CvBox2D CBlob::GetEllipse() const { CvBox2D elipse; // necessitem 6 punts per calcular l'elipse if( edges != NULL && edges->total > 6) { elipse = cvFitEllipse2( edges ); } else { elipse.center.x = 0.0; elipse.center.y = 0.0; elipse.size.width = 0.0; elipse.size.height = 0.0; elipse.angle = 0.0; } return elipse; } /*************************************************************************** Implementaciķ de les classes per al cālcul de característiques sobre el blob Implementation of the helper classes to perform operations on blobs /**************************************************************************/ /** - FUNCIĶ: Moment - FUNCIONALITAT: Calcula el moment pq del blob - RESULTAT: - retorna el moment pq especificat o 0 si el moment no estā implementat - RESTRICCIONS: - Implementats els moments pq: 00, 01, 10, 20, 02 - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 20-07-2004. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - 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, only implemented the 00, 01, 10, 20, 02 pq moments - AUTHOR: Ricard Borrās - CREATION DATE: 20-07-2004. - MODIFICATION: Date. Author. Description. */ double CBlobGetMoment::operator()(const CBlob &blob) const { //Moment 00 if((m_p==0) && (m_q==0)) return blob.Area(); //Moment 10 if((m_p==1) && (m_q==0)) return blob.SumX(); //Moment 01 if((m_p==0) && (m_q==1)) return blob.SumY(); //Moment 20 if((m_p==2) && (m_q==0)) return blob.SumXX(); //Moment 02 if((m_p==0) && (m_q==2)) return blob.SumYY(); return 0; } /** - FUNCIĶ: HullPerimeter - FUNCIONALITAT: Calcula la longitud del perimetre convex del blob. Fa servir la funciķ d'OpenCV cvConvexHull2 per a calcular el perimetre convex. - PARĀMETRES: - RESULTAT: - retorna la longitud del perímetre convex del blob. Si el blob no té coordenades associades retorna el perímetre normal del blob. - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 20-07-2004. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CBlobGetHullPerimeter - 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 CBlobGetHullPerimeter::operator()(const CBlob &blob) const { if(blob.Edges() != NULL && blob.Edges()->total > 0) { CvSeq *hull = cvConvexHull2( blob.Edges(), 0, CV_CLOCKWISE, 1 ); return fabs(cvArcLength(hull,CV_WHOLE_SEQ,1)); } return blob.Perimeter(); } double CBlobGetHullArea::operator()(const CBlob &blob) const { if(blob.Edges() != NULL && blob.Edges()->total > 0) { CvSeq *hull = cvConvexHull2( blob.Edges(), 0, CV_CLOCKWISE, 1 ); return fabs(cvContourArea(hull)); } return blob.Perimeter(); } /** - FUNCIĶ: MinX_at_MinY - FUNCIONALITAT: Calcula el valor MinX a MinY. - PARĀMETRES: - blob: blob del que volem calcular el valor - RESULTAT: - retorna la X minima en la Y minima. - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 20-07-2004. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CBlobGetMinXatMinY - 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 CBlobGetMinXatMinY::operator()(const CBlob &blob) const { double MinX_at_MinY = LONG_MAX; CvSeqReader reader; CvPoint edgeactual; cvStartReadSeq(blob.Edges(),&reader); for(int j=0;jtotal;j++) { CV_READ_SEQ_ELEM(edgeactual,reader); if( (edgeactual.y == blob.MinY()) && (edgeactual.x < MinX_at_MinY) ) { MinX_at_MinY = edgeactual.x; } } return MinX_at_MinY; } /** - FUNCIĶ: MinY_at_MaxX - FUNCIONALITAT: Calcula el valor MinX a MaxX. - PARĀMETRES: - blob: blob del que volem calcular el valor - RESULTAT: - retorna la Y minima en la X maxima. - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 20-07-2004. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CBlobGetMinXatMinY - 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 CBlobGetMinYatMaxX::operator()(const CBlob &blob) const { double MinY_at_MaxX = LONG_MAX; CvSeqReader reader; CvPoint edgeactual; cvStartReadSeq(blob.Edges(),&reader); for(int j=0;jtotal;j++) { CV_READ_SEQ_ELEM(edgeactual,reader); if( (edgeactual.x == blob.MaxX()) && (edgeactual.y < MinY_at_MaxX) ) { MinY_at_MaxX = edgeactual.y; } } return MinY_at_MaxX; } /** - FUNCIĶ: MaxX_at_MaxY - FUNCIONALITAT: Calcula el valor MaxX a MaxY. - PARĀMETRES: - blob: blob del que volem calcular el valor - RESULTAT: - retorna la X maxima en la Y maxima. - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 20-07-2004. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CBlobGetMaxXatMaxY - 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 CBlobGetMaxXatMaxY::operator()(const CBlob &blob) const { double MaxX_at_MaxY = LONG_MIN; CvSeqReader reader; CvPoint edgeactual; cvStartReadSeq(blob.Edges(),&reader); for(int j=0;jtotal;j++) { CV_READ_SEQ_ELEM(edgeactual,reader); if( (edgeactual.y == blob.MaxY()) && (edgeactual.x > MaxX_at_MaxY) ) { MaxX_at_MaxY = edgeactual.x; } } return MaxX_at_MaxY; } /** - FUNCIĶ: MaxY_at_MinX - FUNCIONALITAT: Calcula el valor MaxY a MinX. - PARĀMETRES: - blob: blob del que volem calcular el valor - RESULTAT: - retorna la Y maxima en la X minima. - RESTRICCIONS: - AUTOR: Ricard Borrās - DATA DE CREACIĶ: 20-07-2004. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - FUNCTION: CBlobGetMaxYatMinX - 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 CBlobGetMaxYatMinX::operator()(const CBlob &blob) const { double MaxY_at_MinX = LONG_MIN; CvSeqReader reader; CvPoint edgeactual; cvStartReadSeq(blob.Edges(),&reader); for(int j=0;jtotal;j++) { CV_READ_SEQ_ELEM(edgeactual,reader); if( (edgeactual.x == blob.MinY()) && (edgeactual.y > MaxY_at_MinX) ) { MaxY_at_MinX = edgeactual.y; } } return MaxY_at_MinX; } /** Retorna l'elongaciķ del blob (longitud/amplada) */ /** - FUNCTION: CBlobGetElongation - 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 CBlobGetElongation::operator()(const CBlob &blob) const { double ampladaC,longitudC,amplada,longitud; ampladaC=(double) (blob.Perimeter()+sqrt(pow(blob.Perimeter(),2)-16*blob.Area()))/4; if(ampladaC<=0.0) return 0; longitudC=(double) blob.Area()/ampladaC; longitud=MAX( longitudC , ampladaC ); amplada=MIN( longitudC , ampladaC ); return (double) longitud/amplada; } /** Retorna la compacitat del blob */ /** - FUNCTION: CBlobGetCompactness - 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 CBlobGetCompactness::operator()(const CBlob &blob) const { if( blob.Area() != 0.0 ) return (double) pow(blob.Perimeter(),2)/(4*CV_PI*blob.Area()); else return 0.0; } /** Retorna la rugositat del blob */ /** - FUNCTION: CBlobGetRoughness - 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 CBlobGetRoughness::operator()(const CBlob &blob) const { CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter(); double hullPerimeter = getHullPerimeter(blob); if( hullPerimeter != 0.0 ) return blob.Perimeter() / hullPerimeter;//HullPerimeter(); return 0.0; } /** Retorna la longitud del blob */ /** - FUNCTION: CBlobGetLength - 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 CBlobGetLength::operator()(const CBlob &blob) const { double ampladaC,longitudC; double tmp; tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area(); if( tmp > 0.0 ) ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4; // error intrínsec en els cālculs de l'ārea i el perímetre else ampladaC = (double) (blob.Perimeter())/4; if(ampladaC<=0.0) return 0; longitudC=(double) blob.Area()/ampladaC; return MAX( longitudC , ampladaC ); } /** Retorna l'amplada del blob */ /** - FUNCTION: CBlobGetBreadth - 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 CBlobGetBreadth::operator()(const CBlob &blob) const { double ampladaC,longitudC; double tmp; tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area(); if( tmp > 0.0 ) ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4; // error intrínsec en els cālculs de l'ārea i el perímetre else ampladaC = (double) (blob.Perimeter())/4; if(ampladaC<=0.0) return 0; longitudC = (double) blob.Area()/ampladaC; return MIN( longitudC , ampladaC ); } /** Calcula la distāncia entre un punt i el centre del blob */ /** - FUNCTION: CBlobGetDistanceFromPoint - 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 CBlobGetDistanceFromPoint::operator()(const CBlob &blob) const { double xmitjana, ymitjana; CBlobGetXCenter getXCenter; CBlobGetYCenter getYCenter; xmitjana = m_x - getXCenter( blob ); ymitjana = m_y - getYCenter( blob ); return sqrt((xmitjana*xmitjana)+(ymitjana*ymitjana)); } /** - FUNCIĶ: BlobGetXYInside - FUNCIONALITAT: Calcula si un punt cau dins de la capsa rectangular del blob - RESULTAT: - retorna 1 si hi estā; 0 si no - RESTRICCIONS: - AUTOR: Francesc Pinyol Margalef - DATA DE CREACIĶ: 16-01-2006. - MODIFICACIĶ: Data. Autor. Descripciķ. */ /** - 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 CBlobGetXYInside::operator()(const CBlob &blob) const { if( blob.Edges() == NULL || blob.Edges()->total == 0 ) return 0.0; // passem els punts del blob a un vector de punts de les STL CvSeqReader reader; CBlob::vectorPunts vectorEdges; CBlob::vectorPunts::iterator itEdges, itEdgesSeguent; CvPoint edgeactual; bool dinsBlob; // agafem tots els punts amb la mateixa y que l'actual cvStartReadSeq( blob.Edges(), &reader); for( int i=0; i< blob.Edges()->total; i++) { CV_READ_SEQ_ELEM( edgeactual ,reader ); if( edgeactual.y == m_p.y ) vectorEdges.push_back( edgeactual ); } if( vectorEdges.size() == 0 ) return 0.0; // ordenem el vector per les Y's i les X's d'esquerra a dreta std::sort( vectorEdges.begin(), vectorEdges.end(), CBlob::comparaCvPoint() ); // recorrem el punts del blob de la mateixa fila que el punt d'entrada // i mirem si la X del punt d'entrada estā entre dos coordenades "plenes" // del blob itEdges = vectorEdges.begin(); itEdgesSeguent = vectorEdges.begin() + 1; dinsBlob = true; while( itEdges != (vectorEdges.end() - 1) ) { if( (*itEdges).x <= m_p.x && (*itEdgesSeguent).x >= m_p.x && dinsBlob ) { vectorEdges.clear(); return 1.0; } itEdges++; itEdgesSeguent++; dinsBlob = !dinsBlob; } vectorEdges.clear(); return 0.0; } #ifdef BLOB_OBJECT_FACTORY /** - FUNCIĶ: RegistraTotsOperadors - FUNCIONALITAT: Registrar tots els operadors definits a blob.h - PARĀMETRES: - fabricaOperadorsBlob: fābrica on es registraran els operadors - RESULTAT: - Modifica l'objecte fabricaOperadorsBlob - RESTRICCIONS: - Només es registraran els operadors de blob.h. Si se'n volen afegir, cal afegir-los amb el mčtode Register de la fābrica. - AUTOR: rborras - DATA DE CREACIĶ: 2006/05/18 - MODIFICACIĶ: Data. Autor. Descripciķ. */ void RegistraTotsOperadors( t_OperadorBlobFactory &fabricaOperadorsBlob ) { // blob shape fabricaOperadorsBlob.Register( CBlobGetArea().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetBreadth().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetCompactness().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetElongation().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetExterior().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetLength().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetPerimeter().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetRoughness().GetNom(), Type2Type()); // extern pixels fabricaOperadorsBlob.Register( CBlobGetExternPerimeterRatio().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetExternHullPerimeterRatio().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetExternPerimeter().GetNom(), Type2Type()); // hull fabricaOperadorsBlob.Register( CBlobGetHullPerimeter().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetHullArea().GetNom(), Type2Type()); // elipse info fabricaOperadorsBlob.Register( CBlobGetMajorAxisLength().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetMinorAxisLength().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetAxisRatio().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetOrientation().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetOrientationCos().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetAreaElipseRatio().GetNom(), Type2Type()); // min an max fabricaOperadorsBlob.Register( CBlobGetMaxX().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetMaxY().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetMinX().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetMinY().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetMaxXatMaxY().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetMaxYatMinX().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetMinXatMinY().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetMinYatMaxX().GetNom(), Type2Type()); // grey level stats fabricaOperadorsBlob.Register( CBlobGetMean().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetStdDev().GetNom(), Type2Type()); // coordinate info fabricaOperadorsBlob.Register( CBlobGetXYInside().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetDiffY().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetDiffX().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetXCenter().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetYCenter().GetNom(), Type2Type()); fabricaOperadorsBlob.Register( CBlobGetDistanceFromPoint().GetNom(), Type2Type()); // moments fabricaOperadorsBlob.Register( CBlobGetMoment().GetNom(), Type2Type()); } #endif