code小生 一个专注大前端领域的技术平台

公众号回复Android加入安卓技术群

作者:字节流动
声明:本文来自公众号字节流动投稿,转发等请联系原作者授权

首先这可能是一个伪命题,小姐姐需要瘦身大长腿效果吗?恩,小姐姐都是自带瘦身大长腿的,有没有?

OpenGL ES 实现瘦身大长腿效果

瘦身大长腿

实现原理

OpenGL ES 实现瘦身和大长腿效果比较方便,使用纹理映射技术借助于 OpenGL 的图像双线性插值算法可以轻易实现图像的伸缩效果

回顾下前面讲的,什么是纹理?在 OpenGL 中,纹理实际上是一个可以被采样的复杂数据集合,是 GPU 使用的图像数据结构,纹理分为 2D 纹理、 立方图纹理和 3D 纹理。

2D 纹理是 OpenGLES 中最常用和最常见的纹理形式,是一个图像数据的二维数组。纹理中的一个单独数据元素称为纹素或纹理像素。

什么是纹理映射?纹理映射就是通过为图元的顶点坐标指定恰当的纹理坐标,通过纹理坐标在纹理图中选定特定的纹理区域,最后通过纹理坐标与顶点的映射关系,将选定的纹理区域映射到指定图元上。

纹理坐标系

渲染坐标系

纹理映射也称为纹理贴图,简单地说就是将纹理坐标(纹理坐标系)所指定的纹理区域,映射到顶点坐标(渲染坐标系或OpenGLES 坐标系)对应的区域。

OpenGL 拉伸的原理我们搞清楚了,还有一个问题需要解决:由于不同手机屏幕的分辨率一般不同,这就导致图片被渲染到屏幕上之后,得到结果图的分辨率不符合我们的预期。

这里我们需要用到 OpenGL 离屏渲染技术,离屏渲染顾名思义,可以让渲染操作不用再渲染到屏幕上,而是渲染到一块离屏缓存中。

然后可以使用 glReadPixels 或者 HardwareBuffer 将渲染后的图像数据读出来,从而实现在后台利用 GPU 完成对图像的处理,避免了直接将结果图渲染到屏幕上导致的分辨率问题。

效果实现

实现瘦身大长腿效果使用到的着色器脚本,主要就是实现一个常规的纹理采样。

const char vShaderStr[] ="#version 300 es                            \n""layout(location = 0) in vec4 a_position;   \n""layout(location = 1) in vec2 a_texCoord;   \n""out vec2 v_texCoord;                       \n""uniform mat4 u_MVPMatrix;                  \n""void main()                                \n""{                                          \n""   gl_Position = u_MVPMatrix * a_position; \n""   v_texCoord = a_texCoord;                \n""}                                          \n";const char fShaderStr[] ="#version 300 es                            \n""precision mediump float;                   \n""in vec2 v_texCoord;                        \n""layout(location = 0) out vec4 outColor;    \n""uniform sampler2D s_TextureMap;            \n""void main()                                \n""{                                          \n""    outColor = texture(s_TextureMap, v_texCoord);\n""}";

瘦身效果实现

瘦身效果

瘦身效果实现是将指定的身体区域映射到一个宽度相对减小的区域,而指定身体区域之外的部分保持原来的比例,这样渲染出来图像的身体区域进行了压缩(瘦身)。类似,想实现变胖(有人要变胖吗?)的效果,便是将指定的身体区域映射到一个宽度相对增大的区域。

瘦身原理图

如图所示,为实现瘦身我们使用了 8 个顶点 V0~V7 ,8 个顶点将图像分割成了 6 个三角面片,其中 V2、V3、V4、V5 四个顶点所围成的区域表示要发生形变的区域,箭头方向表示形变的方式是压缩,各个顶点坐标的 x 分量需要偏移 m_dt (根据压缩方向确定正负偏移)。

实现瘦身效果的着色器程序使用的顶点坐标和纹理坐标:

/** 8 points horizontal mode*/
GLfloat vFboVertices[] = {-1.0f, 1.0f, 0.0f,-1.0f, -1.0f, 0.0f,(x1 - m_dt) / (1 + m_dt), -1.0f, 0.0f,(x1 - m_dt) / (1 + m_dt), 1.0f, 0.0f,(x2 + m_dt) / (1 + m_dt), 1.0f, 0.0f,(x2 + m_dt) / (1 + m_dt), -1.0f, 0.0f,1.0f, -1.0f, 0.0f,1.0f, 1.0f, 0.0f,
};
//fbo 纹理坐标
GLfloat vFboTexCoors[] = {0.0f, 0.0f,0.0f, 1.0f,m_DeformationRect.left, 1.0f,m_DeformationRect.left, 0.0f,m_DeformationRect.right, 0.0f,m_DeformationRect.right, 1.0f,1.0f, 1.0f,1.0f, 0.0f,
};

其中 m_dt 表示控制形变程度的形变因子,m_DeformationRect 表示一个归一化的区域选择框。我们可以在 UI 上调节进度条来控制改变形变程度,滑动选择框来制定形变的区域。

大长腿效果实现

大长腿效果

大长腿效果的实现可以类比瘦身,将指定的腿部区域映射到一个高度相对增大的区域,而指定腿部区域之外的部分保持原来的比例,这样渲染出来图像的腿部区域进行了拉伸(大长腿)

类似,想实现小短腿(如果有人用到的话)的效果,便是将指定的身体区域映射到一个高度相对减小的区域(实现压缩)。

大长腿效果实现原理

如图所示,为实现大长腿效果我们同样使用了 8 个顶点 V0~V7 其中 V1、V4、V7、V2 四个顶点所围成的区域表示要发生形变的区域,箭头方向表示形变的方式是拉伸,各个顶点坐标的 y 分量需要偏移 m_dt (根据拉伸方向确定正负偏移)。

实现瘦身效果的着色器程序使用的顶点坐标和纹理坐标:

/** 8 points vertical mode*/
GLfloat vFboVertices[] = {-1.0f, 1.0f, 0.0f,-1.0f, (y1 + m_dt) / (1 + m_dt), 0.0f,1.0f, (y1 + m_dt) / (1 + m_dt), 0.0f,1.0f, 1.0f, 0.0f,-1.0f, (y2 - m_dt) / (1 + m_dt), 0.0f,-1.0f, -1.0f, 0.0f,1.0f, -1.0f, 0.0f,1.0f, (y2 - m_dt) / (1 + m_dt), 0.0f,
};
//fbo 纹理坐标
GLfloat vFboTexCoors[] = {0.0f, 0.0f,0.0f, m_DeformationRect.top,1.0f, m_DeformationRect.top,1.0f, 0.0f,0.0f, m_DeformationRect.bottom,0.0f, 1.0f,1.0f, 1.0f,1.0f, m_DeformationRect.bottom,
};

不同的是,大长腿效果的实现是竖直方向上的拉伸,而瘦身的实现是水平方向上的拉伸。

另外还需注意的是,我们对图片进行拉伸或者缩放之后,结果图的实际尺寸会发生改变,所以每次调整形变后,都需要为离屏渲染的帧缓冲区对象 FBO 绑定对应新尺寸的纹理作为颜色附着。

//由于图像尺寸改变,删除旧纹理
if (m_FboTextureId) {glDeleteTextures(1, &m_FboTextureId);
}
//生成新纹理
glGenTextures(1, &m_FboTextureId);
glBindTexture(GL_TEXTURE_2D, m_FboTextureId);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, GL_NONE);glBindFramebuffer(GL_FRAMEBUFFER, m_FboId);
glBindTexture(GL_TEXTURE_2D, m_FboTextureId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_FboTextureId,0);
//判断是水平拉伸还是竖直拉伸,然后按照新图像的尺寸初始化纹理
if (m_bIsVerticalMode) {glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_RenderImg.width,static_cast<GLsizei>(m_RenderImg.height * (1 + m_dt)), 0, GL_RGBA,GL_UNSIGNED_BYTE, nullptr);
} else {glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,static_cast<GLsizei>(m_RenderImg.width * (1 + m_dt)),m_RenderImg.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
}
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {LOGCATE("MyGLRender::InitBuffers glCheckFramebufferStatus status != GL_FRAMEBUFFER_COMPLETE");
}
glBindTexture(GL_TEXTURE_2D, GL_NONE);
glBindFramebuffer(GL_FRAMEBUFFER, GL_NONE);

离屏渲染时,由于图像尺寸发生改变,这个也需要对视口进行调整:

//判断是水平拉伸还是竖直拉伸,设置视口大小
if (m_bIsVerticalMode) {glViewport(0, 0, static_cast<GLsizei>(m_RenderImg.width),static_cast<GLsizei>(m_RenderImg.height * (1 + m_dt)));
} else {glViewport(0, 0, static_cast<GLsizei>(m_RenderImg.width * (1 + m_dt)),static_cast<GLsizei>(m_RenderImg.height));
}

与 AI 算法结合

AI 算法检测的人体

我们现在是手动指定形变区域实现瘦身和大长腿效果,但是如果与身体关键点检测算法一起使用,我们便可以省去手动操作这一步。

拿到身体的关键点(算法检测结果)便可以计算出人体及各个部位的区域,按照类似的原理我们还可以实现瘦腰、瘦腿、丰胸等效果,我们后续将与 AI 算法结合来开发更加丰富的功能。

推荐:

Android性能优化之躺着就能APK瘦身

Android 瘦身不反弹最佳实践

Android应用瘦身,从18MB到12.5MB

使用 OpenGL 为 Camera 添加各种滤镜

Android APK 瘦身实践

如果你有写博客的好习惯

欢迎投稿

觉得不错,点个在看呗~

Hi 小姐姐,这是你要的瘦身大长腿效果?相关推荐

  1. 爬取偶像/私房小姐姐图片--爬虫基础篇

    1.废话不多说,直接上源码,有注释,相信你们能看懂 """ objective:爬取任意偶像/单词的百度图片(eg:佟丽娅.清纯小姐姐.蔡徐坤) coding: UTF- ...

  2. 海王小姐姐想分身,技术哥哥一分钟满足!

    午后,我戴着耳机专心致志地工作,正在享受敲键盘的快感. 突然,公司的行政小姐姐轻声哒哒哒地跑到我工位旁边蹲下,然后拍拍我的手,示意有事情找我. 平时不怎么熟悉的美女找我,我摘下耳机,正在疑惑. 小姐姐 ...

  3. newduba首页怎么去掉_京喜小程序首页瘦身实践

    前言 在 web 开发场景,减少代码体积虽然是性能优化的一个方向,还没到锱铢必较的程度.但是在小程序场景,由于代码包上传阶段限制了主包 2M 和总包 16M(近期微信官方正在内测将总包上限调整至 20 ...

  4. ikbc机械键盘打字出现重复_抖音开啤酒小姐姐同款面具,ikbc白无垢樱花机械键盘开箱体验...

    现如今机械键盘同质化越来越严重,就跟智能手机领域一样,不看看背面的LOGO的话,还真没法认出是哪家的.目前,对于绝大多数人来说,还是属于颜值党的,总之,帅就完事了.外设圈很小,愿意掏几百块买一把键盘的 ...

  5. CSDN公众号新功能上线,居然还能搜出小姐姐???

    为了给各位打工人更好的搜索体验 CSDN总是在学习新技能 这次CSDN公众号又给大家带来了一项全新的搜索技能 在CSDN旗下的公众号内回复消息 就能自动回复想搜索的内容啦 小编来给大家演示一下,在公众 ...

  6. Python分析101位《创造营2020》小姐姐,谁才是你心中的颜值担当?

    来源 | CDA 数据分析师 责编 |  Carol Show me data,用数据说话. 今天我们聊一聊<创造营2020>各个小姐姐,点击下方视频,先睹为快: 最近可以追的综艺真是太多 ...

  7. 刚刚!我被产品小姐姐的笔记本深深吸引了....

    今天我看到产品小姐姐的一个东西,我惊呆了,因为我好像看到了黑科技,事情是这个样子的.... 由于加班写代码,在比较疲劳的时候,就站起来随意的在办公室里走走,放松一下自己的脑神经. 走到一个产品小姐姐身 ...

  8. 小姐姐带你一起学:如何用Python实现7种机器学习算法(附代码)

    编译 | 林椿眄 出品 | AI科技大本营(公众号ID:rgznai100) [AI科技大本营导读]Python 被称为是最接近 AI 的语言.最近一位名叫Anna-Lena Popkes的小姐姐在G ...

  9. AI复原上海民国名媛影像!1929年的小姐姐,时装精致不输现在

    萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI 中国最早的时装秀,是什么样的? 自修复100年前的北京影像后,微博博主@大谷Spitzer这次又用AI工具,复原了民国时期的这场「花生骚」( ...

  10. 困扰数学家50年的问题,竟被博士小姐姐用一周业余时间解决了

    晓查 贾浩楠 发自 凹非寺 量子位 报道 | 公众号 QbitAI 一个多月前,著名英国数学家约翰·康威(John Conway)因患新冠肺炎逝世. 斯人已逝,但他留给了世界丰富的知识遗产,最知名的莫 ...

最新文章

  1. Datawhale两岁啦!
  2. lamp整合三连发(2)
  3. tftp ubuntu安装
  4. 14.PHP_PHP与XML技术
  5. 网站实现点击 “加入收藏 ”功能 - 代码篇
  6. 用DOS命令快把系统看透
  7. deepin下深度终端使用ssh-agent(xshell中的xagent功能)
  8. 计算机ascii码表
  9. 24种常见的逻辑关系谬误
  10. 应用MySQL数据库的实现本地BLAST及BLAST2GO
  11. Office2007 sp补丁包安装失败解决办法
  12. Mac 连接不上Mysql数据库的解决方案
  13. 电源输出的Overshoot和Undershoot 测试
  14. Oops是什么有什么用
  15. java计算人民币整数金额_java 使用BigDecimal进行货币金额计算的操作
  16. 利用aether api实现从指定maven仓库下载jar包
  17. excel如何批量让图片水平居中垂直居中对齐?
  18. 计算机学报——主题“区块链”,检索到25篇
  19. 腾讯云、阿里云和百度云的优劣势各是什么?
  20. 云计算的云指的是什么?通俗解释云计算能做什么

热门文章

  1. 01表盘控件-08时钟仪表盘-gaugeclock
  2. 【LeetCode】275. H指数 II
  3. STM32单片机(11) DS18B20温度传感器实验
  4. QT中的explicit关键字的意思
  5. C++ read()和write()读写二进制文件(超级详细)
  6. 天猫精灵通过AliOS网桥控制Zigbee设备
  7. PPT怎么画坐标 坐标轴刻度数字对齐
  8. 网络维护汇总经典问题集
  9. 有关HTML的小众面试题
  10. 2021-06-22