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

How to replace ipp functions : ippiRotate_32f_C1R and ippiResizeCenter_32f_C1R ?

Pham_Minh_N_
Beginner
1,066 Views

Hi every one,

I've used ippiRotate_32f_C1R and ippiResizeCenter_32f_C1R functions in my project at VS2008 and Intel Parallel Studio 2011. Now, I'd like to migrate this project to VS2015 and Intel Parallel Studio XE 2016. But, unfortunately, ippiRotate_32f_C1R and ippiResizeCenter_32f_C1R functions are not supported in IPP library of Intel Parallel Studio 2016.

How can I replace these functions in Intel Parallel Studio 2016 ?

I'm looking forward to your replies.

Thanks

 

0 Kudos
7 Replies
Valentin_K_Intel
Employee
1,066 Views

Hi Pham,

Sorry for the delayed answer. Instead of ippiRotate_32f_C1R function you can use the ippiWarpAffine<Interpolation> functions with ippiGetRotateTransform function: https://software.intel.com/en-us/node/589797
The example for rotation operation can be found here: https://software.intel.com/en-us/node/589842

The problem with replacing old ippiResizeCenter method with new functions was discussed here: https://software.intel.com/en-us/forums/intel-integrated-performance-primitives/topic/557838

The ippiResizeCenter method changes an image size and shifts the destination image relative to the given point. The ippiResize<interpolationtype> method scales an image respecting (0,0) point. To implement an integer-valued shift of the scaled image you need to shift the destination image pointer that is passed to the processing function. Shifting the pointer you need to specify the destination ROI so that the shifted region does not exceed the destination image bounds.
You can used ippiWarpAffine<interpolationtype> method to implement image scaling with a real-valued shift.

IppStatus resizeShiftCubic_32f_C1R(Ipp32f* pSrc, IppiSize srcSize, Ipp32s srcStep, Ipp32f* pDst, IppiSize dstSize, Ipp32s dstStep, IppiPoint dstShift)
{
  IppiResizeSpec_32f* pSpec = 0;
  int specSize = 0, initSize = 0, bufSize = 0; Ipp8u* pBuffer  = 0;
  Ipp32u numChannels = 1; IppiPoint dstOffset = {0, 0}; IppStatus status = ippStsNoErr;
  IppiBorderType border = ippBorderRepl;
  Ipp8u* pInit = NULL;
  IppiRect dstRoi = {dstShift.x, dstShift.y, dstSize.width, dstSize.height};
  IppiSize dstRoiSize = {0};
  Ipp32f* pDstRoi = (Ipp32f*)((Ipp8u*)pDst + dstRoi.y * dstStep) + dstRoi.x * numChannels;

  if (dstShift.x < 0)
  {
      dstOffset.x   = -dstShift.x;
      dstRoi.width -= dstShift.x;
      dstShift.x    = 0;
      pDstRoi = pDstRoi + dstOffset.x * numChannels;
  }

  if (dstShift.y < 0)
  {
      dstOffset.y    = -dstShift.y;
      dstRoi.height -= dstShift.y;
      dstShift.y     = 0;
      pDstRoi = (Ipp32f*)((Ipp8u*)pDstRoi + dstOffset.y * dstStep);
  }

  if (dstRoi.x + dstRoi.width > dstSize.width)
  {
      dstRoi.width = dstSize.width - dstRoi.x;
  }

  if (dstRoi.y + dstRoi.height > dstSize.height)
  {
      dstRoi.height = dstSize.height - dstRoi.y;
  }

  dstRoiSize.width  = dstRoi.width;
  dstRoiSize.height = dstRoi.height;

  /* Spec and init buffer sizes */
  status = ippiResizeGetSize_32f(srcSize, dstSize, ippCubic, 0, &specSize, &initSize);

  /* Memory allocation */
  pSpec   = (IppiResizeSpec_32f*)ippsMalloc_8u(specSize);

  pInit = ippsMalloc_8u(initSize);

  /* Filter initialization */
  if (status >= ippStsNoErr) status = ippiResizeCubicInit_32f(srcSize, dstSize, 0.f, 0.5f, pSpec, pInit);

  ippsFree(pInit);

  /* work buffer size */
  if (status >= ippStsNoErr) status = ippiResizeGetBufferSize_32f(pSpec, dstSize, numChannels, &bufSize);

  pBuffer = ippsMalloc_8u(bufSize);

  /* Resize processing */
  if (status >= ippStsNoErr) status = ippiResizeCubic_32f_C1R(pSrc, srcStep, pDstRoi, dstStep, dstOffset, dstRoiSize, border, 0, pSpec, pBuffer);

  ippsFree(pSpec);
  ippsFree(pBuffer);

  return status;

}

Best regards,
Valentin
0 Kudos
Tam_N_1
Beginner
1,066 Views

Hi Valentin,

I'm Tam, Pham's colleague.

Thank you for given code.  This code changes an image size and shifts the destination image relative to the given point which is lack of scaling source ROI as ResizeCenter:
IppStatus ippiResizeCenter_<mod>(const Ipp<datatype>* const pSrc[3], IppiSize srcSize, int srcStep, IppiRect srcRoi, Ipp<datatype>* const pDst[3], int dstStep, IppiSize dstRoiSize, double xFactor, double yFactor, double xCenter, double yCenter, int interpolation);

How does this code work with xFactor, yFactor? Please help us.

Thank you.

 

0 Kudos
Valentin_K_Intel
Employee
1,066 Views

Hi Tam,

The given code can be used only for integer xCenter, yCenter coefficients and xFactor, yFactor calculated by the following formulas:
xFactor = (double)dstSize.width / srcSize.width
yFactor = (double)dstSize.height / srcSize.height .

Do you use arbitrary real xFactor, yFactor coefficients or not integer xCenter, yCenter coefficients? 

Best regards,
Valentin

0 Kudos
Tam_N_1
Beginner
1,066 Views

Hi Valentin,

The problem is that the old  ippiResizeCenter doesn't exist in new IPP 9.0 so we are looking a equivalent function (function with same interface as ippiResizeCenter and it should give the same result as IppiResizeCenter).

As you see, IppiResizeCenter parameters have double xCenter, yCenter, and arbitrary real xFactor, yFactor. This  means evenif srcImage and dstImage have the same size, with  xFactor,yFactor !=1 ==> dstImage result will have  zoom in/out effect at xCenter,yCenter. (this is what we need).

You given code not have xFactor, yFactor explicitly. They are calculated base on srcImage/dstImage ratio as you mentioned.

To solve this, we've tried 2 approaches:

1/ We calculated the fixed region of srcImage base on xFactor, yFactor, xCenter, yCenter. Then use your resize code to zoom in/out this fixed region to dstImage.

2/ We zoom in/out the whole srcImage base on xFactor,yFactor. Then we cut part of the zoomed srcImage into dstImage based on xCenter,yCenter.

Both approaches didn't not give the same result as IppiResizeCenter, so we are in stuck.( These approaches sometimes worked with nearest interpolation, but we want to use linear interpolation only).

Could you give us some advise to solve this? Or please give use some information about how IppiResizeCenter work internally (so that we can create my own function).

The strict is the replacement must give the closest result as IppiResizeCenter does. 

Thank you and looking forward to your answer soon.

Tam Nguyen.

  

 

0 Kudos
Tam_N_1
Beginner
1,066 Views

I found a code which I think it should be close to ippiResizeCenter:

			float A, B, C, D, interValue ;
			int x, y;
			double x_ratio = 1.0 / xFactor;
			double y_ratio = 1.0 / yFactor;
			float x_diff, y_diff, ya, yb ;
			int offset = 0 ;
			for (int i=0; i<dstSize.height; i++) {
				for (int j=0; j<dstSize.width; j++) {
					x = (int)(x_ratio * (j ) + xCenter * x_ratio) ;
					y = (int)(y_ratio * (i ) + yCenter * y_ratio) ;
					x_diff = (x_ratio * (j ) + xCenter * x_ratio) - x ;
					y_diff = (y_ratio * (i ) + yCenter * y_ratio) - y ;
					int index = y*srcROI.width+x ;
					A = srcImage[index];
					B = srcImage[index+1];
					C = srcImage[index+srcROI.width];
					D = srcImage[index+srcROI.width+1];
		            
					// Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
					interValue = (
							A*(1-x_diff)*(1-y_diff) +  B*(x_diff)*(1-y_diff) +
							C*(y_diff)*(1-x_diff)   +  D*(x_diff*y_diff)
							) ;

					dstImage_R[offset++] = interValue ;                                   
				}
			}

I attached output of original ippiResizeCenter and above manual code. Please share your idea about this. Do I miss something?

Input image 8,8 
41 62 95 92 71 3 53 23 
67 64 42 82 38 11 68 41 
34 5 27 21 69 22 47 29 
0 45 36 16 12 33 44 78 
69 81 91 18 67 73 62 16 
24 27 4 95 99 64 57 35 
78 61 2 47 35 41 37 90 
58 91 53 26 94 11 59 42 

Output using ippiResizeCenter  xFactor = 2, yFactor = 2, xCenter = yCenter = 4
27 24.2727 21.5455 38.4545 60.2727 56.1818 34.8182 26.5455 
31.0909 25.4711 19.8512 27.5868 38.6612 38.7025 31.3884 30.3884 
35.1818 26.6694 18.157 16.719 17.0496 21.2231 27.9587 34.2314 
56 38.1488 20.2975 22.281 29.2231 36.2397 43.3058 48.0909 
81 52.1983 23.3967 31.9504 49.843 59.3802 63.3471 64.4545 
67.2727 54.4215 41.5702 52.3554 69.0496 74.314 71.9587 68.7438 
27.7273 48.7603 69.7934 79.9174 87.314 83.7769 72.9504 64.9835 
3.63636 41.1983 78.7603 86.6694 87.1653 79.8512 67.3306 58.6446 

Output using manual code xFactor = 2, yFactor = 2  xCenter = yCenter = 4
27 24 21 45 69 45.5 22 34.5 
31.5 25 18.5 29.5 40.5 34 27.5 36.5 
36 26 16 14 12 22.5 33 38.5 
63.5 40.25 17 28.25 39.5 46.25 53 53 
91 54.5 18 42.5 67 70 73 67.5 
47.5 52 56.5 69.75 83 75.75 68.5 64 
4 49.5 95 97 99 81.5 64 60.5 
3 37 71 69 67 59.75 52.5 49.75 

Regards

0 Kudos
Valentin_K_Intel
Employee
1,066 Views

Hi Tam,

Thank you for the question. I have investigated the issue. The code you provided does not do the same that ippiResizeCenter does.
The function ippiResizeCenter makes the resize transform such that the given source image point (xCenter, yCenter) is mapped to the center of the given destination ROI. Additionaly ippiResizeCenter corrects xFactor, yFactor coefficients depending on the given source, destination image ROIs and xCenter, yCenter values. 

The similar operation can be performed with using WarpAffine functionality. However the result of this operation is not the same as the result from the function ippiResizeCenter.

    IppiWarpSpec* pSpec = 0;
    int specSize = 0, initSize = 0, bufSize = 0;
    Ipp8u* pBuffer  = 0;
    Ipp8u* pInitBuf = 0;
    Ipp32u numChannels = 1;
    IppiPoint dstOffset = {0};
    IppStatus status = ippStsNoErr;
    IppiBorderType border = ippBorderRepl;

    double xFactor = 2.0, yFactor = 2.0;
    double xCenter = 4.0, yCenter = 4.0;

    IppiSize srcSize = {8, 8};
    IppiSize dstSize = {8, 8};
    IppiRect srcRoi  = {0, 0, 8, 8};
    IppiRect dstRoi  = {0, 0, 8, 8};

    int srcStep = 8 * sizeof(Ipp32f);
    int dstStep = 8 * sizeof(Ipp32f);

    Ipp32f pSrc[8*8]  = { 41, 62, 95, 92, 71, 3, 53, 23,
                          67, 64, 42, 82, 38, 11, 68, 41,
                          34,  5, 27, 21, 69, 22, 47, 29,
                           0, 45, 36, 16, 12, 33, 44, 78,
                          69, 81, 91, 18, 67, 73, 62, 16,
                          24, 27,  4, 95, 99, 64, 57, 35,
                          78, 61,  2, 47, 35, 41, 37, 90,
                          58, 91, 53, 26, 94, 11, 59, 42};
    Ipp32f pDst[8*8] = {0};

    double coeffs[2][3] = {0};

    /* scale coefficients */
    coeffs[0][0] = srcSize.width  > 1 ? (xFactor * srcSize.width  - 1) / (srcSize.width  - 1) : 1;
    coeffs[1][1] = srcSize.height > 1 ? (xFactor * srcSize.height - 1) / (srcSize.height - 1) : 1;
    /* shift coefficients */
    coeffs[0][2] = dstSize.width  / 2.0 - coeffs[0][0] * xCenter;
    coeffs[1][2] = dstSize.height / 2.0 - coeffs[1][1] * yCenter;


    /* Spec and init buffer sizes */
    status = ippiWarpAffineGetSize(srcSize, dstSize, ipp32f, coeffs, ippLinear, ippWarpForward, ippBorderRepl, &specSize, &initSize);

    if (status != ippStsNoErr) return status;

    /* Memory allocation for Warp Spec structure */
    pSpec    = (IppiWarpSpec*)ippsMalloc_8u(specSize);

    if (pSpec == NULL) return ippStsNoMemErr;

    /* Filter initialization */
    status = ippiWarpAffineLinearInit(srcSize, dstSize, ipp32f, coeffs, ippWarpForward, numChannels, ippBorderRepl, 0, 0, pSpec);
    ippsFree(pInitBuf);

    if (status != ippStsNoErr)
    {
        ippsFree(pSpec);
        return status;
    }

    /* work buffer size */
    status = ippiWarpGetBufferSize(pSpec, dstSize, &bufSize);
    if (status != ippStsNoErr)
    {
        ippsFree(pSpec);
        return status;
    }

    /* Memory allocation for work buffer */
    pBuffer = ippsMalloc_8u(bufSize);
    if (pBuffer == NULL)
    {
        ippsFree(pSpec);
        return ippStsNoMemErr;
    }

    /* Affine transform processing */
    status = ippiWarpAffineLinear_32f_C1R(pSrc, srcStep, pDst, dstStep, dstOffset, dstSize, pSpec, pBuffer);

    ippsFree(pSpec);
    ippsFree(pBuffer);

Best regards,
Valentin

0 Kudos
Tam_N_1
Beginner
1,066 Views

Hi Valentin,

Thank you for your answer. It took me  a lot time to figure out how to use new IPP function. I used warp affine for resize center.

Morever, I think it is possible to use new Resize functions to replace the olde resize center by calculate the dstROI (consit dstOffset and dstSize). However, dstOffset seem not work properly for ippiResize function..

I have post new thread here:

https://software.intel.com/en-us/forums/intel-integrated-performance-primitives/topic/621927

Thank you a lot for your time.

Best regards,

Tam.

0 Kudos
Reply