zoukankan      html  css  js  c++  java
  • two Pass方法连通域检测

    原理:

    Two-Pass方法检测连通域的原理可参见这篇博客:http://blog.csdn.net/lichengyu/article/details/13986521

    参考下面动图,一目了然。

    代码:

    代码中标记图的数据类型要注意,如果first pass中标记数多于255,就不要用uchar类型,我直接设置为int类型。

      1 #include "opencv2/imgproc/imgproc.hpp"
      2 #include "opencv2/highgui/highgui.hpp"
      3 #include <map>
      4 #include <cassert>
      5 #include <iostream>
      6 
      7 using namespace std;
      8 
      9 const int max_size = 1000;
     10 int parent[max_size] = { 0 };
     11 
     12 // 找到label x的根节点
     13 int Find(int x, int parent[])
     14 {
     15     assert(x < max_size);
     16     int i = x;
     17     while (0 != parent[i])
     18         i = parent[i];
     19     return i;
     20 }
     21 
     22 // 将label x 和 label y合并到同一个连通域
     23 void Union(int x, int y, int parent[])
     24 {
     25     assert(x < max_size && y < max_size);
     26     int i = x;
     27     int j = y;
     28     while (0 != parent[i])
     29         i = parent[i];
     30     while (0 != parent[j])
     31         j = parent[j];
     32     if (i != j)
     33         parent[i] = j;
     34 }
     35 
     36 cv::Mat twoPassConnectComponent(cv::Mat &binaryImg)
     37 {
     38     int imgW = binaryImg.cols;
     39     int imgH = binaryImg.rows;
     40     int channel = binaryImg.channels();
     41     int type = binaryImg.type();
     42     // first pass
     43     int label = 0;
     44 
     45     cv::Mat dst = cv::Mat::zeros(cv::Size(imgW, imgH), CV_32SC1);
     46     for (int y = 0; y < imgH; y++)
     47     {
     48         for (int x = 0; x < imgW; x++)
     49         {
     50             if (binaryImg.at<uchar>(y, x) != 0)
     51             {
     52                 int left = (x - 1 < 0) ? 0 : dst.at<int>(y, x - 1);
     53                 int up = (y - 1 < 0) ? 0 : dst.at<int>(y - 1, x);
     54 
     55                 if (left != 0 || up != 0)
     56                 {
     57                     if (left != 0 && up != 0)
     58                     {
     59                         dst.at<int>(y, x) = min(left, up);
     60                         if (left <= up)
     61                             Union(up, left, parent);
     62                         else if (up<left)
     63                             Union(left, up, parent);
     64                     }
     65                     else
     66                         dst.at<int>(y, x) = max(left, up);
     67                 }
     68                 else
     69                 {
     70                     dst.at<int>(y, x) = ++label;
     71                 }
     72             }
     73         }
     74     }
     75 
     76     //second pass 
     77     for (int y = 0; y < imgH; y++)
     78     {
     79         for (int x = 0; x < imgW; x++)
     80         {
     81             if (binaryImg.at<uchar>(y, x) != 0)
     82                 dst.at<int>(y, x) = Find(dst.at<int>(y, x), parent);
     83         }
     84     }
     85 
     86     return dst;
     87 }
     88 
     89 cv::Scalar getRandomColor()
     90 {
     91     uchar r = 255 * (rand() / (1.0 + RAND_MAX));
     92     uchar g = 255 * (rand() / (1.0 + RAND_MAX));
     93     uchar b = 255 * (rand() / (1.0 + RAND_MAX));
     94     return cv::Scalar(b, g, r);
     95 }
     96 
     97 cv::Mat showColorLabel(cv::Mat label)
     98 {
     99     int imgW = label.cols;
    100     int imgH = label.rows;
    101     std::map<int, cv::Scalar> colors;
    102 
    103     cv::Mat colorLabel = cv::Mat::zeros(imgH, imgW, CV_8UC3);
    104     int *pLabel = (int*)label.data;
    105     uchar *pColorLabel = colorLabel.data;
    106     for (int i = 0; i < imgH; i++)
    107     {
    108         for (int j = 0; j < imgW; j++)
    109         {
    110             int idx = (i*imgW + j) * 3;
    111             int pixelValue = pLabel[i*imgW + j];
    112             if (pixelValue > 0)
    113             {
    114                 if (colors.count(pixelValue) <= 0)
    115                 {
    116                     colors[pixelValue] = getRandomColor();
    117                 }
    118                 cv::Scalar color = colors[pixelValue];
    119                 pColorLabel[idx + 0] = color[0];
    120                 pColorLabel[idx + 1] = color[1];
    121                 pColorLabel[idx + 2] = color[2];
    122             }
    123         }
    124     }
    125 
    126     return colorLabel;
    127 }
    128 
    129 int main() 
    130 {
    131     // 加载图像
    132     string imageName = "data/source_images/logo.png";
    133     cv::Mat image = cv::imread(imageName, 1);
    134     if (!image.data) 
    135     {
    136         cout << "No image data" << endl;
    137         getchar();
    138         return -1;
    139     }
    140     //转为灰度图
    141     cv::cvtColor(image, image, CV_RGB2GRAY);
    142     //阈值化,情景为255,背景为0
    143     cv::Mat threshImg;
    144     cv::threshold(image, threshImg, 200, 255, cv::THRESH_BINARY);
    145     cv::bitwise_not(threshImg, threshImg);
    146 
    147     //连通域检测 two Pass方法标记图像
    148     cv::Mat labelImg = twoPassConnectComponent(threshImg);
    149 
    150     //不同连通区域用不同颜色表示
    151     cv::Mat colorLabelImg=showColorLabel(labelImg);
    152 
    153     //显示
    154     cv::imshow("thresh", threshImg);
    155     cv::imshow("label", labelImg*20);
    156     cv::imshow("colorLabel", colorLabelImg);
    157     cv::waitKey(0);
    158 }
    View Code

    结果:

    使用OpenCV的logo为素材图,如下:

    (1)转为灰度图然后阈值化

    (2)寻找连通域

    (3)不同连通区域不同颜色显示

        

       

     封装后的代码见我的码云code:https://gitee.com/rxdj/twoPassMethod.git

     

  • 相关阅读:
    494. Target Sum 添加标点符号求和
    636. Exclusive Time of Functions 进程的执行时间
    714. Best Time to Buy and Sell Stock with Transaction Fee有交易费的买卖股票
    377. Combination Sum IV 返回符合目标和的组数
    325. Maximum Size Subarray Sum Equals k 和等于k的最长子数组
    275. H-Index II 递增排序后的论文引用量
    274. H-Index论文引用量
    RabbitMQ学习之HelloWorld(1)
    java之struts2的数据处理
    java之struts2的action的创建方式
  • 原文地址:https://www.cnblogs.com/riddick/p/8280883.html
Copyright © 2011-2022 走看看