问题描述
我从模拟器中以gil::image_view
的形式获取图像流,需要将它们转换为cv::Mat
以便进行进一步处理。到目前为止,我或多或少从this answer复制了代码,但并没有真正理解它:
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映像,而不必使用额外的通道。
解决方法
当时,尽管缺乏所有权,但我并没有真正想到image_view
可以指向基础原始数据的存储位置。查看所有这些auto
所翻译的内容并不能解决混乱问题。写下问题给了我一个解决的想法。
假设数据已经在内存中,则很容易访问原始数据,供下游库使用。以下代码段可以帮助其他人解决此问题:
- 转换为其他图像格式(此处为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);
- 直接转换为
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(),CV_8UC4,&image_view(0,0));