//Find_Connected_Component参数说明:
/*mask———一副灰度图
polygon1_hull0———用多边形拟合选1,用凸包拟合选0
scale———设置不被删除的连通轮廓大小
num————连通轮廓的最大数目
bbs——指向连通轮廓的外接矩形
center——指向连通轮廓的中心*/
#define CVCONTOUR_APPROX_LEVEL 2//数越大连通区域的边界越简单
#define CVCLOSE_ITR 1 //图像形态学运算的次数
void Find_Connected_Component(IplImage *mask,int polygon1_hull0=1,float scale=4
,int *num=0,CvRect *bbs=0,CvPoint *centers=0)//连通域去噪声
{
static CvMemStorage* mem_storage=0;
static CvSeq* contours=0;
//先开操作,后闭操作
cvMorphologyEx(mask,mask,0,0,CV_MOP_OPEN,CVCLOSE_ITR);
cvMorphologyEx(mask,mask,0,0,CV_MOP_CLOSE,CVCLOSE_ITR);
//找到所有轮廓
if(!mem_storage)
{
mem_storage=cvCreateMemStorage(0);
}
else{
cvClearMemStorage(mem_storage);
}
CvContourScanner scanner=cvStartFindContours(mask,mem_storage,sizeof(CvContour),CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
//丢弃太小的轮廓,用多边形或凸包拟合剩下的轮廓
CvSeq* c;
int numCont=0;
while(c=cvFindNextContour(scanner))
{
double len=cvContourPerimeter(c);//连通域周长
double q=(mask->height+mask->width)/scale;
//cout<<len<<" ";
if(len<q){cvSubstituteContour(scanner,NULL);}
else{
CvSeq* c_new;
if(polygon1_hull0)
{
//多边形拟合
c_new=cvApproxPoly(c,sizeof(CvContour),mem_storage,CV_POLY_APPROX_DP,CVCONTOUR_APPROX_LEVEL,0);
}
else{
//凸包拟合
c_new=cvConvexHull2(c,mem_storage,CV_CLOCKWISE,1);
}
cvSubstituteContour(scanner,c_new);
numCont++;
}
}
contours=cvEndFindContours(&scanner);
const CvScalar CVX_WHITE=CV_RGB(0xff,0xff,0xff);//白色
const CvScalar CVX_BLACK=CV_RGB(0x00,0x00,0x00); //黑色
//重绘连通区域
cvZero(mask);
IplImage *maskTemp;
int numFilled=0;
if(num!=NULL)
{
int N=*num,i=0;
CvMoments moments;
double M00,M01,M10;
maskTemp=cvCloneImage(mask);
for(i=0,c=contours;c!=NULL;c=c->h_next,i++)
{
if(i<N)
{
cvDrawContours(maskTemp,c,CVX_WHITE,CVX_WHITE,-1,CV_FILLED,8);
//找中心
if(centers){
cvMoments(maskTemp,&moments,1);
M00=cvGetSpatialMoment(&moments,0,0);
M10=cvGetSpatialMoment(&moments,1,0);
M01=cvGetSpatialMoment(&moments,0,1);
centers[i].x=(int)(M10/M00);
centers[i].y=(int)(M01/M00);
}
if(bbs!=NULL){
bbs[i]=cvBoundingRect(c);
}
cvZero(maskTemp);
numFilled++;
}
//画区域
cvDrawContours(mask,c,CVX_WHITE,CVX_WHITE,-1,CV_FILLED,8);
}
//*num=numFilled;
cvReleaseImage(&maskTemp);
}
else
{
for(c=contours;c!=NULL;c=c->h_next)
cvDrawContours(mask,c,CVX_WHITE,CVX_WHITE,-1,CV_FILLED,8);
}
*num=numCont;
}
from: http://wenku.baidu.com/link?url=FT1EFNPSlRZo7DA44IQUbCiZfM9AAq6VVajoFA3WFdZXQsswTccP8gtiA1350oKj-g7ydV9BqBW5KjEeAolF5l15QUjwXNqJvcKHs4BQCja