Quality of ippiResize

Quality of ippiResize

I have a problem with the downscaling I hope someone can help me with. The quality I get from downscaling is poor. Except for Supersampling all other resize functions produce similar results. This means that Bicubic looks the same as Nearest neighbor, which is quite bad.

Am I calling these functions incorrectly, or is there a way to get the IPP library to perform a good looking downsample that is not Supersampling?

thanks,
-Jon Clegg

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

Hi Jon,

it would be easier for us to help you when you provide more details or even demonstrate poor qulaity of resize function with sample picture.

Whithout that I have no idea what can wrong at your side. What version of IPP do you use, how you link with IPP statically or dynamically? What is your platform specification, like OS, processor?

Regards,
Vladimir

Vladimir,

I'm using ippResize. You can reproduce my results using the ippIP Demo application that ships with the IPP version 5.1.

Open up a bmp file. Select Process->Process by->Geometric Transforms->Resize ippResize_8u_C3R. Select Nearest Neighbor. Repeat the process but select Lanczos3 instead.

The result from Lanczos3 and Nearest Neighbor are similar in quality, both show a aliasing. The only method that produces a high quality result is Super Sampling.

Here is some output from my test:

http://www.mediaexcel.com/temp/super.bmp

http://www.mediaexcel.com/temp/lanczos3.bmp

http://www.mediaexcel.com/temp/nearest.bmp

thanks,

-Jon

Jon,

I recommend you to use ippiResizeSqrPixel function, which provides better quality, see ippi.h file

/* /////////////////////////////////////////////////////////////////////////////
//
// Name: ippiResizeSqrPixel
// Purpose: Performs RESIZE transform of the source image by xFactor and yFactor
// |X'| |xFactor 0 | |X| |xShift|
// | | = | | * | | + | |
// |Y'| | 0 yFactor| |Y| |yShift|
// Parameters:
// pSrc source image data
// srcSize size of src
// srcStep step in src
// srcROI region of interest of src
// pDst resultant image data
// dstStep step in dst
// dstROI region of interest of dst
// xFactor, yFactor they specify fractions of resizing
// xShift, yShift they specify shifts of resizing:
// interpolation type of interpolation to perform for resizing the input image:
// IPPI_INTER_NN nearest neighbor interpolation
// IPPI_INTER_LINEAR linear interpolation
// IPPI_INTER_CUBIC cubic convolution interpolation
// IPPI_INTER_LANCZOS interpolation by 3-lobed Lanczos-windowed sinc function
// Returns:
// ippStsNoErr no errors
// ippStsNullPtrErr pSrc == NULL or pDst == NULL or pBu ffer == NULL
// ippStsSizeErr width or height of images is less or equal zero
// ippStsWrongIntersectROI srcRoi has not intersection with the source image, no operation
// ippStsResizeFactorErr xFactor or yFactor is less or equal zero
// ippStsInterpolationErr (interpolation != IPPI_INTER_NN) &&
// (interpolation != IPPI_INTER_LINEAR) &&
// (interpolation != IPPI_INTER_CUBIC) &&
// (interpolation != IPPI_INTER_LANCZOS)
// Notes:
// not in-place
// square pixel realization (other algorithm for linear, cubic and lanczos interpolations)
// supporting neighbor, linear, cubic and lanczos interpolations modes now
*/
IPPAPI(IppStatus, ippiResizeSqrPixel_8u_C1R, (
const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp8u* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_8u_C3R, (
const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp8u* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_8u_C4R, (
const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp8u* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_8u_AC4R, (
const Ipp8u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp8u* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_8u_P3R, (
const Ipp8u* const pSrc[3], IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp8u* const pDst[3], int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI( IppStatus, ippiResizeSqrPixel_8u_P4R, (
const Ipp8u* const pSrc[4], IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp8u* const pDst[4], int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_16u_C1R, (
const Ipp16u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp16u* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_16u_C3R, (
const Ipp16u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp16u* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_16u_C4R, (
const Ipp16u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp16u* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_16u_AC4R, (
const Ipp16u* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp16u* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_16u_P3R, (
const Ipp16u* const pSrc[3], IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp16u* const pDst[3], int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_16u_P4R, (
const Ipp16u* const pSrc[4], IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp16u* const pDst[4], int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_32f_C1R, (
const Ipp32f* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp32f* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_32f_C3R, (
&nbs p; const Ipp32f* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp32f* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_32f_C4R, (
const Ipp32f* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp32f* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_32f_AC4R, (
const Ipp32f* pSrc, IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp32f* pDst, int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_32f_P3R, (
const Ipp32f* const pSrc[3], IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp32f* const pDst[3], int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))
IPPAPI(IppStatus, ippiResizeSqrPixel_32f_P4R, (
const Ipp32f* const pSrc[4], IppiSize srcSize, int srcStep, IppiRect srcROI,
Ipp32f* const pDst[4], int dstStep, IppiRect dstROI,
double xFactor, double yFactor, double xShift, double yShift,
int interpolation, Ipp8u *pBuffer))

Regards,
Vladimir

Thank you! This is exactly what I was looking for.

-Jon

Hello,

I'm also using the 'ippiResize' function. I encountered a problem and I hope you can help me. I use the 'ippiResize' with the 'IPPI_INTER_LINEAR' (interpolation). However, the result of this resize is different from the result I get when I use the Matlab function 'imresize' (also with bilinear interpolation). Do you know why? Do you know how to fix it?

When I use the 'nearest neighbour' interpolation I get identical results for the IPP and Matlab function.

Thanks, Yaniv.

Hello Yaniv,

could you please describe your issue in a little bit more details? What version of IPP do you use? How do you link IPP into your application, statically or dynamically? What was operation system and hardware platform you run test on? How do you compare results? What version of Matlab do you use? It would be nice if you can attach to that thread your source image data, data produced by IPP function and data you considered as a corrrect. Also would be helpful to have your test case sources (if it is not a big application).

Regards,
Vladimir

I'm not a user of IPP, but I think that Linear, bicubic and Lancsoz interpolation algorithms are designed for upscaling the image by nature. (If I'm not mistaken). That means they take existing values (for example two pixels), and calculate the pixels in between those pixels by applying interpolation from existing ones, thus enlarging the image. Supersampling algorith does work for making the image smaller by combining existing pixel values to a single one, thus shrinking the input image.

Nearest neighbor can do both jobs, because it only copies existing pixels data. That should be the problem. I think that when you try to downscale the image using bicubic, IPP reverts to NN algorithm instead.

I overcame this when I was using IPL with a code something like this

if (destWidth < m_width && destHeight < m_height)

iplResize(image, image2, destWidth, m_width, destHeight, m_height, IPL_INTER_SUPER);

else

iplResize(image, image2, destWidth, m_width, destHeight, m_height, IPL_INTER_CUBIC);

Hi,
I encountered the same problem.
Regardless of the interpolation method ippiResize_8u_C4R producesimages of very poor quality.
It would be nice if someone from IPP helps us.

Greetings,
Dex

Hi Dex,

it would be nice if you describe your "the same problem" in a bit more details. It also would be helpful if you can attach output pictures which you think demonstrate the poor quality of ippiResize function. In what direction you use resize, to downsample or upsample the image? What is your resize factors and what is image size? What version of IPP do you use and what platform you are running this?

Did you try ippiResizeSquarePixel function instead of ippiResize?

Regards,
Vladimir

Thank you for the prompt answer.

I had an input image of dimensions 5000x7520.

The image has been resized using both ippiResize and my own simple resizing function to 340x512 images (please instruct me how to attach the images).

I have WinXP, Pentium D 3.4Ghz, and xFactor = yFactor = 0.068, IPP 5.1.
dstStep = 4*340, srcStep = 20000, srcRoi=(0,0,5000,7520), dstRoi = (0,0,340,512).

I *want* bilinear interpolation, whence aliasing is highly undesirable.

Having in mind characteristics of bilinear interpolation, I can explain the introduced aliasing only by a problem in ippiResize_8u_C4R. I tested ippiResizeSqrPixel, but it was almost the same.

Thanks for providing details. Our experts recommend to use IPPI_INTER_SUPER interpolation to avoid aliasing as much as possible. You can take a look on sample image attached to this message where we run ippiResize of jaehne test image with your sizes for two interpolation settings: IPPI_INTER_LINEAR and IPPI_INTER_SUPER.

Feel the difference:)

Regards,
Vladimir

Attachments: 

AttachmentSize
Download ippiResize.JPG83.07 KB

Hi Vladimir,

My application crashes, because of

ippiResize_8u_C4R(pSrc, srcSize, srcStep, srcROI,

pDst, dstStep, dstSize,

dX, dY, iMethod).

Here is the exact description:

srcSize = (512, 4), srcStep = 2048, srcROI = (0, 0, 512, 4)

dstSize = (64, 64), dstStep = 256

dX = dY = 0.125

Interestingly, if I have:

srcSize = (4, 512), srcStep = 16, srcROI = (0, 0, 4, 512)

dstSize = (64, 64), dstStep = 256

dX = dY = 0.125,

then ippiResize_8u_C4R doesnt crash.

Finally, the crash occurs only under certain circumstances.

Therefore, I run my application from GlobalFlags (in Debugging Tool for Windows) with all Enable heap checked.

I assume that the problem is srcSize.height * dY = 0.5, but the crash can definitely be avoided by ippiResize_8u_C4R.

Besides, in the second case srcSize.width * dX= 0.5 doesnt cause any problems.

Can you help me?

Greetings,

Dex

Vladimir, I performed some more tests and I saw that the crash occurs when my input image (in the example above)is 512x4, 512x5, 512x6, and 512x7.

Thus, I have no problems for 512x1, 512x2, 512x3, 512x8, and larger heights.

I triple checked my memory allocations and I'm sure I do everything right.

Leave a Comment

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