利用Blender模拟激光扫描效果

以相机视作激光源,按照渲染图片的范围对指定物体进行扫描

Blender ray_cast文档
需要注意的是,各参数均为目标的局部坐标系下,故调用的时候需要将全局坐标系下的坐标转换到目标的局部坐标系下,对输出的结果也应转换到全局坐标系下

import bpy
from mathutils import *
import numpy as np
import pickle

# 获取相机对象
camera = bpy.data.objects['Camera']
# 
goal = bpy.data.objects['猴头']

focal_length = 50 # mm
sensor_width = 36 # mm

# 渲染图片大小
img_width = 640 # px

img_height = 480 # px
result = np.zeros((640,480,3))

# 计算像元大小
meta_pix_size = sensor_width / img_width  # mm/px



z = -1
#  假设指示器距离相机1m
def laser_scan(origin, direction):
    global  goal, camera

    # 选中目标
    nearest_point = None
    result = goal.ray_cast(origin, direction, distance=200)
    if result[0]:
        nearest_point = result[1]
		# 将结果转换到全局坐标系下
        nearest_point = goal.matrix_world @ nearest_point
    else:
        nearest_point = (0,0,0)
    return nearest_point
        


# 将相机坐标转换到目标的局部坐标系下
origin = camera.location - goal.location


# 以下循环利用几何关系,假定存在深度为1的物体A,各像素对应下的物体A的空间坐标,依次获取方向向量——从相机中心发出一束激光,从左往右,从上往下遍历扫描
for h in range(img_height):
    delta_h_pix = h-img_height/2
    delta_h_distance = -1*delta_h_pix * meta_pix_size # mm
    y = delta_h_distance / focal_length # m   
    for w in range(img_width):
        #print(f"{h}:{w}")
        delta_w_pix = w-img_width/2
        delta_w_distance = delta_w_pix * meta_pix_size # mm
        x = delta_w_distance / focal_length # m

        # 将按照像素位置和深度计算的相机局部坐标系下的目标点转换到全局坐标系下
        global_pos = camera.matrix_world @ Vector((x,y,z))
        
        # 计算方向
        direction = global_pos - camera.location
       
        point = laser_scan(origin, direction)
        result[w,h,:]=point
        
fout = open(r'pointclouds.pkl', 'wb')
pickle.dump(result, fout)

fout.close()

场景渲染图渲染图
场景图场景图
输出结果可视化扫描结果

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值