Google Tango Leibniz API中的彩色图像

时间:2015-05-13 22:43:05

标签: android c camera yuv google-project-tango

我正在尝试从Google Tango中捕获onFrameAvailable方法中的图像数据。我正在使用Leibniz版本。在头文件中,据说缓冲区包含HAL_PIXEL_FORMAT_YV12像素数据。在release notes中,他们说缓冲区包含YUV420SP。但在documentation中,据说像素是RGBA8888格式()。我有点困惑,另外。我不是真的得到图像数据,而是大量的洋红色和绿色。现在我正试图从YUV转换为类似于this one的RGB。我猜这个步幅也有问题。这里是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时遇到类似的问题?

3 个答案:

答案 0 :(得分:0)

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字节纹理,并按原样加载数据。片段着色器将使用相同的纹理坐标。

答案 1 :(得分:0)

顺便说一句,如果有人在Leibniz版本上捕获图像数据时遇到问题:其中一位开发人员告诉我,相机有一个错误,应该用Nash版本修复。

该错误导致我的缓冲区为空,但是当我使用Nash更新时,我再次获得了数据。但是,现在的问题是我使用的数据没有意义。我想/希望原因是平板电脑还没有获得OTA更新(实际发布日期与OTA软件更新之间可能存在差距)。

答案 2 :(得分:0)

试试以下代码:

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

我成功了。