2016-10-11 109 views
0

我的目标是用OpenCV函数(如NL表示去噪)来增强我的预先存在的图像处理流水线(用Halide编写)。 OpenCV函数将无法使用Halide的调度功能,因此我的计划是在每个OpenCV阶段之前实现每个Halide Func。剩下的问题是如何从Halide Image(Func实现的结果)最佳转换为OpenCV Mat(作为OpenCV函数的输入)以及完成时从OpenCV Mat到Halide Image。我的Halide图像是浮点类型,有3个通道。如何将OpenCV Mat转换为Halide Image并返回?

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

回答

0

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

对于第一种方法,可以使用一个垫构造函数的数据指示字:

float* data = new float[3 * width * height]; 
cv::Mat image(height, width, CV_32FC3, data, AUTO_STEP); 

对于第二种方法,可以使用通常的构造或垫::创建方法:

cv::Mat image(height, width, CV_32FC3); 

无论哪种方式,你可以使用类似下面的代码来包装内存在卤化物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功能在相同的存储器上运行。

+0

非常感谢您的回答Eric。我将代码设置为按照您所描述的方式工作,并且在大多数情况下,它适用于OpenCV和Halide。 一个奇怪的问题是,当我从buffer_t制作图像时:Image input(buffer);输出看起来不正确。 – Kantthpel

+0

对不起,看起来我们不能编辑评论。我的意思是说,当我保存从缓冲区创建的图像时,输出看起来不正确。但是,当通过任何Func传递时,数据看起来被正确存储,因为将不执行计算的Func的输出保存在正确的输出中。 看来,通过Func传递图像的行为正在纠正从缓冲区创建的图像中的错误 – Kantthpel

+0

对于奇怪的行为的替代方案可能是save_image卤化物函数无法正确解析在缓冲。我认为这种情况的原因是,当输入数据是平面的时候,图像在通过空白Func之前和之后看起来都是正确的。但是,当输入数据交错时(OpenCV的默认值),那么只有通过空白Func传递的图像看起来是正确的。 – Kantthpel