连通区域

#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <stack>

#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 = 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 ;

					// save equivalence
					for (size_t k = 1; k < 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 = 2; i < 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 = 0; i < rows; i++)
	{
		int* data = _lableImg.ptr<int>(i) ;
		for (int j = 0; j < cols; j++)
		{
			int& pixelLabel = data[j] ;
			pixelLabel = labelSet[pixelLabel] ;
		}
	}
}

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(int argc, char** argv)
{
	IplImage* img1 = cvLoadImage("E:\newocr\ocr\test.jpg", 1);
	cv::Mat binImage(img1);
	//cv::Mat binImage = cv::imread("E:\newocr\ocr\test.jpg", 0) ;
	cv::threshold(binImage, binImage, 50, 1, CV_THRESH_BINARY_INV) ;
	cv::imshow("labelImg", binImage) ;
	// 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 ;
}

 

连通区域

时间: 2024-10-10 09:08:34

连通区域的相关文章

OpenCV:二值图像连通区域分析与标记算法实现

编译环境: 操作系统:Win8.1  64位 IDE平台:Visual Studio 2013 Ultimate OpenCV:2.4.8 一.连通域 在图像中,最小的单位是像素,每个像素周围有8个邻接像素,常见的邻接关系有2种:4邻接与8邻接.4邻接一共4个点,即上下左右,如下左图所示.8邻接的点一共有8个,包括了对角线位置的点,如下右图所示.         如果像素点A与B邻接,我们称A与B连通,于是我们不加证明的有如下的结论: 如果A与B连通,B与C连通,则A与C连通. 在视觉上看来,彼

使用OpenCV查找二值图中最大连通区域

http://blog.csdn.net/shaoxiaohu1/article/details/40272875 使用OpenCV查找二值图中最大连通区域 标签: OpenCVfindCoutours 2014-10-19 22:31 2802人阅读 评论(0) 收藏 举报  分类: 图像与OpenCV(15)  版权声明:本文为shaoxiaohu原创文章,欢迎转载,请注明出处,谢谢. 上一篇博文中介绍了matlab查找最大连通区域的方法,OpenCV函数中也有类似的函数与之对应,findC

Opencv2系列学习笔记10(提取连通区域轮廓) 另一个

http://blog.csdn.net/lu597203933/article/details/17362457 连通区域指的是二值图像中相连像素组成的形状.而内.外轮廓的概念及opencv1中如何提取二值图像的轮廓见我的这篇博客:http://blog.csdn.net/lu597203933/article/details/14489225 轮廓的简单提取算法如下: 系统性地扫描图像直到遇到连通区域的一个点,以它为起始点,跟踪它的轮廓,标记边界上的像素.当轮廓完整闭合,扫描回到上一个位置,

【CCL】连通区域提取

根据朋友给的一份原理写的 感觉还挺清楚 #include "cv.h" #include "highgui.h" #include <stdio.h> using namespace cv; #define MAXWIDTH 352 #define MAXHEIGHT 288 typedef struct PTNode{ int data; int parent; }PTNode; void GetCCL(Mat &imgsrc, Mat &am

连通区域标记-行程扫描算法

1.连通域 对于一幅图像来说,它的基本组成单元是像素,每一个像素又对应一个灰度值. 联通区域标记针对的是二值图像,二值图像顾名思义就是它的灰度值只存在两种值---0或255的图像,一个连通区域指的是图像中那些位置相邻,灰度值相同的像素集合所组成的区域. 像素和像素之间的邻域关系有4邻域和8邻域,4邻域指的是当前像素的上下左右位置处的像素,8邻域是指上下左右和对角线位置处的像素. 如右图所示,分别对应的是像素的4邻域和8邻域位置关系   (x,y-1)   (x-1,y) (x,y) (x+1,y

【连通区域个数】

#include <iostream> using namespace std; void DFS(int R,int W,int i, int j,int **visited,int **mVexs) { int r,w; visited[i][j] = 1; //将该位置的访问标签置为1 // 遍历该顶点的所有邻接顶点.若是没有访问过且元素为1,则继续深度访问 if(j>=1) { r = i;w = j-1; { if (!visited[r][w] && mVex

opencv 二值图像剔除小连通区域

二值图像剔除小面积连通区域在二值图像连通区域分析时很有用,之前做的使用采用了for循环的形式,后来学习了c++标准库,发现可以使用vector.erase(std::remove_if())的方法直接剔除.\ 统计二值图像的连通区域通过cv::findcontours()实现,二值图像轮廓的容器是std::vector.连通区域的面积可以由函数cv::contourArea()得到. 剔除小面积连通区域后,可以使用函数cv::drawContours()函数将轮廓画出,将其第三个参数设置为-1为

OpenCV二值图求最大连通区域算法(广度优先算法 BFS)

#include <iostream> #include <opencv2\opencv.hpp> #include <vector> #include <opencv2/core.hpp> #include <opencv2/highgui.hpp> #include <windows.h> #include <math.h> #include <queue> using namespace std;usin

【转】matlab函数_连通区域

转载自einyboy的博文Matlab的regionprops详解 1. matlab函数bwareaopen──删除小面积对象格式:BW2 = bwareaopen(BW,P,conn)作用:删除二值图像BW中面积小于P的对象,默认情况下使用8邻域.算法:(1)Determine the connected components.  L = bwlabeln(BW, conn);(2)Compute the area of each component.  S = regionprops(L,