Blender生成COLMAP数据集

news2024/11/26 8:58:46

最近在做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 radians


W = 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_list

def parent_obj_to_camera(b_camera):
    origin = (0, 0, 0.4)
    b_empty = bpy.data.objects.new("Empty", None)
    b_empty.location = origin
    b_camera.parent = b_empty  # setup parenting

    scn = bpy.context.scene
    scn.collection.objects.link(b_empty)
    bpy.context.view_layer.objects.active = b_empty
    return b_empty

scene = 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 = True

cam = 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 # 337

b_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_Z

meta_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_START
    
    for 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 pd

depth_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 math

blender2opencv = 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 = None

with 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 * W
    cy = 0.5 * H
with open('created/sparse_/cameras.txt', 'w') as f:
    f.write(f'1 PINHOLE {W} {H} {fx} {fy} {cx} {cy}')
    idx = 1
    for cam, mat in meta['transform_matrix'].items():
        # print(cam, mat)
        fname = "image_"+cam.split('_')[1]+".png"
        pose = np.array(mat) @ blender2opencv
        fname2pose[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(以上述代码为例)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1600093.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【亲测有用】2024年timm从本地加载模型

有图有真相:https://github.com/huggingface/pytorch-image-models/discussions/1826 好使。 其他的过时的方法就别看了。(当然我这个过几年也会过时)

亚马逊国际获得AMAZON商品详情 API (属性主图价格等)

要获取亚马逊国际的商品详情API,包括商品的属性、主图、价格等信息,可以按照以下步骤操作: 请求示例,API接口接入Anzexi58 了解亚马逊开发者中心:首先,访问亚马逊开发者中心,详细阅读相关的API…

基于小程序实现的4s店管理系统

作者主页:Java码库 主营内容:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路 关注作者有好处 文末获取源码 技术选型 【后端】:Java 【框架】:ssm 【…

OpenAI宣布GPT-4-Turbo全面升级,GPT-4 Turbo 新增视觉理解能力,可同时处理文本和图像信息

OpenAI宣布GPT-4-Turbo全面升级,GPT-4 Turbo with Vision新增视觉理解能力,可同时处理文本和图像信息,极大简化了开发流程。 OpenAI宣布GPT-4 Turbo全面升级!根据官方说法,这一波 GPT 的升级包括: 更长的上…

如果补货机器人也开始搬砖

过去几年,如果一位顾客的欲购商品疑似缺货,“请稍等,我去后台查一下”便是最常听到的一句话。随着过去几年劳动力短缺的加剧,货架并不总像许多人习惯的那样满满当当。为减轻不断补货的负担,使员工可以将精力集中于其他…

ArduPilot开源飞控之ROS系统简介

ArduPilot开源飞控之ROS系统简介 1. 源由2. ROS系统3. 安装2.1 安装Docker2.2 安装ROS2 4. 总结5. 补充资料 1. 源由 之前在ArduPilot开源飞控之硬件SBC分析中讨论过,个人角度最推荐其中两个系统是: Rpanion-server【推荐,简单】BlueOS【推…

OpenHarmony实战开发-如何实现发布图片评论功能。

介绍 本示例将通过发布图片评论场景,介绍如何使用startAbilityForResult接口拉起相机拍照,并获取相机返回的数据。 效果图预览 使用说明 通过startAbilityForResult接口拉起相机,拍照后获取图片地址。 实现思路 1.创建CommentData类&…

反转链表【java】

给定一个链表的头节点head反转链表 方法一:循环 1.定义三个指针: pre指针:刚开始指向空 prenull cur指针:刚开始指向head节点 curhead temp指针:保存cur指针指向节点的下一个节点 2. 不断循环改变相邻两个节点的指…

3.2 iHRM人力资源 - 组织架构 - 编辑及删除

iHRM人力资源 - 组织架构 文章目录 iHRM人力资源 - 组织架构一、编辑功能1.1 表单弹层并数据回显1.2 编辑校验1.3 编辑 二、删除功能 一、编辑功能 编辑功能和新增功能用的组件其实是一个,结构几乎是一样的,其实是复用了组件,我们也省去了很…

中国新质生产力水平(原始+测算+结果)-企业和各省数据集

新质生产力是一个至少涵盖科技、绿色和数字三大方面的集成体,对其评价测度需要依托多属性综合评价方法。文章构建了包含3个一级指标、6个二级指标和18个三级指标的综合体系,采用改进的熵权-TOPSIS方法对指标进行赋权,从而得到全国新质生产力发…

Github 2024-04-12 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-04-12统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6TypeScript项目2Cuda项目1C++项目1C项目1HTML项目1Jupyter Notebook项目1JavaScript项目1Python - 100天从新手到大师 创建周期:22…

AV1:帧内预测(二)

在上一篇文章中介绍了AV1帧内预测的各个工具,本文进一步介绍其中的相关细节。 参考像素准备 帧内预测是利用当前帧已重建的像素预测当前块,和HEVC一样,AV1的帧内预测参考像素来自当前块上方和左侧的重建像素。 对于尺寸为wxh的块&#xff0…

Vue 阶段练习:记事本

将 Vue快速入门 和 Vue 指令的学习成果应用到实际场景中(如该练习 记事本),我们能够解决实际问题并提升对 Vue 的技能掌握。 目录 功能展示 需求分析 我的代码 案例代码 知识点总结 功能展示 需求分析 列表渲染删除功能添加功能底部统计…

正在海外乘风破浪的扫地机器人,手握怎样的发展利器?

“懒人经济”能造就多大的市场,可以从扫地机器人行业的发展窥见。 据国际数据分析机构捷孚凯报告,截至2022年底,我国扫地机器人已占据50%以上的海外市场份额。其中,科沃斯、石头科技等头部企业成为出海的“主力军”。 以石头科技…

网工内推 | 等保测评工程师,朝九晚六,周末双休,有相关认证优先

01 江苏国保测评中心 招聘岗位:等保测评工程师 职责描述: 1.测评类项目的物理安全测评、主机安全测评、数据安全测评、应用安全测评、风险评估、差距分析等并编制相关报告; 2.协助业务部门完成网络安全等级保护测评、信息安全咨询、信息安全风险评估等项…

4.配置USART串口实现printf打印

通过TTL转USB实现电脑和单片机连通,是我们调试必不可少的工具 查看原理图,使用USART1,它们的TX和RX分别在PA9和PA10 新建Usart.c存放串口模块的初始化 这段代码是复制了正点原子的工程,添加到前面 #if SYSTEM_SUPPORT_OS #include "includes.h" //ucos 使用 …

rhce.定时任务和延迟任务项目

一 . 在系统中设定延迟任务要求如下: 在系统中建立 easylee 用户,设定其密码为 easylee 延迟任务由 root 用户建立 要求在 5 小时后备份系统中的用户信息文件到/backup中 确保延迟任务是使用非交互模式建立 确保系统中只有 root 用户和easylee用户可以…

GitHub提交PR

本教程只做开源代码库Github工程提交pr的教程,不做其他的深入的讲解 Github和Gitlab的操作类似,只不过Github叫PR,GitLab叫MR,基本上做法是一致的 以开源项目QuickChat为例 https://github.com/Binx98/QuickChat https://github…

ShardingSphere:强大的分布式数据库中间件【图文】

ShardingSphere的诞生 ShardingSphere的结构 Sharding-JDBC :它提供了一个轻量级的 Java 框架,在 Java 的 JDBC 层提供额外的服务。使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动&…

225 基于matlab的天牛须优化算法及其对BP神经网络的优化

基于matlab的天牛须优化算法及其对BP神经网络的优化,优化后的阀值权值赋予网络预测。最后输出BP和BAS-BP训练和预测结果。程序已调通,可直接运行。 225 天牛须优化算法 BP神经网络 - 小红书 (xiaohongshu.com)