我的目标是使用OpenCV函数(例如NL表示去噪)来扩充我预先存在的图像处理管道(用Halide编写)。 OpenCV函数将无法使用Halide的调度功能,因此我的计划是在每个OpenCV阶段之前实现每个Halide Func。剩下的问题是如何最好地从Halide Image(Func实现的结果)转换为OpenCV Mat(作为OpenCV函数的输入)以及从OpenCV Mat转换为Halide Image完成后。我的Halide图像是float类型,有3个通道。
一个明显的解决方案是编写将数据从一种数据类型复制到另一种数据类型的函数,但这对我来说是浪费。复制数据不仅花费宝贵的时间,而且还会浪费内存,因为图像将被存储为两种不同的数据类型。有没有办法使用指针或数据缓冲区来简单地以新格式重新包装图像数据?希望这个过程是可逆的,所以我可以从Halide转到OpenCV,然后在OpenCV功能完成后回到Halide。
答案 0 :(得分:1)
是的,您可以避免复制数据。我看到两种可能的方法:自己分配内存并在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函数在相同的内存上运行。
答案 1 :(得分:0)
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);
halide_dimension_t是该维度的最小坐标,范围,然后是步幅/步幅。