【UE Unreal Camera】【保姆级教程二】【包含源代码】手把手教你通过UE获取摄像头帧数据

  【UE Unreal Camera】【保姆级教程二】【包含源代码】手把手教你通过UE获取摄像头帧数据~
c6ebbaddb1aff.png)

概述

  在UE 摄像头教程一中,我们已经通过Unreal自带的媒体播放器打开了摄像头,并且将摄像头的数据展示在了游戏画面中。当然这只是最基本的功能,一般情况下,我们需要对摄像头的画面数据进行处理,比如进行人脸的检测,或者在图像中绘制新内容,或者仅仅是保存图像数据,这时候应该怎么办呢?关于这一部分内容,网上资料其实挺少的,官方文档也没有具体的说明,不过不用担心,我已经帮你踩好坑了,跟着我一步步来就可以了~

方法介绍

  首先梳理一下逻辑,我们是如何打开摄像头和预览画面的?
  1. 为了打开相机,首先通过MediaPlayer(CameraMeidaPlayer)来打开相机,在创建MediaPlayer的时候系统会自动为它创建一个MediaTexture(CameraMeidaPlayer_Video)此时我们已经可以在UE 的编辑器中看到MediaPlayer和MediaTexture中已经展示出了摄像头的画面了。
  2. 为了展示画面,我们在游戏关卡中拖了一个Plane(平面),然后将MediaTexture拖到Plane上,此时引擎又为我们创建了一个材质(CameraMediaPlayer_Video_Mat)。
  这是我们上一节所作的工作。看一下我们的内容浏览器,现在我们有CameraMeidaPlayer,CameraMediaPlayer_Video_Mat,CameraMeidaPlayer_Video三个东西。

在这里插入图片描述  获取帧数据的核心也就是如何将CameraMediaPlayer_Video_Mat转化为帧数据,在C++代码中也就是包含图像信息的数组了。具体思想,就是通过渲染目标(RenderTarget2D)来将图像信息导出。
  简单来讲,渲染目标(Render Target)就是一种可以在运行时写入的纹理。从引擎的角度讲,渲染目标会存储颜色、法线以及AO等信息。

具体步骤

  1. 创建一个RenderTarget2D,这里将其命名为CameraRender2D。
在这里插入图片描述
  2. 在蓝图界面中创建一个RenderTarget2D的变量,这里命名为RenderTarget,然后将它的默认值指向在内容管理器中的CameraRender2D.
在这里插入图片描述
  3. 在蓝图界面中创建一个Material的变量,这里命名为CameraMaterial,然后将它的默认值指向在内容管理器中的CameraMdiaPlayer_Video_Mat.
在这里插入图片描述
  4. 开始绘制蓝图了。图中的实例是以点击屏幕中的plane,每点一次,就会对RenderTarget2D进行绘制,绘制好以后,RenderTarget2D就保存好了图像信息,这个时候将它输入到ProcessData中,使用C++对图像数据进行处理,得到我们想要的结果后,就可以通过渲染目标释放掉资源。
在这里插入图片描述
  在c++中,如何将Target2D转换为图像数据呢?通过如下代码,首先我们在上述步骤得到了Target2D,函数中作为参数rt输入。首先将rt转化成了Unreal中的数据格式 TArray 的数组,然后将这个数组转成更通用的c形式的unsigned char格式。也就是说,我们已经得到了图像的数据,将它保存在下图中unsinged char格式的指针中啦!注意图像数据格式是RGBA格式,从代码中不难看出。至于如何操纵这个图像数据,就请大家自由发挥啦~

bool ProcessData(UTextureRenderTarget2D* rt) {
    
    
   //Get Imagedata in the format of TArray<FColor>
    if (rt == nullptr) {
    
    
        GEngine->AddOnScreenDebugMessage(INDEX_NONE, 20.0f, FColor::Yellow, TEXT("UTextureRenderTarget2D == nullptr,exit"));
        return false;
    }
    FTextureRenderTargetResource* rtResource = rt->GameThread_GetRenderTargetResource();
    FReadSurfaceDataFlags readPixelFlags(RCM_UNorm);
    readPixelFlags.SetLinearToGamma(true);

    TArray<FColor> outBMP;
    outBMP.AddUninitialized(rt->GetSurfaceWidth() * rt->GetSurfaceHeight());
    rtResource->ReadPixels(outBMP, readPixelFlags);


    for (FColor& color : outBMP)
        color.A = 255;
    //Convert the image data format from TArray to const char*(c style)
 unsigned long dataSize = sizeof(unsigned char) * 4 * (rt->GetSurfaceWidth() * rt->GetSurfaceHeight());
    unsigned char *imgData = (unsigned char *)malloc(dataSize);
    memset(imgData, 0, dataSize);
    int cusPos = 0;
    for (FColor& color : outBMP) {
    
    
        memcpy(imgData + cusPos, (unsigned char*)&color.R, 1);
        cusPos += 1;
        memcpy(imgData + cusPos, (unsigned char*)&color.G, 1);
        cusPos += 1;
        memcpy(imgData + cusPos, (unsigned char*)&color.B, 1);
        cusPos += 1;
        memcpy(imgData + cusPos, (unsigned char*)&color.A, 1);
        cusPos += 1;
    }
 }

  大家有做到这个步骤吗?如果你的RenderTarget已经有图像,就像我下图所示的一样,那么恭喜你,你已经正确的完成了以上步骤。
在这里插入图片描述

方法介绍

Demo工程说明

  Demo工程包含以上所讲内容实例,进入工程以后,点击运行,就可以看到Windows电脑摄像头打开,并显示在游戏中。打包出来以后同样可以在Android手机上使用。(注意Mac电脑和iOS手机不可用)
  关注公众号后发送:Unreal-Camera即可。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41937380/article/details/127649323