【问题标题】:Warp \ bend effect on a UIView?UIView上的翘曲\弯曲效果?
【发布时间】:2014-01-18 18:38:38
【问题描述】:

我正在尝试获得与图片中描述的效果类似的效果。左侧的白色区域不是原始照片上,它会将像素推开。我试过使用 Core Image(它提供了一些接近的效果),但它对我的需要来说太慢了。我需要让效果变得活泼,这样我才能让它对触摸做出响应。

iOS sdk 中是否有一个关闭效果\ 动画可以用 UIVIew 做类似的事情? (我找不到任何接近的东西) 如果没有,有人可以提供如何使用 OpenGL 进行攻击吗? (代码示例非常受欢迎)

(此效果将在我正在编写的开源类中发挥重要作用,因此如果有更简单的解决方案,我不希望使用 GPUImage 等第 3 方类(我的目标是此类依赖免费))

【问题讨论】:

  • 如果只是从图像中切掉白色区域可以吗?或者您需要图像的其余部分一起拉伸?
  • @kamran 白色区域只是背景。在拉伸效果之后,我需要拉伸完整的图像,而不需要剪掉任何东西。
  • 您是否尝试过在图像上使用带有 UIView 动画或 CABasicAnimation 的 CATransform3D?
  • @kamran 是的。我无法获得所需的行为。
  • 是的,我也在用 CATransform3D 测试你的图像,但我猜它不起作用。让我再测试一下,如果它不起作用,那么您唯一能做的就是使用图层和图层蒙版来实现您想要的目的,但在这种情况下,图像可能会被裁剪。

标签: ios objective-c opengl-es warp


【解决方案1】:

沙,

我所做的是在我的 OpenGL 坐标中布置一个矩形网格点。 (我使用了 50x50 的网格)。然后我在同一坐标空间中定义一个或多个控制点。我有一个我写的通用捏拉伸算法。它需要一个控制点、一个半径和一个有符号整数来表示吸引/排斥网格点的数量,并将其应用于我的网格坐标。对于捏合,它将网格点拉近控制点,而对于拉伸,它将控制点推开。变化在控制点处最大,随着与控制点的距离增加到半径值而下降。

更改网格坐标后,我会定义一组三角形条带,用于绘制图像的整个(扭曲的)矩形区域。我可以通过一个 OpenGL 绘图调用将我的整个纹理渲染到扭曲的网格上。 OpenGL 负责拉伸图像像素以适应我的控制点网格中的扭曲三角形。这是一个使用多个控制点创建胖脸外观的前后图像示例。它显示了网格,因此您可以看到它在做什么。这是我的丑杯子,所以提前道歉:

还有拉伸后的图片:

在我的例子中,我希望图像周边的控制点保持在原位,并且只扭曲图像的内部,因此我添加了额外的代码逻辑来将周边控制点锁定到位。这就是为什么图像的框架没有像您的图像那样被推入。然而,这需要额外的代码。

代码最终使用距离公式计算出每个网格点与控制点的距离,然后用三角函数计算角度,乘以改变距离,然后再用三角函数计算新位置对于每个网格点。不过,由于我只转换了 50x50 的控制点网格,因此速度足以跟上。

我们的应用 Face Dancer 在应用商店免费提供。 (在这个链接下载它:Face Dancer in the App store你可能想下载它并尝试一下。(它包括许多免费的变形,然后提供额外的变形作为应用内购买)还有一个付费的“Plus”版本包含所有的变形。

当您运行 Face Dancer 时,如果您用两根手指双击图像,它会显示用于创建变形的控制点网格,以便您查看它在做什么。

有一个名为 GLCameraRipple 的 OpenGL 示例应用程序,它包含在 Xcode 中并从文档链接。我建议将其作为起点。它从摄像头获取视频并将其绘制到屏幕上。如果您触摸屏幕,它会扭曲图像,就好像屏幕是一池水,而您的手指会在其中产生涟漪。它使用了我所描述的网格扭曲技术。

不幸的是,我不认为该应用程序使用 GLKit,这是使用 OpenGL ES 2.0 的一种更简单的方法。 GLKit 提供了许多使其更易于使用的功能,包括 GLKViews 和 GLKViewControllers。

【讨论】:

  • 感谢邓肯的详细解答。在研究这个问题时(在发布这个问题之前),我在网上看到了你的一个解释,然后已经下载了 Face Dancer,以便更好地理解这个问题。我希望有一种方法可以通过像核心动画这样简单的东西来避免 OpenGL(有一个非常好的私有 API“波纹”动画,所以我希望有类似的东西用于扭曲)但我想没有其他方法......OpenGL我来了。
  • 我的荣幸。这符合您的赏金标准吗?
  • 我会等待赏金用完,以防有人想出一个关于如何避免 OpenGL 的创意。如果不是,您的答案肯定符合赏金标准。
  • Duncan,查看我刚刚添加的答案中发布的开源类。我还没有深入研究代码,但是从浏览项目来看,它看起来像是你上面描述的一个很好的例子。
  • @Segev,看起来真的很酷。我已经下载了这个项目,希望能尽快花点时间看看。
【解决方案2】:

有一个新的很棒的开源类,它用一个很好的例子完全回答了我的问题。你可以找到它here

【讨论】:

  • 这个太棒了...我已经使用这个实现了平移手势的面部变形。它很酷但很棘手......谢谢兄弟。
【解决方案3】:

您可能会看到的另一件事是在 iOS 6 中添加的 Core Image 孔失真滤镜 (CIHoleDistortion)。它创建的效果与您正在寻找的效果非常相似。这是从我编写的测试程序生成的示例图像,非常接近。

但是,您会注意到 Apple 的过滤器会导致图像从框架边缘“拉开”。我认为这是一个错误,但祝 Apple 能够修复它:

【讨论】:

  • 谢谢邓肯。当我研究这个问题时,我发现CIHoleDistortion 并且在测试它时它没有满足我的要求。我不确定它是什么(也许是圆形的对称性,而我正在寻求更抽象的东西?)无论如何我已经很难和沉重地进入 OpenGL ES :) 再次感谢您用很好的答案更新这个问题!
【解决方案4】:

您展示的内容看起来像网状扭曲。使用 OpenGL 会很简单,但“简单的 OpenGL”就像简单的火箭科学。

我为我的公司编写了一个名为 Face Dancer 的 iOS 应用程序,它能够使用 OpenGL 对来自内置摄像头的视频进行 60 fps 的网格扭曲动画,但工作量很大。 (它确实对面部进行了有趣的镜子类型变化 - 想想现场的“胖摊”,以及许多其他效果。)

【讨论】:

  • 您能否详细介绍您所面临的挑战,以及您通常是如何克服这些挑战的?
  • 我正在寻找的唯一效果是上面的。如果 OpenGL 是我唯一的选择,我将开始学习如何做到这一点。有没有人知道的任何好的教程,它会专注于上述内容,而不会造成混乱?
  • 我不知道除了 OpenGL 或其他构建在 OpenGL 之上的方法之外的任何其他方法可以进行这种转换。您要做的是将图像映射到 OpenGL 纹理,然后将纹理切割成“网格”中的一系列镶嵌三角形。当你想要扭曲你的图像时,你将网格的点推入,然后将你的纹理绘制到现在扭曲的三角形网格上。
  • @Aaron,对我来说最大的挑战是:a) 弄清楚如何将像素通过系统移动到 OpenGL,然后以足够快的速度移动到屏幕上以跟上视频帧速率。我从 2011 年 WWDC 中找到了一个名为 Chromakey 的示例应用程序,它使用 CVPixelBuffers 做了一些技巧,因此视频帧保留在 GPU 内存中,没有缓冲区复制。 b) 处理 OpenGL 设置和配置。 OpenGL 是一个庞大而复杂的 API,有很多繁琐的设置。如果您不一直这样做,那将非常难以承受,并且在您做对之前,您的代码将失败并出现无用的 OpenGL 错误。
【解决方案5】:

我将研究两种方法:首先,核心图像过滤器,其中包括许多您似乎需要的失真过滤器。主要问题是其中许多在 iOS 中不可用(但在 OSX 上......)。

其次,GPUImage 库有许多您也可以使用的失真滤镜。这是一个讨论如何使用它们的问题:

How can you apply distortions to a UIImage using OpenGL ES?

【讨论】:

  • GPUImage 将是一个不错的选择,但 OP 说他不想使用第三方框架。对于 OP,请了解在 BSD 或类似源代码许可下许可的代码允许您将代码用于商业目的,甚至将包含它的框架转售给其他客户。如果你自己做的话,你应该期望花费几个星期(至少!)来加快 OpenGL 的速度并完成它。 OpenGL 有一个巨大的学习曲线。
猜你喜欢
  • 2015-01-10
  • 1970-01-01
  • 2019-09-28
  • 1970-01-01
  • 2015-01-23
  • 2018-04-02
  • 1970-01-01
  • 2015-12-10
  • 1970-01-01
相关资源
最近更新 更多