Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is iplRotate() not giving me correct results?

sigh I'm sorry to say that I'm using Intel IPL (Image Processing Library) in some image processing code I'm working on. This is the tale of my struggle with getting my images to rotate correctly.

  1. I have a source image. It has a size (w, h) which is not necessarily square.
  2. It is going to be rotated by angle theta.
  3. I've calculated the output size required to fit an image of size (w, h) rotated by angle theta. This size is (dw, dh). I've allocated a destination buffer with that size.
  4. I want to rotate the source image by angle theta about the source image's center (w/2, h/2) and have that rotated image be centered in my destination buffer.

iplRotate() takes 2 shift parameters, xShift and yShift, which indicate the distance the image should be shifted along the x and y axis after the rotate is performed.

The problem is I cannot get iplRotate to center the rotated image in the destination image. It's always off center.

My best guess for what xShift and yShift should be is the following:

  • xShift = dw - w
  • yShift = dh - h

But this doesn't work, and I'm not sure what else to do to calculate xShift and yShift. Does anyone have any suggestions for how to use iplRotate to do what I want?

One last bit of info: I've attempted to use iplGetRotateShift() to calculate xShift and yShift, again, to no avail. I would imagine that this would work:

iplGetRotateShift(dw / 2.0, dh / 2.0, theta, &xShift, &yShift);

But it does not.


Edit: I rewrote the code using Intel IPP 6.0 instead of IPL and I'm seeing identical wrong results. I can't imagine that Intel got rotation wrong in 2 different libraries, so I must be doing something wrong.


Edit: I tried the following (IPP) code that Dani van der Meer suggested:

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;
ippiAddRotateShift(w / 2.0, h / 2.0, angle, &xShift, &yShift);

Unfortunately, still no luck. That does not work either.

like image 713
Rob Avatar asked Feb 28 '23 17:02

Rob


1 Answers

When using iplGetRotateShift you need to specify the center of rotation in the source image. This will work well if the size of the source and destination image is the same.

In your case you want an extra shift to center the image in your destination image:

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;

To combine the two shift you need to use ippiAddRotateShift instead of ippiGetRotateShift.

Note: These functions refer to the IPP library version 5.3 (the version I have). I am not sure that AddRotateShift is available in IPL. But you mentioned in the question that you tried the same using IPP, so hopefully you can use IPP instead of IPL.

You get something like this

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;
ippiAddRotateShift(w / 2.0, h / 2.0, angle, &xShift, &yShift);

If you use these shifts in the call to ippiRotate the image should be centered in the destination image.

I hope this helps.

EDIT: Here is the code I used to test (the change from w to dw and h to dh and the rotation angle are just random):

//Ipp8u* dst_p; Initialized somewhere else in the code
//Ipp8u* src_p; Initialized somewhere else in the code
int w = 1032;
int h = 778;
int dw = w - 40; // -40 is just a random change
int dh = h + 200; // 200 is just a random change
int src_step = w * 3;
int dst_step = dw * 3;
IppiSize src_size = { w, h };
IppiRect src_roi  = { 0, 0, w, h };
IppiRect dst_rect = { 0, 0, dw, dh };
double xShift = ((double)dw - (double)w) / 2.0;
double yShift = ((double)dh - (double)h) / 2.0;
ippiAddRotateShift((double)w / 2, (double)h / 2, 37.0, &xShift, &yShift);
ippiRotate_8u_C3R(src_p, src_size, src_step, src_roi, 
          dst_p, dst_step, dst_rect, 37.0, xShift, yShift, IPPI_INTER_NN);
like image 88
Dani van der Meer Avatar answered Mar 11 '23 07:03

Dani van der Meer