00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <limits.h>
00019 #include <Blob.h>
00020 #include <cv.h>
00021
00045 CBlob::CBlob()
00046 {
00047 etiqueta = -1;
00048 exterior = 0;
00049 area = 0.0f;
00050 perimeter = 0.0f;
00051 parent = -1;
00052 minx = LONG_MAX;
00053 maxx = 0;
00054 miny = LONG_MAX;
00055 maxy = 0;
00056 sumx = 0;
00057 sumy = 0;
00058 sumxx = 0;
00059 sumyy = 0;
00060 sumxy = 0;
00061 mean = 0;
00062 stddev = 0;
00063 externPerimeter = 0;
00064
00065 m_storage = cvCreateMemStorage(0);
00066 edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2,
00067 sizeof(CvContour),
00068 sizeof(CvPoint),m_storage);
00069 }
00070
00091 CBlob::CBlob( const CBlob &src )
00092 {
00093
00094 etiqueta = src.etiqueta;
00095 exterior = src.exterior;
00096 area = src.Area();
00097 perimeter = src.Perimeter();
00098 parent = src.parent;
00099 minx = src.minx;
00100 maxx = src.maxx;
00101 miny = src.miny;
00102 maxy = src.maxy;
00103 sumx = src.sumx;
00104 sumy = src.sumy;
00105 sumxx = src.sumxx;
00106 sumyy = src.sumyy;
00107 sumxy = src.sumxy;
00108 mean = src.mean;
00109 stddev = src.stddev;
00110 externPerimeter = src.externPerimeter;
00111
00112
00113 CvSeqReader reader;
00114 CvSeqWriter writer;
00115 CvPoint edgeactual;
00116
00117
00118 m_storage = cvCreateMemStorage(0);
00119 edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2,
00120 sizeof(CvContour),
00121 sizeof(CvPoint),m_storage);
00122
00123 cvStartReadSeq( src.Edges(), &reader);
00124 cvStartAppendToSeq( edges, &writer );
00125
00126 for( int i=0; i< src.Edges()->total; i++)
00127 {
00128 CV_READ_SEQ_ELEM( edgeactual ,reader);
00129 CV_WRITE_SEQ_ELEM( edgeactual , writer );
00130 }
00131
00132 cvEndWriteSeq( &writer );
00133 }
00134 CBlob::CBlob( const CBlob *src )
00135 {
00136
00137 etiqueta = src->etiqueta;
00138 exterior = src->exterior;
00139 area = src->Area();
00140 perimeter = src->Perimeter();
00141 parent = src->parent;
00142 minx = src->minx;
00143 maxx = src->maxx;
00144 miny = src->miny;
00145 maxy = src->maxy;
00146 sumx = src->sumx;
00147 sumy = src->sumy;
00148 sumxx = src->sumxx;
00149 sumyy = src->sumyy;
00150 sumxy = src->sumxy;
00151 mean = src->mean;
00152 stddev = src->stddev;
00153 externPerimeter = src->externPerimeter;
00154
00155
00156 CvSeqReader reader;
00157 CvSeqWriter writer;
00158 CvPoint edgeactual;
00159
00160
00161 m_storage = cvCreateMemStorage(0);
00162 edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2,
00163 sizeof(CvContour),
00164 sizeof(CvPoint),m_storage);
00165
00166 cvStartReadSeq( src->Edges(), &reader);
00167 cvStartAppendToSeq( edges, &writer );
00168
00169 for( int i=0; i< src->Edges()->total; i++)
00170 {
00171 CV_READ_SEQ_ELEM( edgeactual ,reader);
00172 CV_WRITE_SEQ_ELEM( edgeactual , writer );
00173 }
00174
00175 cvEndWriteSeq( &writer );
00176 }
00177
00198 CBlob::~CBlob()
00199 {
00200
00201 cvClearSeq(edges);
00202
00203 cvReleaseMemStorage( &m_storage );
00204 }
00205
00230 CBlob& CBlob::operator=(const CBlob &src )
00231 {
00232
00233 if (this != &src)
00234 {
00235
00236 cvClearSeq(edges);
00237
00238 cvReleaseMemStorage( &m_storage );
00239
00240
00241 m_storage = cvCreateMemStorage(0);
00242 edges = cvCreateSeq( CV_SEQ_KIND_GENERIC|CV_32SC2,
00243 sizeof(CvContour),
00244 sizeof(CvPoint),m_storage);
00245
00246
00247 etiqueta = src.etiqueta;
00248 exterior = src.exterior;
00249 area = src.Area();
00250 perimeter = src.Perimeter();
00251 parent = src.parent;
00252 minx = src.minx;
00253 maxx = src.maxx;
00254 miny = src.miny;
00255 maxy = src.maxy;
00256 sumx = src.sumx;
00257 sumy = src.sumy;
00258 sumxx = src.sumxx;
00259 sumyy = src.sumyy;
00260 sumxy = src.sumxy;
00261 mean = src.mean;
00262 stddev = src.stddev;
00263 externPerimeter = src.externPerimeter;
00264
00265
00266 CvSeqReader reader;
00267 CvSeqWriter writer;
00268 CvPoint edgeactual;
00269
00270 cvStartReadSeq( src.Edges(), &reader);
00271 cvStartAppendToSeq( edges, &writer );
00272
00273 for( int i=0; i< src.Edges()->total; i++)
00274 {
00275 CV_READ_SEQ_ELEM( edgeactual ,reader);
00276 CV_WRITE_SEQ_ELEM( edgeactual , writer );
00277 }
00278
00279 cvEndWriteSeq( &writer );
00280 }
00281 return *this;
00282 }
00283
00312 void CBlob::FillBlob( IplImage *imatge, CvScalar color, int offsetX , int offsetY ) const
00313 {
00314
00315
00316 if( edges == NULL || edges->total == 0 ) return;
00317
00318 CvPoint edgeactual, pt1, pt2;
00319 CvSeqReader reader;
00320 vectorPunts vectorEdges = vectorPunts( edges->total );
00321 vectorPunts::iterator itEdges, itEdgesSeguent;
00322 bool dinsBlob;
00323 int yActual;
00324
00325
00326 cvStartReadSeq( edges, &reader);
00327 itEdges = vectorEdges.begin();
00328 while( itEdges != vectorEdges.end() )
00329 {
00330 CV_READ_SEQ_ELEM( edgeactual ,reader);
00331 *itEdges = edgeactual;
00332 itEdges++;
00333 }
00334
00335 std::sort( vectorEdges.begin(), vectorEdges.end(), comparaCvPoint() );
00336
00337
00338 itEdges = vectorEdges.begin();
00339 itEdgesSeguent = vectorEdges.begin() + 1;
00340 dinsBlob = true;
00341 while( itEdges != (vectorEdges.end() - 1))
00342 {
00343 yActual = (*itEdges).y;
00344
00345 if( ( (*itEdges).x != (*itEdgesSeguent).x ) &&
00346 ( (*itEdgesSeguent).y == yActual )
00347 )
00348 {
00349 if( dinsBlob )
00350 {
00351 pt1 = *itEdges;
00352 pt1.x += offsetX;
00353 pt1.y += offsetY;
00354
00355 pt2 = *itEdgesSeguent;
00356 pt2.x += offsetX;
00357 pt2.y += offsetY;
00358
00359 cvLine( imatge, pt1, pt2, color );
00360 }
00361 dinsBlob =! dinsBlob;
00362 }
00363 itEdges++;
00364 itEdgesSeguent++;
00365 if( (*itEdges).y != yActual ) dinsBlob = true;
00366 }
00367 vectorEdges.clear();
00368 }
00369
00392 void CBlob::CopyEdges( CBlob &destination ) const
00393 {
00394 CvSeqReader reader;
00395 CvSeqWriter writer;
00396 CvPoint edgeactual;
00397
00398 cvStartReadSeq( edges, &reader);
00399 cvStartAppendToSeq( destination.Edges(), &writer );
00400
00401 for( int i=0; i<edges->total; i++)
00402 {
00403 CV_READ_SEQ_ELEM( edgeactual ,reader);
00404 CV_WRITE_SEQ_ELEM( edgeactual , writer );
00405 }
00406
00407 cvEndWriteSeq( &writer );
00408 }
00409
00430 void CBlob::ClearEdges()
00431 {
00432
00433 cvClearSeq( edges );
00434 }
00435
00460 bool CBlob::GetConvexHull( CvSeq **dst ) const
00461 {
00462 if( edges != NULL && edges->total > 0)
00463 {
00464 *dst = cvConvexHull2( edges, 0, CV_CLOCKWISE, 0 );
00465 return true;
00466 }
00467 return false;
00468 }
00469
00492 CvBox2D CBlob::GetEllipse() const
00493 {
00494 CvBox2D elipse;
00495
00496 if( edges != NULL && edges->total > 6)
00497 {
00498 elipse = cvFitEllipse2( edges );
00499 }
00500 else
00501 {
00502 elipse.center.x = 0.0;
00503 elipse.center.y = 0.0;
00504 elipse.size.width = 0.0;
00505 elipse.size.height = 0.0;
00506 elipse.angle = 0.0;
00507 }
00508 return elipse;
00509 }
00510
00511
00512
00513
00514
00515
00516
00517
00518
00542 double CBlobGetMoment::operator()(const CBlob &blob) const
00543 {
00544
00545 if((m_p==0) && (m_q==0))
00546 return blob.Area();
00547
00548
00549 if((m_p==1) && (m_q==0))
00550 return blob.SumX();
00551
00552
00553 if((m_p==0) && (m_q==1))
00554 return blob.SumY();
00555
00556
00557 if((m_p==2) && (m_q==0))
00558 return blob.SumXX();
00559
00560
00561 if((m_p==0) && (m_q==2))
00562 return blob.SumYY();
00563
00564 return 0;
00565 }
00566
00594 double CBlobGetHullPerimeter::operator()(const CBlob &blob) const
00595 {
00596 if(blob.Edges() != NULL && blob.Edges()->total > 0)
00597 {
00598 CvSeq *hull = cvConvexHull2( blob.Edges(), 0, CV_CLOCKWISE, 1 );
00599 return fabs(cvArcLength(hull,CV_WHOLE_SEQ,1));
00600 }
00601 return blob.Perimeter();
00602 }
00603
00604 double CBlobGetHullArea::operator()(const CBlob &blob) const
00605 {
00606 if(blob.Edges() != NULL && blob.Edges()->total > 0)
00607 {
00608 CvSeq *hull = cvConvexHull2( blob.Edges(), 0, CV_CLOCKWISE, 1 );
00609 return fabs(cvContourArea(hull));
00610 }
00611 return blob.Perimeter();
00612 }
00613
00636 double CBlobGetMinXatMinY::operator()(const CBlob &blob) const
00637 {
00638 double MinX_at_MinY = LONG_MAX;
00639
00640 CvSeqReader reader;
00641 CvPoint edgeactual;
00642
00643 cvStartReadSeq(blob.Edges(),&reader);
00644
00645 for(int j=0;j<blob.Edges()->total;j++)
00646 {
00647 CV_READ_SEQ_ELEM(edgeactual,reader);
00648 if( (edgeactual.y == blob.MinY()) && (edgeactual.x < MinX_at_MinY) )
00649 {
00650 MinX_at_MinY = edgeactual.x;
00651 }
00652 }
00653
00654 return MinX_at_MinY;
00655 }
00656
00679 double CBlobGetMinYatMaxX::operator()(const CBlob &blob) const
00680 {
00681 double MinY_at_MaxX = LONG_MAX;
00682
00683 CvSeqReader reader;
00684 CvPoint edgeactual;
00685
00686 cvStartReadSeq(blob.Edges(),&reader);
00687
00688 for(int j=0;j<blob.Edges()->total;j++)
00689 {
00690 CV_READ_SEQ_ELEM(edgeactual,reader);
00691 if( (edgeactual.x == blob.MaxX()) && (edgeactual.y < MinY_at_MaxX) )
00692 {
00693 MinY_at_MaxX = edgeactual.y;
00694 }
00695 }
00696
00697 return MinY_at_MaxX;
00698 }
00699
00722 double CBlobGetMaxXatMaxY::operator()(const CBlob &blob) const
00723 {
00724 double MaxX_at_MaxY = LONG_MIN;
00725
00726 CvSeqReader reader;
00727 CvPoint edgeactual;
00728
00729 cvStartReadSeq(blob.Edges(),&reader);
00730
00731 for(int j=0;j<blob.Edges()->total;j++)
00732 {
00733 CV_READ_SEQ_ELEM(edgeactual,reader);
00734 if( (edgeactual.y == blob.MaxY()) && (edgeactual.x > MaxX_at_MaxY) )
00735 {
00736 MaxX_at_MaxY = edgeactual.x;
00737 }
00738 }
00739
00740 return MaxX_at_MaxY;
00741 }
00742
00765 double CBlobGetMaxYatMinX::operator()(const CBlob &blob) const
00766 {
00767 double MaxY_at_MinX = LONG_MIN;
00768
00769 CvSeqReader reader;
00770 CvPoint edgeactual;
00771
00772 cvStartReadSeq(blob.Edges(),&reader);
00773
00774 for(int j=0;j<blob.Edges()->total;j++)
00775 {
00776 CV_READ_SEQ_ELEM(edgeactual,reader);
00777 if( (edgeactual.x == blob.MinY()) && (edgeactual.y > MaxY_at_MinX) )
00778 {
00779 MaxY_at_MinX = edgeactual.y;
00780 }
00781 }
00782
00783 return MaxY_at_MinX;
00784 }
00785
00800 double CBlobGetElongation::operator()(const CBlob &blob) const
00801 {
00802 double ampladaC,longitudC,amplada,longitud;
00803
00804 ampladaC=(double) (blob.Perimeter()+sqrt(pow(blob.Perimeter(),2)-16*blob.Area()))/4;
00805 if(ampladaC<=0.0) return 0;
00806 longitudC=(double) blob.Area()/ampladaC;
00807
00808 longitud=MAX( longitudC , ampladaC );
00809 amplada=MIN( longitudC , ampladaC );
00810
00811 return (double) longitud/amplada;
00812 }
00813
00828 double CBlobGetCompactness::operator()(const CBlob &blob) const
00829 {
00830 if( blob.Area() != 0.0 )
00831 return (double) pow(blob.Perimeter(),2)/(4*CV_PI*blob.Area());
00832 else
00833 return 0.0;
00834 }
00835
00850 double CBlobGetRoughness::operator()(const CBlob &blob) const
00851 {
00852 CBlobGetHullPerimeter getHullPerimeter = CBlobGetHullPerimeter();
00853
00854 double hullPerimeter = getHullPerimeter(blob);
00855
00856 if( hullPerimeter != 0.0 )
00857 return blob.Perimeter() / hullPerimeter;
00858
00859 return 0.0;
00860 }
00861
00876 double CBlobGetLength::operator()(const CBlob &blob) const
00877 {
00878 double ampladaC,longitudC;
00879 double tmp;
00880
00881 tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area();
00882
00883 if( tmp > 0.0 )
00884 ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4;
00885
00886 else
00887 ampladaC = (double) (blob.Perimeter())/4;
00888
00889 if(ampladaC<=0.0) return 0;
00890 longitudC=(double) blob.Area()/ampladaC;
00891
00892 return MAX( longitudC , ampladaC );
00893 }
00894
00909 double CBlobGetBreadth::operator()(const CBlob &blob) const
00910 {
00911 double ampladaC,longitudC;
00912 double tmp;
00913
00914 tmp = blob.Perimeter()*blob.Perimeter() - 16*blob.Area();
00915
00916 if( tmp > 0.0 )
00917 ampladaC = (double) (blob.Perimeter()+sqrt(tmp))/4;
00918
00919 else
00920 ampladaC = (double) (blob.Perimeter())/4;
00921
00922 if(ampladaC<=0.0) return 0;
00923 longitudC = (double) blob.Area()/ampladaC;
00924
00925 return MIN( longitudC , ampladaC );
00926 }
00927
00942 double CBlobGetDistanceFromPoint::operator()(const CBlob &blob) const
00943 {
00944 double xmitjana, ymitjana;
00945 CBlobGetXCenter getXCenter;
00946 CBlobGetYCenter getYCenter;
00947
00948 xmitjana = m_x - getXCenter( blob );
00949 ymitjana = m_y - getYCenter( blob );
00950
00951 return sqrt((xmitjana*xmitjana)+(ymitjana*ymitjana));
00952 }
00953
00977 double CBlobGetXYInside::operator()(const CBlob &blob) const
00978 {
00979 if( blob.Edges() == NULL || blob.Edges()->total == 0 ) return 0.0;
00980
00981
00982 CvSeqReader reader;
00983 CBlob::vectorPunts vectorEdges;
00984 CBlob::vectorPunts::iterator itEdges, itEdgesSeguent;
00985 CvPoint edgeactual;
00986 bool dinsBlob;
00987
00988
00989 cvStartReadSeq( blob.Edges(), &reader);
00990
00991 for( int i=0; i< blob.Edges()->total; i++)
00992 {
00993 CV_READ_SEQ_ELEM( edgeactual ,reader );
00994 if( edgeactual.y == m_p.y )
00995 vectorEdges.push_back( edgeactual );
00996 }
00997
00998 if( vectorEdges.size() == 0 ) return 0.0;
00999
01000
01001 std::sort( vectorEdges.begin(), vectorEdges.end(), CBlob::comparaCvPoint() );
01002
01003
01004
01005
01006 itEdges = vectorEdges.begin();
01007 itEdgesSeguent = vectorEdges.begin() + 1;
01008 dinsBlob = true;
01009
01010 while( itEdges != (vectorEdges.end() - 1) )
01011 {
01012 if( (*itEdges).x <= m_p.x && (*itEdgesSeguent).x >= m_p.x && dinsBlob )
01013 {
01014 vectorEdges.clear();
01015 return 1.0;
01016 }
01017
01018 itEdges++;
01019 itEdgesSeguent++;
01020 dinsBlob = !dinsBlob;
01021 }
01022
01023 vectorEdges.clear();
01024 return 0.0;
01025 }
01026
01027 #ifdef BLOB_OBJECT_FACTORY
01028
01043 void RegistraTotsOperadors( t_OperadorBlobFactory &fabricaOperadorsBlob )
01044 {
01045
01046 fabricaOperadorsBlob.Register( CBlobGetArea().GetNom(), Type2Type<CBlobGetArea>());
01047 fabricaOperadorsBlob.Register( CBlobGetBreadth().GetNom(), Type2Type<CBlobGetBreadth>());
01048 fabricaOperadorsBlob.Register( CBlobGetCompactness().GetNom(), Type2Type<CBlobGetCompactness>());
01049 fabricaOperadorsBlob.Register( CBlobGetElongation().GetNom(), Type2Type<CBlobGetElongation>());
01050 fabricaOperadorsBlob.Register( CBlobGetExterior().GetNom(), Type2Type<CBlobGetExterior>());
01051 fabricaOperadorsBlob.Register( CBlobGetLength().GetNom(), Type2Type<CBlobGetLength>());
01052 fabricaOperadorsBlob.Register( CBlobGetPerimeter().GetNom(), Type2Type<CBlobGetPerimeter>());
01053 fabricaOperadorsBlob.Register( CBlobGetRoughness().GetNom(), Type2Type<CBlobGetRoughness>());
01054
01055
01056 fabricaOperadorsBlob.Register( CBlobGetExternPerimeterRatio().GetNom(), Type2Type<CBlobGetExternPerimeterRatio>());
01057 fabricaOperadorsBlob.Register( CBlobGetExternHullPerimeterRatio().GetNom(), Type2Type<CBlobGetExternHullPerimeterRatio>());
01058 fabricaOperadorsBlob.Register( CBlobGetExternPerimeter().GetNom(), Type2Type<CBlobGetExternPerimeter>());
01059
01060
01061
01062 fabricaOperadorsBlob.Register( CBlobGetHullPerimeter().GetNom(), Type2Type<CBlobGetHullPerimeter>());
01063 fabricaOperadorsBlob.Register( CBlobGetHullArea().GetNom(), Type2Type<CBlobGetHullArea>());
01064
01065
01066
01067 fabricaOperadorsBlob.Register( CBlobGetMajorAxisLength().GetNom(), Type2Type<CBlobGetMajorAxisLength>());
01068 fabricaOperadorsBlob.Register( CBlobGetMinorAxisLength().GetNom(), Type2Type<CBlobGetMinorAxisLength>());
01069 fabricaOperadorsBlob.Register( CBlobGetAxisRatio().GetNom(), Type2Type<CBlobGetAxisRatio>());
01070 fabricaOperadorsBlob.Register( CBlobGetOrientation().GetNom(), Type2Type<CBlobGetOrientation>());
01071 fabricaOperadorsBlob.Register( CBlobGetOrientationCos().GetNom(), Type2Type<CBlobGetOrientationCos>());
01072 fabricaOperadorsBlob.Register( CBlobGetAreaElipseRatio().GetNom(), Type2Type<CBlobGetAreaElipseRatio>());
01073
01074
01075 fabricaOperadorsBlob.Register( CBlobGetMaxX().GetNom(), Type2Type<CBlobGetMaxX>());
01076 fabricaOperadorsBlob.Register( CBlobGetMaxY().GetNom(), Type2Type<CBlobGetMaxY>());
01077 fabricaOperadorsBlob.Register( CBlobGetMinX().GetNom(), Type2Type<CBlobGetMinX>());
01078 fabricaOperadorsBlob.Register( CBlobGetMinY().GetNom(), Type2Type<CBlobGetMinY>());
01079
01080 fabricaOperadorsBlob.Register( CBlobGetMaxXatMaxY().GetNom(), Type2Type<CBlobGetMaxXatMaxY>());
01081 fabricaOperadorsBlob.Register( CBlobGetMaxYatMinX().GetNom(), Type2Type<CBlobGetMaxYatMinX>());
01082 fabricaOperadorsBlob.Register( CBlobGetMinXatMinY().GetNom(), Type2Type<CBlobGetMinXatMinY>());
01083 fabricaOperadorsBlob.Register( CBlobGetMinYatMaxX().GetNom(), Type2Type<CBlobGetMinYatMaxX>());
01084
01085
01086 fabricaOperadorsBlob.Register( CBlobGetMean().GetNom(), Type2Type<CBlobGetMean>());
01087 fabricaOperadorsBlob.Register( CBlobGetStdDev().GetNom(), Type2Type<CBlobGetStdDev>());
01088
01089
01090 fabricaOperadorsBlob.Register( CBlobGetXYInside().GetNom(), Type2Type<CBlobGetXYInside>());
01091 fabricaOperadorsBlob.Register( CBlobGetDiffY().GetNom(), Type2Type<CBlobGetDiffY>());
01092 fabricaOperadorsBlob.Register( CBlobGetDiffX().GetNom(), Type2Type<CBlobGetDiffX>());
01093 fabricaOperadorsBlob.Register( CBlobGetXCenter().GetNom(), Type2Type<CBlobGetXCenter>());
01094 fabricaOperadorsBlob.Register( CBlobGetYCenter().GetNom(), Type2Type<CBlobGetYCenter>());
01095 fabricaOperadorsBlob.Register( CBlobGetDistanceFromPoint().GetNom(), Type2Type<CBlobGetDistanceFromPoint>());
01096
01097
01098 fabricaOperadorsBlob.Register( CBlobGetMoment().GetNom(), Type2Type<CBlobGetMoment>());
01099
01100 }
01101
01102 #endif