如何在使用Intel IPP时处理OpenCV Mat图像?

14

我最近开始使用英特尔性能库(IPP)来进行图像处理。对于那些没有听说过IPP的人,可以将IPP视为线性代数处理的MKL的类比。

我已经在OpenCV中实现了一个有些复杂的视觉系统,我想用更快的IPP例程替换掉一些OpenCV例程(例如卷积和FFT)。我的OpenCV代码始终使用cv :: Mat 图像数据结构。但是,根据IPP代码示例,IPP似乎更喜欢CIppiImage数据结构。

我的系统在OpenCV中进行了几个图像转换,然后我想在IPP中完成一些操作,最后再在OpenCV中继续工作。以下是让OpenCV和IPP良好配合的一种简单方法:

 cv::Mat = load original image
 use OpenCV to do some work on cv::Mat
 write cv::Mat to file

 CIppiImage = read cv::Mat from file //for IPP
 use IPP to do some work on CIppiImage
 write CIppiImage to file

 cv::Mat = read CIppiImage from file
 use OpenCV to do more work on cv::Mat
 write final image to file

然而,这有点繁琐,而且读写文件可能会增加整个执行时间。


我试图使在图像处理程序中在OpenCV和IPP之间轻松切换。以下是几个解决问题的方法:

  1. 是否有一种一行代码就可以将cv::Mat转换为CIppiImage,反之亦然的方法?
  2. 我对cv::Mat的实现细节非常熟悉,但我不太了解CIppiImagecv::MatCIppiImage的数据布局是否相同?如果是这样,我能否执行类似下面的强制类型转换?CIppiImage cimg = (CIppiImage)(&myMat.data[0])
1个回答

8

有一种干净的方法可以将OpenCV数据传递到IPP函数中。

如果我们有一个OpenCV的Mat,我们可以将*Mat.data[0]强制转换为const Ipp<type>*。例如,如果我们处理8位无符号字符(8u)数据,我们可以将(const Ipp8u*)&img.data[0]插入IPP函数中。这里是一个使用ippiFilter函数和典型的Lena图像的示例:

Mat img = imread("./Lena.pgm"); //OpenCV 8U_C1 image
Mat outImg = img.clone(); //allocate space for convolution results

int step = img.cols; //pitch
const Ipp32s kernel[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};
IppiSize kernelSize = {3,3};
IppiSize dstRoiSize = {img.cols - kernelSize.width + 1, img.rows - kernelSize.height + 1};
IppiPoint anchor = {2,2};
int divisor = 1;

IppStatus status = ippiFilter_8u_C1R((const Ipp8u*)&img.data[0], step,
                                     (Ipp8u*)&outImg.data[0], step, dstRoiSize,
                                     kernel, kernelSize, anchor, divisor);

当我将上面的代码中的outImg写入文件时,它会给出预期的结果:enter image description here 这与我使用相同参数运行Nvidia版本nppiFilter得到的结果相匹配:enter image description here

我在原问题中提到了一个名为CIppiImage的结构体。 CIppiImage只是一个数组的简单包装器。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接