IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> python 实现raycast射线检测的两种方法记录和对比:trimesh vs. python mesh raycast(更好) -> 正文阅读

[Python知识库]python 实现raycast射线检测的两种方法记录和对比:trimesh vs. python mesh raycast(更好)

背景需求

项目需要用python实现常见的raycast射线检测。即:
给定一个点,一个方向,一个mesh。
求:从改点沿该方向发送射线,与mesh是否有交点,如果有,给出交点坐标,距离等信息。

找到两种亲测可行的解决方案:

两个包的安装

trimesh
支持 pip install 直接下载安装

python mesh raycast 包:
需要按照github主页里的说明进行安装,即运行命令:
git clone https://github.com/cprogrammer1994/python-mesh-raycast
cd python-mesh-raycast
python setup.py develop

两个包的用法:

没有找到全面的文档,都是看的github里面的example和源码。

trimesh

https://github.com/mikedh/trimesh/blob/master/examples/ray.py

注意他的origins和directions都是n*3的,也就是需要默认用不同点和方向,做多次raycast检测。只有一个点和方向的话,也要套一层[]

    # test on a sphere mesh
    mesh = trimesh.primitives.Sphere()

    # create some rays
    ray_origins = np.array([[0, 0, -5],
                            [2, 2, -10]])
    ray_directions = np.array([[0, 0, 1],
                               [0, 0, 1]])

  # run the mesh- ray test
    locations, index_ray, index_tri = mesh.ray.intersects_location(
        ray_origins=ray_origins,
        ray_directions=ray_directions)
    print(locations) # 打印相交的点的坐标

python mesh raycast

单个三角形的mesh:


import mesh_raycast

triangles = np.array([
    [0.0, 0.0, 0.0],
    [4.0, 0.0, 0.0],
    [0.0, 4.0, 0.0],
], dtype='f4')

result = mesh_raycast.raycast(source=(0.4, 0.8, 5.0), direction=(0.0, 0.0, -1.0), mesh=triangles)

结果如下,result包含很多字段,需要自取。可以看到比trimesh多了我们想要的distance:

{
    'face': 0,
    'point': (0.4, 0.8, 0.0),
    'normal': (0.0, 0.0, 1.0),
    'coeff': (0.1, 0.2),
    'distance': 5.0,
    'dot': 1.0,
}

多个三角形的mesh也可以:

 triangles = np.array([
        [0.0, 0.0, 0.0],
        [4.0, 0.0, 0.0],
        [0.0, 4.0, 0.0],

        [0.0, 0.0, 2.0],
        [2.0, 0.0, 2.0],
        [0.0, 2.0, 2.0],
    ], dtype='f4')

    source = (1.0, 1.0, 5.0)
    direction = mesh_raycast.direction(source, (0.5, 0.5, -0.5))
    result = mesh_raycast.raycast(source=source, direction=direction, mesh=triangles)

二者对比

这里用trimesh读入本地的一个obj文件作为mesh。

import trimesh
    import numpy as np
    import mesh_raycast
    import time
    objPath = 'DatasetGen/untitled.obj'
    mesh = trimesh.load_mesh(objPath) #load or load_mesh

    if (type(mesh) == trimesh.scene.scene.Scene):
        print("scene")
        print(list(mesh.geometry.values())[0])

    elif (type(mesh) == trimesh.base.Trimesh):
        print("single object")
        # 移动到中心
        mesh=mesh_centerize(mesh)
        print(np.min(mesh.vertices,0))
        print(np.max(mesh.vertices, 0))

然后进行碰撞检测:

		# 全局变量
        UAV_height = 50
        # 计算raycast
  		ray_origins = np.array([0,UAV_height,0]) # 3*1
        ray_directions =  np.array([0,-1,0]) # 3*1
        # raycast方法一:trimesh
        t1 = time.time()
        locations, index_ray, index_tri = mesh.ray.intersects_location(
            ray_origins=[ray_origins], # n*3*1
            ray_directions=[ray_directions]) # n*3*1
        print(locations)
        t2 = time.time()
        print("Ran in {0:.3f} s".format(t2 - t1))


        # raycast方法二:
        t1 = time.time()
        triangles = mesh.vertices[mesh.faces]
        triangles = np.array(triangles, dtype='f4')  # 一定要有这一行,不然会有错。

        result = mesh_raycast.raycast(ray_origins, ray_directions, mesh=triangles)
        first_result = min(result, key=lambda x: x['distance'])
        print(first_result['point'])
        t2 = time.time()
        print("Ran in {0:.3f} s".format(t2 - t1))
        

主要的注意点是triangles一定要用np.array处理一下,不然直接用会不对。

结果是:

single object
[-35.7634975  -0.066495  -44.813048 ]
[35.7634975 12.359008  44.813048 ]
[[0.       0.292007 0.      ]]
Ran in 1.129 s
(0.0, 0.2920074462890625, 0.0)
Ran in 0.015 s

可见方法二,python mesh raycast快多了。
这是意料之中的,因为在trimesh的ray.py代码中,已经说了自己速度很慢:
https://github.com/mikedh/trimesh/blob/master/examples/ray.py

Do simple mesh- ray queries. Base functionality only
requires numpy, but if you install pyembree you get the
same API with a roughly 50x speedup.

这个pyembree我还没试过。

而方法二是用C实现的,那当然快了:

SThis module is using glm and the Python’s c-api. The implementation can be found in the mesh_raycast.cpp.

而且我的应用里确实需要用到distance。那当然选python mesh raycast了~

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-09-19 07:56:01  更:2021-09-19 07:56:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:32:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码