Я использую 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. Мне кажется, я получил такой образ:
Я не могу понять, что не так.
У меня заканчиваются решения, и я не знаю, что должно работать и где я не прав.Любой совет приветствуется :)
Заранее спасибо за помощь.