【发布时间】:2014-02-16 23:07:39
【问题描述】:
所以我一直在尝试编写一个连通分量标记算法,但它并没有给我想要的结果。现在我有一张带有 3 朵玫瑰(不重叠)的图像,我想用自己的灰度值标记每朵玫瑰。在我应用标记算法之前,我使用一个阈值来去除背景,只保留玫瑰。玫瑰的灰度值为 1(全白),背景的灰度值为 0(黑色)。这是它的样子:
完成此操作后,我应用了标记算法。它应该根据给玫瑰的标签给玫瑰三个不同的灰度值。但相反,该算法在前两朵玫瑰上创建了这种奇怪的渐变图案,而最后一朵似乎是单个灰度值。这是一张图片:
该算法可能看起来很复杂,但实际上非常简单。我首先在列上递归,然后在行上递归,对于每个非背景像素,我检查是否有任何相邻像素已被标记(意味着它们的 objectArray 值不为零)。如果是这样,我将它们添加到邻居列表中。然后我继续检查这个列表是否不为空,如果是,我通过递增对象值并将其值分配给当前像素的标签值来唯一地标记当前像素,并且我还将当前像素的父值设置为这个唯一的标签。如果不为空,则确定邻居列表中的最小标签值,将所有邻居的父值设置为该标签值,并将当前像素的标签和父值设置为该标签值。我对每个像素重复此操作,直到整个图像都被标记。
完成后,我再次递归像素值,这次将每个像素的标签值设置为其父值。然后我继续根据其标签值为像素分配一个新的灰度值。
我不明白为什么算法没有正确标记玫瑰。有人可以帮帮我吗?算法如下:
public void label()
{
int objects = 1;
int[,] objectArray = new int[colors.GetLength(1), colors.GetLength(0)];
DisjointSets disjointSet = new DisjointSets();
int[,] parents = new int[colors.GetLength(1), colors.GetLength(0)];
List<List<int>> eqSet = new List<List<int>>();
for (int i = 0; i < colors.GetLength(1); i++) for (int j = 0; j < colors.GetLength(0); j++)
{
if (this[i, j].Gray == 1)
{
List<Label> neighbors = new List<Label>();
if (i > 0)
{
if (this[i - 1, j].Gray == 1)
{
if (objectArray[i - 1, j] != 0)
{
neighbors.Add(new Label(i - 1, j, 0));
}
}
if (j > 0)
{
if (this[i - 1, j - 1].Gray == 1)
{
if (objectArray[i - 1, j - 1] != 0)
{
neighbors.Add(new Label(i - 1, j - 1, 0));
}
}
}
if (j < colors.GetLength(0))
{
if (this[i - 1, j + 1].Gray == 1)
{
if (objectArray[i - 1, j] != 0)
{
neighbors.Add(new Label(i - 1, j, 0));
}
}
}
}
if (j > 0)
{
if (this[i, j - 1].Gray == 1)
{
if (objectArray[i, j - 1] != 0)
{
neighbors.Add(new Label(i, j - 1, 0));
}
}
if (i < colors.GetLength(1))
{
if (this[i + 1, j - 1].Gray == 1)
{
if (objectArray[i + 1, j - 1] != 0)
{
neighbors.Add(new Label(i + 1, j - 1, 0));
}
}
}
}
if (i < colors.GetLength(1))
{
if (this[i + 1, j].Gray == 1)
{
if (objectArray[i + 1, j] != 0)
{
neighbors.Add(new Label(i + 1, j, 0));
}
}
if (this[i + 1, j + 1].Gray == 1)
{
if (objectArray[i + 1, j + 1] != 0)
{
neighbors.Add(new Label(i + 1, j + 1, 0));
}
}
}
if (j < colors.GetLength(0))
{
if (this[i, j + 1].Gray == 1)
{
if (objectArray[i, j + 1] != 0)
{
neighbors.Add(new Label(i, j + 1, 0));
}
}
}
if (neighbors.Count == 0)
{
objects++;
objectArray[i, j] = objects;
parents[i, j] = objects;
}
if (neighbors.Count > 0)
{
int smallestLabel = 10000;
foreach (Label x in neighbors)
if (objectArray[x.X, x.Y] < smallestLabel)
smallestLabel = objectArray[x.X, x.Y];
foreach (Label x in neighbors)
parents[x.X, x.Y] = smallestLabel;
objectArray[i, j] = smallestLabel;
parents[i, j] = smallestLabel;
}
}
}
for (int i = 0; i < colors.GetLength(1); i++) for (int j = 0; j < colors.GetLength(0); j++)
{
if (this[i, j].Gray == 1)
{
if (objectArray[i, j] != 0)
{
objectArray[i, j] = parents[i, j];
ColorWrap c = this[i, j];
c.X = (float)objectArray[i, j] / objects;
c.Y = (float)objectArray[i, j] / objects;
c.Z = (float)objectArray[i, j] / objects;
this[i, j] = c;
}
}
}
}
【问题讨论】:
-
简单地为构成对象的每个像素设置一个 int 值,我用它来为这些对象赋予特定的灰度值。算法应该检查图像的连接像素,并给它找到的每个“对象”(连接像素的“组”,应该是每一朵玫瑰)一个标签值(例如,构成左上角玫瑰的像素将获得标签值 1,左下角的玫瑰像素将分别获得标签值 2,组成右玫瑰的像素将分别获得标签值 3)。我使用这些标签值给这些像素一个新的灰度值 (c.X = (float)objectArray[i, j] / objects; etc)
-
@user1683526 这是二值图像还是灰度图像?
-
这是一个彩色图像,在我对其进行其余操作之前将其转换为灰度。我可能应该更清楚这一点。
标签: c# algorithm components