区域生长法的C++实现(opencv)

141 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

区域生长法是一种图像分割的常用算法,能够将目标区域精确得分割出来。我的程序是将图像最中央的白色圆形区域提取出来,因此第一个种子点选择在了图像中央。

待处理图片(test.png):

待处理的图像

区域生长图片(growArea.png):

处理结果

code:

#include <opencv2\opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;


Mat AreaGrow(Mat mat)
{
	//mat为输入图像
	//定义第一个种子点位置为图片最中心处
	//注:opencv里面图像的x坐标是列数,y坐标是行数

	int firstSeed_x = round(mat.cols / 2);    //四舍五入取整,防止坐标为小数
	int firstSeed_y = round(mat.rows / 2);
	Point firstSeed = Point(firstSeed_x, firstSeed_y);

	Mat growArea = Mat::zeros(mat.size(), CV_8UC1);    //生长区域
	 //为第一个生长点赋值
	growArea.at<uchar>(Point(firstSeed.x, firstSeed.y)) = mat.at<uchar>(Point(firstSeed.x, firstSeed.y));  
	Point waitSeed;    //待生长种子点
	int waitSeed_value = 0;    //待生长种子点像素值
	int opp_waitSeed_value = 0;   //mat_thresh中对应待生长种子点处的像素值
	vector<Point> seedVector;     //种子栈
	seedVector.push_back(firstSeed);    //将种子放入栈中最后一个位置
	int direct[4][2] = { {0,-1},{1,0}, {0,1}, {-1,0} };   //4邻域,应该用4邻域减小时间复杂度
	//int direct[8][2] = { {-1,-1}, {0,-1}, {1,-1}, {1,0}, {1,1}, {0,1}, {-1,1}, {-1,0} };  //8邻域

	while (!seedVector.empty())     //种子栈不为空则生长,即遍历栈中所有元素后停止生长
	{
		Point seed = seedVector.back();     //取出最后一个元素
		seedVector.pop_back();         //删除栈中最后一个元素,防止重复扫描
		for (int i = 0; i < 4; i++)    //遍历种子点的4邻域
		{
			waitSeed.x = seed.x + direct[i][0];    //第i个坐标0行,即x坐标值
			waitSeed.y = seed.y + direct[i][1];    //第i个坐标1行,即y坐标值

			//检查是否是边缘点
			if (waitSeed.x < 0 || waitSeed.y < 0 ||
				waitSeed.x >(mat.cols - 1) || (waitSeed.y > mat.rows - 1))
				continue;

			waitSeed_value = growArea.at<uchar>(Point(waitSeed.x, waitSeed.y));   //为待生长种子点赋对应位置的像素值
			opp_waitSeed_value = mat.at<uchar>(Point(waitSeed.x, waitSeed.y));
			if (waitSeed_value == 0)     //判断waitSeed是否已经被生长,避免重复生长造成死循环
			{
				if (opp_waitSeed_value != 0)     //区域生长条件
				{
					growArea.at<uchar>(Point(waitSeed.x, waitSeed.y)) = mat.at<uchar>(Point(waitSeed.x, waitSeed.y));
					seedVector.push_back(waitSeed);    //将满足生长条件的待生长种子点放入种子栈中
				}
			}
		}
	}
	return growArea;
}


int main()
{
	Mat img = imread("test.png",0);
	if (img.empty())
	{
		cout << "请确认img图像文件是否正确" << endl;
		return -1;
	}

	Mat growArea = AreaGrow(img);
	imshow("growArea", growArea);
	waitKey();
	destroyAllWindows;
	imwrite("growArea.png", growArea);

	return 0;
}