#include#include #include #include #include #include #include #include using namespace std;using namespace cv;#define WHITE 1#define GRAY 2#define BLACK 3#define INFINITE 255typedef CvPoint ElemType;typedef struct{ bool vSign;//像素点是否被访问过的标记,ture已访问,false表示未访问,给图片添加的一个属性 int pixelValue;//像素值}isVisit;typedef struct{ CvPoint regionPoint;//该连通区域起点的坐标 int regionId;//第i个连通区域的标号 int pointNum;//第i个连通区域的像素点的总个数}connectRegionNumSet;int calConnectRegionNumsBfs(IplImage *srcGray, vector >& validPicture, vector ®ionSet);int main() { IplImage * src = cvLoadImage("ff.jpg"); IplImage * srcGray = NULL; if (src->nChannels == 1) goto next; srcGray = cvCreateImage(cvSize(src->width, src->height), 8, 1); cvCvtColor(src, srcGray, CV_RGB2GRAY); next: if (!srcGray) cvThreshold(src, srcGray, 66, 255, CV_THRESH_BINARY); else cvThreshold(srcGray, srcGray, 66, 255, CV_THRESH_BINARY); cvNamedWindow("srcBinaryGray"); cvShowImage("srcBinaryGray", srcGray); vector >validPoint; validPoint.resize(srcGray->height); for (int i = 0; i width); vector regionSet;//存放找到的各个连通区域 regionSet.size()为连通区域的个数。 cout << "连通区域的数目:" << calConnectRegionNumsBfs(srcGray, validPoint, regionSet) << endl << endl;//计算连通区域数目 char text[3];//设置连通区域的编号,最小标号为0,最大编号为99 CvFont font; cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX, 0.6, 0.6, 0, 1, 8);//设置字体//参数从左到右:字体初始化,字体格式,字体宽度,字体高度,字体倾斜度,字体粗细,字体笔画类型 int max_pointNum = 0; //最大连通区域的像素点个数 int max_regionId = 0; for (int i = 0; i << regionSet[i].regionPoint.x << "," << regionSet[i].regionPoint.y << ")" << ",像素总点数=" << regionSet[i].pointNum << endl; cout << "ID:"< << endl; if (i < 10) { //连通区域的个数为个位数 text[0] = '0'; text[1] = '0' + i; } else { //连通区域的个数为十位数 text[0] = '0' + (i) / 10; text[1] = '0' + (i) % 10; } text[2] = '\0'; cvPutText(src, text, regionSet[i].regionPoint, &font, cvScalar(0, 0, 255)); //找到最大连通区域,并标记---------------------------------------------- if (max_pointNum < regionSet[i].pointNum) { max_regionId = i; max_pointNum = regionSet[i].pointNum; } } cout << "第" << max_regionId << "个连通区域最大" <<"像素总点数=" << regionSet[max_regionId].pointNum << endl; cvNamedWindow("src"); cvShowImage("src", src); //cvShowImage("srcGray", srcGray); cvWaitKey(0); cvReleaseImage(&src); cvReleaseImage(&srcGray); cvDestroyAllWindows();}int calConnectRegionNumsBfs(IplImage *srcGray, vector >& validPicture, vector ®ionSet){ int regionId = 0;//管理连通区域标号的变量 connectRegionNumSet regionSetTemp;//临时用到的regionSetTemp类型中间变量 uchar * ptr = (uchar*)(srcGray->imageData); for (int y = 0; y < srcGray->height; y++) { //给图片加上一个是否已访问的属性 ptr = (uchar*)(srcGray->imageData + y*srcGray->widthStep); for (int x = 0; x < srcGray->width; x++) { validPicture[y][x].pixelValue = (int)ptr[x]; validPicture[y][x].vSign = false;//开始时默认都未访问 } } queue q; CvPoint foundValidPoint; for (int y = 0; y < srcGray->height; y++) { //给图片加上一个是否已访问的属性 for (int x = 0; x < srcGray->width; x++) { if (validPicture[y][x].pixelValue && !validPicture[y][x].vSign) { //找到下一个连通区域的起点,即像素值非零且未被访问过的点 int eachRegionAcc = 1;//表示即将要寻找的连通区域的总像素点个数;//将validPicture[y][x]点默认为即将生成的连通区域的起点 regionSetTemp.regionPoint = cvPoint(x, y);//x表示列,y表示行 regionSetTemp.regionId = regionId++; regionSetTemp.pointNum = 1; regionSet.push_back(regionSetTemp);//将该点设置为已访问,并对其执行入栈操作 validPicture[y][x].vSign = true; q.push(cvPoint(x, y)); while (!q.empty()) { foundValidPoint = q.front(); q.pop(); int i = foundValidPoint.x;//t int j = foundValidPoint.y;//k int minY = (j - 1 < 0 ? 0 : j - 1); int maxY = ((j + 1 > srcGray->height - 1 ? srcGray->height - 1 : j + 1)); int minX = (i - 1 < 0 ? 0 : i - 1); int maxX = (i + 1 > srcGray->width - 1 ? srcGray->width - 1 : i + 1); for (int k = minY; k <= maxY; k++) { //在八连通范围内(两点之间距离小于根号2的点),表示其相邻点,入栈c for (int t = minX; t <= maxX; t++) { if (validPicture[k][t].pixelValue && !validPicture[k][t].vSign)//validPicture[k][t]如果没有访问过 { validPicture[k][t].vSign = true;//标志为已访问,防止死循环 q.push(cvPoint(t, k)); eachRegionAcc++;//相邻点的数目加1 } } } } if (eachRegionAcc > 1) //要求:连通区域的点数至少要有两个 regionSet[regionSet.size() - 1].pointNum = eachRegionAcc; else { //单个像素点不算,如果单个像素点也算,去掉该else语句即可 regionSet.pop_back();//上述默认的即将生成的连通区域不符合要求,出栈 regionId--; } } } } return regionSet.size();}
原图:
处理之后