You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中基于OpenGL+MediaPipe AAR实现真实唇部肤色修改的方案问询

解决方案:实现唇部自然颜色填充

方案一:合并渲染到同一着色器程序

当前问题核心是相机纹理与填充多边形分属不同着色器程序,无法直接在片段着色器中完成颜色混合。最直接的解决方式是将两者的渲染逻辑合并到一套着色器中:

  1. 修改顶点着色器:同时传递顶点的纹理坐标(与相机纹理UV对应),以及唇部区域的顶点标记(也可后续在片段着色器中判断区域)
  2. 调整片段着色器逻辑:
    • 先采样相机纹理获取原始画面颜色
    • 判断当前片段是否属于唇部区域(可通过顶点标记,或利用纹理坐标结合唇部关键点计算)
    • 使用mix函数混合原始纹理色与目标填充色,示例代码:
      vec4 originalColor = texture2D(uTexture, vTexCoord);
      vec4 fillColor = vec4(1.0, 0.5, 0.5, 0.3); // 半透明唇色
      vec4 finalColor = mix(originalColor, fillColor, fillColor.a);
      gl_FragColor = finalColor;
      
  3. 适配Java层代码:在drawLandmarks中补充传递顶点纹理坐标,注意MediaPipe的NormalizedLandmark原点在左上角,需翻转y轴适配OpenGL纹理坐标系(原点在左下角):
    // 转换y坐标
    vertex[lastAddedIndex++] = 1.0f - starts.y;
    

方案二:使用帧缓冲(FBO)实现后处理混合

若不想修改原有纹理渲染的着色器,可通过FBO先将相机纹理渲染到离屏缓冲,再在唇部绘制时采样该缓冲完成混合:

  1. 初始化帧缓冲:创建FBO并绑定同分辨率的纹理作为颜色附件
  2. 预渲染相机纹理到FBO:在绘制唇部多边形前,先将相机纹理渲染到FBO中
  3. 唇部着色器采样FBO纹理:
    • 在填充用的片段着色器中,采样FBO纹理获取原始相机画面颜色
    • 用mix函数混合填充色与原始色,实现自然叠加效果
  4. 注意事项:FBO尺寸需与GLSurfaceView分辨率严格一致,避免画面拉伸变形

方案三:启用OpenGL原生混合模式

如果坚持使用两套着色器程序,可通过OpenGL的混合功能直接实现颜色叠加,无需修改着色器逻辑:

  1. 开启混合功能:在绘制唇部多边形前执行以下代码:
    GLES20.glEnable(GLES20.GL_BLEND);
    GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
    
  2. 调整填充色透明度:在片段着色器中设置带透明度的填充色,降低叠加后的突兀感:
    gl_FragColor = vec4(1.0, 0.4, 0.4, 0.2); // 低透明度唇色
    
  3. 保证绘制顺序:必须先渲染相机纹理,再绘制唇部多边形,混合逻辑才能生效

针对你现有代码的细节优化

你当前的drawLandmarks代码使用GL_TRIANGLE_FAN绘制,需确保顶点顺序正确,避免多边形扭曲。另外,若要在着色器中采样纹理,需在Java层将相机纹理ID传递给着色器的uniform变量:

int textureHandle = GLES20.glGetUniformLocation(program, "uTexture");
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, cameraTextureId);
GLES20.glUniform1i(textureHandle, 0);

内容的提问来源于stack exchange,提问作者Dev007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 00:50:32