如何转换OpenCV垫卤化物图像和回来

How to convert OpenCV Mat to Halide Image and back?

本文关键字:卤化物 图像 回来 OpenCV 何转换 转换      更新时间:2023-10-16

我的目标是用OpenCV函数(如NL means去噪)增强我已有的图像处理管道(用Halide编写)。OpenCV函数将无法使用Halide的调度功能,所以我的计划是在每个OpenCV阶段之前实现每个Halide函数。剩下的问题是如何最好地从卤化图像(函数实现的结果)转换到OpenCV Mat(作为OpenCV函数的输入),并在完成后从OpenCV Mat转换到卤化图像。我的Halide图像类型为float,有3个通道。

一个明显的解决方案是编写将数据从一种数据类型复制到另一种数据类型的函数,但这让我觉得很浪费。复制数据不仅要花费宝贵的时间,而且还会浪费内存,因为图像将被存储为两种不同的数据类型。是否有一种方法可以使用指针或数据缓冲区来简单地以新格式重新包装图像数据?希望这个过程是可逆的,所以我可以从Halide到OpenCV,然后在OpenCV函数完成后回到Halide。

buffer_t现在已经消失了,所以我应该更新这个答案。当前制作一个封装OpenCV垫(使用交错存储布局)的缓冲区的方法是:

Halide::Runtime::Buffer<float>::make_interleaved(image.data, image.cols, image.rows, image.channels());

如果OpenCV矩阵在行之间有填充,则较长的形式为:

halide_dimension_t shape[3] = {{0, image.cols, image.step1(1)}, 
                               {0, image.rows, image.step1(0)},
                               {0, image.channels(), 1}};
Halide::Runtime::Buffer<float> buffer(image.data, 3, shape);

a halde_dimension_t是最小坐标,范围,然后是该维度的步幅/步长。

是的,您可以避免复制数据。我看到两种可能的方法:要么自己分配内存,并在OpenCV Mat实例和Halide buffer_t结构中引用该内存;或者让OpenCV的Mat类分配内存,并在buffer_t结构中引用该内存。

对于第一种方法,您可以使用Mat构造函数,该构造函数接受一个数据指针:
float* data = new float[3 * width * height];
cv::Mat image(height, width, CV_32FC3, data, AUTO_STEP);
对于第二种方法,您可以使用通常的构造函数或Mat::create方法:
cv::Mat image(height, width, CV_32FC3);

无论哪种方式,您都可以使用下面的代码将内存封装在Halide buffer_t结构中:

buffer_t buffer;
memset(&buffer, 0, sizeof(buffer));
buffer.host = image.data;
buffer.elem_size = image.elemSize1();
buffer.extent[0] = image.cols;
buffer.extent[1] = image.rows;
buffer.extent[2] = image.channels();
buffer.stride[0] = image.step1(1);
buffer.stride[1] = image.step1(0);
buffer.stride[2] = 1;

现在您应该能够在同一内存上操作OpenCV和Halide函数