在图像分割领域中,区域生长是一个很有用的算法,它往往可以从局部区域中逐渐分将图像分割成具有不同相似性的几部分。区域生长算法的关键部分在于种子点的选取和相似性准则的判定,这直接影响到图像分割效果,种子点可以通过人工方法(前景或背景)选取,也可以通过图像预处理算法自动获取。
实现区域生长算法过程如下(以灰度图为例,判定准则为相邻像素间灰度差):
1.种子点获取。
2.种子点入栈,考虑种子点周围八领域灰度值,若邻域像素满足生长条件,则该点入栈。
3.获取栈顶元素,考虑其邻域像素,若满足则入栈,不满则舍弃,重复该过程直至栈为空。
4.获取下一个种子点,重复2,3直到所有种子点已全部完成生长,程序结束。
class ImageGrow //区域生长类
{
public:
cv::Mat Image; //原图像
cv::Mat Image_Grow; //标记图像
std::vector seed; //待生长种子点
std::vector region_grow_point; //生长后像素点集
public:
void Region_Grow(int); //生长算法
void Show_Image(); //显示生长后图像
};
void ImageGrow::Region_Grow(int thre)
{
cv::Mat flagmat=cv::Mat::zeros(Image.size(),CV_8U); //用于标记区域生长情况
std::stack pointstack; //用于存放像素点的栈
std::vector direction(8); //8邻域编码,用于遍历生长点周围像素
direction[0]=cv::Point2i(-1,-1);
direction[1]=cv::Point2i(-1,0);
direction[2]=cv::Point2i(-1,1);
direction[3]=cv::Point2i(0,-1);
direction[4]=cv::Point2i(0,1);
direction[5]=cv::Point2i(1,-1);
direction[6]=cv::Point2i(1,0);
direction[7]=cv::Point2i(1,1);
cv::Point2i src,test_src;
int src_value;
for(int i=0;i(src.y,src.x)=255;
src_value=Image.at(src.y,src.x);
while(!pointstack.empty()) //栈非空则一直执行生长算法
{
src=pointstack.top(); //提取栈顶像素点
region_grow_point.push_back(src);
pointstack.pop();
for(int j=0;j(Image.cols-1) || test_src.y>(Image.rows-1))
continue;
//检查像素点是否越界
if(!flagmat.at(test_src.y,test_src.x))//若该像素点之前没有被标记过则对该像素点进行判别
{
int cur_value=Image.at(test_src.y,test_src.x);
if(abs(src_value-cur_value)(test_src.y,test_src.x)=255;
pointstack.push(test_src);
}
}
}
}
}
Image_Grow=flagmat.clone();
}
void ImageGrow::Show_Image() //显示图像
{
cv::Mat Image_Color(Image.size(),CV_8UC3,cv::Scalar(0,0,0));//创建三通道图像
std::vector channels;
cv::split(Image_Color,channels);
channels[0]=Image.clone();
channels[1]=Image.clone();
channels[2]=Image.clone();
cv::RNG rng;
int a=rng.uniform(0,255),b=rng.uniform(0,255),c=rng.uniform(0,255); //获取随机数,用于显示生长区域
for(int i=0;i(region_grow_point[i].y,region_grow_point[i].x)=a;
channels[1].at(region_grow_point[i].y,region_grow_point[i].x)=b;
channels[2].at(region_grow_point[i].y,region_grow_point[i].x)=c;
}
cv::merge(channels,Image_Color);
cv::namedWindow("Image2",CV_WINDOW_NORMAL);
cv::imshow("Image2",Image_Color);
cv::imwrite("the grow Image.jpg",Image_Color);
}
int main()
{
ImageGrow Test; //创建区域生长类对象
Test.Image=cv::imread("F:/biaoding.jpg",0); //以灰度图方式读取图像
Test.seed.push_back(cv::Point2i(600,500));//设置生长点,这边采用手动标记方式
Test.Region_Grow(100); //区域生长,设置生长阈值,可根据实际情况设定
cv::namedWindow("Image1",CV_WINDOW_NORMAL);
cv::imshow("Image1",Test.Image);
Test.Show_Image(); //显示图像
cv::imwrite("the origion Image.jpg",Test.Image);
cv::waitKey(-1);
return 0;
}
最后,上测试图
原图:
生长图(种子点选在标定板矩形框空白处)