简体   繁体   English

使用 2D 图像坐标的透视变换

[英]Perspective transformation using coordinates of a 2D image

Given a 2D image, I want to transform it to a given plane using a function() to transform the original coordinates to new coordinates on the same screen, with correct proportion.给定一个 2D 图像,我想将其转换为给定平面,使用 function() 将原始坐标转换为同一屏幕上的新坐标,并具有正确的比例。

An example of what I mean: Perspective Transformation我的意思的一个例子:透视变换

Now, translating the x coordinates I've been able to do, the problem is the translation of 'y' coordinates.现在,翻译我已经能够做的x坐标,问题是'y'坐标的翻译。 I've been able to translate them linearly, but that's not what I want to achieve, because there is no perspective when transforming the coordinate linearly.我已经能够线性地翻译它们,但这不是我想要实现的,因为在线性变换坐标时没有透视。

I've tried searching for solutions for quite a while now, and I haven't been able to get one.我已经尝试寻找解决方案很长一段时间了,但我一直没有找到。 I have come across plenty of examples using openCV and using matrices, but that isn't exactly what I want.我遇到了很多使用 openCV 和矩阵的例子,但这并不是我想要的。

What I'm looking for is a function, given (x, y) coordinates of an image, return (x', y') coordinates which corresponds to the perspective projection (see example).我正在寻找的是 function,给定图像的 (x, y) 坐标,返回对应于透视投影的 (x', y') 坐标(参见示例)。

This is my current C++ code:这是我当前的 C++ 代码:

struct Coor {
    Coor(float x, float y) : x(x), y(y) {};

    float x;
    float y;
};

const float WINDOW_SIZE = 100.0f;
const Coor PERSPECTIVE_POINT = {
    WINDOW_SIZE * 0.5f,
    WINDOW_SIZE * 0.3f
};

Coor transform(float x, float y) {
    float perspectiveHeight = WINDOW_SIZE - PERSPECTIVE_POINT.y;
    float linearProportionY = y / WINDOW_SIZE;

    float transformedX = PERSPECTIVE_POINT.x + ((x - PERSPECTIVE_POINT.x) * linearProportionY);

    // This is what I can't compute correctly (I know the proportion is not linearProportionY, it's a placeholder)
    float transformedY = PERSPECTIVE_POINT.y + (perspectiveHeight * linearProportionY);

    return Coor(transformedX, transformedY);
}

Any help would be gladly appreciated!任何帮助将不胜感激!

Your image doesn't seem right.你的形象似乎不对。 In actual perspective transformation, only infinitely far points would merge on the horizon.在实际的透视变换中,只有无限远的点会在地平线上合并。

One possible way to apply the transform is in several steps:应用转换的一种可能方法是分几个步骤:

  1. With an affine (linear+offset) transform, place the plane into 3D space使用仿射(线性+偏移)变换,将平面放入 3D 空间
  2. Divide x and y by z xy除以z
  3. With another affine transform, move the result to the desired location.使用另一个仿射变换,将结果移动到所需位置。

UPDATE: sample code更新:示例代码

// 1. making a small horizontal plane
float X = x/WINDOW_SIZE - 0.5f; // X∈[-0.5, 0.5]
float Y = -0.5f;
float Z = 2.0f - y/WINDOW_SIZE; // Z∈[1.0, 2.0]

// 2. perspective transform
float u = X / Z; // u∈[-0.5, 0.5]
float v = Y / Z; // v∈[-0.5, -0.25]

// 3. scaling the result to fill the window
x = 0.5f * WINDOW_SIZE.x + WINDOW_SIZE * u;
y = 0.5f * WINDOW_SIZE.y - WINDOW_SIZE * v;

You may need to adjust coefficients to make it look more to your taste.您可能需要调整系数以使其看起来更符合您的口味。

And remember, only artists think in terms of perspective points.请记住,只有艺术家会根据观点来思考。 In 3D graphics, camera orientation and field of view are the correct things.在 3D 图形中,相机方向和视野是正确的。 (and, matrices to handle that easier) (并且,更容易处理的矩阵)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM