0

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

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

4

2 回答 2

3

buffer_t 现在不见了,所以我应该更新这个答案。当前制作包装 OpenCV mat(使用交错存储布局)的缓冲区的方法是:

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);

halide_dimension_t 是最小坐标、范围,然后是该维度中的步幅/步长。

于 2020-07-09T17:13:02.020 回答
2

是的,您可以避免复制数据。我看到了两种可能的方法:要么自己分配内存,要么在 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 函数在同一内存上进行操作。

于 2016-10-11T16:31:25.683 回答