我有一张图片,这是其中的一小部分:
如您所见,这是黑色背景上的白色像素。我们可以在这些像素(或更确切地说,点)之间画出想象中的线条。通过这些线条,我们可以将区域围起来。
我该如何找到这张图片中不包含白色像素的最大凸多边形黑色区域呢?
下面是我手绘的一个示例,它展示了最大凸黑色区域的意思:
P.S.:这张图片不是噪声,它表示小于10000000的质数按水平顺序排列。
我有一张图片,这是其中的一小部分:
如您所见,这是黑色背景上的白色像素。我们可以在这些像素(或更确切地说,点)之间画出想象中的线条。通过这些线条,我们可以将区域围起来。
我该如何找到这张图片中不包含白色像素的最大凸多边形黑色区域呢?
下面是我手绘的一个示例,它展示了最大凸黑色区域的意思:
P.S.:这张图片不是噪声,它表示小于10000000的质数按水平顺序排列。
试图找到最大凸面积是一个困难的任务。你是否只想找到最大面积的矩形?这个问题容易解决,可以在O(n) - 像素数的线性时间内解决。该算法如下。
假设你要找到自由(白色)像素的最大矩形(抱歉,我的图片是不同颜色的 - 白色等同于黑色,灰色等同于白色)。
你可以通过两次遍历的线性O(n)
时间算法(其中n为像素数)来非常高效地完成这项工作:
1)在第一次遍历中,从底部到顶部按列遍历,对于每个像素,标记可用像素的数量:
重复操作,直到:
2)在第二次遍历中,逐行读取current_number
。对于每个数字k
,保持连续数字的总和>= k
(即高度为k
的潜在矩形)。关闭高度k > current_number
以上的总和(潜在矩形),并查看总和(矩形面积)是否大于当前最大值 - 如果是,则更新最大值。在每行末尾,关闭所有打开的潜在矩形(对于所有k
)。
这样你就可以得到所有的最大矩形了。当然,这不同于最大凸面积,但可能会给出一些提示(一些启发式)在哪里寻找最大凸面积。
您可以将像素视为顶点,并对点集执行Delaunay三角剖分。然后,您需要找到最大的一组连接三角形,这些三角形不会创建凹形状并且没有任何内部顶点。
如果我正确理解了你的问题,那么这是一个连通组件标记的实例。你可以从这个链接开始学习:http://en.wikipedia.org/wiki/Connected-component_labeling
我认为你可以把 b) 简化成 a) 的问题,然后只需要找到最有效的方法来确定一个点是否在三角形内。搜索空间的缩小可以通过以下方式实现:取一个三角形并将所有边延长至无限长度。这将使得三角形外部的区域分为 6 个子区域。对我们有利的是,只有其中的 3 个子区域可能包含符合凸性约束条件的点。因此,对于每个测试点,您需要确定它是否在凸扩展子区域中,而这又是一个关于它是否在某个三角形内的问题。
整个多边形随着演变趋近于圆形时,仍允许凸性扩展的区域将变得越来越小。曾经处于凹区域的点将不会再次成为凸性扩展区域的一部分,因此您可以快速减少需要考虑扩展的点的数量。此外,在测试扩展点时,您还可以进一步缩小可能考虑的点列表。如果一个点测试为 false,则它位于另一个点的凹区域内,因此该测试点凹区域内的所有其他点都不需要考虑,因为它们也位于内部点的凹区域内。您应该能够非常快速地缩小可能考虑的点列表。
当然,你还需要为每个空三角形执行此操作。
不幸的是,我不能保证通过始终添加最大新区域来使你的多边形变成可能的最大多边形。