Что такое хороший способ прочитать кадр камеры и сделать его текстурой? - PullRequest
0 голосов
/ 09 июля 2019

Я использую ARcore Unity SDK для Pixel 3. Мне нужно прочитать текущий кадр камеры во время выполнения и сделать его текстурой, которую я могу использовать на съемочной сцене.

Я вижу в документации, что существуют разные способы (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 голосов
/ 09 июля 2019

Что вы пытаетесь сделать, это просто изменить рамку камеры на текстуру? Сделайте актив текстуры рендеринга и поместите его в «Target Texture» указанной камеры, если вы хотите создать систему с мини-картой (как я предполагаю, это наиболее распространенное использование), вы можете подать указанную текстуру в необработанное изображение, как они берут текстуры

...