Google Tango Leibniz API 中的彩色图像
Color Image in the Google Tango Leibniz API
我正在尝试从 Google Tango 的 onFrameAvailable 方法中捕获图像数据。我正在使用莱布尼茨版本。在头文件中,缓冲区包含 HAL_PIXEL_FORMAT_YV12 像素数据。在release notes they say the buffer contains YUV420SP. But in the documentation it is said the pixels are RGBA8888 format (). I am a little confused and additionally. I don't really get image data but a lot of magenta and green. Right now I am trying to convert from YUV to RGB similar to this one。我想步幅也有问题。这是 onFrameAvailable 方法的代码:
int size = (int)(buffer->width * buffer->height);
for (int i = 0; i < buffer->height; ++i)
{
for (int j = 0; j < buffer->width; ++j)
{
float y = buffer->data[i * buffer->stride + j];
float v = buffer->data[(i / 2) * (buffer->stride / 2) + (j / 2) + size];
float u = buffer->data[(i / 2) * (buffer->stride / 2) + (j / 2) + size + (size / 4)];
const float Umax = 0.436f;
const float Vmax = 0.615f;
y = y / 255.0f;
u = (u / 255.0f - 0.5f) ;
v = (v / 255.0f - 0.5f) ;
TangoData::GetInstance().color_buffer[3*(i*width+j)]=y;
TangoData::GetInstance().color_buffer[3*(i*width+j)+1]=u;
TangoData::GetInstance().color_buffer[3*(i*width+j)+2]=v;
}
}
我正在片段着色器中进行 yuv 到 rgb 的转换。
有没有人获得过 Google Tango Leibniz 版本的 RGB 图像?或者有人在从 YUV 转换为 RGB 时遇到类似问题?
YUV420SP(又名NV21)目前是正确的。一个解释是here。在这种格式中,您有一个 width
x height
数组,其中每个元素都是一个 Y 字节,后跟一个 width/2
x height/2
数组,其中每个元素是一个 V 字节和一个U字节。您的代码正在实现 YV21,它具有用于 V 和 U 的单独数组,而不是将它们交织在一个数组中。
您提到您正在片段着色器中进行 YUV 到 RGB 的转换。如果您只想绘制相机图像,那么您可以使用 TangoService_connectTextureId()
和 TangoService_updateTexture()
而不是 TangoService_connectOnFrameAvailable()
。这种方法已经在 OpenGL 纹理中为您提供相机图像,该纹理为您的片段着色器提供 RGB 值,而无需担心像素格式细节。您需要绑定到 GL_TEXTURE_EXTERNAL_OES
(而不是 GL_TEXTURE_2D
),并且您的片段着色器看起来像这样:
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec4 v_t;
uniform samplerExternalOES colorTexture;
void main() {
gl_FragColor = texture2D(colorTexture, v_t.xy);
}
如果您出于某种原因确实想将 YUV 数据传递给片段着色器,则无需将其预处理为浮点数即可。事实上,您根本不需要解压它——对于 NV21,只需为 Y 定义一个 1 字节的纹理,为 VU 定义一个 2 字节的纹理,然后按原样加载数据。您的片段着色器将对两者使用相同的纹理坐标。
顺便说一下,如果有人在 Leibniz 版本上捕获图像数据时也遇到了问题:一位开发人员告诉我相机有一个错误,应该在 Nash 版本中修复它。
错误导致我的缓冲区为空,但是当我使用 Nash 更新时,我再次获得了数据。但是,现在的问题是我使用的数据没有意义。我 guess/hope 原因是平板电脑还没有获得 OTA 更新(实际发布日期和 OTA 软件更新之间可能存在差距)。
只需尝试以下代码:
//C#
public bool YV12ToPhoto(byte[] data, int width, int height, out Texture2D photo)
{
photo = new Texture2D(width, height);
int uv_buffer_offset = 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[uv_buffer_offset + ((i / 2) * width) + x_index + 1];
int vValue = data[uv_buffer_offset + ((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;
photo.SetPixel(width - j - 1, height - i - 1, co);
}
}
return true;
}
我成功了
我正在尝试从 Google Tango 的 onFrameAvailable 方法中捕获图像数据。我正在使用莱布尼茨版本。在头文件中,缓冲区包含 HAL_PIXEL_FORMAT_YV12 像素数据。在release notes they say the buffer contains YUV420SP. But in the documentation it is said the pixels are RGBA8888 format (). I am a little confused and additionally. I don't really get image data but a lot of magenta and green. Right now I am trying to convert from YUV to RGB similar to this one。我想步幅也有问题。这是 onFrameAvailable 方法的代码:
int size = (int)(buffer->width * buffer->height);
for (int i = 0; i < buffer->height; ++i)
{
for (int j = 0; j < buffer->width; ++j)
{
float y = buffer->data[i * buffer->stride + j];
float v = buffer->data[(i / 2) * (buffer->stride / 2) + (j / 2) + size];
float u = buffer->data[(i / 2) * (buffer->stride / 2) + (j / 2) + size + (size / 4)];
const float Umax = 0.436f;
const float Vmax = 0.615f;
y = y / 255.0f;
u = (u / 255.0f - 0.5f) ;
v = (v / 255.0f - 0.5f) ;
TangoData::GetInstance().color_buffer[3*(i*width+j)]=y;
TangoData::GetInstance().color_buffer[3*(i*width+j)+1]=u;
TangoData::GetInstance().color_buffer[3*(i*width+j)+2]=v;
}
}
我正在片段着色器中进行 yuv 到 rgb 的转换。
有没有人获得过 Google Tango Leibniz 版本的 RGB 图像?或者有人在从 YUV 转换为 RGB 时遇到类似问题?
YUV420SP(又名NV21)目前是正确的。一个解释是here。在这种格式中,您有一个 width
x height
数组,其中每个元素都是一个 Y 字节,后跟一个 width/2
x height/2
数组,其中每个元素是一个 V 字节和一个U字节。您的代码正在实现 YV21,它具有用于 V 和 U 的单独数组,而不是将它们交织在一个数组中。
您提到您正在片段着色器中进行 YUV 到 RGB 的转换。如果您只想绘制相机图像,那么您可以使用 TangoService_connectTextureId()
和 TangoService_updateTexture()
而不是 TangoService_connectOnFrameAvailable()
。这种方法已经在 OpenGL 纹理中为您提供相机图像,该纹理为您的片段着色器提供 RGB 值,而无需担心像素格式细节。您需要绑定到 GL_TEXTURE_EXTERNAL_OES
(而不是 GL_TEXTURE_2D
),并且您的片段着色器看起来像这样:
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec4 v_t;
uniform samplerExternalOES colorTexture;
void main() {
gl_FragColor = texture2D(colorTexture, v_t.xy);
}
如果您出于某种原因确实想将 YUV 数据传递给片段着色器,则无需将其预处理为浮点数即可。事实上,您根本不需要解压它——对于 NV21,只需为 Y 定义一个 1 字节的纹理,为 VU 定义一个 2 字节的纹理,然后按原样加载数据。您的片段着色器将对两者使用相同的纹理坐标。
顺便说一下,如果有人在 Leibniz 版本上捕获图像数据时也遇到了问题:一位开发人员告诉我相机有一个错误,应该在 Nash 版本中修复它。
错误导致我的缓冲区为空,但是当我使用 Nash 更新时,我再次获得了数据。但是,现在的问题是我使用的数据没有意义。我 guess/hope 原因是平板电脑还没有获得 OTA 更新(实际发布日期和 OTA 软件更新之间可能存在差距)。
只需尝试以下代码:
//C#
public bool YV12ToPhoto(byte[] data, int width, int height, out Texture2D photo)
{
photo = new Texture2D(width, height);
int uv_buffer_offset = 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[uv_buffer_offset + ((i / 2) * width) + x_index + 1];
int vValue = data[uv_buffer_offset + ((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;
photo.SetPixel(width - j - 1, height - i - 1, co);
}
}
return true;
}
我成功了