为什么iplRotate()没有给我正确的结果?

时间:2009-05-15 21:07:06

标签: c++ windows image-processing intel-ipp

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

  1. 我有一张源图片。它的大小(w,h),不一定是正方形。
  2. 它将按角度 theta 旋转。
  3. 我已计算出适合按角度 theta 旋转的尺寸(w,h)的图像所需的输出尺寸。此大小为(dw,dh)。我已经分配了一个具有该大小的目标缓冲区。
  4. 我想围绕源图像的中心(w / 2,h / 2)以角度 theta 旋转源图像,并 >旋转的图像在我的目标缓冲区中居中。
  5. iplRotate ()需要2个移位参数, xShift yShift ,这表示图像应沿x和y移动的距离执行旋转后的轴。

    问题是我无法让iplRotate将旋转的图像置于目标图像的中心。它总是偏离中心。

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

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

    但这不起作用,我不知道还有什么办法来计算 xShift yShift 。有没有人有任何关于如何使用iplRotate做我想要的建议?

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

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

    但事实并非如此。


    修改 我使用英特尔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 个答案:

答案 0 :(得分:5)

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

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

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

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

注意:这些函数是指IPP库版本5.3(我的版本)。我不确定AddLotateShift在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);

答案 1 :(得分:1)

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

您的结果将是一个包含一些负值的新框。如果你理解我的意思,你想“转回”所以无论你有什么负面价值都会变为零。

答案 2 :(得分:1)

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

iplGetRotateShift( w / 2.0,  h / 2.0, angle, &xShift, &yShift );

答案 3 :(得分:1)

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

在数学上

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

所以如果theta = pi / 6说,那么如果w = 100且h = 150,那么可能dw = 162?

你得到的错误位置是否因theta而异?据推测它适用于theta = 0?那么theta = pi / 2和theta = pi / 4?