前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >原创:好玩的视频人像抠图

原创:好玩的视频人像抠图

作者头像
字节流动
发布2022-04-06 12:42:20
1.7K0
发布2022-04-06 12:42:20
举报
文章被收录于专栏:字节流动

前面文章人像抠图 + OpenGL ES 还能这样玩?没想到吧,我们介绍了利用人像抠图算法生成的 mask 图,然后结合 OpenGL 可以产生一些有趣的效果。

抠图技术应用很广泛,比如很多手机的相机自带“人像留色”滤镜:人体区域保留彩色,人体区域之外灰度化。所以人像留色的关键技术在于高精度高性能的分割算法。

本文将基于开源的人像抠图算法模型和 OpenGL 做一个实时的人像分割 app , 该 app 目前已开源,感兴趣的同学可以参考该项目利用matting算法做一些有趣的特效。

本文主要参考飞鸽传书的开源项目 ncnn_Android_RobustVideoMatting ,它使用的是腾讯的 ncnn 神经网络计算框架,ncnn 是一个为手机端极致优化的高性能神经网络前向计算框架。无第三方依赖,跨平台,手机端 cpu 的速度快于目前所有已知的开源框架。

ncnn 地址:https://github.com/Tencent/ncnn

不过 ncnn_Android_RobustVideoMatting 数据源使用的是 NdkCamera ,这对做应用层开发的同学来说,学习和移植起来很不方便。

所以本文采用 Android Camera2 (Java)获取实时预览图像,将算法模型和 OpenGL 渲染控件封装成一个类,初学者可以很方便地利用这些类进行移植和二次开发,可以轻易实现自己想要的效果。

将算法模型封装成一个类,可以很方便将其移植到你的播放器或者相机里

代码语言:javascript
复制
#ifndef NCNN_ANDROID_ROBUSTVIDEOMATTING_MAIN_BODYSEG_H
#define NCNN_ANDROID_ROBUSTVIDEOMATTING_MAIN_BODYSEG_H
#include <ImageDef.h>
#include <android/looper.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
#include <android/asset_manager_jni.h>
#include <android/sensor.h>
#include "LogUtil.h"
#include "nanodet.h"

class BodySeg {
public:
    BodySeg(){}
    ~BodySeg(){}

    void Init(AAssetManager* mgr);

    void SetCameraOrt(int ort);

    void Process(NativeImage *pInput, NativeImage *pOutput, NativeImage *pOutMask);

    void UnInit();

private:
    void LoadModel(AAssetManager* mgr);

private:
    int camera_facing;
    int camera_orientation;
    mutable int accelerometer_orientation;
    ASensorManager* sensor_manager = nullptr;
    mutable ASensorEventQueue* sensor_event_queue = nullptr;
    const ASensor* accelerometer_sensor = nullptr;
    NanoDet* nanoDet = nullptr;
};

模型类封装的非常简单,Process 执行分割输出分割结果和 mask 图。

Java 层获取相机预览数据传入 Native 做分割处理。

代码语言:javascript
复制
    private ImageReader.OnImageAvailableListener mOnPreviewImageAvailableListener = new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
            Image image = reader.acquireLatestImage();
            if (image != null) {
                if (mCamera2FrameCallback != null) {
                    mCamera2FrameCallback.onPreviewFrame(CameraUtil.YUV_420_888toNV21(image), image.getWidth(), image.getHeight());
                }
                image.close();
            }
        }
    };

Native 层渲染 Matting 结果和 mask 灰度图的类(渲染控件)。

代码语言:javascript
复制
class GLCameraRender: public BaseGLRender {
public:
    //初始化预览帧的宽高
    virtual void Init(AAssetManager* mgr);
    //渲染一帧视频
    virtual void RenderVideoFrame(NativeImage *pImage, NativeImage **ppSegResult);
    virtual void UnInit();

    //GLSurfaceView 的三个回调
    virtual void OnSurfaceCreated();
    virtual void OnSurfaceChanged(int w, int h);
    virtual void OnDrawFrame();

    static GLCameraRender *GetInstance();
    static void ReleaseInstance();

    //更新变换矩阵,Camera预览帧需要进行旋转
    virtual void UpdateMVPMatrix(int angleX, int angleY, float scaleX, float scaleY);

private:
    GLCameraRender();
    virtual ~GLCameraRender();
    bool CreateFrameBufferObj();
    void GetRenderFrameFromFBO();
    ......
};

渲染组件类包含了 GLSurfaceView 的三个回调,主要就是借助于 GLSurfaceView 创建 OpenGL 渲染上下文环境,RenderVideoFrame 传入 matting 结果和相关的 mask 灰度图,然后进行上屏渲染。

-- END --

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 字节流动 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
人体分析
腾讯云神图·人体分析(Body Analysis)基于腾讯优图领先的人体分析算法,提供人体检测、行人重识别(ReID)等服务。支持识别图片或视频中的半身人体轮廓;支持通过人体检测,识别行人的穿着、体态等属性信息。可应用于人像抠图、背景特效、人群密度检测等场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档