11

我正在尝试使用 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. 但我很难计算规模。如何转换给定的平移位移以获得比例?

4

5 回答 5

2

您有两个图像f1f2f1(m, n) = f2(m/a , n/a)f1按因子 a 缩放

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

比较BS Reddy,BN Chatterji:一种基于 FFT 的平移、旋转和尺度不变图像配准技术,IEEE Transactions On Image Processing Vol。5 第 8 期,IEEE,1996

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

于 2013-01-09T22:48:02.903 回答
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
于 2013-04-30T08:13:09.767 回答
1

比例因子的值确实是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)

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

于 2014-06-24T07:54:22.083 回答
1

该线程有助于我开始研究旋转不变相位相关,因此我希望我的输入将有助于解决任何挥之不去的问题。

我们的目标是计算比例和旋转(在代码中计算不正确)。让我们首先从logPolar 文档中收集方程。他们在那里声明如下:

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

于 2017-03-29T11:58:58.397 回答
0

从相位相关的值来看,坐标是直角坐标,因此 (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)。

于 2013-07-08T06:17:17.700 回答