C++ 为什么iplRotate()不能给我正确的结果?

C++ 为什么iplRotate()不能给我正确的结果?,c++,windows,image-processing,intel-ipp,C++,Windows,Image Processing,Intel Ipp,唉,很抱歉,在我正在编写的一些图像处理代码中使用了英特尔IPL(图像处理库)。这是我努力使图像正确旋转的故事 我有一个源图像。它的大小(w,h),不一定是正方形 它将以角度θ旋转 我已经计算了适合大小(w,h)按角度θ旋转的图像所需的输出大小。此大小为(dw,dh)。我已经分配了一个这样大小的目标缓冲区 我想通过角度θ旋转源图像,使其围绕源图像的中心(w/2,h/2),并使旋转后的图像在目标缓冲区中居中 iplRotate()采用两个移位参数,xShift和yShift,指示执行旋转后图像应沿x

唉,很抱歉,在我正在编写的一些图像处理代码中使用了英特尔IPL(图像处理库)。这是我努力使图像正确旋转的故事

  • 我有一个源图像。它的大小(w,h),不一定是正方形
  • 它将以角度θ旋转
  • 我已经计算了适合大小(w,h)按角度θ旋转的图像所需的输出大小。此大小为(dw,dh)。我已经分配了一个这样大小的目标缓冲区
  • 我想通过角度θ旋转源图像,使其围绕源图像的中心(w/2,h/2),并使旋转后的图像在目标缓冲区中居中
  • iplRotate()采用两个移位参数,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);
    
    但事实并非如此


    编辑: 我用“英特尔IPP 6.0”而不是IPL重写了代码,我看到了相同的错误结果。我无法想象英特尔在两个不同的库中出现了旋转错误,所以我一定是做错了什么


    编辑: 我尝试了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);
    
    不幸的是,仍然没有运气。这也不行。

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


    您的结果将是一个带有一些负值的新框。如果你明白我的意思,你想“向后移位”,这样无论你的负值是多少,都会变成零。

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

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

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

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

    xShift = (dw - w) / 2.0;
    yShift = (dh - h) / 2.0;
    
    要组合这两个移位,需要使用IPPIADDROATESHIFT而不是IPPIGETROATESHIFT

    注意:这些函数指的是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的变化以及旋转角度都是随机的):


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

    数学上

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

    如果θ=pi/6,那么如果w=100,h=150,那么假设dw=162


    你得到的错误位置是否随θ变化?假设它与θ=0一起工作?那么θ=π/2和θ=π/4呢?

    我已经试过了-但是,因为我的目标图像是旋转图像的最终大小,而不是源图像的大小,所以最终旋转图像偏离中心。我不清楚您到底想做什么。是否要将源图像围绕其原点(0,0)旋转θ角,然后将旋转后的图像置于目标图像的中心?或者,是否要围绕源图像(w/2,h/2)的中心旋转源图像,然后使其在目标图像中居中?@jd141,第二个-我要围绕源图像(w/2,h/2)的中心旋转源图像,然后使其在目标图像中居中。IPL的文档让我相信这是可能的。它在IPL中非常接近-因为没有iplAddRotateShift,我在调用iplGetRotateShift(x/2.0,…)后添加了(dx-x)/2.0。它仍然是10-15像素,虽然-我将不得不尝试与IPP,看看我得到什么。谢谢很抱歉,这也不起作用:-(我试过IPP,它给了我和IPL一样的错误结果。非常奇怪……我测试了我的代码,它看起来工作得很好,图像的中心在src和dst图像中是相同的。为了确保我发布了我用来测试的完整代码块,我会尝试一下-谢谢发布!出于好奇,你为什么要设置src_step to(w*3)?src_p是Ipp8u*类型-图像的步长不是只有w吗?我使用RGB图像。每个像素是3字节,因此步长(以字节为单位)是w*3。我面前没有代码,但我相当确定这是我用来计算
    //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);