为什么从Project Tango平板电脑中提取的图像显示为灰色?

时间:2015-08-03 20:18:16

标签: c++ c google-project-tango

  • 我正在使用Project Tango C API
  • 我正在将TangoImageBuffer.data指向的整个缓冲区写入文件。

    // open a file
    std::fstream f(app.getNextFileName(), std::ios::out | std::ios::binary);
    
    // write the entire stride * height * 4 buffer into the file
    f.write((const char *) tango_image_buffer->data, 
        tango_image_buffer->stride * buffer->height * 4 * sizeof(uint8_t)
    );
    
    f.close();
    
  • 然后我将文件导出到我的PC并使用python-opencv和numpy进行可视化:

    import sys
    
    import cv2
    import numpy as np
    
    # dimensions of the image
    stride    = 1280
    width     = 1280
    height    = 720
    
    # I am using 3 channels so that the resulting image is not
    # transluscent
    channels  = 3
    
    input_filename  = sys.argv[1]
    output_filename = sys.argv[2]
    
    # load the image buffer into a list
    data = np.fromfile(input_filename, dtype=np.uint8)
    
    # create a height x width x channels matrix with the datatype uint8 
    # and all elements set to zero
    img = np.zeros((height, width, channels), dtype=np.uint8);
    
    # map elements in array to image matrix
    for y in range(0, height):    
        for x in range(0, width):
            img[y, x, 0] = data[y * stride + x + 2] #blue
            img[y, x, 1] = data[y * stride + x + 1] #green
            img[y, x, 2] = data[y * stride + x + 0] #red
    
    # display and save the resulting image
    cv2.namedWindow("tango-rgba")
    cv2.imshow("tango-rgba", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    cv2.imwrite(output_filename, img)
    
  • 不幸的是,生成的图片looks gray

  • 图像为灰色。仔细检查像素后,您会发现像素的红色,绿色和蓝色成分为different

  • 编辑:我已更改此帖子以指定我使用的缓冲区是RGBA8888格式。从Project Tango Reference,"仅提供RGBA 8888"

  • 编辑:实际上似乎没有使用RGBA8888格式。 rhashimoto建议格式为YV12。

  • 编辑:图像格式实际上是NV21(见下面的答案)。

1 个答案:

答案 0 :(得分:3)

似乎在写这篇文章时,Project Tango Reference确实是不正确的。

图像格式为NV21。

char format_str[100] = {0};

switch (tango_image_buffer->format)
{
  case TANGO_HAL_PIXEL_FORMAT_RGBA_8888:
        sprintf(format_str, "%s", "RGBA8888");
        break;
  case TANGO_HAL_PIXEL_FORMAT_YV12:
        sprintf(format_str, "%s", "YV12");
        break;
  case TANGO_HAL_PIXEL_FORMAT_YCrCb_420_SP:
        sprintf(format_str, "%s", "NV21");
        break;
  default:
        break;

}
__android_log_print(ANDROID_LOG_VERBOSE, "Capture Info",
        "stride: %u, width: %u, height: %u, timestamp: %lf, frame: %llu, format: %s",
        tango_image_buffer->stride, 
        tango_image_buffer->width, 
        tango_image_buffer->height,
        tango_image_buffer->timestamp, 
        tango_image_buffer->frame_number, 
        format_str);

上面一段代码的输出是:

   V/Capture Info﹕ stride: 1280, width: 1280, height: 720, timestamp: 22157.368703, frame: 0, format: NV21

这是我在python中使用opencv和numpy的新可视化代码:

import sys

import cv2
import numpy as np

input_filename  = sys.argv[1]
output_filename = sys.argv[2]


# dimensions of the image
stride    = 1280
width     = 1280
height    = 720
channels  = 4

# load file into buffer
data = np.fromfile(input_filename, dtype=np.uint8)

# create yuv image
yuv = np.ndarray((height + height / 2, width), dtype=np.uint8, buffer=data)

# create a height x width x channels matrix with the datatype uint8 for rgb image
img = np.zeros((height, width, channels), dtype=np.uint8);

# convert yuv image to rgb image
cv2.cvtColor(yuv, cv2.COLOR_YUV2BGRA_NV21, img, channels)

# display and save the resulting image
cv2.namedWindow("tango-rgba")
cv2.imshow("tango-rgba", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite(output_filename, img)

resulting image

TLDR:图像格式为NV21。 OpenCV提供将NV21转换为RGB的功能。 result看起来很棒。