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