0

我从模拟器中以 a 的形式获取图像流,gil::image_view需要将它们转换为以cv::Mat进行进一步处理。到目前为止,我或多或少地从这个答案中复制了代码,但并没有真正理解它:

auto image_view = // data received from an API
using pixel = decltype(image_view)::value_type;
static_assert(sizeof(pixel) == 4, "RGBA");
pixel raw_data[image_view.width() * image_view.height()];
boost::gil::copy_pixels(image_view, boost::gil::interleaved_view(image_view.width(),
                                                                 image_view.height(),
                                                                 raw_data,
                                                                 image_view.width() *
                                                                 sizeof(pixel)));
auto mat = cv::Mat(image_view.height(), image_view.width(), CV_8UC4, raw_data);

我确定没有使用alpha通道,所以我还可以定义另一个image_view:

auto rgb_view = boost::gil::color_converted_view<boost::gil::rgb8_pixel_t>(image_view);
using pixel = decltype(rgb_view)::value_type;
static_assert(sizeof(pixel) == 3, "RGB");
...

对于这种情况,使用复制像素boost::gil::copy_pixels(...)是有意义的,因为无法在恒定时间内将交错的 rgba8 转换为 rgb8。

鉴于应用程序的性质,我很确定图像已经在内存中的某个地方。因此,从技术上讲,我可以只使用指向第一个元素的指针来创建我的 OpenCV 图像,而代价是使用额外的通道。

4

1 回答 1

1

当时,我并没有真正想到image_view可以指向底层原始数据的内存位置,尽管缺乏所有权。查看所有这些autos 翻译成的内容并没有帮助解决混乱。写这个问题给了我一个解决它的想法。

假设数据已经在内存中,访问原始数据非常容易,下游库可以使用这些原始数据。以下代码片段可以帮助其他人处理该问题:

  1. 转换为另一种图像格式(此处为 24bpp),然后转换为cv::Mat: 需要复制所有像素
auto image_view = // data received from an API
auto rgb_view = boost::gil::color_converted_view<boost::gil::rgb8_pixel_t>(image_view);
using pixel = decltype(rgb_view)::value_type;
static_assert(sizeof(pixel) == 3, "RGB");
pixel raw_data[rgb_view.width() * rgb_view.height()];
boost::gil::copy_pixels(image_view, boost::gil::interleaved_view(rgb_view.width(),
                                                                 rgb_view.height(),
                                                                 raw_data,
                                                                 rgb_view.width() *
                                                                 sizeof(pixel)));
auto mat = cv::Mat(image_view.height(), image_view.width(), CV_8UC3, raw_data);
  1. 直接转换为cv::Mat:无需复制
auto image_view = // data received from an API
static_assert(sizeof(decltype(image_view)::value_type) == 4, "RGBA");
auto mat = cv::Mat(image_view.height(), image_view.width(), CV_8UC4, &image_view(0, 0));
于 2020-11-06T15:22:25.167 回答