Matlab里的种子填充法bwlabel函数C++实现

Matlab里的种子填充法bwlabel函数C++实现

种子填充法原理

关于种子填充法的详细原理可以参考OpenCV_连通区域分析(Connected Component Analysis/Labeling)

大致算法如下:
设二值化图像A中,像素值为255的点是前景,为0的点是背景。A(x, y)为坐标(x, y)处的像素值,遍历图像的每个像素:
1、 如果像素值不等于255,则继续访问下一个元素。
2、 如果像素值为A(x, y) = 255,则新建一个新的label,当前值A(x, y) = label,并且
a. 检查其4个邻域,如果有属于前景的像素也给它赋予label值,并将它的坐标压栈。
b. 弹出栈顶坐标,重复a的过程,知道堆栈为空。
此时,便找到了一个连通区域,该区域内的像素值被标记为label。
3、 重复1、2的过程,检测出所有的区域。

在这里插入图片描述
代码实现

//返回种子填充区域的面积大小
int bwLabel(Mat & src, Mat & dst, vector<Feather> & featherList)
{

	int labelValue = 0;
	Point seed, neighbor;
	stack<Point> pointStack;    // 堆栈

	int area = 0;               // 用于计算连通域的面积
	int leftBoundary = 0;       // 连通域的左边界,即外接最小矩形的左边框,横坐标值,依此类推
	int rightBoundary = 0;
	int topBoundary = 0;
	int bottomBoundary = 0;
	Rect box;                   // 外接矩形框
	Rect box2;                //标签矩形框
	Feather feather;

	featherList.clear();    // 清除数组

	dst.release();
	dst = src.clone();

	int rows = dst.rows;
	int cols = dst.cols;
	//cvtColor(dst, dst , CV_GRAY2BGR);

	for (int j = 0; j < cols; j++)
	{
		//uchar *pRow = dst.ptr<uchar>(j);
		for (int i = 0; i < rows; i++)
		{
			if (dst.at<uchar>(i, j) == 255)
			{
				area = 0;
				labelValue++;           // labelValue最大为254,最小为1.
				seed = Point(j, i);     // Point(横坐标,纵坐标)
				dst.at<uchar>(seed) = labelValue;
				pointStack.push(seed);

				area++;
				leftBoundary = seed.x;
				rightBoundary = seed.x;
				topBoundary = seed.y;
				bottomBoundary = seed.y;

				while (!pointStack.empty())
				{
					neighbor = Point(seed.x + 1, seed.y);
					if ((seed.x != (cols - 1)) && (dst.at<uchar>(neighbor) == 255))
					{
						dst.at<uchar>(neighbor) = labelValue;
						pointStack.push(neighbor);

						area++;
						if (rightBoundary < neighbor.x)
							rightBoundary = neighbor.x;
					}

					neighbor = Point(seed.x, seed.y + 1);
					if ((seed.y != (rows - 1)) && (dst.at<uchar>(neighbor) == 255))
					{
						dst.at<uchar>(neighbor) = labelValue;
						pointStack.push(neighbor);

						area++;
						if (bottomBoundary < neighbor.y)
							bottomBoundary = neighbor.y;

					}

					neighbor = Point(seed.x - 1, seed.y);
					if ((seed.x != 0) && (dst.at<uchar>(neighbor) == 255))
					{
						dst.at<uchar>(neighbor) = labelValue;
						pointStack.push(neighbor);

						area++;
						if (leftBoundary > neighbor.x)
							leftBoundary = neighbor.x;
					}

					neighbor = Point(seed.x, seed.y - 1);
					if ((seed.y != 0) && (dst.at<uchar>(neighbor) == 255))
					{
						dst.at<uchar>(neighbor) = labelValue;
						pointStack.push(neighbor);

						area++;
						if (topBoundary > neighbor.y)
							topBoundary = neighbor.y;
					}

					seed = pointStack.top();
					pointStack.pop();
				}

				//int 转换为String
				std::string s = std::to_string(labelValue);

				box = Rect(leftBoundary, topBoundary, rightBoundary - leftBoundary, bottomBoundary - topBoundary);
				rectangle(dst, box, Scalar(0, 255, 0), 2);
				box2 = Rect(leftBoundary, topBoundary - 40, 40, 40);
				rectangle(dst, box2, Scalar(0, 255, 0), -1);
				putText(dst, s, Point(leftBoundary + 5, topBoundary - 10), FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 0, 0), 4, 8);
				Mat ROI_img = src(Rect(leftBoundary, topBoundary, rightBoundary - leftBoundary, bottomBoundary - topBoundary));
				int roi_width = rightBoundary - leftBoundary;
				int roi_height = bottomBoundary - topBoundary;
				Point roi_point = Point(leftBoundary, topBoundary);

				feather.area = area;
				feather.boundingbox = box;
				feather.labelbox = box2;
				feather.label = labelValue;
				feather.num = s;
				feather.textpoint = Point(leftBoundary + 5, topBoundary - 10);
				feather.ROI = ROI_img;
				//feather.ROIwidth = roi_width;
				//feather.ROIheight = roi_height;
				//feather.ROIpoint = roi_point;
				featherList.push_back(feather);`在这里插入代码片`

				//ROI.push_back(ROI_img);
				ROIwidth.push_back(roi_width);
				ROIheight.push_back(roi_height);
				ROIpoint.push_back(roi_point);
				count_num = labelValue;
			}
		}
	}
	return labelValue;
}

//彩色显示
Scalar GetRandomColor()
{
	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 Scalar(b, g, r);
}
void main()
{
Mat srcL = imread("preprocess_image/Redraw_imgL.bmp", 0);
	vector<Feather> featherListL;                    // 存放连通域特征
	Mat dstL;
    bwLabel(srcL, dstL, featherListL) ;

	Mat label_imgL;
	cvtColor(dstL, label_imgL, CV_GRAY2BGR);
	// 为了方便观察,可以将label“放大”
	for (int i = 0; i < dstL.rows; i++)
	{
		//uchar *p = dst.ptr<uchar>(i);
		for (int j = 0; j < dstL.cols; j++)
		{
			//p[j] = 30 * p[j];
			if (dstL.at<uchar>(i, j) > 0)
			{
				label_imgL.at<Vec3b>(i, j)[0] = (label_imgL.at<Vec3b>(i, j)[0] + 10) * 15;
				label_imgL.at<Vec3b>(i, j)[1] = (label_imgL.at<Vec3b>(i, j)[1] + 2) * 15;
				label_imgL.at<Vec3b>(i, j)[2] = (label_imgL.at<Vec3b>(i, j)[2] + 10) * 15;
			}
		}
	}

	for (vector<Feather>::iterator it = featherListL.begin(); it < featherListL.end(); it++)
	{
		//cout << it->label << "\t" << it->area << endl;
		rectangle(label_imgL, it->boundingbox, Scalar(0, 255, 0), 2);
		rectangle(label_imgL, it->labelbox, Scalar(0, 255, 0), -1);
		putText(label_imgL, it->num, it->textpoint, FONT_HERSHEY_SIMPLEX, 0.8, Scalar(0, 0, 0), 4, 8);
	}
}

原图片在这里插入图片描述
标记后图片在这里插入图片描述
不懂的问题欢迎交流!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MATLAB中的bwlabel函数用于将二值图像中的连通区域标记为不同的整数值。该函数的语如下: [L, num] = bwlabel(BW, n) 其中,BW是二值图像,n是可选参数,表示连接方式。默认情况下,n为8,表示8连通。如果n为4,则表示4连通。 函数的输出包括: L:标记后的图像,每个连通区域的像素值都被标记为不同的整数值。 num:连通区域的数量。 例如,下面的代码将对一个二值图像进行标记,并输出标记后的图像和连通区域的数量: BW = imread('binary_image.png'); [L, num] = bwlabel(BW); imshow(L); disp(num); 该函数在图像处理中常用于分割图像中的不同区域,或者提取图像中的特定目标。 ### 回答2: Matlabbwlabel函数是一个二值图像处理函数,主要用于获取二进制图像中像素连通区域的标签。该函数可以将二值图像分割为不同的连通区域,每个连通区域都赋予唯一的标签,标签的值从1开始,依次递增。bwlabel函数的完整语格式如下: [L, num] = bwlabel(BW, N) 其中,BW表示二值图像矩阵,N表示像素连通时采用的连接模式,取值范围为4或8。L是一个与BW大小相同的矩阵,存储每个像素的标签,num表示图像中像素连通区域的数量。 bwlabel函数实现原理是遍历图像中的每个像素,并将像素与其周围的相邻像素进行比较,根据像素值的变化将属于同一连通区域的像素进行标记。标记的方式可以采用广度优先搜索或深度优先搜索。 使用bwlabel函数时,需要注意以下几点: 1.输入图像必须是二值图像,即像素值只有0或1,如果是灰度图像需要先进行二值化处理; 2.连接模式的选择必须与图像的实际情况相符,通常情况下采用8连通模式进行像素连接; 3.bwlabel函数返回的标签矩阵L是整数类型,每个像素的值对应于其所属连通区域的标签值; 4.如果图像中存在孤立的像素(即像素值为1但未与其他像素相连通),则会将其单独标记为一个连通区域,标签值为2; 总之,Matlabbwlabel函数在图像分割、目标检测、物体识别等领域有着广泛的应用,可以方便地进行像素连通区域的标记和计数。在使用bwlabel函数时,需要灵活选择连接模式,避免因不正确的连接模式导致分割结果错误。 ### 回答3: MATLABbwlabel函数主要用于二进制图像中像素连通分量的标记,即将一张二值图像中的每个连通区域用不同的数码进行标记,相同的数码表示同属于一个连通分量。 该函数的语格式为: [L, num] = bwlabel(BW, n) 其中,BW表示要进行标记的二值图像,n是可选的操作参数,表示要识别的相邻像素的连接性,n可以取值为4或8。L是输出矩阵,它与输入图像大小相同,每个像素与相应地标记连接。num表示二值图像中连通分量的数量。 该函数实现步骤如下: 1. 对于输入的二值图像BW,设定标记值count为0,创建一个标记矩阵L,其大小与BW相同。 2. 对于BW中的每个像素点,如果其值为1且其未被标记,则将其视为该连通分量的起始像素,将count+1,并以该count值对该连通分量进行标记。 3. 对于起始像素,使用递归方式进行像素的四向或八向查找,将相邻的像素标记为相同的标记值。在标记完该连通分量后,返回到上一个起始像素,进行下一个连通分量的标记。 4. 返回标记矩阵L和连通分量数量num。 bwlabel函数的使用可以帮助我们进行目标识别、形态分析等操作,是图像处理中非常常用的函数之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值