连通域查找【未完】

参考:

https://blog.csdn.net/qq_37059483/article/details/78018539

https://blog.csdn.net/xjt2015/article/details/51283387

http://www.cnblogs.com/ronny/p/img_aly_01.html

http://www.cnblogs.com/tiandsp/archive/2012/12/06/2805276.html

  1 #include <opencv2opencv.hpp>
  2 #include <iostream>
  3 #include <vector>
  4 #include <stack>
  5 using namespace std;
  6 using namespace cv;
  7 
  8 typedef struct _Feather
  9 {
 10     int label;              // 连通域的label值
 11     int area;               // 连通域的面积
 12     Rect boundingbox;       // 连通域的外接矩形框
 13 } Feather;
 14 
 15 /*
 16 Input:
 17 src: 待检测连通域的二值化图像
 18 Output:
 19 dst: 标记后的图像
 20 featherList: 连通域特征的清单
 21 return:
 22 连通域数量。
 23 */
 24 int bwLabel(Mat & src, Mat & dst, vector<Feather> & featherList)
 25 {
 26     int rows = src.rows;
 27     int cols = src.cols;
 28 
 29     int labelValue = 0;
 30     Point seed, neighbor;
 31     stack<Point> pointStack;    // 堆栈
 32 
 33     int area = 0;               // 用于计算连通域的面积
 34 
 35     int leftBoundary = 0;       // 连通域的左边界,即外接最小矩形的左边框,横坐标值,依此类推
 36     int rightBoundary = 0;
 37     int topBoundary = 0;
 38     int bottomBoundary = 0;
 39     Rect box;                   // 外接矩形框
 40     Feather feather;
 41 
 42     featherList.clear();    // 清除数组
 43 
 44     dst.release();
 45     dst = src.clone();
 46     for (int i = 0; i < rows; i++)
 47     {
 48         uchar *pRow = dst.ptr<uchar>(i);
 49         for (int j = 0; j < cols; j++)
 50         {
 51             //【注:一旦连通域赋值为1;遍历当前行的下一行时候,就会自动跳过下面if判断】
 52             if (pRow[j] == 255)
 53             {
 54                 area = 0;
 55                 labelValue++;           // labelValue最大为254,最小为1.
 56                 seed = Point(j, i); //(731,49)    // Point(横坐标,纵坐标)(x,y)
 57                                     //int p = dst.ptr<uchar>(i)[j];
 58                 dst.at<uchar>(seed) = labelValue;//1
 59                 pointStack.push(seed);//坐标压栈
 60 
 61                 area++;
 62                 leftBoundary = seed.x;//731
 63                 rightBoundary = seed.x;//731
 64                 topBoundary = seed.y;//49
 65                 bottomBoundary = seed.y;//49
 66 
 67                 while (!pointStack.empty())
 68                 {
 69                     //<1>右邻像素点
 70                     neighbor = Point(seed.x + 1, seed.y);
 71                     if ((seed.x != (cols - 1)) && (dst.at<uchar>(neighbor) == 255))
 72                     {
 73                         dst.at<uchar>(neighbor) = labelValue;//【注:】赋值便签1,保证不走回头路和分类连通域
 74                         pointStack.push(neighbor);
 75 
 76                         area++;
 77                         if (rightBoundary < neighbor.x)//更新边界
 78                             rightBoundary = neighbor.x;
 79                     }
 80                     //<2>下邻像素点
 81                     neighbor = Point(seed.x, seed.y + 1);
 82                     if ((seed.y != (rows - 1)) && (dst.at<uchar>(neighbor) == 255))
 83                     {
 84                         dst.at<uchar>(neighbor) = labelValue;
 85                         pointStack.push(neighbor);
 86 
 87                         area++;
 88                         if (bottomBoundary < neighbor.y)
 89                             bottomBoundary = neighbor.y;
 90 
 91                     }
 92                     //<3>左邻像素点
 93                     neighbor = Point(seed.x - 1, seed.y);
 94                     //int testx = seed.x;
 95                     //int testp = dst.at<uchar>(neighbor);
 96                     if ((seed.x != 0) && (dst.at<uchar>(neighbor) == 255))
 97                     {
 98                         dst.at<uchar>(neighbor) = labelValue;
 99                         pointStack.push(neighbor);
100 
101                         area++;
102                         if (leftBoundary > neighbor.x)
103                             leftBoundary = neighbor.x;
104                     }
105                     //<4>上邻边界点
106                     neighbor = Point(seed.x, seed.y - 1);
107                     if ((seed.y != 0) && (dst.at<uchar>(neighbor) == 255))
108                     {
109                         dst.at<uchar>(neighbor) = labelValue;
110                         pointStack.push(neighbor);
111 
112                         area++;
113                         if (topBoundary > neighbor.y)
114                             topBoundary = neighbor.y;
115                     }
116 
117                     seed = pointStack.top();
118                     pointStack.pop();
119                 }
120                 box = Rect(leftBoundary, topBoundary, rightBoundary - leftBoundary, bottomBoundary - topBoundary);
121                 rectangle(src, box, 255);
122                 feather.area = area;
123                 feather.boundingbox = box;
124                 feather.label = labelValue;
125                 featherList.push_back(feather);
126             }
127         }
128     }
129     return labelValue;
130 }
131 
132 int main(int argc, char *argv[])
133 {
134     Mat src(imread("test3.jpg", 0));
135     if (src.empty())
136         exit(-1);
137     threshold(src, src, 127, 255, THRESH_BINARY);   // 二值化图像
138     vector<Feather> featherList;                    // 存放连通域特征
139     Mat dst;
140     cout << "连通域数量: " << bwLabel(src, dst, featherList) << endl;
141 
142     // 为了方便观察,可以将label“放大”
143     for (int i = 0; i < dst.rows; i++)
144     {
145         uchar *p = dst.ptr<uchar>(i);
146         for (int j = 0; j < dst.cols; j++)
147         {
148             p[j] = 30 * p[j];
149         }
150     }
151 
152     cout << "标号" << "	" << "面积" << endl;
153     for (vector<Feather>::iterator it = featherList.begin(); it < featherList.end(); it++)
154     {
155         cout << it->label << "	" << it->area << endl;
156         rectangle(dst, it->boundingbox, 255);
157     }
158     cv::namedWindow("dst", WINDOW_NORMAL);
159     imshow("src", src);
160     imshow("dst", dst);
161 
162     waitKey();
163     destroyAllWindows();
164 
165     system("pause");
166     return 0;
167 }

原文地址:https://www.cnblogs.com/winslam/p/9570744.html