【问题标题】:How to obtain the scale and rotation angle from LogPolar transform如何从 LogPolar 变换中获取比例和旋转角度
【发布时间】:2017-03-30 09:16:10
【问题描述】:

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

算法:

  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;
}

日志极坐标图像:

对于上面的示例图像,平移位移为(16.2986, 36.9105)。我已经成功获得了旋转角度,也就是44.29。但我很难计算规模。给定的平移位移如何转换得到尺度?

【问题讨论】:

  • 您好,您能浏览一下 George Wolberg 的论文“ROBUST IMAGE REGISTRATION USING LOG-POLAR TRANSFORM”...我认为如何在 Log- 中恢复比例和旋转非常简单明了极地空间....
  • @G453 我已经阅读了这篇论文以及其他一些论文。我不知道是论文中的解释不清楚还是我这么愚蠢,但我仍然无法编写正确的代码来恢复规模。
  • 移位向量有2个坐标,一个是角度,一个是刻度的对数。
  • @n.m.对我知道那个。我正在寻找的是 公式 来恢复给定移位向量、源图像宽度和高度、对数极坐标宽度和高度等的比例。
  • 给定位移向量 (rho,theta),角度为 theta,比例为 exp(rho)。没有其他相关数据。

标签: c++ opencv


【解决方案1】:

你有两个图像 f1f2 f1(m, n) = f2(m/a , n/a) is f1 被因子 a 缩放

在对数表示中,等价于 f1(log m, log n) = f2(logm - log a, log n - log a) 其中 log a 是相位相关图像的变化。

比较B。 S. Reddy, B. N. Chatterji:一种基于 FFT 的平移、旋转和 尺度不变的图像配准,IEEE 图像处理交易卷。 5 第 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?
  • 确保您考虑了链接的 IEEE 文档第 2 页 C 中描述的对数转换。
  • 顺便说一下,在您的代码中,您也计算了平移移位。您必须在第二步中使用角度和比例校正后的图像作为输入。
【解决方案2】:

here is python version

告诉你

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

【讨论】:

    【解决方案3】:

    比例因子的值确实是exp(pt.y)。但是,由于您为 cvLogPolar 函数使用了 40 的“幅度比例参数”,因此您现在需要将 pt.x 除以 40 以获得正确的位移值:

    Scale = exp( pt.x / 40) = exp(16.2986 / 40) = 1.503
    

    cvLogPolar 函数的“幅度比例参数”的值不会影响旋转角度 pt.x 产生的位移,因为根据数学计算,它抵消了。因此,您的旋转公式给出了正确的值。

    另一方面,我认为旋转的公式实际上应该是:

    旋转 = pt.y*360/(a.cols)

    但是,由于某种奇怪的原因,您添加的“>> 1”导致结果乘以 2(我相信您通过乘以 180 而不是 360 来补偿?)删除它,然后您会明白我的意思。

    此外,“>>1”会导致除以 2:

    cvPoint2D32f(a.cols >> 1, a.rows >> 1)

    如果要将cvLogPolar函数的center参数设置为图像的中心(就是你想要的):

    cvPoint2D32f(a.cols/2, a.rows/2)

    cvPoint2D32f(b.cols/2, b.rows/2)

    然后,您还将获得正确的旋转值(即与您获得的值相同)和比例。

    【讨论】:

      【解决方案4】:

      这个帖子有助于我开始研究旋转不变相位相关,所以我希望我的意见能帮助解决任何挥之不去的问题。

      我们的目标是计算比例和旋转(在代码中计算不正确)。让我们从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)(即旋转),我们得到 ​​p>

      (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 ) 来计算中心,而不是上面代码中的内容。这个logpolar example opencv code 有一些很好的信息。

      【讨论】:

        【解决方案5】:

        从相位相关的值来看,坐标是直角坐标,因此 (16.2986, 36.9105) 是 (x,y)。尺度计算为

        scale = log((x^2 + y^ 2)^0.5) 约为 1.6(接近 1.5)。

        当我们使用公式计算角度时 theta = arctan(y/x) = 66(approx)。 theta 值是实际值的方式(在这种情况下为 45)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-09-09
          • 2020-05-15
          • 1970-01-01
          • 2022-12-09
          • 2010-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多