读取相机框架并使之成为纹理的好方法是什么?

时间:2019-07-08 22:44:04

标签: unity3d arcore

我在Pixel 3上使用ARcore Unity SDK。 我需要在运行时读取相机的当前帧,并使其成为可以在ma场景上使用的纹理。

我在文档中看到有不同的方式(Frame.CameraImage.Texture,Frame.CameraImage.AcquireCameraImageBytes(),TextureReaderApi),但是我找不到哪个折旧了。 我检查了GitHub问题并尝试了一些解决方案:

使用Frame.CameraImage.Texture:

MyObject.GetComponent<Renderer>().material.mainTexture = Frame.CameraImage.Texture

这可行,但是纹理每帧更新一次,所以我尝试了这个:

yield return new WaitForEndOfFrame();
Texture2D texture2D = (Texture2D)Frame.CameraImage.Texture;
var pix = texture2D.GetPixels32();
var destTex = new Texture2D(texture2D.width, texture2D.height);
destTex.SetPixels32(pix);
destTex.Apply();
MyObject.GetComponent<Renderer>().material.mainTexture = destTex;         

此功能仅在即时预览模式下有效,而在我构建应用程序并在设备上运行时不起作用。 (我有白色的纹理)


我尝试了如下的TextureReaderAPI:

void Start()
{
    textureReader.OnImageAvailableCallback += OnImageAvailable;
}

public void OnImageAvailable(TextureReaderApi.ImageFormatType format, int width, int height, IntPtr pixelBuffer, int bufferSize)
{
   Texture2D TextureToRender = new Texture2D(width, height, 
   TextureFormat.RGBA32, false, false);
   byte[] Texture_Raw = new byte[width * height * 4];

   System.Runtime.InteropServices.Marshal.Copy(pixelBuffer, Texture_Raw, 0, 
   bufferSize);

   TextureToRender.LoadRawTextureData(Texture_Raw);
   TextureToRender.Apply();
   GetComponent<Renderer>().material.mainTexture = TextureToRender; 
}

但是我遇到了这个错误:DllNotFoundException:arcore_camera_utility GoogleARCore.Examples.ComputerVision.TextureReaderApi.Create,因此永远不会触发回调函数。


我还尝试了AcquireCameraImageBytes函数,然后将结果从YUV转换为RGB:

private void Update()
{
 using (var image = Frame.CameraImage.AcquireCameraImageBytes())
 {

         if (!image.IsAvailable)
         {
             return;
         }

         _OnImageAvailable(image.Width, image.Height, image.Y, 0);
     }


}

private void _OnImageAvailable(int width, int height, IntPtr pixelBuffer, 
int bufferSize)
{

    Debug.Log("UPDATE_Image"); 

    Texture2D m_TextureRender = new Texture2D(width, height, TextureFormat.RGBA32, false, false);
    bufferSize = width * height * 3 / 2;
    byte[] bufferYUV = new byte[bufferSize];
    System.Runtime.InteropServices.Marshal.Copy(pixelBuffer, bufferYUV, 0, bufferSize);
    Color color = new Color();
    for (int y = 0; y < height; y++)
    {
        for (int x = 0; x < width; x++)
        {

            float Yvalue = bufferYUV[y * width + x];
            float Uvalue = bufferYUV[(y / 2) * (width / 2) + x / 2 + (width * height)];
            float Vvalue = bufferYUV[(y / 2) * (width / 2) + x / 2 + (width * height) + (width * height) / 4];
            color.r = Yvalue + (float)(1.37705 * (Vvalue - 128.0f));
            color.g = Yvalue - (float)(0.698001 * (Vvalue - 128.0f)) - (float)(0.337633 * (Uvalue - 128.0f));
            color.b = Yvalue + (float)(1.732446 * (Uvalue - 128.0f));

            color.r /= 255.0f;
            color.g /= 255.0f;
            color.b /= 255.0f;

            if (color.r < 0.0f)
                color.r = 0.0f;
            if (color.g < 0.0f)
                color.g = 0.0f;
            if (color.b < 0.0f)
                color.b = 0.0f;

            if (color.r > 1.0f)
                color.r = 1.0f;
            if (color.g > 1.0f)
                color.g = 1.0f;
            if (color.b > 1.0f)
                color.b = 1.0f;

            color.a = 1.0f;
            m_TextureRender.SetPixel(width - 1 - x, y, color);
        }
    }

    m_TextureRender.Apply();
    MyObject.GetComponent<Renderer>().material.mainTexture = m_TextureRender;
}

在即时预览中,我收到此错误:EntryPointNotFoundException:AImage_getPlaneData。 它几乎可以在构建中使用,但是我从YUV转换为RGB时出了点问题,我想是这样的图像:
enter image description here 我不知道怎么了。

我的解决方案用光了,不知道应该做什么,哪里不对。欢迎任何建议:)

预先感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您要尝试的只是将相机的框架更改为纹理? 制作一个渲染纹理资产并将其放入所述相机的“目标纹理”中,如果您要制作一个小型地图系统(因为我猜这是最常见的用途),则可以将所述纹理输入到原始图像中,因为它们带有纹理