Community
cancel
Showing results for 
Search instead for 
Did you mean: 
umundry
Beginner
239 Views

pan/zoom image

Jump to solution

I am having a horrible time recreating the equivalent of the deprecated ippiResizeSqrPixel function. I need to be able to pan as well as zoom an image. There seems to be a bug in the ippiResize functions as pointed out by someone else somewhere here in the forum (at the end of this: https://software.intel.com/en-us/forums/intel-integrated-performance-primitives/topic/610642). I can't get the destination ROI settings correct.

Would somebody please provide some code which works, using a zoom factor and panX/panY offsets as input?

Thank you very much!!

0 Kudos
1 Solution
Valentin_K_Intel
Employee
239 Views

Hi Umudry,

It turned out that the problem is not connected with the pixel model.
The code for the point pixel model:

IppStatus ResizeShift_8u_C1R(const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
 Ipp8u* pDst, int dstStep, IppiSize dstRoiSize,
 double xFactor, double yFactor, double xShift, double yShift)
{
    IppStatus status = ippStsNoErr;
    IppiWarpSpec* pSpec = 0;
    double coeffs[2][3] = { 0 };
    int specSize = 0;
    int initSize = 0;
    int bufSize = 0;
    Ipp8u* pBuffer = 0;
    Ipp8u* pInit = 0;
    IppiPoint dstOffset = { 0, 0 };
    IppiBorderType borderType = ippBorderConst;
    Ipp64f borderValue = 0;
    IppiWarpDirection direction = ippWarpForward;
    Ipp32u numChannels = 1;
    Ipp32f valueB = 0.0f;
    Ipp32f valueC = 0.0f;
    int smoothEdge = 0;
    IppiInterpolationType interpolationType;
    IppiSize srcRoiSize;
    IppiSize resizeSrcRoiSize;

    interpolationType = ippCubic;
    // Set pSrcRoi to top-left corner of source ROI
    Ipp8u* pSrcRoi = (Ipp8u*)((Ipp8u*)pSrc + srcROI.y * srcStep) + srcROI.x * numChannels;
    // Set size of source ROI
    srcRoiSize.width = srcROI.width;
    srcRoiSize.height = srcROI.height;

    double xCenter = srcROI.width / 2;
    double yCenter = srcROI.height / 2;

    // Calculate center point relative to srcRoi offset.
    double xCenterSrcRoi = xCenter - srcROI.x - xShift;
    double yCenterSrcRoi = yCenter - srcROI.y - yShift;

    // Set scale coefficients
    coeffs[0][0] = (srcRoiSize.width > 1) ? (srcRoiSize.width  * xFactor - 1) / (srcRoiSize.width - 1) : 1;
    coeffs[1][1] = (srcRoiSize.height > 1) ? (srcRoiSize.height * yFactor - 1) / (srcRoiSize.height - 1) : 1;

    // Set shift coefficients
    coeffs[0][2] = (dstRoiSize.width / 2.0f) - (coeffs[0][0] * xCenterSrcRoi);
    coeffs[1][2] = (dstRoiSize.height / 2.0f) - (coeffs[1][1] * yCenterSrcRoi);

    // Get size of specification structure buffer and initialization buffer
    status = ippiWarpAffineGetSize(srcRoiSize, dstRoiSize, ipp8u, coeffs, interpolationType, direction, borderType, &specSize, &initSize);
    if (status < ippStsNoErr) return status;
    // Allocate memory for specification structure buffer
    pSpec = (IppiWarpSpec*)ippsMalloc_8u(specSize);
    if (pSpec == 0)
    {
        return ippStsNoMemErr;
    }
    //Initialize specification structure buffer correspond to interpolation type

    pInit = ippsMalloc_8u(initSize);
    status = ippiWarpAffineCubicInit(srcRoiSize, dstRoiSize, ipp8u, coeffs, direction, numChannels, valueB, valueC, borderType, &borderValue, smoothEdge, pSpec, pInit);
    ippsFree(pInit);

    if (status < ippStsNoErr)
    {
        ippsFree(pSpec);
        return status;
    }
    // Get work buffer size
    status = ippiWarpGetBufferSize(pSpec, dstRoiSize, &bufSize);
    if (status < ippStsNoErr)
    {
        ippsFree(pSpec);
        return status;
    }
    // Allocate work buffer
    pBuffer = ippsMalloc_8u(bufSize);
    if (pBuffer == 0)
    {
        ippsFree(pSpec);
        return ippStsNoMemErr;
    }
    //Execute warping processing correspond to interpolation type
    status = ippiWarpAffineCubic_8u_C1R(pSrcRoi, srcStep, pDst, dstStep, dstOffset, dstRoiSize, pSpec, pBuffer);

    // Free memory
    ippsFree(pSpec);
    ippsFree(pBuffer);
    return status;
}

ippStsSizeWrn occurs because of the fact that Init function is called for resizeSrcRoiSize that is less than dstRoiSize.

Best regards,
Valentin

View solution in original post

20 Replies
Tam_N_1
Beginner
239 Views

Hi there,

You can use Warp Affine instead of ippiResize. dstOffset and dstRoi in Warp Affine works perfectly.

You can use the code which Valentine supported. I modified it a bit to match your need

IppStatus ResizeShift_32f_C1R(const Ipp32f* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
                        Ipp32f* pDst, int dstStep, IppiSize dstRoiSize,
                        double xFactor, double yFactor, double xShift, double yShift)
{
    IppStatus status = ippStsNoErr;                    
    IppiWarpSpec* pSpec = NULL;                        
    double coeffs[2][3] = { 0 };                    
    int specSize = 0;                            
    int initSize = 0;                                
    int bufSize = 0;                                
    Ipp8u* pBuffer = NULL;                            
    Ipp8u* pInit = NULL;                            
    IppiPoint dstOffset = { 0, 0 };                    
    IppiBorderType borderType = ippBorderConst;        
    Ipp64f borderValue = 0;                            
    IppiWarpDirection direction = ippWarpForward;    
    Ipp32u numChannels = 1;                            
    Ipp32f valueB = 0.0f;                            
    Ipp32f valueC = 0.0f;                            
    int smoothEdge = 0;                                
    IppiInterpolationType interpolationType;        
    IppiSize srcRoiSize;                            
    IppiSize resizeSrcRoiSize;                        

    // Get interpolation filter type
  
     interpolationType = ippCubic;
    // Set pSrcRoi to top-left corner of source ROI
    Ipp32f* pSrcRoi = (Ipp32f*)((Ipp8u*)pSrc + srcROI.y * srcStep) + srcROI.x * numChannels;
    // Set size of source ROI
    srcRoiSize.width = srcROI.width;
    srcRoiSize.height = srcROI.height;
    // Calculate size of resize source ROI
    resizeSrcRoiSize.width =  (int)(srcRoiSize.width  * xFactor);
    resizeSrcRoiSize.height = (int)(srcRoiSize.height * yFactor);
    // Set scale coefficients

    coeffs[0][0] = (srcRoiSize.width > 1) ? (srcRoiSize.width  * xFactor - 1) / (srcRoiSize.width - 1) : 1;
    coeffs[1][1] = (srcRoiSize.height > 1)? (srcRoiSize.height * yFactor - 1) / (srcRoiSize.height - 1) : 1;
    coeffs[0][2] = xShift;
	coeffs[1][2] = yShift;

    // Get size of specification structure buffer and initialization buffer
    status = ippiWarpAffineGetSize(srcRoiSize, resizeSrcRoiSize, ipp32f, coeffs, interpolationType, direction, borderType, &specSize, &initSize);
    if (status < ippStsNoErr) return status;
    // Allocate memory for specification structure buffer
    pSpec = (IppiWarpSpec*)ippsMalloc_8u(specSize);
    if (pSpec == NULL)
    {
        return ippStsNoMemErr;
    }
    //Initialize specification structure buffer correspond to interpolation type

    pInit = ippsMalloc_8u(initSize);
    status = ippiWarpAffineCubicInit(srcRoiSize, resizeSrcRoiSize, ipp32f, coeffs, direction, numChannels, valueB, valueC, borderType, &borderValue, smoothEdge, pSpec, pInit);
     ippsFree(pInit);
  
    if (status < ippStsNoErr)
    {
        ippsFree(pSpec);
        return status;
    }
    // Get work buffer size
    status = ippiWarpGetBufferSize(pSpec, resizeSrcRoiSize, &bufSize);
    if (status < ippStsNoErr)
    {
        ippsFree(pSpec);
        return status;
    }
    // Allocate work buffer
    pBuffer = ippsMalloc_8u(bufSize);
    if (pBuffer == NULL)
    {
        ippsFree(pSpec);
        return ippStsNoMemErr;
    }
    //Execute warping processing correspond to interpolation type
 
    status = ippiWarpAffineCubic_32f_C1R(pSrcRoi, srcStep, pDst, dstStep, dstOffset, dstRoiSize, pSpec, pBuffer);
    
    // Free memory
    ippsFree(pSpec);
    ippsFree(pBuffer);
    return status;
}

 

umundry
Beginner
239 Views

Hi Tam,

I only saw an hour ago that you had responded. There was a time when one would get an email notification when a comment was posted. Oh well.

Anyway, I tried your version of the code, except I have byte-sized pixels in src as well as dst.

Therefore I modified the function to

IppStatus ResizeShift_8u_C1R(const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,

Ipp8u* pDst, int dstStep, IppiSize dstRoiSize,

double xFactor, double yFactor, double xShift, double yShift)

changing the pBuffer to Ipp8u*

and making the warp call ippiWarpAffineCubic_8u_C1R()

I get an ippStsContextMatchErr (-17), exactly what I got last week and caused me to post this.

What could be wrong?

Thank you!

Tam_N_1
Beginner
239 Views

Hi Umundry,

I guess you did not change ipp32f type to ipp8u type in ippiWarpAffineGetSize and ippiWarpAffineCubicInit function.

Try my code:

IppStatus ResizeShift_8u_C1R(const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
	Ipp8u* pDst, int dstStep, IppiSize dstRoiSize,
	double xFactor, double yFactor, double xShift, double yShift)
{
	IppStatus status = ippStsNoErr;
	IppiWarpSpec* pSpec = 0;
	double coeffs[2][3] = { 0 };
	int specSize = 0;
	int initSize = 0;
	int bufSize = 0;
	Ipp8u* pBuffer = 0;
	Ipp8u* pInit = 0;
	IppiPoint dstOffset = { 0, 0 };
	IppiBorderType borderType = ippBorderConst;
	Ipp64f borderValue = 0;
	IppiWarpDirection direction = ippWarpForward;
	Ipp32u numChannels = 1;
	Ipp32f valueB = 0.0f;
	Ipp32f valueC = 0.0f;
	int smoothEdge = 0;
	IppiInterpolationType interpolationType;
	IppiSize srcRoiSize;
	IppiSize resizeSrcRoiSize;

	interpolationType = ippCubic;
	// Set pSrcRoi to top-left corner of source ROI
	Ipp8u* pSrcRoi = (Ipp8u*)((Ipp8u*)pSrc + srcROI.y * srcStep) + srcROI.x * numChannels;
	// Set size of source ROI
	srcRoiSize.width = srcROI.width;
	srcRoiSize.height = srcROI.height;
	// Calculate size of resize source ROI
	resizeSrcRoiSize.width = (int)(srcRoiSize.width  * xFactor);
	resizeSrcRoiSize.height = (int)(srcRoiSize.height * yFactor);
	// Set scale coefficients

	coeffs[0][0] = (srcRoiSize.width > 1) ? (srcRoiSize.width  * xFactor - 1) / (srcRoiSize.width - 1) : 1;
	coeffs[1][1] = (srcRoiSize.height > 1) ? (srcRoiSize.height * yFactor - 1) / (srcRoiSize.height - 1) : 1;
	coeffs[0][2] = xShift;
	coeffs[1][2] = yShift;

	// Get size of specification structure buffer and initialization buffer
	status = ippiWarpAffineGetSize(srcRoiSize, resizeSrcRoiSize, ipp8u, coeffs, interpolationType, direction, borderType, &specSize, &initSize);
	if (status < ippStsNoErr) return status;
	// Allocate memory for specification structure buffer
	pSpec = (IppiWarpSpec*)ippsMalloc_8u(specSize);
	if (pSpec == 0)
	{
		return ippStsNoMemErr;
	}
	//Initialize specification structure buffer correspond to interpolation type

	pInit = ippsMalloc_8u(initSize);
	status = ippiWarpAffineCubicInit(srcRoiSize, resizeSrcRoiSize, ipp8u, coeffs, direction, numChannels, valueB, valueC, borderType, &borderValue, smoothEdge, pSpec, pInit);
	ippsFree(pInit);

	if (status < ippStsNoErr)
	{
		ippsFree(pSpec);
		return status;
	}
	// Get work buffer size
	status = ippiWarpGetBufferSize(pSpec, resizeSrcRoiSize, &bufSize);
	if (status < ippStsNoErr)
	{
		ippsFree(pSpec);
		return status;
	}
	// Allocate work buffer
	pBuffer = ippsMalloc_8u(bufSize);
	if (pBuffer == 0)
	{
		ippsFree(pSpec);
		return ippStsNoMemErr;
	}
	//Execute warping processing correspond to interpolation type

	status = ippiWarpAffineCubic_8u_C1R(pSrcRoi, srcStep, pDst, dstStep, dstOffset, dstRoiSize, pSpec, pBuffer);

	// Free memory
	ippsFree(pSpec);
	ippsFree(pBuffer);
	return status;
}

 

umundry
Beginner
239 Views

Thank you Tam, yes, that fixed that problem, my fault, sorry.

Since I don't understand the coeffs param (I can't find a good explanation of it and is not what I would normally use (which would be a 4x4 matrix)), the next problem is that the zoom center in your code is at (0,0), in my case it needs to be in the center of the destination matrix, and the panning needs to happen on the destination image. The latter is probably trivial (just multiplying the shift values by the factor values). So how do I get the zoom center shifted?

A good explanation of the coeffs param would also be very helpful.

Thank you again and Best Regards,

Uwe

Tam_N_1
Beginner
239 Views

Hi Umundry,

I think that you could calculate the xShift and yShift value correctly to make resized image in center of destination matrix.

Let xCenter and yCenter is center point of source image. You can map this point (xCenter, yCenter) to the center of destination image by calculating shift coefficients as following:

	// Calculate size of resize source ROI
	resizeSrcRoiSize.width  = (int)(srcRoiSize.width  * xFactor);
	resizeSrcRoiSize.height = (int)(srcRoiSize.height * yFactor);
	// Calculate center point relative to srcRoi offset.
	double xCenterSrcRoi = xCenter - srcROI.x;
	double yCenterSrcRoi = yCenter - srcROI.y;
	// Set scale coefficients
        //  .................
	// Set shift coefficients
	coeffs[0][2] = (dstRoiSize.width  / 2.0f) - (coeffs[0][0] * xCenterSrcRoi);
	coeffs[1][2] = (dstRoiSize.height / 2.0f) - (coeffs[1][1] * yCenterSrcRoi);

 

umundry
Beginner
239 Views

Thank you Tam!

It is getting ever closer, the zoom is now from center, perfect. The only remaining problem now is that the width of the output image is clipped horizontally as a function of zoom factors. The larger the zoom factors, the further the right edge output image moves to the right, and the smaller they get, the more is clipped off the right side of the output image. At zoom factors of 1.0 I see exactly the left half of the output image.

On the side, I believe you omitted the xShift and yShift in your latest code snipped, they need to be added to the coeffs[0]2[] and coeffs[1][2] respectively...?

Thank you one more time!

Tam_N_1
Beginner
239 Views

Hi,

I have replaced

coeffs[0][2] = xShift;
coeffs[1][2] = yShift;

to

coeffs[0][2] = (dstRoiSize.width  / 2.0f) - (coeffs[0][0] * xCenterSrcRoi);
coeffs[1][2] = (dstRoiSize.height / 2.0f) - (coeffs[1][1] * yCenterSrcRoi);

xShift, yShift is replaced by xCenter, yCenter. You only need to define the the point at {xCenter,yCenter} in source image. After scaling, this point will place at center point of destination image.

This is same as the function ippiResizeCenter: 

http://scc.ustc.edu.cn/zlsc/sugon/intel/ipp/ipp_manual/IPPI/ippi_ch12/functn_ResizeCenter.htm

 

Chao_Y_Intel
Employee
239 Views

HI, 

In the new IPP 2017 beta release, we are release some integration wrapper, which will include some high level APIs for the resize.  It will be easier to use it. I provide you an update here, when the package is ready. 

thanks,
Chao

umundry
Beginner
239 Views

Hello Tam,

this is still not working as expected.

The incoming srcROI is { 0, 0, 284, 284 }

The requested dstROI is { 0, 0, 617, 249 }

xFactor and yFactor is 1, and xShift and yShift are zero.

With that I would expect the upper left corner of the image be placed at { 167, -18 }, i.e. the upper and lower portions of the image be clipped as they hang over at top and bottom of dstROI, that is, the output image would be centered horizontally and vertically in the dstROI.

Instead the upper left corner of the image is anchored at { 0, 0} causing the image to always be aligned on the left, and not centered horizontally in the dst image matrix. You have set the dstOffset to {0,0}. If I tinker with that it causes the output image to be clipped more or less on the right, i.e. the higher the dstOffset.x, the more the image is clipped on the right. That is, with larger dstOffset.x the image gets more narrow, but the image remains anchored to the left edge of the dst matrix. I need it centered.

What is wrong?

Thank you!

umundry
Beginner
239 Views

Hello Tam,

further to my post from minutes ago I see that coeffs[0][2] and coeffs[1][2] do indeed contain the expected upper left corner of the output image (166.5, -17.5), so it seems the warp does not honor these. Something is wrong, but what is?

I wished I could find a detailed description of this coeffs business. Do you have a link to that? The documentation is too vague on this.

Thank you!

umundry
Beginner
239 Views

Hi Tam,

To give you a visual as to what is happening I am attaching a video showing the clipping on the right side of the image as a function of xFactor/yFactor. When the factors are set to cover the entire viewport, everything is fine. Larger zoom factors are also fine. But as the zoom factor gets smaller the clipping appears.

Tam_N_1
Beginner
239 Views

Hi,

I guess, in your case, you need to calculate pointer correspond to your dstRoi. If possible, send part of your code here which may be easier for me to help you. 

Regards,

 

Valentin_K_Intel
Employee
239 Views

Hi Umundry, Tam, 

It seems the problem can be connected with the pixel model of WarpAffine, where the pixel is just a point without size. To use the square pixel model the following values should be added to the shift coefficients:

coeffs[0][2] += 0.5 * coeffs[0][0] - 0.5;
coeffs[1][2] += 0.5 * coeffs[1][1] - 0.5;

The formulas above can be obtained from the assumption that the pixel is a rectangle with size 1x1.

So the scale operation for the source pixel with indices (j,i) without shifting can be represented as:

dx[j,i] = (j + 0.5) * xFactor - 0.5 = j * xFactor + (0.5 * xFactor - 0.5)
dy[j,i] = (i + 0.5) * y
Factor - 0.5 = i * yFactor + (0.5 * yFactor - 0.5)

Where dx[j,i], dy[j,i] - mapped coordinates of the source pixel with indices (j,i). 0.5 - shifting to the pixel center

Best regards,
Valentin

umundry
Beginner
239 Views

Hello Tam, Valentin,

I have modified the code to include Valentin's suggestion. The result is exactly the same as shown in the video. Somehow the warp incorrectly adjusts the dstROI width. Strangely the height seems to work properly. Tam, to offset the dst pointer to the upper left corner of the dstROI is what I am trying to prevent. Currently I am doing this pan/zoom business in 2 steps 1) resize 2) pan. That involves exactly what you are suggesting. The problem with that is it requires all sorts of limit checks so the dstROI is not going beyond the limits of the output matrix, and is ugly. That is why I am after getting the warp working properly. Here is the current latest code (which produces the results seen in the video, i.e. clips the right edge of the output image).

IppStatus ResizeShift_8u_C1R(const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
 Ipp8u* pDst, int dstStep, IppiSize dstRoiSize,
 double xFactor, double yFactor, double xShift, double yShift)
{
 IppStatus status = ippStsNoErr;
 IppiWarpSpec* pSpec = 0;
 double coeffs[2][3] = { 0 };
 int specSize = 0;
 int initSize = 0;
 int bufSize = 0;
 Ipp8u* pBuffer = 0;
 Ipp8u* pInit = 0;
 IppiPoint dstOffset = { 0, 0 };
 IppiBorderType borderType = ippBorderConst;
 Ipp64f borderValue = 0;
 IppiWarpDirection direction = ippWarpForward;
 Ipp32u numChannels = 1;
 Ipp32f valueB = 0.0f;
 Ipp32f valueC = 0.0f;
 int smoothEdge = 0;
 IppiInterpolationType interpolationType;
 IppiSize srcRoiSize;
 IppiSize resizeSrcRoiSize;

 interpolationType = ippCubic;
 // Set pSrcRoi to top-left corner of source ROI
 Ipp8u* pSrcRoi = (Ipp8u*)((Ipp8u*)pSrc + srcROI.y * srcStep) + srcROI.x * numChannels;
 // Set size of source ROI
 srcRoiSize.width = srcROI.width;
 srcRoiSize.height = srcROI.height;
 // Calculate size of resize source ROI
 resizeSrcRoiSize.width = (int)(srcRoiSize.width  * xFactor);
 resizeSrcRoiSize.height = (int)(srcRoiSize.height * yFactor);

 double xCenter = srcROI.width / 2;
 double yCenter = srcROI.height / 2;

 // Calculate center point relative to srcRoi offset.
 double xCenterSrcRoi = xCenter - srcROI.x - xShift;
 double yCenterSrcRoi = yCenter - srcROI.y - yShift;

 // Set scale coefficients
 coeffs[0][0] = (srcRoiSize.width > 1) ? (srcRoiSize.width  * xFactor - 1) / (srcRoiSize.width - 1) : 1;
 coeffs[1][1] = (srcRoiSize.height > 1) ? (srcRoiSize.height * yFactor - 1) / (srcRoiSize.height - 1) : 1;

 // Set shift coefficients
 coeffs[0][2] = (dstRoiSize.width / 2.0f) - (coeffs[0][0] * xCenterSrcRoi);
 coeffs[1][2] = (dstRoiSize.height / 2.0f) - (coeffs[1][1] * yCenterSrcRoi);

 coeffs[0][2] += 0.5 * coeffs[0][0] - 0.5;
 coeffs[1][2] += 0.5 * coeffs[1][1] - 0.5;

 // Get size of specification structure buffer and initialization buffer
 status = ippiWarpAffineGetSize(srcRoiSize, resizeSrcRoiSize, ipp8u, coeffs, interpolationType, direction, borderType, &specSize, &initSize);
 if (status < ippStsNoErr) return status;
 // Allocate memory for specification structure buffer
 pSpec = (IppiWarpSpec*)ippsMalloc_8u(specSize);
 if (pSpec == 0)
 {
  return ippStsNoMemErr;
 }
 //Initialize specification structure buffer correspond to interpolation type

 pInit = ippsMalloc_8u(initSize);
 status = ippiWarpAffineCubicInit(srcRoiSize, resizeSrcRoiSize, ipp8u, coeffs, direction, numChannels, valueB, valueC, borderType, &borderValue, smoothEdge, pSpec, pInit);
 ippsFree(pInit);

 if (status < ippStsNoErr)
 {
  ippsFree(pSpec);
  return status;
 }
 // Get work buffer size
 status = ippiWarpGetBufferSize(pSpec, resizeSrcRoiSize, &bufSize);
 if (status < ippStsNoErr)
 {
  ippsFree(pSpec);
  return status;
 }
 // Allocate work buffer
 pBuffer = ippsMalloc_8u(bufSize);
 if (pBuffer == 0)
 {
  ippsFree(pSpec);
  return ippStsNoMemErr;
 }
 //Execute warping processing correspond to interpolation type
 status = ippiWarpAffineCubic_8u_C1R(pSrcRoi, srcStep, pDst, dstStep, dstOffset, dstRoiSize, pSpec, pBuffer);

 // Free memory
 ippsFree(pSpec);
 ippsFree(pBuffer);
 return status;
}

 

Tam_N_1
Beginner
239 Views

Hi

Could you support the piece of code which call ResizeShift_8u_C1R functions? And please note about which arguments will change values when you zoom in/out as demo video? It will be more clearer to figure out your settings.

Regards,

Tam

Valentin_K_Intel
Employee
239 Views

Hello,

I suppose that the approach with the square pixel model via WarpAffine can be compatible only with the border type ippBorderRepl.

Best regards,
Valentin

umundry
Beginner
239 Views

Hi Valentin,

I just tried, it makes no difference if the border type is const or repl.

Thanks!

umundry
Beginner
239 Views

Hello Tam,

below is a call to the function which demonstrates the problem. As you can see, the source height is larger than the destination height, so the destination image will be higher than the source (with xFactor and yFactor set to 1.0). With that, after the call please check out row 0 of the destination matrix. Data will start in column 166 of row 0 (as expected), and it should extend to column 166 + 284 = 450, but it ends at column 283. So the right half of the image is cut off:

  pDst[163] 0
  pDst[164] 0
  pDst[165] 0
  pDst[166] 128
  pDst[167] 255
  pDst[168] 255
  pDst[169] 255

...

  pDst[279] 255 
  pDst[280] 255 
  pDst[281] 255 
  pDst[282] 255 
  pDst[283] 255 
  pDst[284] 0 
  pDst[285] 0 
  pDst[286] 0 
  pDst[287] 0 

I am also getting an ippStsSizeWrn (48) status when I make the warp call as a result of the below call.

What may be wrong?

Thanks!

 

 

  IppiSize srcSize = { 284, 284 };
  IppiRect srcROI = { 0, 0, srcSize.width, srcSize.height };
  byte *pSrc = new byte[srcSize.width * srcSize.height];
  memset(pSrc, 255, srcSize.width * srcSize.height);

  IppiSize dstSize = { 617, 249 };
  byte *pDst = new byte[dstSize.width * dstSize.height];
  memset(pDst, 0, dstSize.width * dstSize.height);

  double xFactor = 1.0;
  double yFactor = 1.0;

  ippStatus = ResizeShift_8u_C1R(pSrc, srcSize, srcSize.width, srcROI, pDst, dstSize.width, dstSize, xFactor, yFactor, 0, 0);

 

Valentin_K_Intel
Employee
240 Views

Hi Umudry,

It turned out that the problem is not connected with the pixel model.
The code for the point pixel model:

IppStatus ResizeShift_8u_C1R(const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
 Ipp8u* pDst, int dstStep, IppiSize dstRoiSize,
 double xFactor, double yFactor, double xShift, double yShift)
{
    IppStatus status = ippStsNoErr;
    IppiWarpSpec* pSpec = 0;
    double coeffs[2][3] = { 0 };
    int specSize = 0;
    int initSize = 0;
    int bufSize = 0;
    Ipp8u* pBuffer = 0;
    Ipp8u* pInit = 0;
    IppiPoint dstOffset = { 0, 0 };
    IppiBorderType borderType = ippBorderConst;
    Ipp64f borderValue = 0;
    IppiWarpDirection direction = ippWarpForward;
    Ipp32u numChannels = 1;
    Ipp32f valueB = 0.0f;
    Ipp32f valueC = 0.0f;
    int smoothEdge = 0;
    IppiInterpolationType interpolationType;
    IppiSize srcRoiSize;
    IppiSize resizeSrcRoiSize;

    interpolationType = ippCubic;
    // Set pSrcRoi to top-left corner of source ROI
    Ipp8u* pSrcRoi = (Ipp8u*)((Ipp8u*)pSrc + srcROI.y * srcStep) + srcROI.x * numChannels;
    // Set size of source ROI
    srcRoiSize.width = srcROI.width;
    srcRoiSize.height = srcROI.height;

    double xCenter = srcROI.width / 2;
    double yCenter = srcROI.height / 2;

    // Calculate center point relative to srcRoi offset.
    double xCenterSrcRoi = xCenter - srcROI.x - xShift;
    double yCenterSrcRoi = yCenter - srcROI.y - yShift;

    // Set scale coefficients
    coeffs[0][0] = (srcRoiSize.width > 1) ? (srcRoiSize.width  * xFactor - 1) / (srcRoiSize.width - 1) : 1;
    coeffs[1][1] = (srcRoiSize.height > 1) ? (srcRoiSize.height * yFactor - 1) / (srcRoiSize.height - 1) : 1;

    // Set shift coefficients
    coeffs[0][2] = (dstRoiSize.width / 2.0f) - (coeffs[0][0] * xCenterSrcRoi);
    coeffs[1][2] = (dstRoiSize.height / 2.0f) - (coeffs[1][1] * yCenterSrcRoi);

    // Get size of specification structure buffer and initialization buffer
    status = ippiWarpAffineGetSize(srcRoiSize, dstRoiSize, ipp8u, coeffs, interpolationType, direction, borderType, &specSize, &initSize);
    if (status < ippStsNoErr) return status;
    // Allocate memory for specification structure buffer
    pSpec = (IppiWarpSpec*)ippsMalloc_8u(specSize);
    if (pSpec == 0)
    {
        return ippStsNoMemErr;
    }
    //Initialize specification structure buffer correspond to interpolation type

    pInit = ippsMalloc_8u(initSize);
    status = ippiWarpAffineCubicInit(srcRoiSize, dstRoiSize, ipp8u, coeffs, direction, numChannels, valueB, valueC, borderType, &borderValue, smoothEdge, pSpec, pInit);
    ippsFree(pInit);

    if (status < ippStsNoErr)
    {
        ippsFree(pSpec);
        return status;
    }
    // Get work buffer size
    status = ippiWarpGetBufferSize(pSpec, dstRoiSize, &bufSize);
    if (status < ippStsNoErr)
    {
        ippsFree(pSpec);
        return status;
    }
    // Allocate work buffer
    pBuffer = ippsMalloc_8u(bufSize);
    if (pBuffer == 0)
    {
        ippsFree(pSpec);
        return ippStsNoMemErr;
    }
    //Execute warping processing correspond to interpolation type
    status = ippiWarpAffineCubic_8u_C1R(pSrcRoi, srcStep, pDst, dstStep, dstOffset, dstRoiSize, pSpec, pBuffer);

    // Free memory
    ippsFree(pSpec);
    ippsFree(pBuffer);
    return status;
}

ippStsSizeWrn occurs because of the fact that Init function is called for resizeSrcRoiSize that is less than dstRoiSize.

Best regards,
Valentin

View solution in original post

umundry
Beginner
134 Views

Hello Valentin,

that fixed the problem for good, works perfectly now. Tam was very close except one minor detail :-)

Thank you both for your efforts and time!

Reply