Blender生成COLMAP数据集

2024-04-17 02:20
文章标签 数据 生成 blender colmap

本文主要是介绍Blender生成COLMAP数据集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近在做3DGS方向,整理了一下Blender生成自己的数据集。

1 Introduction

在Blender中构建场景(light, object, camera),利用Blender的python脚本对其渲染,导出多视角下渲染出的RGB图和depth map,并将transform.json转为COLMAP格式,以便直接用于SfM初始化高斯点云。

2 Python script of Blender for generating RGB and depth map

利用如下python脚本,生成一组400*400的RGB图和detph map。


import os
import os.path as osp
import bpy
import numpy as np
import json
from mathutils import Vector, Matrix, Euler
from math import radiansW = 400
H = 400
NUM_OBJ = 5
OBJ_NAMES = {1: 'xxx',2: 'xxx',
}# save path
RESULTS_PATH = 'xxx'
os.makedirs(RESULTS_PATH, exist_ok=True)def listify_matrix(matrix):matrix_list = []for row in matrix:matrix_list.append(list(row))return matrix_listdef parent_obj_to_camera(b_camera):origin = (0, 0, 0.4)b_empty = bpy.data.objects.new("Empty", None)b_empty.location = originb_camera.parent = b_empty  # setup parentingscn = bpy.context.scenescn.collection.objects.link(b_empty)bpy.context.view_layer.objects.active = b_emptyreturn b_emptyscene = bpy.context.scene
scene.use_nodes = True
tree = scene.node_tree
links = tree.links
# Empty the node tree and initialize
for n in tree.nodes:tree.nodes.remove(n)    
render_layers = tree.nodes.new('CompositorNodeRLayers')# Set up rendering of depth map
depth_file_output = tree.nodes.new(type="CompositorNodeOutputFile")
depth_file_output.base_path = ''
depth_file_output.format.file_format = 'OPEN_EXR'
depth_file_output.format.color_depth = '32'
links.new(render_layers.outputs['Depth'], depth_file_output.inputs[0])# Background
scene.render.dither_intensity = 0.0
scene.render.film_transparent = Truecam = scene.objects['Camera']
cam.location = (0.0, -3.6, -1.0)
cam_constraint = cam.constraints.new(type='TRACK_TO')
cam_constraint.track_axis = 'TRACK_NEGATIVE_Z'
cam_constraint.up_axis = 'UP_Y'
b_empty = parent_obj_to_camera(cam)
cam_constraint.target = b_empty# Meta data to store in JSON file
meta_data = {'camera_angle_x': cam.data.angle_x,'img_h': H,'img_w': W
}
meta_data['frames'] = {}# Render with multi-camera
N_VIEW_X = 2
X_ANGLE_START = 0
X_ANGLE_END = -60
N_VIEW_Z = 15
Z_ANGLE_START = 0
Z_ANGLE_END = 360 # 337b_empty.rotation_euler = (X_ANGLE_START, 0, Z_ANGLE_START)
x_stepsize = (X_ANGLE_END - X_ANGLE_START) / N_VIEW_X
z_stepsize = (Z_ANGLE_END - Z_ANGLE_START) / N_VIEW_Zmeta_data['transform_matrix'] = {}
for vid_x in range(N_VIEW_X):b_empty.rotation_euler[0] += radians(x_stepsize)b_empty.rotation_euler[2] = Z_ANGLE_STARTfor vid_z in range(N_VIEW_Z):b_empty.rotation_euler[2] += radians(z_stepsize)img_path = osp.join(RESULTS_PATH, 'images')os.makedirs(img_path, exist_ok=True)vid = vid_x * N_VIEW_Z + vid_z   # Render scene.render.filepath = osp.join(img_path, 'color', 'image_%04d.png'%(vid))depth_file_output.base_path = osp.join(img_path, 'depth')depth_file_output.file_slots[0].path = 'image_%04d'%(vid)bpy.ops.render.render(write_still=True)print((vid_x, vid_z), cam.matrix_world)meta_data['transform_matrix'][f'camera_{vid :04d}'] = listify_matrix(cam.matrix_world)# save camera params
with open(osp.join(RESULTS_PATH, 'transforms.json'), 'w') as fw:json.dump(meta_data, fw, indent=4)

3 Read Depth map (.exr)


import os
os.environ["OPENCV_IO_ENABLE_OPENEXR"]="1"
import cv2
import numpy as np
import matplotlib.pyplot as plt
import pandas as pddepth_dir = 'D:\BlenderWorkplace\darkroom\source\output\images\depth'
for depth_name in os.listdir(depth_dir):depth = cv2.imread(depth_dir+'\\'+depth_name, cv2.IMREAD_UNCHANGED)[:, :, 0]print(depth_name, max(depth.flatten()), min(depth.flatten()))

4 Blender2COLMAP (transform.json->images.txt and cameras.txt)

Refer to https://blog.csdn.net/qq_38677322/article/details/126269726

将Blender生成的相机参数transform.json转为COLMAP格式的cameras.txt(内参)和images.txt(外参).

import numpy as np
import json
import os
import imageio
import mathblender2opencv = np.array([[1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]])
# 注意:最后输出的图片名字要按自然字典序排列,例:0, 1, 100, 101, 102, 2, 3...因为colmap内部是这么排序的
fnames = list(sorted(os.listdir('output/images/color')))
print(fnames)
fname2pose = {}
uni_pose = Nonewith open('output/transforms.json', 'r') as f:meta = json.load(f)fx = 0.5 * W / np.tan(0.5 * meta['camera_angle_x'])  # original focal length
if 'camera_angle_y' in meta:fy = 0.5 * H / np.tan(0.5 * meta['camera_angle_y'])  # original focal length
else:fy = fx
if 'cx' in meta:cx, cy = meta['cx'], meta['cy']
else:cx = 0.5 * Wcy = 0.5 * H
with open('created/sparse_/cameras.txt', 'w') as f:f.write(f'1 PINHOLE {W} {H} {fx} {fy} {cx} {cy}')idx = 1for cam, mat in meta['transform_matrix'].items():# print(cam, mat)fname = "image_"+cam.split('_')[1]+".png"pose = np.array(mat) @ blender2opencvfname2pose[fname] = pose
with open('created/sparse_/images.txt', 'w') as f:for fname in fnames:pose = fname2pose[fname]R = np.linalg.inv(pose[:3, :3])T = -np.matmul(R, pose[:3, 3])q0 = 0.5 * math.sqrt(1 + R[0, 0] + R[1, 1] + R[2, 2])q1 = (R[2, 1] - R[1, 2]) / (4 * q0)q2 = (R[0, 2] - R[2, 0]) / (4 * q0)q3 = (R[1, 0] - R[0, 1]) / (4 * q0)f.write(f'{idx} {q0} {q1} {q2} {q3} {T[0]} {T[1]} {T[2]} 1 {fname}\n\n')idx += 1
with open('created/sparse_/points3D.txt', 'w') as f:f.write('')

结果如下:
在这里插入图片描述
在这里插入图片描述

5 COLMAP-SfM过程 (对3DGS初始化)

5.1 提取图像特征

Input: source/output/images/color(渲染出的RGB图像路径)
Output: initial database.db

colmap feature_extractor --database_path database.db --image_path source/output/images/color

5.2 导入相机内参

Refer to https://www.cnblogs.com/li-minghao/p/11865794.html

由于我们的相机内参只有一组,无需脚本导入,只需打开colmap界面操作。
在这里插入图片描述

5.3 特征匹配

colmap exhaustive_matcher --database_path database.db

5.4 三角测量

colmap point_triangulator --database_path database.db --image_path source/output/images/color --input_path source/created/sparse --output_path source/triangulated/sparse

由此,输出的结果为cameras.bin, images.bin, points3D.bin,存放在source/triangulated/sparse(以上述代码为例)。

这篇关于Blender生成COLMAP数据集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/910545

相关文章

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

使用SpringBoot+InfluxDB实现高效数据存储与查询

《使用SpringBoot+InfluxDB实现高效数据存储与查询》InfluxDB是一个开源的时间序列数据库,特别适合处理带有时间戳的监控数据、指标数据等,下面详细介绍如何在SpringBoot项目... 目录1、项目介绍2、 InfluxDB 介绍3、Spring Boot 配置 InfluxDB4、I

Java整合Protocol Buffers实现高效数据序列化实践

《Java整合ProtocolBuffers实现高效数据序列化实践》ProtocolBuffers是Google开发的一种语言中立、平台中立、可扩展的结构化数据序列化机制,类似于XML但更小、更快... 目录一、Protocol Buffers简介1.1 什么是Protocol Buffers1.2 Pro

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

Python使用python-pptx自动化操作和生成PPT

《Python使用python-pptx自动化操作和生成PPT》这篇文章主要为大家详细介绍了如何使用python-pptx库实现PPT自动化,并提供实用的代码示例和应用场景,感兴趣的小伙伴可以跟随小编... 目录使用python-pptx操作PPT文档安装python-pptx基础概念创建新的PPT文档查看

在ASP.NET项目中如何使用C#生成二维码

《在ASP.NET项目中如何使用C#生成二维码》二维码(QRCode)已广泛应用于网址分享,支付链接等场景,本文将以ASP.NET为示例,演示如何实现输入文本/URL,生成二维码,在线显示与下载的完整... 目录创建前端页面(Index.cshtml)后端二维码生成逻辑(Index.cshtml.cs)总结