1. blensor 软件下载安装
点云仿真软件Blensor介绍 - JusticeZQ - 博客园 (cnblogs.com)
参考这篇文章,进行基础的安装以及官方demo的跑通,这里默认已经掌握了模型的导入以及最基本代码的跑通。在我使用时遇到了一点问题,就是我的模型已经是点云再直接导入到blensor中是无法直接采样的,所以这里我先将我的点云文件进行了重建,代码如下:
import open3d as o3d
import os
data = r'path_to_file'##这里改为文件地址
for i in range(150):
# 读取点云数据
pcd = o3d.io.read_point_cloud(os.path.join(data +"\\raw_model_%d.ply" % i))
# 创建泊松网格对象
poisson_mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd)
# 对泊松网格进行平滑处理
poisson_mesh = poisson_mesh.filter_smooth_taubin(number_of_iterations=5)
# 保存重建结果
o3d.io.write_triangle_mesh(os.path.join(data + '\\raw_model_%d.ply' % i), poisson_mesh)
print(i)
2. blensor使用
在上面重建完成后就是要进行文件的导入了,单个模型的导入可以直接手动完成,但我使用的模型较多,而blensor也提供了相关的python代码方便使用。
for k in range(150):
file_path = r"file_path"##这里改为导入文件地址
file_path = os.path.join(file_path+'\\raw_model_%d.ply' % k)
#先对之前的模型进行删除
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
#导入模型
bpy.ops.import_mesh.ply(filepath = file_path)
#选择相机并将相机设为活跃目标
bpy.ops.object.select_by_type(type='CAMERA')
objects = bpy.context.scene.objects
object_name = "Camera"
for obj in objects:
if obj.name == object_name:
obj.select = True
bpy.context.scene.objects.active = obj
else:
obj.select = False
导入完模型后,需要对模型进行扫描采样工作,这里用的也是tof相机,有关lidar相机的使用之后会再补充。由于tof相机是直接拍照采样,所以这里设置了14个点位进行一个环绕相机的实现(或者可以直接用随机取位置然后run很多次/狗头),
for n in range(10):
#这里是通过改变相机采样的角度来简单实现梯度采样
l = [25,30,35,40,45,50,55,60,65,70]
bpy.data.objects["Camera"].tof_lens_angle_w = l[n]
bpy.data.objects["Camera"].tof_lens_angle_h = l[n]
for item in bpy.data.objects:
if item.type == 'MESH' and item.name.startswith('NoisyScan'):
bpy.data.objects.remove(item)
elif item.type == 'MESH' and item.name.startswith('Scan'):
bpy.data.objects.remove(item)
bpy.ops.blensor.delete_scans()
bpy.ops.blensor.scan()
"""location"""
dir_path = "C:\\Users\\25808\\Desktop\\new\\Data10\\raw_model_%d\\tof" % k
if not os.path.exists(dir_path):
os.makedirs(dir_path)
r = 5#这个是环绕相机的半径也可以自己修改
j = 0
while j <14:
if j == 0:
x = r
y = 0
z = 0
elif j == 1:
x = -r
y = 0
z = 0
elif j == 2:
x = 0
y = r
z = 0
elif j == 3:
x = 0
y = -r
z = 0
elif j == 4:
x = 0
y = 0
z = r
elif j == 5:
x = 0
y = 0
z = -r
elif j == 6:
x = math.sqrt(r)
y = math.sqrt(r)
z = math.sqrt(r)
elif j == 7:
x = -math.sqrt(r)
y = math.sqrt(r)
z = math.sqrt(r)
elif j == 8:
x = math.sqrt(r)
y = -math.sqrt(r)
z = math.sqrt(r)
elif j == 9:
x = -math.sqrt(r)
y = -math.sqrt(r)
z = math.sqrt(r)
elif j == 10:
x = math.sqrt(r)
y = math.sqrt(r)
z = -math.sqrt(r)
elif j == 11:
x = -math.sqrt(r)
y = math.sqrt(r)
z = -math.sqrt(r)
elif j == 12:
x = math.sqrt(r)
y = -math.sqrt(r)
z = -math.sqrt(r)
elif j == 13:
x = -math.sqrt(r)
y = -math.sqrt(r)
z = -math.sqrt(r)
l = np.linalg.norm([x,y,z])
bpy.data.objects['Camera'].location[0] = x
bpy.data.objects['Camera'].location[1] = y
bpy.data.objects['Camera'].location[2] = z
bpy.data.objects['Camera'].rotation_euler[0] = np.arccos(z/l)
bpy.data.objects['Camera'].rotation_euler[1] = 0 * np.pi / 180
if y < 0:
bpy.data.objects['Camera'].rotation_euler[2] = np.arctan(-x/(y))
elif y > 0:
bpy.data.objects['Camera'].rotation_euler[2] = np.arctan(-x/(y)) + np.pi
elif y == 0:
bpy.data.objects['Camera'].rotation_euler[2] = -np.arctan(-x/(y+0.0001))
filename = dir_path + '\\' + 'level%d.txt'%n
#os.makedirs(dir_path)
f = open(filename, "w")
i = 0 # Store the number of points in the point cloud
for item in bpy.data.objects:
if item.type == 'MESH' and item.name.startswith('Scan'):
# print('write once')
for sp in item.data.vertices:
str = '%#5.3f\t%#5.3f\t%#5.3f \n' % (sp.co[0], sp.co[1], sp.co[2])
i = i + 1
f.write(str)
f.close()
j +=1
bpy.ops.blensor.delete_scans()
bpy.ops.blensor.scan()
通过上面的代码,基本可以实现对模型的采样与保存啦,然后由于我学术不精,保存的文件都是txt文件,这就需要再通过python来实现一下批量转化成为ply文件,其他文件的转化可以问问度娘。
3. txt2ply
import os
from tqdm import tqdm
def convert_txt_to_ply(input_file, output_file):
# 读取文本文件内容
with open(input_file, 'r') as file:
lines = file.readlines()
# 提取数据部分
data_lines = lines[0:] # 假设第一行是注释,从第二行开始为数据
# 构建PLY代码
ply_code = "ply\n"
ply_code += "format ascii 1.0\n"
ply_code += "element vertex {}\n".format(len(data_lines))
ply_code += "property float x\n"
ply_code += "property float y\n"
ply_code += "property float z\n"
ply_code += "end_header\n"
for line in data_lines:
values = line.strip().split() # 假设数据以空格分隔
x, y, z = map(float, values) # 假设数据是三维坐标点
ply_code += "{} {} {}\n".format(x, y, z)
# 写入PLY文件
with open(output_file, 'w') as file:
file.write(ply_code)
file_path = "/path"#地址地址
# 调用函数进行转换
for i in tqdm(range(150)):
for j in range(10):
fp = os.path.join(file_path + '\\raw_model_%d\\TOF2' % i)
if not os.path.exists(fp):
os.makedirs(fp)
convert_txt_to_ply(os.path.join(file_path + '\\raw_model_%d\\tof\\level%d.txt' % (i, j)), os.path.join(fp + '\\level%d.ply' % j))
最后是我的blensor用的代码:
import bpy
import numpy as np
from mathutils import *
import blensor
import os
import random
import math
for k in range(150):
file_path = r"C:\Users\25808\Desktop\new\DATASET"
file_path = os.path.join(file_path+'\\raw_model_%d.ply' % k)
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.object.select_by_type(type='MESH')
bpy.ops.object.delete()
bpy.ops.import_mesh.ply(filepath = file_path)
bpy.ops.object.select_by_type(type='CAMERA')
objects = bpy.context.scene.objects
object_name = "Camera"
for obj in objects:
if obj.name == object_name:
obj.select = True
bpy.context.scene.objects.active = obj
else:
obj.select = False
for n in range(10):
l = [25,30,35,40,45,50,55,60,65,70]
bpy.data.objects["Camera"].tof_lens_angle_w = l[n]
bpy.data.objects["Camera"].tof_lens_angle_h = l[n]
for item in bpy.data.objects:
if item.type == 'MESH' and item.name.startswith('NoisyScan'):
bpy.data.objects.remove(item)
elif item.type == 'MESH' and item.name.startswith('Scan'):
bpy.data.objects.remove(item)
bpy.ops.blensor.delete_scans()
bpy.ops.blensor.scan()
"""location"""
dir_path = "C:\\Users\\25808\\Desktop\\new\\Data10\\raw_model_%d\\tof" % k
if not os.path.exists(dir_path):
os.makedirs(dir_path)
r = 5
j = 0
while j <14:
if j == 0:
x = r
y = 0
z = 0
elif j == 1:
x = -r
y = 0
z = 0
elif j == 2:
x = 0
y = r
z = 0
elif j == 3:
x = 0
y = -r
z = 0
elif j == 4:
x = 0
y = 0
z = r
elif j == 5:
x = 0
y = 0
z = -r
elif j == 6:
x = math.sqrt(r)
y = math.sqrt(r)
z = math.sqrt(r)
elif j == 7:
x = -math.sqrt(r)
y = math.sqrt(r)
z = math.sqrt(r)
elif j == 8:
x = math.sqrt(r)
y = -math.sqrt(r)
z = math.sqrt(r)
elif j == 9:
x = -math.sqrt(r)
y = -math.sqrt(r)
z = math.sqrt(r)
elif j == 10:
x = math.sqrt(r)
y = math.sqrt(r)
z = -math.sqrt(r)
elif j == 11:
x = -math.sqrt(r)
y = math.sqrt(r)
z = -math.sqrt(r)
elif j == 12:
x = math.sqrt(r)
y = -math.sqrt(r)
z = -math.sqrt(r)
elif j == 13:
x = -math.sqrt(r)
y = -math.sqrt(r)
z = -math.sqrt(r)
l = np.linalg.norm([x,y,z])
bpy.data.objects['Camera'].location[0] = x
bpy.data.objects['Camera'].location[1] = y
bpy.data.objects['Camera'].location[2] = z
bpy.data.objects['Camera'].rotation_euler[0] = np.arccos(z/l)
bpy.data.objects['Camera'].rotation_euler[1] = 0 * np.pi / 180
if y < 0:
bpy.data.objects['Camera'].rotation_euler[2] = np.arctan(-x/(y))
elif y > 0:
bpy.data.objects['Camera'].rotation_euler[2] = np.arctan(-x/(y)) + np.pi
elif y == 0:
bpy.data.objects['Camera'].rotation_euler[2] = -np.arctan(-x/(y+0.0001))
filename = dir_path + '\\' + 'level%d.txt'%n
#os.makedirs(dir_path)
f = open(filename, "w")
i = 0 # Store the number of points in the point cloud
for item in bpy.data.objects:
if item.type == 'MESH' and item.name.startswith('Scan'):
# print('write once')
for sp in item.data.vertices:
str = '%#5.3f\t%#5.3f\t%#5.3f \n' % (sp.co[0], sp.co[1], sp.co[2])
i = i + 1
f.write(str)
f.close()
j +=1
bpy.ops.blensor.delete_scans()
bpy.ops.blensor.scan()