UE5制作视差图
双目深度估计开源数据集很多都是用UE制作的,那么我们自己能否通过UE制作自己想要的场景的数据集呢。最近花了点时间研究了一下,分享给需要的小伙伴。
主要使用的是UnrealCV插件,UnrealCV是一个开源项目,旨在帮助计算机视觉研究人员使用虚幻引擎(UE)构建虚拟世界。
下载UnrealCV
GitHub - unrealcv/unrealcv: UnrealCV: Connecting Computer Vision to Unreal Engine
下载并安装对应版本的UE5,参考这个链接:
https://blog.csdn.net/ButDanJi/article/details/133919089
注意UnrealCV的版本和UE5的版本必须一致,例如UnrealCV5.2 必须对应UE5.2,否则可能会报错
进入UE,新建项目,例如这里可以创建一个第一人称游戏的项目:

项目创建完成后,关闭UE。在对应项目下新建Plugins文件夹,并把unrealcv放在项目的Plugins下,例如:E:\UE_Project\testproject5\Plugins\unrealcv-5.2
打开UE下的unrealcv.ini文件,E:\UnrealEngine-5.2.0-release\Engine\Binaries\Win64\unrealcv.ini
将EnableRightEye设置为True
再次打开UE,打开这个项目,此时会提示安装UnrealCV

点击yes安装UnrealCV,等待一段时间后会进入项目,点击编辑-插件,搜索UnrealCV,如果安装成功能搜到UnrealCV且处于启动状态

点击窗口-加载布局-UE4经典布局
在放置Actor下搜索fusion camera actor,放置2个相机到场景中

点击play 运行关卡

按下`输入vget /unrealcv/status

会得到以下日志:
LogUnrealCV: Warning: vget helper function, the real command is vget /unrealcv/status
LogUnrealCV: Warning: Is Listening
No Client Connected
9001
Configuration
Config file: E:/UnrealEngine-5.2.0-release/Engine/Binaries/Win64/unrealcv.ini
Port: 9001
Width: 640
Height: 480
FOV: 90.000000
EnableInput: true
EnableRightEye: true
此时UnrealCV已准备完毕,UnrealCV服务器正处于监听状态,接下来我们通过python构建客户端连接到UnrealCV进行采图
下载
https://github.com/ibaiGorordo/UnrealCV-stereo-depth-generation
注意直接运行会报错,UnrealCV的用法有改变,不能直接使用client.connect()
需要在代码开头加上
ip = '127.0.0.1'
port = 9001
client = Client((ip, port))
至于原因可以参考我在UnrealCV下问的帖子:
Can not connect to localhost · Issue #258 · unrealcv/unrealcv
这个项目可以获得平面深度,但不是视差图,我用以下代码获得视差图:
def convert_plane_depth_to_disp(plane_depth, f=320.0, baseline_meters=1.0):disp = f * baseline_meters * (1.0 / plane_depth)return disp
这个代码是参考自以下链接:https://github.com/wuwushrek/AirSim/blob/56e2c5c3ec461f2d95c6a9e80c98767078e718ac/PythonClient/generate_stereo_data.py#L67
于是最后的代码为(这里是示例,相机的姿态等参数需要自己修改):
from unrealcv import Client
import sys
import numpy as np
import cv2
import io
ip = '127.0.0.1'
port = 9001
client = Client((ip, port))camera_poses=np.array([[-106.933, 459.372, 167.895, 0.213, -80.610, 0.000],
[-97.576, 413.807, 168.308, 2.901, -79.483, 0.000],
[-88.197, 346.847, 166.356, 3.644, -89.711, 0.000],
[-82.595, 278.711, 172.572, 5.711, -85.554, 0.000],
[-73.239, 149.936, 176.386, 0.058, -89.777, 0.000],
[-71.879, 58.805, 175.112, 1.199, -89.030, 0.000],
[-69.923, 10.021, 161.958, 4.062, -59.268, 0.000],
[-28.289, -68.530, 159.251, 2.186, -61.090, 0.000],
[-28.289, -68.530, 159.251, 2.831, -43.937, 0.000],
[-28.289, -68.530, 159.251, 1.782, 0.917, 0.000],
[-28.289, -68.530, 159.251, 3.708, 33.667, 0.000],
[-28.289, -68.530, 159.251, 0.167, 92.277, 0.000],
[-32.458, 5.207, 157.922, 2.922, 93.428, 0.000],
[-35.463, 90.040, 156.689, 1.045, 97.168, 0.000],
[-46.087, 180.173, 155.370, 1.167, 96.643, 0.000],
[-52.370, 234.121, 154.580, 1.167, 96.315, 0.000],
[-52.370, 234.121, 154.580, 3.425, 54.474, 0.000],
[-52.370, 234.121, 154.580, 5.985, 18.172, 0.000],
[-52.370, 234.121, 154.580, 5.675, -10.430, 0.000],
[-52.370, 234.121, 154.580, 11.879, -34.452, 0.000],
[-52.370, 234.121, 154.580, 13.122, -66.362, 0.000],
[-52.370, 234.121, 154.580, 14.454, -81.988, 0.000]])fps = 45
times = np.arange(0,camera_poses.shape[0]*fps,fps)
filled_times = np.arange(0,camera_poses.shape[0]*fps)filtered_poses = np.array([np.interp(filled_times, times, axis) for axis in camera_poses.T]).Tclass UnrealcvStereo():def __init__(self):client.connect() if not client.isconnected():print('UnrealCV server is not running. Run the game downloaded from http://unrealcv.github.io first.')sys.exit(-1)def __str__(self):return client.request('vget /unrealcv/status')@staticmethoddef set_position(pose):# Set position of the first cameraclient.request(f'vset /camera/1/location {pose[0]} {pose[1]} {pose[2]}')client.request(f'vset /camera/1/rotation {pose[3]} {pose[4]} {pose[5]}')client.request(f'vset /camera/2/location {pose[0]} {pose[1]} {pose[2]}')client.request(f'vset /camera/2/rotation {pose[3]} {pose[4]} {pose[5]}')@staticmethoddef get_stereo_pair(eye_distance):res = client.request('vset /action/eyes_distance %d' % eye_distance)res = client.request('vget /camera/1/lit png')left = cv2.imdecode(np.frombuffer(res, dtype='uint8'), cv2.IMREAD_UNCHANGED)res = client.request('vget /camera/2/lit png')right = cv2.imdecode(np.frombuffer(res, dtype='uint8'), cv2.IMREAD_UNCHANGED)return left, right@staticmethoddef convert_depth(PointDepth, f=320):H = PointDepth.shape[0]W = PointDepth.shape[1]i_c = float(H) / 2 - 1j_c = float(W) / 2 - 1columns, rows = np.meshgrid(np.linspace(0, W-1, num=W), np.linspace(0, H-1, num=H))DistanceFromCenter = ((rows - i_c)**2 + (columns - j_c)**2)**(0.5)PlaneDepth = PointDepth / (1 + (DistanceFromCenter / f)**2)**(0.5)return PlaneDepth@staticmethoddef get_depth():res = client.request('vget /camera/1/depth npy')point_depth = np.load(io.BytesIO(res))return UnrealcvStereo.convert_depth(point_depth)@staticmethoddef color_depth(depth_map, max_dist):norm_depth_map = 255*(1-depth_map/max_dist)norm_depth_map[norm_depth_map < 0] =0norm_depth_map[depth_map == 0] =0return cv2.applyColorMap(cv2.convertScaleAbs(norm_depth_map,1), cv2.COLORMAP_MAGMA)def convert_plane_depth_to_disp(plane_depth, f=320.0, baseline_meters=1.0):disp = f * baseline_meters * (1.0 / plane_depth)return disp
if __name__ == '__main__':eye_distance = 10max_depth = 5stereo_generator = UnrealcvStereo()for pose in filtered_poses:stereo_generator.set_position(pose)# Set the eye distanceleft, right = stereo_generator.get_stereo_pair(eye_distance)depth_map = stereo_generator.get_depth()baseline_cm =25# Parameters for cameracx = float(depth_map.shape[1]) / 2.0 - 1.0cy = float(depth_map.shape[0]) / 2.0 - 1.0f = cxdisparity = convert_plane_depth_to_disp(plane_depth=depth_map, f=f, baseline_meters=baseline_cm/100.0)color_depth_map = stereo_generator.color_depth(disparity, max_depth)left = cv2.cvtColor(left, cv2.COLOR_BGRA2BGR)right = cv2.cvtColor(right, cv2.COLOR_BGRA2BGR)output_path = "C:/Users/chen/Desktop/output_image.jpg"output_path1 = "C:/Users/chen/Desktop/output_image1.jpg"output_path2 = "C:/Users/chen/Desktop/output_image2.jpg"cv2.imwrite(output_path, color_depth_map) cv2.imwrite(output_path1, left)cv2.imwrite(output_path2, right)combined_image = np.hstack((left, right, color_depth_map))cv2.imshow("stereo", combined_image)# Press key q to stopif cv2.waitKey(1) == ord('q'):breakcv2.destroyAllWindows()
运行python文件(运行时,UE的项目必须处于运行状态,即play状态)
这时就能获得双目图像和视差图了。

再往后就是换成自己想要的场景并修改两个相机的姿态以及baseline_meters等参数,修改完就可以得到想要的图像了
相关文章:
UE5制作视差图
双目深度估计开源数据集很多都是用UE制作的,那么我们自己能否通过UE制作自己想要的场景的数据集呢。最近花了点时间研究了一下,分享给需要的小伙伴。 主要使用的是UnrealCV插件,UnrealCV是一个开源项目,旨在帮助计算机视觉研究人…...
海浪波高预测(背景调研)
#新星杯14天创作挑战营第7期# ps:图片由通义千问生成 历史工作: 针对更高细粒度、更高精度的波浪高度预测任务: Mumtaz Ali 等人提出了一种多元线性回归模型(MLR-CWLS),该模型利用协方差加权最小二乘法&a…...
代码随想录算法训练营第四十二天-动态规划-股票-188.买卖股票的最佳时机IV
题目要求进行k次买卖其实就是上一题的扩展,把2次扩展为k次定义动规数组依然是二维,第一个维度表示第几天,第二个维度表示第几次买入和卖出所以第二个维度的长度应该是2k1在for循环内,要使用一个内循环来表示第几次买入或卖出&…...
Gradle配置指南:深入解析settings.gradle.kts(Kotlin DSL版)
文章目录 Gradle配置指南:深入解析settings.gradle.kts(Kotlin DSL版)settings.gradle.kts 基础配置选项单项目配置多项目配置 高级配置选项插件管理(Plugin Management)基础配置模板案例:Android项目标准配…...
软件工程经济学-日常作业+大作业
目录 一、作业1 作业内容 解答 二、作业2 作业内容 解答 三、作业3 作业内容 解答 四、大作业 作业内容 解答 1.建立层次结构模型 (1)目标层 (2)准则层 (3)方案层 2.构造判断矩阵 (1)准则层判断矩阵 (2)方案层判断矩阵 3.层次单排序及其一致性检验 代码 …...
论文阅读(三):微阵列数据的图形模型和多变量分析
1.论文链接:Graphical Models and Multivariate Analysis of Microarray Data 摘要: 基因表达数据的通常分析忽略了基因表达值之间的相关性。从生物学上讲,这种假设是不合理的。本章介绍的方法允许通过稀疏高斯图形模型来描述基因之间的相关…...
【大模型LLM面试合集】大语言模型架构_MHA_MQA_GQA
MHA_MQA_GQA 1.总结 在 MHA(Multi Head Attention) 中,每个头有自己单独的 key-value 对;标准的多头注意力机制,h个Query、Key 和 Value 矩阵。在 MQA(Multi Query Attention) 中只会有一组 k…...
向上调整算法(详解)c++
算法流程: 与⽗结点的权值作⽐较,如果⽐它⼤,就与⽗亲交换; 交换完之后,重复 1 操作,直到⽐⽗亲⼩,或者换到根节点的位置 这里为什么插入85完后合法? 我们插入一个85,…...
【Transformer】手撕Attention
import torch from torch import nn import torch.functional as F import mathX torch.randn(16,64,512) # B,T,Dd_model 512 # 模型的维度 n_head 8 # 注意力头的数量多头注意力机制 class multi_head_attention(nn.Module): def __init__(self, d_model, n_hea…...
844.比较含退格的字符串
目录 题目思路解法收获 题目 给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。 注意:如果对空文本输入退格字符,文本继续为空。 思路 如何解退格之后left…...
图书管理系统 Axios 源码__编辑图书
目录 功能概述: 代码实现(index.js): 代码解析: 图书管理系统中,删除图书功能是核心操作之一。下是基于 HTML、Bootstrap、JavaScript 和 Axios 实现的删除图书功能的详细介绍。 功能概述: …...
LabVIEW纤维集合体微电流测试仪
LabVIEW开发纤维集合体微电流测试仪。该设备精确测量纤维材料在特定电压下的电流变化,以分析纤维的结构、老化及回潮率等属性,对于纤维材料的科学研究及质量控制具有重要意义。 项目背景 在纤维材料的研究与应用中,电学性能是评估其性能…...
Commander 一款命令行自定义命令依赖
一、安装 commander 插件 npm install commander 二、基本用法 1. 创建一个简单的命令行程序 创建一个 JavaScript 文件,例如 mycli.js,并添加以下代码: // 引入 commander 模块并获取 program 对象。const { program } require("…...
Day24 洛谷普及2004(内涵前缀和与差分算法)
零基础洛谷刷题记录 Day01 2024.11.18 Day02 2024.11.25 Day03 2024.11.26 Day04 2024.11.28 Day05 2024.11.29 Day06 2024 12.02 Day07 2024.12.03 Day08 2024 12 05 Day09 2024.12.07 Day10 2024.12.09 Day11 2024.12.10 Day12 2024.12.12 Day13 2024.12.16 Day14 2024.12.1…...
遗传算法与深度学习实战(33)——WGAN详解与实现
遗传算法与深度学习实战(33)——WGAN详解与实现 0. 前言1. 训练生成对抗网络的挑战2. GAN 优化问题2.1 梯度消失2.2 模式崩溃 2.3 无法收敛3 Wasserstein GAN3.1 Wasserstein 损失3.2 使用 Wasserstein 损失改进 DCGAN 小结系列链接 0. 前言 原始的生成…...
gitlab云服务器配置
目录 1、关闭防火墙 2、安装gitlab 3、修改配置 4、查看版本 GitLab终端常用命令 5、访问 1、关闭防火墙 firewall-cmd --state 检查防火墙状态 systemctl stop firewalld.service 停止防火墙 2、安装gitlab xftp中导入安装包 [rootgitlab ~]#mkdir -p /service/tool…...
SAP SD学习笔记27 - 请求计划(开票计划)之1 - 定期请求(定期开票)
上两章讲了贩卖契约(框架协议)的概要,以及贩卖契约中最为常用的 基本契约 - 数量契约和金额契约。 SAP SD学习笔记26 - 贩卖契约(框架协议)的概要,基本契约 - 数量契约_sap 框架协议-CSDN博客 SAP SD学习笔记27 - 贩卖契约(框架…...
HTML DOM 修改 HTML 内容
HTML DOM 修改 HTML 内容 引言 HTML DOM(文档对象模型)是浏览器内部用来解析和操作HTML文档的一种机制。通过DOM,我们可以轻松地修改HTML文档的结构、样式和行为。本文将详细介绍如何使用HTML DOM来修改HTML内容,包括元素的增删改查、属性修改以及事件处理等。 1. HTML …...
基于VMware的ubuntu与vscode建立ssh连接
1.首先安装openssh服务 sudo apt update sudo apt install openssh-server -y 2.启动并检查ssh服务状态 到这里可以按q退出 之后输入命令 : ip a 红色挡住的部分就是我们要的地址,这里就不展示了哈 3.配置vscode 打开vscode 搜索并安装:…...
Flutter Candies 一桶天下
| | | | | | | | 入魔的冬瓜 最近刚入桶的兄弟,有责任心的开发者,对自己的项目会不断进行优化,达到最完美的状态 自定义日历组件 主要功能 支持公历,农历,节气,传统节日,常用节假日 …...
西门子PLC通信必备:手把手教你用SCL编写Modbus RTU CRC校验功能块
西门子PLC通信实战:SCL实现Modbus RTU CRC校验的工程化解决方案 在工业自动化领域,可靠的数据通信如同设备的神经系统。当两台PLC需要通过RS485接口交换温度传感器读数时,Modbus RTU协议因其简洁高效成为首选。但许多工程师在调试阶段都会遇到…...
3步解锁鸣潮120帧:你的终极游戏体验优化指南
3步解锁鸣潮120帧:你的终极游戏体验优化指南 【免费下载链接】WaveTools 🧰鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 还在为《鸣潮》游戏中的60帧限制而烦恼吗?明明拥有强大的硬件配置,却无法充…...
Switch便携投影底座DIY:3D打印与硬件改造实战指南
1. 项目概述:当Switch遇上投影,一场桌面上的大屏革命作为一个折腾过不少游戏机外设的玩家,我一直在想,有没有办法让Switch的“便携”属性再进化一步?官方底座接电视固然爽,但总被一根线缆束缚在客厅。直到我…...
数据分析师能力展示:从项目构建到报告呈现的完整指南
1. 项目概述:一个数据分析师的能力展示平台最近在GitHub上看到一个挺有意思的项目,叫“dataanalyst-showcase”。光看名字,你可能会觉得这又是一个数据科学项目合集,但点进去仔细研究后,我发现它的定位非常精准——它不…...
成本优化策略:降低云资源支出
成本优化策略:降低云资源支出 一、成本优化策略概述 1.1 成本优化策略的定义 成本优化策略是指通过各种技术和管理手段,降低云资源支出的策略和方法。它包括资源优化、成本监控、预算管理和采购策略等方面。 1.2 成本优化策略的价值 成本降低:…...
三维重建下半场,拼的全是底层基建实力!
三维重建已从算法创新竞赛正式迈入基础设施比拼新阶段,主流技术路线逐步收敛,单纯算法红利见顶,行业竞争核心转向数据、算力、平台、生态等底层综合能力。当下竞争不再只比模型效果,而是聚焦四大核心基建维度:采集传感…...
EmoLLM:大语言模型的情感增强训练与部署实践
1. 项目概述:当大语言模型学会“察言观色”最近在折腾一个挺有意思的开源项目,叫SmartFlowAI/EmoLLM。光看名字你大概能猜到,这玩意儿跟“情绪”和“大语言模型”有关。没错,它的核心目标就是让冷冰冰的LLM(Large Lang…...
数据分析师GitHub作品集构建指南:从项目架构到技术实现
1. 项目概述:一个数据分析师的作品集仓库意味着什么? 在数据驱动的时代,简历上的“精通Python/SQL”已经不够看了。面试官,尤其是那些懂行的技术面试官,更想看到的是你如何用这些工具解决真实世界的问题。这就是为什么…...
创业团队如何利用Taotoken以更低成本快速验证AI产品创意
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 创业团队如何利用Taotoken以更低成本快速验证AI产品创意 对于资源有限的创业团队而言,在产品原型阶段验证AI创意的可行…...
WarcraftHelper:魔兽争霸3现代化增强插件,解锁经典游戏新体验
WarcraftHelper:魔兽争霸3现代化增强插件,解锁经典游戏新体验 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是…...
