我有一个卫星图像,我想得到所有的绿地区域。 在实践中,我需要从bmp加载图像,选择一种颜色和公差,并获得许多作为照片中绿色区域的多边形。 我怎么能在C#中做到这一点? (我需要这个用于飞行模拟)
答案 0 :(得分:1)
嗯,第一步是弄清楚给定的像素是否在该区域内。我觉得这很简单。然后,您可以创建“开启”或“关闭”的像素区域。
然后你需要将像素转换为多边形。如何做到这一点取决于您需要的粒度。如果您想要高精度,可以使用Marching Squares来获取您所在地区的多边形。如果您需要简单的多边形,则需要更高级的方法来跟踪边界。
答案 1 :(得分:1)
使用LockBits并迭代每个字节(取决于像素格式 - 索引图像使用调色板,因此您需要首先查询它以获得在您的容差范围内的调色板索引 - 对于非索引(和非1bpp / 16ppgreyscale)您可以直接访问颜色通道 - 请参阅GDI FAQ获取帮助。 您范围内的每个彩色像素都可以直接写入另一个图像(即只有您想要的像素 - 其余部分填充不可见的像素 - Alpha 0) - 或者写入集合中。我个人会先做前者。这非常快(如果你使用LockBits)。然后是使用像素行走算法的边缘检测来计算“碎片”(如果你喜欢的不规则多边形)。 AForge图书馆可能会帮到你。
答案 2 :(得分:0)
嗯。听起来像是一个“魔杖”算法(来自PhotoShop / PSP中具有该名称的控件,允许您单击一个像素来选择特定颜色阈值内的所有相邻像素)。
因此,第一步是选择位于标识为“绿色”的位图上的像素,该像素应该是多边形的一部分。然后,您可以从该点递归地向左,向右,向上和向下移动,并测试该点处的像素是否在您从原始像素的颜色设置的阈值限制内。如果集合在阈值范围内并且尚未在集合中,则将该点添加到集合中,并继续遍历;如果该点不是“足够绿”,或已经被映射,则返回。有一些方法可以通过限制后续递归调用可以遍历的方向来限制“回溯”。例如,假设我们打了四个电话,上下,左右移动。从“原点”向左移动的呼叫可以从该点开始进一步呼叫向左或向上移动。
现在你有一组像素,大致对应一组几何点。然后,您必须确定定义多边形边界的这些点的子集。这被称为计算这些点的“凸包”,维基百科有许多算法可以在C#中实现:http://en.wikipedia.org/wiki/Convex_hull_algorithms。
最容易理解的可能是Graham Scan:将所有点排列在列表中,从第一个点开始(A),在第二个点(B)画一条线,然后确定是否有一条线从B到第三点(C)将构成从A到B的方向的“左转”或“右转”。如果它是“左转”,则通过从B到C绘制线来转弯,然后像以前一样将该行与从C到D的行进行比较。如果它是“右转”,则忘记B作为凸包的可能顶点,从A到C绘制,然后检查C到D的线是否是左转。每当你看到“右转”时,忽略定义线条的三个点的当前“中间点”,而是在另外两个点之间追踪一条线。继续,从最后一个点回到A列表,直到这些点定义一系列所有从最后一行的方向“向左转”的行。这是一组点的“凸包”,它可以在NlogN时间内的任何点列表上完成。
明白“凸壳”就是这样;你永远不会得到凹形(如星星)。如果这很重要,你需要调整算法以允许一些“右转”,但不允许任何线段交叉。