14

我正在尝试研究一种将一个“形状”变形为另一个“形状”的算法。两种形状都是任意的,甚至可能有更小、不连贯的形状。

到目前为止,我的基本想法如下:定位形状的边缘,沿着这些边缘放置点,然后对目标图像执行相同的操作,然后将点移动到它们的目标。

这是一个插图:

变形

我只是不知道从哪里开始。上图是简化图,实际用例具有更复杂的形状/轮廓。我的主要问题是:如何处理不相交的形状?我能想到的最好的办法是找出两部分之间的最近点,并将它们连接在一起作为路径的一部分。但是我将如何实现呢?

我还没有任何代码,我仍处于计划阶段。我想我要问的是是否有人可以将我链接到任何可能有帮助的资源,或提供任何指示。搜索谷歌已经产生了一些有趣的变形算法,但它们都处理完整的图像,并涉及将图像分解成碎片以重塑它们,这不是我想要的。

请注意,这将在 JavaScript 中使用,但如果更容易,也可以在 PHP 中预先计算。

4

4 回答 4

5

我在 JavaScript 中找到了一个关于轮廓变形和补间动画的演示(使用 Raphael.js),展示了如何使用 Raphael.js 将一条曲线变形为另一条曲线。

此外,这个相关的问题(关于 JavaScript 中的形状补间)可能包含一些与这个问题相关的答案。

MorpherJS也可能适用于此目的。可以在这里找到一些使用 MorpherJS 进行轮廓变形的演示。

于 2013-03-25T19:58:42.100 回答
5

最好将问题分解为多个可以独立解决的较小问题。这样你在解决这个问题后也拥有独立的功能,可以添加到一些全局模块集合中。

首先我们需要弄清楚from_shape中的哪个像素去to_shape中的哪个像素。
我们可以通过以下方法来解决这个问题:

  1. 将 to_shape 放在 from_shape 上。

  2. 对于 from_shape 中的每个像素,找到它最接近的 to_shape 像素。
    形状中的每个像素都必须有一个唯一的 id,例如,该 id 可以是它的 xy 位置。

  3. 现在您可以记录 from_shape 中的每个唯一像素,以及它进入 to_shape 中的哪个唯一像素。

  4. 删除重叠的形状并回到原来的形状,
    刚才from_shape中的每个像素都知道它在to_shape中的目的地。

我们还需要知道每个像素有哪些“兄弟姐妹”。
同级是紧邻另一个像素的像素。
要找到它,请转到给定像素,从中收集半径为 1 的所有像素,所有这些像素都是黑色的......是来自像素的兄弟姐妹。当像素移动到目的地时,此信息对于将形状保持为单个单元是必要的。跳过兄弟姐妹会大大加快和简化变形,但如果没有它们,形状可能会在变形过程中变得支离破碎。可能想从无兄弟版本开始,看看情况如何。

最后我们实现变形:

  1. 有 morph_time_duration。
    对于 from_shape 中的每个像素,在 to_shape 中找到到其目的地的距离。
    该距离除以 morph_time_duration 就是变形期间像素的速度。
    此外,朝向目的地的角度是旅行的角度。
    所以现在你有了速度和角度。

  2. 因此,在变形过程中的每一帧,给定的 from_pixel 现在都知道行进的方向、速度,并且还知道它的兄弟姐妹。因此,在每一帧中,在以它的速度向它的方向移动之后,只需在它的新位置绘制像素。然后为所有像素兄弟画一条线。

这将显示你的变形。

于 2013-03-29T06:10:56.000 回答
2

这样做不会很容易,但我可以给你几个起点。如果你想要一个简单的 javascript 实现,一个很好的起点是: http ://raphaeljs.com/animation.html ,它正在做你想要的。因此,您可以检查调用了哪些方法并通过库源浏览这些方法以查看实现。

如果您需要在 PHP 中变形 2 个图像,我建议您使用某种扩展,而不是在普通 PHP 中这样做。这是一个使用 ImageMagick 的示例: http ://www.fmwconcepts.com/imagemagick/shapemorph2/index.php

如果您想了解更多关于它的内部结构: http ://web.mit.edu/manoli/www/ecimorph/ecimorph.html#algo

希望其中之一有所帮助。

于 2013-03-25T04:40:22.747 回答
1

简短的回答,如果你想自己动手,这不是一项简单的任务。有很多关于这些主题的数学可以执行这些转换(显然,你发现的最常见的处理最常见的形状),但这可能对你来说也可能不是,而且它不会那么容易弄清楚如何进行非标准转换。

如果您只是在寻找一种合乎逻辑的方法,这就是我要开始的地方(多年来没有做过数学,也没有研究过链接的图形库的内部工作原理):

  1. 选择一个距离,以任何有意义的单位测量,也许是像素。

  2. 识别每个形状中的每个连续边。在每个形状的一个边缘上选择一个任意点(例如,在 (0,0) 表示左上角的平面上,每个形状上最接近 (0,0) 的边缘点),然后在该平面上对齐您的单独形状观点。出于您转换的目的,该点将保持静态,所有其他点将符合它。

  3. 如果您的形状有两个或更多不同的边缘,请按周长排序。考虑较短的长度从属于较长的长度。使用与步骤 2 中类似的过程来选择任意点以将这两条边连接在一起。

  4. 在您选择的每个点上,以您在步骤 1 中选择的距离为间隔计算边缘周围的点。

  5. (留给读者作为练习)将不同边缘上的点整合在一起并形成目标形状,必要时对齐、减少或添加边缘上的点。

或者,您可以选择任意数量的点而不是任意距离,然后将它们沿着边缘适当地分布在它们适合的任何距离处,然后将这些点整合在一起。

只是抛出一些想法,我真的不知道问题有多深。

于 2013-03-26T19:50:24.420 回答