本文已参与「新人创作礼」活动,一起开启掘金创作之路。
区域生长法是一种图像分割的常用算法,能够将目标区域精确得分割出来。我的程序是将图像最中央的白色圆形区域提取出来,因此第一个种子点选择在了图像中央。
待处理图片(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;
}