将 3D 矩形映射到 2D 屏幕

发布于 2024-11-03 11:04:33 字数 424 浏览 5 评论 0原文

我已经搜索过了,但我就是无法弄清楚这一点。其他问题没有帮助或者我不明白它们。

问题是,我的 3D 图像中有很多点。这些点针对的是矩形,由于透视原因,从 3D 相机的角度来看,该矩形看起来不像矩形。任务是将矩形中的点映射到屏幕上。我见过一些被称为“四边形到四边形变换”的方法,但大多数都是用于将二维四边形映射到另一个四边形。但我已经获得了现实世界中矩形的 X、Y 和 Z 坐标,因此我正在寻找一些更简单的方法。有谁知道任何实用的算法或方法吗?

如果有帮助的话,我的 3D 相机实际上是带有 OpenNI 和 NITE 中间件的 Kinect 设备,并且我正在使用 WPF。

提前致谢。

编辑: 我还在维基百科上找到了使用角度和余弦的 3d 投影页面,但这似乎是一种困难的方法(在 3d 图像中查找角度),我不确定这是否是真正的解决方案。

I've searched SO but I just can't figure this out. The other questions didn't help or I didn't understand them.

The problem is, I have a bunch of points in a 3D image. The points are for a rectangle, which doesn't look like a rectangle from the 3d camera's view because of perspective. The task is to map the points from that rectangle to the screen. I've seen some ways which some call "quad to quad transformations" but most of them are for mapping a 2d quadrilateral to another one. But I've got the X, Y and Z coordinates of the rectangle in the real world so I'm looking for some easier ways. Does anyone know any practical algorithm or method of doing this?

If it helps, my 3d camera is actually a Kinect device with OpenNI and NITE middlewares, and I'm using WPF.

Thanks in advance.

edit:
I also found the 3d-projection page on Wikipedia that used angles and cosines but that seems to be a difficult way (finding angles in the 3d image) and I'm not sure if it's the real solution or not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

忆悲凉 2024-11-10 11:04:34

您可能想查看投影矩阵

这就是任何 3D 光栅器“展平”3D 体积的方式2D 屏幕。

You might want to check out projection matrices

That's how any 3D rasterizer "flattens" 3D volumes on a 2D screen.

雨落□心尘 2024-11-10 11:04:34

查看此代码 获取给定 WPF 相机的投影矩阵:

private static Matrix3D GetProjectionMatrix(OrthographicCamera camera, double aspectRatio)
{ 
    // This math is identical to what you find documented for
    // D3DXMatrixOrthoRH with the exception that in WPF only
    // the camera's width is specified.  Height is calculated
    // from width and the aspect ratio.
    double w = camera.Width;
    double h = w / aspectRatio;
    double zn = camera.NearPlaneDistance;
    double zf = camera.FarPlaneDistance;
    double m33 = 1 / (zn - zf);
    double m43 = zn * m33;
    return new Matrix3D(
        2 / w, 0, 0, 0,
        0, 2 / h, 0, 0,
        0, 0, m33, 0,
        0, 0, m43, 1);
}

private static Matrix3D GetProjectionMatrix(PerspectiveCamera camera, double aspectRatio)
{ 
    // This math is identical to what you find documented for
    // D3DXMatrixPerspectiveFovRH with the exception that in
    // WPF the camera's horizontal rather the vertical
    // field-of-view is specified.
    double hFoV = MathUtils.DegreesToRadians(camera.FieldOfView);
    double zn = camera.NearPlaneDistance;
    double zf = camera.FarPlaneDistance;
    double xScale = 1 / Math.Tan(hFoV / 2);
    double yScale = aspectRatio * xScale;
    double m33 = (zf == double.PositiveInfinity) ? -1 : (zf / (zn - zf));
    double m43 = zn * m33;
    return new Matrix3D(
        xScale, 0, 0, 0,
        0, yScale, 0, 0,
        0, 0, m33, -1,
        0, 0, m43, 0);
}

/// <summary>
///     Computes the effective projection matrix for the given
///     camera.
/// </summary>
public static Matrix3D GetProjectionMatrix(Camera camera, double aspectRatio)
{
    if (camera == null)
    {
        throw new ArgumentNullException("camera");
    }
    PerspectiveCamera perspectiveCamera = camera as PerspectiveCamera;
    if (perspectiveCamera != null)
    {
        return GetProjectionMatrix(perspectiveCamera, aspectRatio);
    }
    OrthographicCamera orthographicCamera = camera as OrthographicCamera;
    if (orthographicCamera != null)
    {
        return GetProjectionMatrix(orthographicCamera, aspectRatio);
    }
    MatrixCamera matrixCamera = camera as MatrixCamera;
    if (matrixCamera != null)
    {
        return matrixCamera.ProjectionMatrix;
    }
    throw new ArgumentException(String.Format("Unsupported camera type '{0}'.", camera.GetType().FullName), "camera");
}

See this code to get the projection matrix for a given WPF camera:

private static Matrix3D GetProjectionMatrix(OrthographicCamera camera, double aspectRatio)
{ 
    // This math is identical to what you find documented for
    // D3DXMatrixOrthoRH with the exception that in WPF only
    // the camera's width is specified.  Height is calculated
    // from width and the aspect ratio.
    double w = camera.Width;
    double h = w / aspectRatio;
    double zn = camera.NearPlaneDistance;
    double zf = camera.FarPlaneDistance;
    double m33 = 1 / (zn - zf);
    double m43 = zn * m33;
    return new Matrix3D(
        2 / w, 0, 0, 0,
        0, 2 / h, 0, 0,
        0, 0, m33, 0,
        0, 0, m43, 1);
}

private static Matrix3D GetProjectionMatrix(PerspectiveCamera camera, double aspectRatio)
{ 
    // This math is identical to what you find documented for
    // D3DXMatrixPerspectiveFovRH with the exception that in
    // WPF the camera's horizontal rather the vertical
    // field-of-view is specified.
    double hFoV = MathUtils.DegreesToRadians(camera.FieldOfView);
    double zn = camera.NearPlaneDistance;
    double zf = camera.FarPlaneDistance;
    double xScale = 1 / Math.Tan(hFoV / 2);
    double yScale = aspectRatio * xScale;
    double m33 = (zf == double.PositiveInfinity) ? -1 : (zf / (zn - zf));
    double m43 = zn * m33;
    return new Matrix3D(
        xScale, 0, 0, 0,
        0, yScale, 0, 0,
        0, 0, m33, -1,
        0, 0, m43, 0);
}

/// <summary>
///     Computes the effective projection matrix for the given
///     camera.
/// </summary>
public static Matrix3D GetProjectionMatrix(Camera camera, double aspectRatio)
{
    if (camera == null)
    {
        throw new ArgumentNullException("camera");
    }
    PerspectiveCamera perspectiveCamera = camera as PerspectiveCamera;
    if (perspectiveCamera != null)
    {
        return GetProjectionMatrix(perspectiveCamera, aspectRatio);
    }
    OrthographicCamera orthographicCamera = camera as OrthographicCamera;
    if (orthographicCamera != null)
    {
        return GetProjectionMatrix(orthographicCamera, aspectRatio);
    }
    MatrixCamera matrixCamera = camera as MatrixCamera;
    if (matrixCamera != null)
    {
        return matrixCamera.ProjectionMatrix;
    }
    throw new ArgumentException(String.Format("Unsupported camera type '{0}'.", camera.GetType().FullName), "camera");
}
氛圍 2024-11-10 11:04:34

您可以进行基本的正交投影(我正在考虑光线追踪,因此这可能不适用于您正在做的事情):

在此处输入图像描述

代码非常直观:

for y in image.height:
  for x in image.width:
    ray = new Ray(x, 0, z, Vector(0, 1, 0)) # Pointing forward
    intersection = prism.intersection(ray) # Since you aren't shading, you can check only for intersections.

    image.setPixel(x, y, intersection) # Returns black and white image of prism mapped to plane

您只需将方向为 (0, 1, 0) 的向量直接射入太空并记录击中的向量即可。

You could do a basic orthographic projection (I'm thinking in terms of raytracing, so this might not apply to what you're doing):

enter image description here

The code is quite intuitive:

for y in image.height:
  for x in image.width:
    ray = new Ray(x, 0, z, Vector(0, 1, 0)) # Pointing forward
    intersection = prism.intersection(ray) # Since you aren't shading, you can check only for intersections.

    image.setPixel(x, y, intersection) # Returns black and white image of prism mapped to plane

You just shoot vectors with a direction of (0, 1, 0) directly out into space and record which ones hit.

千纸鹤带着心事 2024-11-10 11:04:34

我找到了这个。使用直接的数学而不是矩阵。

这称为透视投影,将 3D 顶点转换为 2D 屏幕顶点。我用它来帮助我制作 3D 程序。

HorizontalFactor = ScreenWidth / Tan(PI / 4)
VerticalFactor = ScreenHeight / Tan(PI / 4)

ScreenX = ((X * HorizontalFactor) / Y) + HalfWidth
ScreenY = ((Z * VerticalFactor) / Y) + HalfHeight

希望这能有所帮助。我想这就是你在寻找的东西。抱歉格式问题(这里是新的)

I found this. Uses straight forward mathematics instead of matricies.

This is called perspective projection to convert from a 3D vertex to a 2D screen vertex. I used this to help me with my 3D program I have made.

HorizontalFactor = ScreenWidth / Tan(PI / 4)
VerticalFactor = ScreenHeight / Tan(PI / 4)

ScreenX = ((X * HorizontalFactor) / Y) + HalfWidth
ScreenY = ((Z * VerticalFactor) / Y) + HalfHeight

Hope this could help. I think its what you where looking for. Sorry about the formatting (new here)

思念绕指尖 2024-11-10 11:04:34

将 3D 世界中的点映射到 2D 屏幕是 OpenGL 和 Direct3d 等框架工作的一部分。正如 Heandel 所说,这称为光栅化。也许你可以使用 Direct3d?

Mapping points in a 3d world to a 2d screen is part of the job of frameworks like OpenGL and Direct3d. It's called Rasterisation like Heandel said. Perhaps you could use Direct3d?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文