Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.

Copying cv::Mat to Ipp<Type>

Constantin_S_
Beginner
1,118 Views

I was wondering if anyone had quick example code for this, I couldn't find any examples in this forum or OpenCV's website. If not, I have a few questions where I am most confused on.

  1. OpenCV is interlaced, in bgr format. Ipp expects planar images though (as per the malloc definition.) For now I think I'll avoid this, and just only convert grayscale images, But this is useful for future work/questions.
  2. The OpenCV widthstep is no longer 32 bit aligned. So my assumption is going to be to transfer row by row from a cv::Mat into an ipp_malloced memory. I'm assuming that OpenCV widthstep < IPP widthstep.
  3. Is there anything else I should worry about?

Thank you in advance!Constantin

0 Kudos
3 Replies
Igor_B_Intel1
Employee
1,118 Views

Hi,

No need to worry. IPP supports both interleaved (C3 suffix) and planar (C1 suffix) images and works with data allocated by cv::Mat object. Not alighned on 32 buffere may affect only performance.

Please take a look on to the example in the attach. It shows how to use cvMat data with IPP.

 Igor S. Belyakov

0 Kudos
Ying_H_Intel
Employee
1,118 Views

Hi Constantin,

We have quick example about IplImage and IPP image in http://software.intel.com/en-us/articles/using-intel-ipp-with-opencv-21

 IplImage* pSrcImg = cvLoadImage( "testimg.bmp", 1 );//lena.jpg

and ippiRemap_8u_C3R((Ipp8u*) pSrcImg->imageData,

also about cvMat

float* pXTable = (float*) malloc(sizeof(float)*nTableSize);

CvMat* pXMap=cvCreateMat(TARGET_HEIGHT,TARGET_WIDTH,CV_32F);
cvSetData (pXMap, (void*) pXTable, sizeof(float)*TARGET_WIDTH);

I'm not sure all of  cv::Mat defintion and corresponding functions. So just comments about IPP

1) IPP should  support interlaces too,  like any  function with C3, which  supposed for 3 channel image, like rgb, bgr etc.  and ippiMaloc_8u_C3  can for general image.

2) IPP function should support no-32bit align memory too.  for example,  if the cv::Mat point to a continous memory (no padding in each row),  if you have the start point of cv::Mat, and know the widthStep,  you can call IPP function directly,  the ipp malloc is not needed.

cv::Mat mtSamples(1, N, CV_32FC1 );
float* pSamples = (float*)mtSamples.datastart;

  ippiRemap_32f_xx(pSamples,

3)  As you see, IplImage and IPP image is  matched each other,  the difference of cv::Mat and IplImage is same as the difference of IPP.  So if there are functions which can cast cv::Mat to IplImage, then you can use same on IPP.   As you point out, the key problem you may need to take care are to feed IPP function with  the pointer of cv::Mat's data and correct widthStep value.

Best Regards,

Ying

0 Kudos
Constantin_S_
Beginner
1,118 Views

Ying and Igor, thank you for your responses. So after more research yesterday I determined the OpenCV (after v2.0) does not pad cv::Mat's anymore. Thus the align function calls are useless. I was interested in correctly using IPP so I implemented a way to copy data over quickly to IPP aligned memory. 

NOTE: This example is only for a single channel image! I was unaware if IPP did BGR or RGB and it wasnt necessry for me. I also allow scaling between 8u or 32f if you wish to switch data types.

unsigned char * row_ptr = 0;
switch(output)
{
  case IPL_DEPTH_8U:
    if(uchar_image_ptr_)
      ippFree(uchar_image_ptr_);
    uchar_image_ptr_ = ippiMalloc_8u_C1(size.width, size.height, &step);
    row_ptr = uchar_image_ptr_;

    if(mat.depth() != CV_8U)
    {
      workspace = mat.clone();
      double scale = 1.0;
      if(mat.depth() == CV_32F || mat.depth() == CV_64F)
        scale = 255.0; //Scale from 0.0 - 1.0 to 0-255
      mat.convertTo(workspace, CV_8U, scale);
    }

    break;

  case IPL_DEPTH_32F:
  if(float_image_ptr_)
    ippFree(float_image_ptr_);
  float_image_ptr_ = ippiMalloc_32f_C1(size.width, size.height, &step);
  row_ptr = (unsigned char *)float_image_ptr_;

  if(mat.depth() != CV_32F)
  {
    workspace = mat.clone();
    double scale = 1.0;
    if(mat.depth() == CV_8U || mat.depth() == CV_16U || mat.depth() == CV_32S)
      scale = 1/255.0; //Scale from 0.0 - 1.0 to 0-255
    mat.convertTo(workspace, CV_32F, 1.0);
    workspace = workspace * scale;
  }

  break;
}

if(step < workspace.step[0])
  std::cerr << "STEPSIZE DOESNT MATCH UP" << std::endl;

for(int row = 0; row < workspace.rows; ++row)
{
  memcpy(row_ptr, workspace.row(row).data, workspace.step[0]);
  row_ptr += step;
}

0 Kudos
Reply