opencv如何标记连通区域 并且提取连通区域

opencv如何标记连通区域 并且提取连通区域,第1张

代码

1)Two-pass算法的一种实现

说明:

基于OpenCV和C++实现,领域:4-领域。实现与算法描述稍渣拿孝有差别(具体为记录具有相敏森等关系的label方法实现上)。

// Connected Component Analysis/Labeling By Two-Pass Algorithm

// Author: www.icvpr.com

// Blog : http://blog.csdn.net/icvpr

#include <iostream>

#include <如稿string>

#include <list>

#include <vector>

#include <map>

#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/highgui/highgui.hpp>

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 - 1

int cols = _binImg.cols - 1

for (int i = 1i <rowsi++)

{

int* data_preRow = _lableImg.ptr<int>(i-1)

int* data_curRow = _lableImg.ptr<int>(i)

for (int j = 1j <colsj++)

{

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

// save equivalence

for (size_t k = 1k <neighborLabels.size()k++)

{

int tempLabel = neighborLabels[k]

int&oldSmallestLabel = labelSet[tempLabel]

if (oldSmallestLabel >smallestLabel)

{

labelSet[oldSmallestLabel] = smallestLabel

oldSmallestLabel = smallestLabel

}

else if (oldSmallestLabel <smallestLabel)

{

labelSet[smallestLabel] = oldSmallestLabel

}

}

}

}

}

}

// update equivalent labels

// assigned with the smallest label in each equivalent label set

for (size_t i = 2i <labelSet.size()i++)

{

int curLabel = labelSet[i]

int preLabel = labelSet[curLabel]

while (preLabel != curLabel)

{

curLabel = preLabel

preLabel = labelSet[preLabel]

}

labelSet[i] = curLabel

}

// 2. second pass

for (int i = 0i <rowsi++)

{

int* data = _lableImg.ptr<int>(i)

for (int j = 0j <colsj++)

{

int&pixelLabel = data[j]

pixelLabel = labelSet[pixelLabel]

}

}

}

2)Seed-Filling种子填充方法

说明:

基于OpenCV和C++实现;领域:4-领域。

// Connected Component Analysis/Labeling By Seed-Filling Algorithm

// Author: www.icvpr.com

// Blog : http://blog.csdn.net/icvpr

#include <iostream>

#include <string>

#include <list>

#include <vector>

#include <map>

#include <stack>

#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/highgui/highgui.hpp>

void icvprCcaBySeedFill(const cv::Mat&_binImg, cv::Mat&_lableImg)

{

// connected component analysis (4-component)

// use seed filling algorithm

// 1. begin with a foreground pixel and push its foreground neighbors into a stack

// 2. pop the top pixel on the stack and label it with the same label until the stack is empty

//

// foreground pixel: _binImg(x,y) = 1

// background pixel: _binImg(x,y) = 0

if (_binImg.empty() ||

_binImg.type() != CV_8UC1)

{

return

}

_lableImg.release()

_binImg.convertTo(_lableImg, CV_32SC1)

int label = 1 // start by 2

int rows = _binImg.rows - 1

int cols = _binImg.cols - 1

for (int i = 1i <rows-1i++)

{

int* data= _lableImg.ptr<int>(i)

for (int j = 1j <cols-1j++)

{

if (data[j] == 1)

{

std::stack<std::pair<int,int>>neighborPixels

neighborPixels.push(std::pair<int,int>(i,j)) // pixel position: <i,j>

++label // begin with a new label

while (!neighborPixels.empty())

{

// get the top pixel on the stack and label it with the same label

std::pair<int,int>curPixel = neighborPixels.top()

int curX = curPixel.first

int curY = curPixel.second

_lableImg.at<int>(curX, curY) = label

// pop the top pixel

neighborPixels.pop()

// push the 4-neighbors (foreground pixels)

if (_lableImg.at<int>(curX, curY-1) == 1)

{// left pixel

neighborPixels.push(std::pair<int,int>(curX, curY-1))

}

if (_lableImg.at<int>(curX, curY+1) == 1)

{// right pixel

neighborPixels.push(std::pair<int,int>(curX, curY+1))

}

if (_lableImg.at<int>(curX-1, curY) == 1)

{// up pixel

neighborPixels.push(std::pair<int,int>(curX-1, curY))

}

if (_lableImg.at<int>(curX+1, curY) == 1)

{// down pixel

neighborPixels.push(std::pair<int,int>(curX+1, curY))

}

}

}

}

}

}

3)颜色标记(用于显示)

// Connected Component Analysis/Labeling -- Color Labeling

// Author: www.icvpr.com

// Blog : http://blog.csdn.net/icvpr

#include <iostream>

#include <string>

#include <list>

#include <vector>

#include <map>

#include <stack>

#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/highgui/highgui.hpp>

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 = 0i <rowsi++)

{

const int* data_src = (int*)_labelImg.ptr<int>(i)

uchar* data_dst = _colorLabelImg.ptr<uchar>(i)

for (int j = 0j <colsj++)

{

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++

}

}

}

}

4)测试程序

// Connected Component Analysis/Labeling -- Test code

// Author: www.icvpr.com

// Blog : http://blog.csdn.net/icvpr

#include <iostream>

#include <string>

#include <list>

#include <vector>

#include <map>

#include <stack>

#include <opencv2/imgproc/imgproc.hpp>

#include <opencv2/highgui/highgui.hpp>

int main(int argc, char** argv)

{

cv::Mat binImage = cv::imread("../icvpr.com.jpg", 0)

cv::threshold(binImage, binImage, 50, 1, CV_THRESH_BINARY_INV)

// connected component labeling

cv::Mat labelImg

icvprCcaByTwoPass(binImage, labelImg)

//icvprCcaBySeedFill(binImage, labelImg)

// 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

}

1、找到Opencv的安装目录,例如安装目录在F盘,找到相应岩者缓的安装目录嫌咐如下所示

2、可以看到上图中有两个粗模目录文件夹,而要找的源代码就在source这个文件夹下,打开这个目录

3、在上图中找到modules,打开后可以看到很多文件夹,每个文件夹下都存放了不同类型领域的源代码。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12450573.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-25
下一篇 2023-05-25

发表评论

登录后才能评论

评论列表(0条)

保存