如何用增加的半径填充圆?

Posted

技术标签:

【中文标题】如何用增加的半径填充圆?【英文标题】:How to fill circle with increasing radius? 【发布时间】:2011-07-17 06:13:30 【问题描述】:

作为更复杂算法的一部分,我需要以下内容:

假设我在离散网格上绘制了一个半径为 R1 的圆(图片)(下图中的绿色) 我想用一个像素绘制半径 R2 大于 R1 的圆(下图中为红色)。 在每个算法步骤中,以每次我有一个实心圆的方式绘制半径增加的圆。

如何在每个步骤中找到要填充的点,以便在每个步骤结束时我已完全归档圆圈?

我在考虑一些圆形光栅化算法,但这会导致填充时出现一些空白。另一种方法是使用一些数学形态学运算,例如膨胀,但这似乎计算成本很高。

我通常正在寻找在任意形状上执行此操作的方法,但最初的圆形算法就足够了。

【问题讨论】:

每一步的形状会隐藏之前的吗? 在每一步我都在寻找一组点(红色),这些点被添加以增加大约 1 个像素的半径。 【参考方案1】:

您最好的选择是绘制并填充一个稍大的红色圆圈,然后绘制并填充绿色圆圈。然后在下一次迭代中重做。

只绘制 1px 的边框是相当棘手的。您的示例图像甚至不是很一致。在某些地方,白色像素与绿色像素成对角线,而在其他地方,该像素为红色。

编辑:

borderPixels = emptySet 对于每个绿色像素,p 对于每个邻居 np 如果 n 是白色的 将 n 添加到 *borderPixels` 用 borderPixels 做任何你想做的事(比如把它们涂成红色)

【讨论】:

图像只是其外观的近似示例。我可以接受可以在某些点改变 1-2 个像素的算法,尤其是对于任意形状。然后,这条“前线”用于检查其他一些图形对象是否有交叉。 谢谢,这个算法是我的第一个解决方案,但是找到“对于每个邻居”基本上是一个 3x3 掩码和它的最大操作的膨胀。我在想存在一些计算成本较低的算法。 如果您要处理任意形状,我不相信。 可爱的算法。我想它可以稍微优化一下,这样您就不会扫描所有内部绿色像素,而只在边界像素上前进。您可能需要维护 2 套 innerBorder(绿色)、outerBorder(白色)。需要以某种方式初始化 innerBorder 以启动算法 @davka,不,如果形状有孔,则不会。 (@Ross 指出圆圈只是一个例子,他实际上是在处理任意形状)【参考方案2】:

我目前的圆形解决方案。

基于众所周知的Midpoint circle algorithm

为 R1 半径的 1 个八分圆创建点集(浅绿色像素) 为 R2 半径的 1 个八分圆创建一组点(深橙色像素) 对于图像中的每一行,比较橙色和绿色像素的 X 坐标,并获得 0 或 1(或其他)之间的像素数(浅橙色)。 对每个八分圆重复(对于某些八分圆,必须比较列而不是行)

此算法可应用于其他类型的参数形状(例如基于贝塞尔曲线)

对于非参数形状(基于像素)图像卷积(膨胀),具有中心对称(圆形)的内核。换句话说,对于形状中的每个像素,寻找具有小半径的圆形邻居并将它们设置为集合的一部分。 (昂贵的计算)

【讨论】:

享受平行贝塞尔曲线的乐趣!...估计我的方法计算成本更低,即使您必须消耗一些内存来创建缓冲区并将结果组合回来... 这也许是我不明白,但你的方式并没有降低计算成本。和我的方案类似,只是做了最后没有用到的操作。例如,不需要填充绿色部分。 “燃烧”内存不是选项。预期结果是像素列表,而不是必须再次处理才能找到它们的图像。【参考方案3】:

另一种选择是绘制一个带有 2 像素宽的红色边框的圆形/形状,然后绘制一个没有边框的绿色填充圆形/形状。这应该留下 大约 1px 宽的边缘。 这取决于您使用的任何技术如何将线条解析为像素。

圆算法倾向于针对画圆进行优化.....See the link here

【讨论】:

以上是关于如何用增加的半径填充圆?的主要内容,如果未能解决你的问题,请参考以下文章

如何用C语言计算圆的周长和面积

如何用java计算一个圆的面积和周长?

如何用背景颜色填充可见页面的其余部分?

具有边框半径的填充与我的图像重叠

用核心图形画一个羽化圆

如何用C语言计算圆的周长和面积