两个局点之间的转换两个

2023-09-10 23:55:06 作者:芳心纵火犯

我有对象,比方说对模型图像。我想计算的目标图像模型,图像对象和对象之间的转换(移动,缩放,旋转)。我想使该对象的可被视为二维因此只有2D变换应计算的假设

I have object let's say on model image. I want to compute transformation (displacement, scale, rotation) between object on model image and object on target image. I want to make assumption that object's can be treated as 2D so only 2D transformations should be computed.

首先,我要在人工辅助的方式来给它。用户选择的模型图像基点,然后瞄准目标像点。点的数目应该由用户(但不超过一些最小2-3点以下)来定义。时分给不同的信息,变换应被平均并从例如该匹配的质量,可以计算

First I want to to it in manually assisted way. The user selects base point on model image and then target point on target image. The number of points should be defined by user (but no less than some minimum 2-3 points). When points gives different information, the transformation should be averaged and for example from this the quality of matching can be computed.

所以,问题是相当关于计算两组分的转型,但我想这样做图片我已经添加了图像处理的标签。

So the questions is rather about computing transformation of two sets of points, but as I want to do it on image I've added image processing tag.

特别欢迎有参考和建议有几张code或伪code。

Especially welcomed are references and advices with some pieces of code or pseudocode.

通过两点是非常容易的问题,唯一的旋转,缩放和线位移应采取,但如何与更多的积分做到这一点,并取平均值和计算一些质量因素。

With two points it's very easy issue, only rotation, scale and displacement of line should be taken, but how to do it with more points, and with averaging it and computing some quality factors.

当前的解决方案是:

void transformFnc(std::vector<PointF> basePoints, std::vector<PointF> targetPoints,
                  PointF& offset, double rotation, double scale)
{
    std::vector<Line> basePointsLines;
    std::vector<Line> targetPointsLines;
    assert(basePoints.size() == targetPoints.size());
    int pointsNumber = basePoints.size();

    for(int i = 0; i < pointsNumber; i++)
    {
         for(int j = i + 1; j < pointsNumber; j++)
         {
             basePointsLines.push_back(Line(basePoints[i], basePoints[j]));
             targetPointsLines.push_back(Line(targetPoints[i], targetPoints[j]));
         }
    }
    std::vector<double> scalesVector;
    std::vector<double> rotationsVector;
    double baseCenterX = 0, baseCenterY = 0, targetCenterX = 0, targetCenterY = 0;
    for(std::vector<Line>::iterator it = basePointsLines.begin(), i = targetPointsLines.begin();
        it != basePointsLines.end(), i != targetPointsLines.end(); it++, i++)
    {
        scalesVector.push_back((*i).length()/(*it).length());
        baseCenterX += (*it).pointAt(0.5).x(); 
        baseCenterY += (*it).pointAt(0.5).y();
        targetCenterX += (*i).pointAt(0.5).x();
        targetCenterY += (*i).pointAt(0.5).y();
        double rotation;
        rotation = (*i).angleTo((*it));
        rotationsVector.push_back(rotation);
    }
    baseCenterX = baseCenterX / pointsNumber;
    baseCenterY = baseCenterY / pointsNumber;
    targetCenterX = targetCenterX / pointsNumber;
    targetCenterY = targetCenterY / pointsNumber;

    offset = PointF(targetCenterX - baseCenterX, targetCenterY - baseCenterY);
    scale = sum(scalesVector) / scalesVector.size();
    rotation = sum(rotationsVector) / rotationsVector.size();
}

只有优化我可以在这个code发现是从规模和轮换那些不同于太多的休息值来消除。

Only optimization I can find in this code is to eliminate from scales and rotations those values which differs too much from the rest.

我在寻找codeS或伪$ C $解命题CS。它也可以参考一些codeS。

因此​​,从答案至今我知道:

So far from answers I know that:

RANSAC算法可以用来 我需要找一些仿射变换的最小二乘意义上的计算算法

推荐答案

首先推广的问题与一个3x3仿射变换矩阵简单的仿射变换:即

First generalize the problem in a simple affine transformation with a 3x3 affine transformation matrix: i.e.

[M11 M12 M13]
[M21 M22 M23]
[M31 M32 M33]

既然我们已经知道,第三行永远是[0 0 1]我们可以简单地忽略它。

Since we already know that the third row will always be [0 0 1] we can simply disregard it.

现在我们就可以说明问题,如下矩阵方程

Now we can describe the problem as the following matrix equation

[xp0]     [x0 y0 1  0  0  0 ]
[yp0]     [0  0  0  x0 y0 1 ]     [M11]
[xp1]     [x1 y1 1  0  0  0 ]     [M12]
[yp1]  =  [0  0  0  x1 y1 1 ]  *  [M13]
[xp2]     [x2 y2 1  0  0  0 ]     [M21]
[yp2]     [0  0  0  x2 y2 1 ]     [M22]
[xp3]     [x3 y3 1  0  0  0 ]     [M23]
[yp3]     [0  0  0  x3 y3 1 ]

其中XP和YP是投影坐标和x和y是原始坐标

where xp and yp are the projected coordinates and x and y are the original coordinates.

让我们把这个

proj = M * trans

我们可以再由

trans = pinv(M) * proj

在这里PINV是伪逆。

where pinv is the pseudo inverse.

这为我们提供了最适合的最小二乘意义上给出的点仿射变换。

This gives us an affine transformation that best fits the points given in the least squares sense.

现在显然这将也给剪,配合翻转以及哪些你不希望非均匀缩放,所以我们需要限制以某种方式来避免剪切的仿射变换。这证明是相当容易的,我们可以使用单个载体来描述旋转(矢量的方向)和缩放(大小的向量,)的其它载体将简单地正交。这由两个减少自由度。

Now obviously this will also give shear, coordinate flips as well as non-uniform scaling which you did not want so we need to limit the affine transformation in some way to avoid shear. This turns out to be quite easy, we can use a single vector to describe the rotation (direction of the vector) and scaling (magnitude of the vector,) the other vector will simply be orthogonal to it. This reduces the degrees of freedom by two.

M21 = -M12
M22 = M11

因此​​减少

So reduce to

[xp0]     [x0  y0 1 0]
[yp0]     [y0 -x0 0 1]
[xp1]     [x1  y1 1 0]     [M11]
[yp1]  =  [y1 -x1 0 1]  *  [M12]
[xp2]     [x2  y2 1 0]     [M13]
[yp2]     [y2 -x2 0 1]     [M23]
[xp3]     [x3  y3 1 0]
[yp3]     [y3 -x3 0 1]

和从M12和M11 M21计算和M22之后,我们已经解决了上述矩阵方程。

and calculate M21 and M22 from M12 and M11 after we have solved the above matrix equation.