区域生长算法
在进行图像分割的时候,我们往往会选择‘’颜色识别‘’,亦或者是‘’边缘识别’‘。然而它们都有个很大的缺陷,那就是不能保留细小的结构,而且容易受外界干扰,往往对阈值的选择苛刻,因此我们将介绍区域生长算法。这一算法可以有效规避这些问题。
先给出区域生长算法的基本框架:
void regionGrowing(Mat& image, Mat& segmented, int seedX, int seedY, int threshold)
{
// 初始化标记矩阵,用于记录已分割的像素
Mat result = Mat::zeros(image.size(), CV_8U);
// 生长队列,用于存储待生长的像素坐标
stack<Point> points;
points.push(Point(x, y));
// 区域生长
while (!points.empty())
{
Point current = points.top();
points.pop();
// 对当前像素的相邻像素进行生长判断
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
int X = current.x + i;
int Y = current.y + j;
// 检查像素是否在图像范围内
if (X >= 0 && X < image.cols && Y >= 0 && Y < image.rows)
{
// 检查像素是否符合生长条件
if (abs(image.at<uchar>(newY, newX) - image.at<uchar(currentPoint)) < threshold)
{
// 将符合条件的像素加入生长队列
points.push(Point(x, y));
}
}
}
}
}
}
解释一下它是如何运作的
区域生长算法会从种子点开始,检查种子点周围的像素,并根据一定的条件确定是否将这些像素加入到待处理的队列中。然后,算法会逐步处理队列中的像素点,继续探索周围的像素,并根据条件不断扩展区域范围,直到整个区域被完全探索并标记。
想象一下,这就像是种下一颗种子,然后它逐渐生长成完整的形状,这就是区域生长的形象表现。
其中先创建一个存储Point
类型元素的栈points
,用于存储待处理的像素点,
stack<Point> points;
然后利用
points.push(Point(x, y));
将x,y作为Point中第一个压入栈中的,根据‘’脱鞋定理‘’(bushi),这个点也因此成为第一个处理的点,也就是所谓的种子点。
前提布置好后,准备开始生长。至于如何生长,这就是需要
- 生长的条件
- 生长的点与种子点的关系
- 是否已生长完的检测
- 对生长点的操作
也就是我们之前给出的基本框架
1.Point current = points.top(); points.pop();
从栈中取出一个像素点作为当前处理点,并将其从栈中移除。也就是 用一,取一,去一。
2.result.at<uchar>(y, x) = 255; points.push(Point(x, y));
将当前像素标记为已访问,并将其加入栈中以便后续处理。at<uchar>
这是访问像素点的方法之一。当然对像素点的处理具体问题具体分析。
3while (!points.empty()){ }
用来判断是否生长完&保持生长
以上就是对区域生长的基本解释说明