Использование изображений OpenCV Mat с Intel IPP?
Недавно я начал использовать Приоритеты производительности Intel (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])
?
Ответы
Ответ 1
Существует чистый способ передачи данных OpenCV в функцию IPP.
Если у нас есть OpenCV Mat
, мы можем применить *Mat.data[0]
к const Ipp<type>*
. Например, если мы имеем дело с 8-битными беззнаковыми данными char (8u
), мы можем подключить (const Ipp8u*)&img.data[0]
к функции IPP. Вот пример использования функции ippiFilter
с типичным изображением Лена:
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
просто простая оболочка для массива.