如何从LogPolar变换中获取比例和旋转角度

11

我正在尝试使用LogPolar变换从两个图像中获取比例和旋转角度。下面是两个300x300的样本图像。第一个矩形是100x100,第二个矩形是150x150,旋转了45度。

enter image description here enter image description here

算法:

  1. 将两个图像都转换为LogPolar形式。
  2. 使用相位相关法找到平移位移。
  3. 将平移位移转换为比例和旋转角度(如何实现?)。

我的代码:

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/imgproc_c.h>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

int main()
{
    cv::Mat a = cv::imread("rect1.png", 0);
    cv::Mat b = cv::imread("rect2.png", 0);
    if (a.empty() || b.empty())
        return -1;

    cv::imshow("a", a);
    cv::imshow("b", b);

    cv::Mat pa = cv::Mat::zeros(a.size(), CV_8UC1);
    cv::Mat pb = cv::Mat::zeros(b.size(), CV_8UC1);
    IplImage ipl_a = a, ipl_pa = pa;
    IplImage ipl_b = b, ipl_pb = pb;
    cvLogPolar(&ipl_a, &ipl_pa, cvPoint2D32f(a.cols >> 1, a.rows >> 1), 40);
    cvLogPolar(&ipl_b, &ipl_pb, cvPoint2D32f(b.cols >> 1, b.rows >> 1), 40);

    cv::imshow("logpolar a", pa);
    cv::imshow("logpolar b", pb);

    cv::Mat pa_64f, pb_64f;
    pa.convertTo(pa_64f, CV_64F);
    pb.convertTo(pb_64f, CV_64F);

    cv::Point2d pt = cv::phaseCorrelate(pa_64f, pb_64f);

    std::cout << "Shift = " << pt 
              << "Rotation = " << cv::format("%.2f", pt.y*180/(a.cols >> 1)) 
              << std::endl;

    cv::waitKey(0);

    return 0;
}

对数极坐标图像:

enter image description here enter image description here

对于上述示例图像,平移量为(16.2986, 36.9105)。我已经成功地获取了旋转角度,即 44.29。但我在计算比例时遇到了困难。如何将给定的平移量转换为比例?


你好,你能否阅读George Wolberg的论文“使用对数极坐标变换进行鲁棒图像配准”?我认为这篇论文非常简单明了,可以清楚地说明如何在对数极坐标空间中恢复比例和旋转。 - G453
@G453 我已经阅读了这篇论文以及其他一些论文。我不知道论文中的解释是否不清楚,还是我太蠢了,但我仍然无法编写恢复比例的正确代码。 - flowfree
位移向量有两个坐标,一个是角度,另一个是比例的对数。 - n. m.
给定位移向量(rho,theta),角度为theta,比例为exp(rho)。没有其他相关数据。 - n. m.
@bsdnoobz,你有没有得到这个问题的答案? - Shohreh
显示剩余2条评论
5个回答

2

这里是Python版本

它告诉我们:

ir = abs(ifft2((f0 * f1.conjugate()) / r0))
    i0, i1 = numpy.unravel_index(numpy.argmax(ir), ir.shape)
    angle = 180.0 * i0 / ir.shape[0]
    scale = log_base ** i1

2

你有两个图像f1f2,其中f1(m, n) = f2(m/a , n/a)。也就是说,f1按比例缩放了a倍。

在对数符号中,这相当于f1(log m, log n) = f2(logm − log a, log n − log a),其中log a是您的相位相关图像中的偏移量。

请参考B. S. Reddy, B. N. Chatterji: An FFT-Based Technique for Translation, Rotation and Scale-Invariant Image Registration, IEEE Transactions On Image Processing Vol. 5 No. 8, IEEE, 1996

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.185.4387&rep=rep1&type=pdf


期望的缩放因子为1.5,x轴上的平移量为16.2986。如果 log a = 16.2986,那么 a = 10 ^ 16.2986 - flowfree
请确保您考虑了IEEE文档中链接的第2页所描述的C语言中的对数转换。 - Oliver
2
顺便提一下,在你的代码中,你也计算了平移偏移量。你必须在第二步中使用角度和比例校正后的图像作为输入来完成这个步骤。 - Oliver

1
这篇帖子对我开始进行旋转不变相位相关起到了帮助作用,因此我希望我的意见能够帮助解决任何未解决的问题。
我们的目标是计算比例和旋转(代码中计算不正确)。让我们从logPolar docs中收集方程式。他们在那里陈述了以下内容:
(1) I = (dx,dy) = (x-center.x, y-center.y)
(2) rho = M * ln(magnitude(I))
(3) phi = Ky * angle(I)_0..360

注意:rho是上述代码中的pt.x,phi是pt.y。
我们还知道:
(4) M = src.cols/ln(maxRadius)
(5) Ky = src.rows/360

首先,让我们解决比例尺的问题。在方程式2中解决幅度(I)(即比例尺),我们得到:

(6) magnitude(I) = scale = exp(rho/M)

然后我们替换M并简化得到:
(7) magnitude(I) = scale = exp(rho*ln(maxRadius)/src.cols) = pow(maxRadius, rho/src.cols)

现在让我们来解决旋转问题。在方程3中解出角度(I)(即旋转),我们得到
(8) angle(I) = rotation = phi/Ky

然后我们替换Ky并简化,得到:
(9) angle(I) = rotation = phi*360/src.rows

因此,比例和旋转可以分别使用方程7和9进行计算。值得注意的是,应该使用方程4来计算M,使用Point2f center((float)a.cols/2, (float)a.rows/2)来计算中心,而不是上面的代码中的内容。在这个对数极坐标示例opencv代码中有很好的信息。

1
比例因子的值确实是exp(pt.y)。然而,由于您在cvLogPolar函数中使用了一个“幅度比例参数”40,现在需要将pt.x除以40以获得正确的位移值:
Scale = exp( pt.x / 40) = exp(16.2986 / 40) = 1.503

"magnitude scale parameter"对于cvLogPolar函数的值不会影响由旋转角度pt.x产生的位移,因为根据数学,它会被消除。因此,您对旋转的公式给出了正确的值。
另外,我认为旋转的公式实际上应该是:
旋转= pt.y*360/(a.cols)
但是,由于您添加的">> 1"会导致结果乘以2(我认为您通过乘以180而不是360来补偿这个问题?),从而导致某些奇怪的原因。删除它,您就会明白我的意思。
此外,“>> 1”会导致在以下位置进行除以2:
cvPoint2D32f(a.cols >> 1, a.rows >> 1)
如果将cvLogPolar函数的中心参数设置为图像的中心(这就是您想要的):
cvPoint2D32f(a.cols/2, a.rows/2)

cvPoint2D32f(b.cols/2, b.rows/2)
然后,您还将获得旋转的正确值(即您获得的相同值)和缩放的值。

0

通过相位相关的值,坐标是直角坐标系,因此(16.2986,36.9105)是(x,y)。比例尺计算为

比例尺= log((x^2 + y^ 2)^0.5),约为1.6(接近1.5)。

当我们使用公式theta = arctan(y/x) = 66(约)来计算角度时。Theta值偏离了实际值(在这种情况下为45)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接