繁体   English   中英

二维图像点与 3d 网格之间的交点

[英]Intersection between 2d image point and 3d mesh

给定:网格,源相机 - 我有内在和外在参数,图像坐标 2d

Output : 3D 点,它是从相机中心穿过图像平面上的 2d 点和网格的光线的交点。 (我试图在网格上找到 3d 点)

这是过程 在此处输入图像描述

来自计算机视觉书中的多视图几何: 在此处输入图像描述

我已经构造了方程(6.14)

我不确定如何继续并获得位于网格上的 3d 点(我还需要靠近相机的点)。

我认为可以通过以下方式完成:

遍历所有顶点并找到顶点与直线之间的距离,并且距离最短的顶点位于直线上(如果它们接近于零或零),并且找到最近的顶点是我猜想找到幅度在相机的中心和最近的顶点之间,最小的一个将意味着该点是最近的?

快速更新:这个 repo 似乎确实适用于光线: github.com/szabolcsdombi/python-mesh-raycast

我想现在的错误在于让D点正确..

正如Grillteller在评论中指出的,这是与 3d 网格的光线相交问题。 据我所知,人类还不知道确定任意网格交点的快速方法。 在您的问题上下文中,您应该使用Ray Tracing ,这也是Grillteller指出的,但是这存在严重的性能问题,尽管它提供了很多着色的可能性。 为了找到光线和网格的交点,光线追踪算法通常使用不同的加速结构。 通常这样的结构是由树划分的空间:

演示文稿很好地解释了其中一些方法和其他方法。

PS:如果你只需要一个简单的可视化,那么最好将问题反过来:对于每个网格元素,执行rasterisation

我使用 python 找到了另一个名为trimesh的实现。

您需要阅读安装指南,然后您可以通过以下方式加载网格:

import numpy as np 
import trimesh

# attach to logger so trimesh messages will be printed to console 
trimesh.util.attach_to_log()

mesh = trimesh.load('models/CesiumMilkTruck.glb', force='mesh')

我找到了将场景中的相机导入为trimesh.scene.Camera的相关行。 然后,您可以使用 function cameras_to_rays(camera) (第 417 行)“每像素返回一条光线,如 camera.resolution 中设置的那样”。

所以现在您拥有每个像素和网格的光线,并且可以创建一个RayMeshIntersector ,如ray_triangle.py所示。 然后,您可以使用intersects_location (第 75 行)计算相应光线撞击网格的笛卡尔图像坐标。

我在这里找到了一个适合您的示例:

"""
raytrace.py
----------------
A very simple example of using scene cameras to generate
rays for image reasons.
Install `pyembree` for a speedup (600k+ rays per second)
"""
from __future__ import division

import PIL.Image

import trimesh
import numpy as np

if __name__ == '__main__':

    # test on a simple mesh
    mesh = trimesh.load('../models/featuretype.STL')

    # scene will have automatically generated camera and lights
    scene = mesh.scene()

    # any of the automatically generated values can be overridden
    # set resolution, in pixels
    scene.camera.resolution = [640, 480]
    # set field of view, in degrees
    # make it relative to resolution so pixels per degree is same
    scene.camera.fov = 60 * (scene.camera.resolution /
                             scene.camera.resolution.max())

    # convert the camera to rays with one ray per pixel
    origins, vectors, pixels = scene.camera_rays()

    # do the actual ray- mesh queries
    points, index_ray, index_tri = mesh.ray.intersects_location(
        origins, vectors, multiple_hits=False)

    # for each hit, find the distance along its vector
    depth = trimesh.util.diagonal_dot(points - origins[0],
                                      vectors[index_ray])
    # find pixel locations of actual hits
    pixel_ray = pixels[index_ray]

    # create a numpy array we can turn into an image
    # doing it with uint8 creates an `L` mode greyscale image
    a = np.zeros(scene.camera.resolution, dtype=np.uint8)

    # scale depth against range (0.0 - 1.0)
    depth_float = ((depth - depth.min()) / depth.ptp())

    # convert depth into 0 - 255 uint8
    depth_int = (depth_float * 255).round().astype(np.uint8)
    # assign depth to correct pixel locations
    a[pixel_ray[:, 0], pixel_ray[:, 1]] = depth_int
    # create a PIL image from the depth queries
    img = PIL.Image.fromarray(a)

    # show the resulting image
    img.show()

    # create a raster render of the same scene using OpenGL
    # rendered = PIL.Image.open(trimesh.util.wrap_as_stream(scene.save_image()))

暂无
暂无

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

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