图像连通域分析(Two-Pass & DFS )

来源:互联网 发布:网络流行语mgt什么意思 编辑:程序博客网 时间:2024/05/22 08:07

参考博客:http://blog.csdn.net/icvpr/article/details/10259577#reply
two-pass法原文中的代码有错误,添加了并查集数据结构后得以解决。
DFS方法无误。
本文代码的作用是,寻找图片中的所以连通域,并保留面积最大的连通域,其他区域删除。

#include <iostream>  #include <opencv2\highgui\highgui.hpp>  #include <opencv2\core\core.hpp>  #include <opencv2\imgproc\imgproc.hpp>  #include <map>  #include <stack>#include <string>  #include <list>    #include <stdio.h>#include <time.h>using namespace std;using namespace cv; void myFillSeedFill(const Mat& _binImg, Mat& _labelImg) {    if(_binImg.empty() || _binImg.type() != CV_8UC1) {        return;    }    _labelImg.release();    _binImg.convertTo(_labelImg, CV_32SC1);    int label = 1;    int rows = _binImg.rows;    int cols = _binImg.cols;    vector<pair<int, int>> area;    int maxLabel = 0;    int maxLabelNum = 0;    for(int i = 0; i < rows; ++i) {        int * p = _labelImg.ptr<int>(i);        for(int j = 0; j < cols; ++j) {            if(p[j] == 1) {                stack<pair<int, int>> s;                s.push(pair<int, int>(i, j));                ++label;                int curLabelNum = 0;                while(!s.empty()) {                    pair<int, int> curPix = s.top();                    int curX = curPix.first;                    int curY = curPix.second;                    int * curxptr = _labelImg.ptr<int>(curX);                    curxptr[curY] = label;                    //_labelImg.at<int>(curX, curY) = label;                    ++curLabelNum;                    s.pop();                    if(curX-1 >= 0) {                        int * prexptr = _labelImg.ptr<int>(curX-1);                        if(prexptr[curY] == 1) {                            s.push(pair<int, int>(curX-1, curY));                        }                    }                    if(curY-1 >= 0) {                        //int * prexptr = _labelImg.ptr<int>(curX-1);                        if(curxptr[curY-1] == 1) {                            s.push(pair<int, int>(curX, curY-1));                        }                    }                    if(curX+1 < rows) {                        int * latexptr = _labelImg.ptr<int>(curX+1);                        if(latexptr[curY] == 1) {                            s.push(pair<int, int>(curX+1, curY));                        }                    }                    if(curY+1 < cols) {                        //int * prexptr = _labelImg.ptr<int>(curX-1);                        if(curxptr[curY+1] == 1) {                            s.push(pair<int, int>(curX, curY+1));                        }                    }                }                if(curLabelNum > maxLabelNum) {                    maxLabelNum = curLabelNum;                    maxLabel = label;                }            }        }    }    for(int i = 0; i < rows; ++i) {        int * p = _labelImg.ptr<int>(i);        for(int j = 0; j < cols; ++j) {            if(p[j] == maxLabel) {                p[j] = 255;            }            else {                p[j] = 0;            }        }    }    //总耗时: 0.5秒}int father[100000];vector<int> labelCnt(1000, 0);void make() {    for(int i = 0; i < 100000; ++i) {        father[i] = i;    }}int Find_Set(int x) {    if(x != father[x]) {        father[x] = Find_Set(father[x]);    }    return father[x];}void Union(int x, int y) {    int fx = Find_Set(x);    int fy = Find_Set(y);    if(fx == fy) {        return;    }    father[fy] = fx;}void icvprCcaByTwoPass(const cv::Mat& _binImg, cv::Mat& _lableImg)  {      // connected component analysis (4-component)      // use two-pass algorithm      // 1. first pass: label each foreground pixel with a label      // 2. second pass: visit each labeled pixel and merge neighbor labels      //       // foreground pixel: _binImg(x,y) = 1      // background pixel: _binImg(x,y) = 0      if (_binImg.empty() ||          _binImg.type() != CV_8UC1)      {          return ;      }      // 1. first pass      _lableImg.release() ;      _binImg.convertTo(_lableImg, CV_32SC1) ;      int label = 1 ;  // start by 2      std::vector<int> labelSet;      labelSet.push_back(0) ;   // background: 0      labelSet.push_back(1) ;   // foreground: 1      int rows = _binImg.rows;      int cols = _binImg.cols;    int* data_firstRows = _lableImg.ptr<int>(0);    if(data_firstRows[0] == 1) {        data_firstRows[0] = ++label;        labelSet.push_back(label);    }    for (int j = 1; j < cols; ++j) {  //第一行初始化label        if(data_firstRows[j] == 1) {            if(data_firstRows[j-1] > 0) {                data_firstRows[j] == data_firstRows[j-1];            } else {                data_firstRows[j] = ++label;                labelSet.push_back(label);            }        }    }    for(int j = 1; j < rows; ++j) {   //第一列初始化label        if(_lableImg.at<int>(j, 0) == 1) {            if(_lableImg.at<int>(j-1, 0) > 0) {                _lableImg.at<int>(j, 0) = _lableImg.at<int>(j-1, 0);            } else {                _lableImg.at<int>(j, 0) = ++label;                labelSet.push_back(label);            }        }    }    //label = 1;    make();    for (int i = 1; i < rows; i++)      {          int* data_preRow = _lableImg.ptr<int>(i-1) ;          int* data_curRow = _lableImg.ptr<int>(i) ;          for (int j = 1; j < cols; j++)          {              if (data_curRow[j] == 1)              {                  std::vector<int> neighborLabels;                  neighborLabels.reserve(2);                  int leftPixel = data_curRow[j-1];                  int upPixel = data_preRow[j];                  if ( leftPixel > 1)                  {                      neighborLabels.push_back(leftPixel) ;                  }                  if (upPixel > 1)                  {                      neighborLabels.push_back(upPixel) ;                  }                  if (neighborLabels.empty())                  {                      labelSet.push_back(++label) ;  // assign to a new label                      data_curRow[j] = label ;                      labelSet[label] = label ;                  }                  else                  {                      std::sort(neighborLabels.begin(), neighborLabels.end());                      int smallestLabel = neighborLabels[0];                        data_curRow[j] = smallestLabel;                      for(size_t k = 1; k < neighborLabels.size(); k++) {                        int tmpLabel = neighborLabels[k];                        Union(tmpLabel, smallestLabel);                        Union(smallestLabel, tmpLabel);                    }                }                             }          }      }      // 2. second pass      for (int i = 0; i < rows; i++)      {          int* data = _lableImg.ptr<int>(i) ;          for (int j = 0; j < cols; j++)          {              data[j] = Find_Set(data[j]);            if(data[j] != 0) {                labelCnt[data[j]]++;            }        }      }    vector<int>::iterator maxLabel = max_element(labelCnt.begin(), labelCnt.end());    cout << *maxLabel << endl;    int maxL = distance(labelCnt.begin(), maxLabel);    cout << maxL << endl;    for (int i = 0; i < rows; i++) {          int* data = _lableImg.ptr<int>(i) ;          for (int j = 0; j < cols; j++) {            if(data[j] == maxL) {                data[j] = 255;            } else {                data[j] = 0;            }        }    }}cv::Scalar icvprGetRandomColor()  {      uchar r = 255 * (rand()/(1.0 + RAND_MAX));      uchar g = 255 * (rand()/(1.0 + RAND_MAX));      uchar b = 255 * (rand()/(1.0 + RAND_MAX));      return cv::Scalar(b,g,r) ;  }  void icvprLabelColor(const cv::Mat& _labelImg, cv::Mat& _colorLabelImg)   {      if (_labelImg.empty() ||          _labelImg.type() != CV_32SC1)      {          return ;      }      std::map<int, cv::Scalar> colors ;      int rows = _labelImg.rows ;      int cols = _labelImg.cols ;      _colorLabelImg.release() ;      _colorLabelImg.create(rows, cols, CV_8UC3) ;      _colorLabelImg = cv::Scalar::all(0) ;      for (int i = 0; i < rows; i++)      {          const int* data_src = (int*)_labelImg.ptr<int>(i) ;          uchar* data_dst = _colorLabelImg.ptr<uchar>(i) ;          for (int j = 0; j < cols; j++)          {              int pixelValue = data_src[j] ;              if (pixelValue > 1)              {                  if (colors.count(pixelValue) <= 0)                  {                      colors[pixelValue] = icvprGetRandomColor() ;                  }                  cv::Scalar color = colors[pixelValue] ;                  *data_dst++   = color[0] ;                  *data_dst++ = color[1] ;                  *data_dst++ = color[2] ;              }              else              {                  data_dst++ ;                  data_dst++ ;                  data_dst++ ;              }          }      }  }  int main()  {      time_t t_start, t_end;   /* Mat img, res;  */    Mat binImage = imread("segmentationMask_bad.jpg",0);    //将读入的彩色图像直接以灰度图像读入    //Mat binImage = imread("liantongyu.jpg",0);   //小图,在递归调用中可用,图太大则只能使用TwoPass方法    //Mat binImage = imread("connect2.jpg",0);      Mat showimg;    showimg.release() ;      binImage.convertTo(showimg, CV_8UC1) ;      for(int i = 0; i < showimg.rows; ++i) {        uchar * p = showimg.ptr<uchar>(i);        for(int j = 0; j < showimg.cols; ++j) {            if(p[j] > 50)                p[j] = 225;            else                p[j] = 0;        }    }    cv::imshow("showing", showimg);    //cv::Mat binImage = cv::imread("../icvpr.com.jpg", 0) ;      //cv::threshold(binImage, binImage, 50, 1, CV_THRESH_BINARY_INV) ;      for(int i = 0; i < binImage.rows; ++i) {        uchar * p = binImage.ptr<uchar>(i);        for(int j = 0; j < binImage.cols; ++j) {            if(p[j] > 50)                p[j] = 1;            else                p[j] = 0;        }    }    // connected component labeling      cv::Mat labelImg ;      t_start = clock();    //icvprCcaByTwoPass(binImage, labelImg) ;         // cost 0.184s    myFillSeedFill(binImage, labelImg);             // cost 0.526s    t_end = clock();    double duration = (double)(t_end - t_start) / CLOCKS_PER_SEC;    cout << "cost " << duration << " s" << endl;    // show result      cv::Mat grayImg ;      //labelImg *= 10 ;      labelImg.convertTo(grayImg, CV_8UC1) ;      cv::imshow("labelImg", grayImg) ;      cv::Mat colorLabelImg ;      icvprLabelColor(labelImg, colorLabelImg) ;      cv::imshow("colorImg", colorLabelImg) ;      cv::waitKey(0) ;      return 0 ;  }
原创粉丝点击