区域增长算法及其实现
背景
我们已经介绍过了
最大熵分割
OTSU算法
他们都有自己的优点和缺点。通常,这些算法不是单独使用的,而是需要与其他算法结合使用。前两类算法都是独立处理图像的灰度信息,不包含图像的空间信息,区域在增长。该算法包含图像的空间信息。
优势:
更灵活。您可以根据项目的需要灵活选择所需的增长规则。分割效果较好,通常可以较好地分割种子点周围的区域。
缺点:
待分割区域不连通,分割成小的封闭区域时,会导致种子点附近只有一小块区域,分割不理想,区域增长算法容易受噪声等影响。该算法为迭代算法,算法时间开销较大。
算法原理:
步:
1、在图像中选取一个种子点(x,y)
2、根据生长规则,判断种子点周围8个点哪几个点可以作为下次生长的点,判断完后,将当前的种子标记为已使用。
3、判断下一生长点
4、直到不再有生长点。
增长规则是如何制定的?大致有以下判断规则:灰度、梯度幅度等。例如判断种子点与下一个生长点的灰度差如何小于某个值,将其添加到种子点。
算法流程:
1、将初始种子点存入vector
2、弹出1个种子点,根据生长规则判断周围8个点哪个符合规则,符合则加入到vector中
3、判断vector的size是不是为0,为0则结束,不为0则继续第二步
Opencv实现:
void Region_Growing(Mat input, Mat& output, Point2i fristseed, int value)
{
vector<Point2i>allseed; //保存种子
allseed.push_back(fristseed); //压入第一个种子
int direction[8][2] = { { -1, -1 }, { 0, -1 }, { 1, -1 }, { 1, 0 }, { 1, 1 }, { 0, 1 }, { -1, 1 }, { -1, 0 } };//种子选取的顺序
output = Mat::zeros(input.size(), CV_8UC1); //创建一个黑图
output.at<uchar>(fristseed.y, fristseed.x) = 255; //第一个种子点设置为
int cerseedvalue = 0; //初始种子点的值
int nextseedvalue = 0; //与种子点相比较的下一点的值
Point2i comparseed; //与种子点相比较的下一点
cerseedvalue = input.at<uchar>(fristseed.y, fristseed.x); // 种子点的灰度值
while (!allseed.empty())
{
fristseed = allseed.back(); //最后一个种子点的
allseed.pop_back(); //弹出最后一个种子点
for (int i = 0; i < 8; ++i)
{
comparseed.x = direction[i][0] + fristseed.x;
comparseed.y = direction[i][1] + fristseed.y;
if (comparseed.x<0 || comparseed.x>(input.cols-1) || comparseed.y<0 || comparseed.y>(input.rows-1))
continue;
if (output.at<uchar>(comparseed.y, comparseed.x) == 0) //判断有没有被使用过
{
nextseedvalue = input.at<uchar>(comparseed.y, comparseed.x); //生长点的值
if (abs(nextseedvalue - cerseedvalue) < value)//生长规则
{
allseed.push_back(comparseed);
output.at<uchar>(comparseed.y, comparseed.x) =255;
}
}
}
}
}
米粒
| 米粒分割图 |
版权声明:本文为博主浮生有梦三千原创文章,版权归属原作者,如果侵权,请联系我们删除!
原文链接:https://blog.csdn.net/qq_44733143/article/details/123037034