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;
        }

我成功了