Copying cv::Mat to Ipp<Type>

Copying cv::Mat to Ipp<Type>

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

4 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

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

Attachments: 

AttachmentSize
Downloadtext/x-c++src matandipp.cpp1.3 KB

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

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;
}

Leave a Comment

Please sign in to add a comment. Not a member? Join today