release notes提到在Unity中无法访问颜色数据,但我相信您可以将回调附加到视频覆盖侦听器并在Unity中接收YUV12字节数组并手动将其转换为RGB565在屏幕上显示,可能使用着色器。
有没有人在Unity中成功访问和显示颜色数据(例如在AR覆盖中)?如果是这样,你可以分享一些关于如何开始的指针/代码吗?
答案 0 :(得分:3)
视频叠加回调适用于Unity。从理论上讲,你可以使用YUV到RGBA着色器并在Unity中渲染它。这样做的唯一缺点是,由于Unity纹理/颜色格式的方式,它将需要多个“memcpy”。
Tango的YV12数据打包在C-API标题中解释:https://developers.google.com/project-tango/apis/c/struct_tango_image_buffer
它说:“首先是宽度x高度的Y样本,然后是V样本,其中一半是步幅,一半是Y数据的行,然后是U样本,其尺寸与V样本相同。” / p>
所以我认为你可以有三个Unity纹理,每个包含一个Y,U,V通道,并将它们传递到一个着色器来计算RGBA颜色。
有关YUV图像和转换的更多信息:http://en.wikipedia.org/wiki/YUV
答案 1 :(得分:3)
我使用以下脚本在Unity四维网格上显示视频叠加。适用于探戈平板电脑。但是fps很低,我猜是因为彩色相机的分辨率(1280 x 720)。
using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Runtime.InteropServices;
using Tango;
public class CameraBackgorund : VideoOverlayListener
{
Texture2D backgroundTexture = null;
// texture data
bool isDirty = false;
byte[] yuv12 = null;
int width;
int height;
private void Update()
{
if (isDirty)
{
if (backgroundTexture == null)
backgroundTexture = new Texture2D (width, height);
// convert from YV12 to RGB
int size = (int)(width * height);
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
byte y = yuv12[i * width + j];
byte v = yuv12[(i / 2) * (width / 2) + (j / 2) + size];
byte u = yuv12[(i / 2) * (width / 2) + (j / 2) + size + (size / 4)];
backgroundTexture.SetPixel(j, height - i - 1, YUV2Color(y, u, v));
}
}
// update texture
backgroundTexture.Apply(true);
GetComponent<MeshRenderer> ().material.mainTexture = backgroundTexture;
isDirty = false;
}
}
protected override void _OnImageAvailable(IntPtr callbackContext,
Tango.TangoEnums.TangoCameraId cameraId,
Tango.TangoImageBuffer imageBuffer)
{
if (cameraId != Tango.TangoEnums.TangoCameraId.TANGO_CAMERA_COLOR)
return;
// allocate for the first time
width = (int)imageBuffer.width;
height = (int)imageBuffer.height;
if (yuv12 == null)
yuv12 = new byte[width * height * 2];
// copy data in yv12 format
IntPtr dataPtr = imageBuffer.data;
int offset = 0;
Int64 stride = (Int64)imageBuffer.stride;
for (int i = 0; i < height; ++i, dataPtr = new IntPtr(dataPtr.ToInt64() + stride), offset += width)
Marshal.Copy(dataPtr, yuv12, offset, width);
for (int i = 0; i < height / 2; ++i, dataPtr = new IntPtr(dataPtr.ToInt64() + stride / 2), offset += width / 2)
Marshal.Copy(dataPtr, yuv12, offset, width / 2);
for (int i = 0; i < height / 2; ++i, dataPtr = new IntPtr(dataPtr.ToInt64() + stride / 2), offset += width / 2)
Marshal.Copy(dataPtr, yuv12, offset, width / 2);
isDirty = true;
}
public static Color YUV2Color(byte y, byte u, byte v)
{
// http://en.wikipedia.org/wiki/YUV
const float Umax = 0.436f;
const float Vmax = 0.615f;
float y_scaled = y / 255.0f;
float u_scaled = 2 * (u / 255.0f - 0.5f) * Umax;
float v_scaled = 2 * (v / 255.0f - 0.5f) * Vmax;
return new Color(y_scaled + 1.13983f * v_scaled,
y_scaled - 0.39465f * u_scaled - 0.58060f * v_scaled,
y_scaled + 2.03211f * u_scaled);
}
}
使用Unity WebCamTexture成功检索颜色,但会破坏深度提供程序。
答案 2 :(得分:0)
您可以使用WebCamTexture.GetPixel获取点位置的颜色,并使用该信息制作纹理。 http://docs.unity3d.com/ScriptReference/WebCamTexture.GetPixel.html
答案 3 :(得分:0)
您可以使用以下代码将YV12转换为2D纹理
private void YV12_To_Texture2D(byte[] data, uint width, uint height, out Texture2D tex)
{
tex = new Texture2D((int)width, (int)height);
uint size = width * height;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int x_index = j;
if (j % 2 != 0)
{
x_index = j - 1;
}
// Get the YUV color for this pixel.
int yValue = data[(i * width) + j];
int uValue = data[size + ((i / 2) * width) + x_index + 1];
int vValue = data[size + ((i / 2) * width) + x_index];
// Convert the YUV value to RGB.
float r = yValue + (1.370705f * (vValue - 128));
float g = yValue - (0.689001f * (vValue - 128)) - (0.337633f * (uValue - 128));
float b = yValue + (1.732446f * (uValue - 128));
Color co = new Color();
co.b = b < 0 ? 0 : (b > 255 ? 1 : b / 255.0f);
co.g = g < 0 ? 0 : (g > 255 ? 1 : g / 255.0f);
co.r = r < 0 ? 0 : (r > 255 ? 1 : r / 255.0f);
co.a = 1.0f;
tex.SetPixel((int)width - j - 1, (int)height - i - 1, co);
}
}
}