专栏首页天天P图攻城狮iOS基于GPUImage的图像形变设计(复杂形变部分)

iOS基于GPUImage的图像形变设计(复杂形变部分)

在上一部分,我们介绍了两种简单形变的GPUImage实现方式,包括自定义FragmentShader,和自定义顶点数组。这一部分,我们将介绍更为复杂的一些图像形变的实现。

Part3:基于自定义vertices的局部图像形变设计

区别于Part2中的自定义vertices和fragment数组的简单图像形变,这里的自定义vertices数组不仅仅局限于图像4个顶点,而是可以任意指定的,从而可以达到对图像的局部区域进行细微的形变调整。这里,我们以调整用户的脸型,从而达到蛇精脸的效果为例,如下图所示:

对于用户图像的人脸区域,我们分隔成若干个三角形切片,然后通过调节这些三角形的顶点来实现形变。具体的做法是:

1) 得到原始三角形顶点位置(原始特征点,图中红色点)

2) 得到需要形变后的三角形顶点位置(形变特征点,图中蓝色点)

3) 通过设置vertices和textureCoordinates来调整三角形(vertices对应新地形变后特征点,textureCoordinates对应原图的原始特征点)

4) 通过OpenGL绘制相应的三角形,即得到形变后的图像

这里需要单独设置的内容相比简单形变要复杂一些,需要同时设置多组vertices和textureCoordinates,并且在绘制三角形时也应该绘制GL_TRIANGLES而非GL_TRIANGLE_STRIP,这是因为很难得到连续顶点的三角形数组。具体代码如下:

这里mVertex和mFragment都是nTriangles*3*2个值(nTriangle个三角形,每个三角形3个顶点,每个顶点2个float值)

另外需要注意的是三角形划分,必须保证一个固定不变的区域内所有面积都要有所覆盖,否则会形成空洞(对于上图的例子,需要在最外围设置一个正方形,保持正方形的4条边不动的情况下,调整正方形区域内的顶点,从而可以达到形变后的图像任然连续这一个结果)。

如上图所示,需要外框点保持不变,通过调节内部的0~98号点(内部点),来实现形变后的图像与原图保持连续。

Part4:基于网格形变的自定义vertices全局图像形变设计

对于Part3中的自定义顶点的方法来实现图像形变而言,需要确定三角形的具体分割,并且仅支持线性的位置调整,对于非线性的位置调整(比如大眼,越离眼睛中心形变越大)则支持能力较弱,这时候就需要使用这里的基于网格形变的自定义vertices全局图像形变方法来进行图像形变了。

这种方法的本质思想是:对于图片上的每一个像素,手动计算出该像素在新的图片中的位置,并且将该像素值填充至该位置。然而,单独计算每一个像素点的位置需要大量的计算资源,无法达到实时处理的性能,为此,通过对图片进行分块,每一块都是一个小三角形。通过对小三角形顶点的位置调整,来大致近似每一个点的位置移动,从而便于OpenGL进行渲染。具体的分块示意图如下所示:

从上图可以看出,当分块足够多时,变相相当于逐像素计算新的位置;而当位置足够少时(比如只有1*1的顶点),则退化为普通的顶点坐标变换。

那么,具体应该如何计算每一个点在新图像中的位置呢?这里给出常用的2种方法:

1) MLS方法:利用论文《Image Deformation Using Moving Least Squares》中的方法,当已知某些点在新图中的新位置之后(锚定点),对于每个像素点,可以依据该像素点与锚定点之间的关系,计算得到该像素点在新图像中的位置,从而达到形变的目的。下图是MLS算法的一个示例:

2) 基于规则的点位置计算:也是最传统的点计算方法。该方法通过设定一些具体的规则(比如,某个像素A的邻域内点往方向v移动x个像素,则对于任意一个像素点,判断它与A之间的关系,如果落在A的邻域内,则往v方向移动x个像素)。这些规则可以很简单(移动、扩大、收缩),也可以很复杂(按指定路径移动,非线性移动),从而可以组合出各种效果。比如Part3中的瘦脸,也可以对脸部轮廓的像素进行移动来实现近似的效果。具体的效果如下图所示,左边是原图,右边是每个网格点移动后形变产生的图片。

上面两种是比较常用的点移动方法。对于点位置的计算,可以放在CPU端进行,再将计算结果赋值给vertices数组,也可以直接传默认的vertices数组,将点位置的计算交给GPU来做。如果通过GPU来计算点的位置,可以获得GPU的并行加速能力,缺点是需要传输额外的数据给GPU(MLS算法需要传点的映射关系;规则方法需要传规则本身),因此各有优缺点。这里举例通过GPU来计算MLS算法中的点位置的变化:


小结:

GPUImage提供了很方便的接口供我们来对图像进行形变的操作。对于简单的形变,可以通过自定义vertices数组来实现,也可以通过改写FragmentShader来实现;对于复杂的形变,可以同时自定义vertices和textureCoordinates数组来通过自定义贴三角形的方式来实现,也可以通过将图像分割成网格状,再绘制每一个小三角形的方式来实现。

下面是各种方式的时间复杂度以及代码复杂度:(假设图像宽度w,高度h)

Part1

Part2

Part3

Part4

顶点计算时间

O(1)

O(1)

O(N),N为三角形数量

O(w0*h0*x),w0,h0为分块数,x为每个顶点的运算量

渲染时间

O(w*h)

O(w*h)

O(w*h),视实际渲染区域大小

O(w*h)

代码复杂度

一般

简单

复杂

复杂

GPU受限*

*:GPU受限:指传输到GPU的用于计算的数据太大,部分GPU可能无法支持


作者简介:dreamqian(钱梦仁),外号"大魔王",天天P图iOS工程师

本文分享自微信公众号 - 天天P图攻城狮(ttpic_dev)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-06-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 微信这家人脸智慧时尚店可以“刷脸”试衣、付款

    过去,办事要“刷脸”,看在你的面子上这事儿兴许才能走的通…… ? 吃饭也要“刷脸”,老板看着是熟客,就能直接打折啦…… ? 现在,直接“刷脸”就可以当会员,打折...

    企鹅号小编
  • “刷脸”购物来了

    微信支付全国首家人脸智慧时尚店亮相深圳。在这里,市民“买买买”连手机都不用带,只需“刷脸”,便能享受快速便捷的“无感”购物体验。 智慧零售能力升级 全国首家人脸...

    企鹅号小编
  • 微信跨界开人脸智慧时尚店 “刷脸”可购物

    作者:联商网 微信跨界领域越来越广泛了,这次推出了人脸智慧时尚店,想要帮助顾客实现“刷脸”购物。 ? 12月26日,微信支付、腾讯社交广告与绫致时装集团达成合作...

    企鹅号小编
  • Facebook推出人脸识别新功能,防止用户肖像遭滥用

    新智元报道 编辑:Cecilia 【新智元导读】Facebook近日发布基于人脸识别技术的新功能"Photo Review",将个人肖像的知情权和控制权交还给用...

    企鹅号小编
  • 刷脸注册、试装、支付……仅靠一张脸就能买买买的时尚店开业了

    如今,人脸识别技术在生活中的应用已经越来越多。2017年12月25日,腾讯社交广告、微信支付与绫致时装集团达成合作,依托于腾讯优图实验室的人脸识别技术等,在全国...

    企鹅号小编
  • 人脸智慧时尚店落地广深,微信支付赋能智慧零售

    12月25日,微信支付、腾讯社交广告与绫致时装集团达成合作,全国首次推出人脸智慧时尚店。微信支付智慧零售行业解决方案通过人脸识别AI技术及精准推荐算法,赋能时尚...

    企鹅号小编
  • 不用@微信官方,教你写头像戴圣诞帽的程序

    前两天朋友圈里面刷屏的“我想要一个圣诞帽,@微信官方”这个活动你们中招了吗?后来大家都知道这只是一个用了P图工具的小玩笑,但大家纷纷玩得不亦乐乎。现在有许多p图...

    企鹅号小编
  • 不用@微信官方了,Python20行自动戴帽!

    这两天被朋友圈里@微信官方要求戴帽的消息刷屏了,会玩的都悄咪咪地用美图秀秀一类的app给自己头像p一顶然后可高兴地表示“哎呀好神奇hhhh”,呆萌的当然就一直等...

    企鹅号小编
  • 当前所有源码链接

    人脸识别源码 OpenCV-C++版本: Github :https://github.com/LiuXiaolong19920720/recognise-yo...

    企鹅号小编
  • “刷脸”就可购物 全国首家人脸智慧时尚店亮相深圳

    微信支付全国首家人脸智慧时尚店亮相深圳。图为顾客体验刷脸支付(鲁力/《南方日报》) 智慧零售能力升级 目前,深圳九方购物中心的Jack & Jones、广州白云...

    企鹅号小编

扫码关注云+社区

领取腾讯云代金券