4

叹息我很抱歉地说我在我正在处理的一些图像处理代码中使用英特尔 IPL(图像处理库)。这是我努力让图像正确旋转的故事。

  1. 我有一个源图像。它的大小(w, h)不一定是正方形。
  2. 它将旋转角度theta
  3. 我已经计算了适合大小为(w, h)的图像旋转角度theta所需的输出大小。这个大小是(dw, dh)。我已经分配了一个具有该大小的目标缓冲区。
  4. 我想通过围绕源图像中心(w/2,h/2)的角度theta旋转源图像,并使旋转后的图像在我的目标缓冲区中居中。

iplRotate () 采用 2 个移位参数xShiftyShift,它们表示执行旋转后图像应沿 x 和 y 轴移动的距离。

问题是我无法让 iplRotate 在目标图像中居中旋转图像。它总是偏离中心。

我对 xShift 和 yShift应该是什么的最佳猜测如下:

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

但这不起作用,我不确定还有什么可以计算xShiftyShift。有人对如何使用 iplRotate 做我想做的事有任何建议吗?

最后一点信息: 我尝试使用 iplGetRotateShift() 再次计算 xShift 和 yShift,但无济于事。我想这会起作用:

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

但事实并非如此。


编辑: 我使用 Intel IPP 6.0 而不是 IPL 重写了代码,我看到了相同的错误结果。我无法想象英特尔在 2 个不同的库中轮换错误,所以我一定做错了什么


编辑: 我尝试了 Dani van der Meer 建议的以下(IPP)代码:

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

不幸的是,仍然没有运气。那也不行。

4

4 回答 4

5

使用 iplGetRotateShift 时,您需要在源图像中指定旋转中心。如果源图像和目标图像的大小相同,这将很有效。

在您的情况下,您需要额外的转变以使图像在目标图像中居中:

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

要结合这两个班次,您需要使用 ippiAddRotateShift 而不是 ippiGetRotateShift。

注意:这些函数参考IPP库5.3版(我有的版本)。我不确定 AddRotateShift 在 IPL 中是否可用。但是您在问题中提到您尝试使用 IPP 进行相同的操作,因此希望您可以使用 IPP 而不是 IPL。

你得到这样的东西

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

如果您在调用 ippiRotate 时使用这些转换,则图像应位于目标图像的中心。

我希望这有帮助。

编辑: 这是我用来测试的代码(从 w 到 dw 和 h 到 dh 的变化和旋转角度只是随机的):

//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);
于 2009-05-20T16:04:11.230 回答
1

如果它仍然不适合您,那么我们可以确认这些假设是有效的吗?特别是第 3 点,您计算 dw 和 dh。

数学上

dw = w * |cos(theta)| + h * |sin(θ)|
dh = h * |cos(theta)| + w * |sin(θ)|

所以如果 theta = pi/6 说,那么如果 w = 100 和 h = 150 那么大概 dw = 162?

您得到的不正确位置是否随 theta 变化?大概它适用于theta = 0?theta=pi/2 和 theta=pi/4 呢?

于 2009-05-25T20:44:58.980 回答
1

根据我对文档的阅读,我认为您使用 iplGetRotateShift 错误。特别是,我认为您需要在源图像中指定旋转中心,而不是目标图像,因此:

iplGetRotateShift( w / 2.0,  h / 2.0, angle, &xShift, &yShift );
于 2009-05-19T05:32:51.873 回答
1

我以前从未使用过(或听说过)IPL,所以我只是在猜测 API 的作用。但是,如果 iplRotate 围绕 (0, 0) 旋转并且如果 iplGetRotateShift 类似,为什么不尝试旋转原始“盒子”的其他 3 个角(忽略 (0, 0),因为它保持不变): (w, 0), ( 0, h) 和 (w, h)。

您的结果将是一个带有一些负值的新框。你想“向后移动”,所以如果你明白我的意思,你所拥有的任何负值都会变为零。

于 2009-05-18T21:52:40.347 回答