zoukankan      html  css  js  c++  java
  • 连通域查找【未完】

    参考:

    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 }

  • 相关阅读:
    springboot系列六、springboot配置错误页面及全局异常
    一行代码完成 Java的 Excel 读写--easyexcel
    Docker搭建Portainer可视化界面
    使用spring-boot-admin对spring-boot服务进行监控
    SpringBoot集成JWT实现权限认证
    安装Docker
    Java的 Excel 读写--easyexcel
    SpringBoot 配置文件提示功能
    Mysql数据库中获取时间
    javascript-观察者模式
  • 原文地址:https://www.cnblogs.com/winslam/p/9570744.html
Copyright © 2011-2022 走看看