簡體   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