Подтвердить что ты не робот

Использование изображений 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])?
4b9b3361

Ответ 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 просто простая оболочка для массива.