我最近开始使用Intel Performance Primitives (IPP)进行图像处理。对于那些没有听说过IPP的人,可以将IPP视为MKL的模拟处理而不是线性代数。
我已经在OpenCV中实现了一个有点复杂的视觉系统,我想换掉一些OpenCV例程(例如卷积和FFT)来实现更快的IPP例程。我的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之间交替。以下是一些可以解决问题的方法:
cv::Mat
转换为CIppiImage
,反之亦然?cv::Mat
实施细节,但我对CIppiImage
了解不多。 cv::Mat
和CIppiImage
具有相同的数据布局吗?如果是这样,我可以做类似下面的演员吗? CIppiImage cimg = (CIppiImage)(&myMat.data[0])
?答案 0 :(得分: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
(来自上面的代码)写入文件时,它会给出预期的结果:
这与我运行Nvidia版本nppiFilter
时使用相同参数得到的结果相符:
我在原始问题中提到了一个名为CIppiImage
的结构。 CIppiImage
只是一个简单的数组包装器。