WildPerception

WildPerception 是一个利用 Unity Perception Package 来生成大规模多视角视频数据集的工具。
其允许用户导入自己的 Humanoid 人物模型,或者利用 SyntheticHumans Package 以合成人物模型,从而在自定义的场景中模拟行人。配合 MultiviewX_Perception 可以得到符合 Wildtrack 格式的数据集。

注意:

  1. 原 MultiviewX_FYP 现更名为 MultiviewX_Perception
  2. CalibrateTool 已集成到了此处,将不再独立导出
  3. 开发使用的 Editor 版本为 2022.3.3f1,不保证之前版本(尤其是2022.2之前)的表现。 Unity Perception Package 要求一定版本的 HDRP 。

Support For SyntheticHumans

  1. 添加 WildPerception、 SyntheticHumans Package 到您的项目中,推荐导入 SyntheticHumans 官方提供的 Samples,具体过程请参考:Install Packages and Set Things Up

  2. 为 TsingLoo.WildPerception.asmdef 添加 AssemblyDefinitionReferences,选择 SyntheticHumans 提供的 Unity.CV.SyntheticHumans.Runtime,而后在页面底部右下角点击 Apply,保存。

    选择 SyntheticHumans 提供的 Unity.CV.SyntheticHumans.Runtime

    在页面底部右下角点击 Apply,保存

  3. 找到 RuntimeModelProvider.cs 脚本,更改 false 为 true

    更改 false 为 true

  4. 将 RuntimeModelProvider 组件分配给场景

    将 RuntimeModelProvider 组件分配给场景

  5. 移除其他的ModelProvider

    移除其他的ModelProvider

  6. 添加 HumanGenerationConfig,Config 的具体配置请参考此文档下半部分:Generate Your First Humans

添加 HumanGenerationConfig

  1. 运行

Import

有两种方法可以将 WildPerception 包添加到您的项目中。

注意:

  1. 由于需要安装相关依赖,应该在联网环境中导入此包

[Method 1] Add package from git URL

注意:

  1. 这需要您的设备有 git 环境,可以去这里安装:git
  2. 由于目前 Package Manager 的限制,若如此做不可打开示例场景 SampleScene_WildPerception,但不影响其他功能。

Unity Editor 中打开 Window -> Package Manager

Add package from git URL

复制本项目地址,填写并添加

复制本项目地址

填写并添加

大约三到五分钟后,添加完成,Unity 开始导入新包。

[Method 2] Add package from disk

通过 git clone 或者直接从 github 上下载ZIP文件,或者从此处[Download WildPerception] 下载包。

直接从 github 上下载ZIP文件

将此ZIP文件解压,放到非项目Assets文件夹中(在项目文件夹外亦可)

放到非项目Assets文件夹中

Unity Editor 中打开 Window -> Package Manager

Add package from disk

将package.json选中并确定。

将package.json选中

大约两分钟后,添加完成,Unity 开始导入新包。

Setup

您可以很快赋予您的场景生成序列帧的能力,只需要简单的几步配置。

若您使用的是方法2来添加此包,不妨打开场景 Packages -> WildPerception -> Sample -> SampleScene_WildPerception。 这个场景中比较简洁,如下图所示,有预制体SceneController 和一些GameObject

需要用到的预制体及生成的GameObject

若您想使用自己搭建的场景,请为这个场景添加预制体 SceneController

为这个场景添加预制体 SceneController

SceneController

SceneController 集成了所有的配置与功能。

场景导入 SceneController 后,可以打开其Inspector面板,请按照您的情况配置。

Main Controller

MainController 是 SceneController上挂载的一个组件

点击 Init Scene,场景中会自动生成所需的GameObject,请在场景中将这些 GameObject 置于所需的位置,随后点击 Assign Transfrom

请设置 MultiviewX_Perception 项目的绝对路径

若使用 LocalFilePedestrianModelProvider, 请设置 Mode_PATH 的绝对路径,此路径务必在一个路径包含”Resources/Models”的文件夹下且此文件夹中有且仅有人物模型的预制体(.prefab),而非.fbx等模型文件。若您的项目中还没有人物模型,可以使用示例模型,其在 com.tsingloo.wildperception-main\Resources\Models 下,请使用其绝对路径。

设置相关路径

对于人物模型,仅仅要求其具有 Humanoid 骨骼,并带有 Animator组件,其 Runtime Animator Controller 可以为空,若为空,将会在其生成时使用您在 People Manager 中配置的默认Runtime Animator Controller。

仅仅要求其具有 Humanoid 骨骼,并带有 Animator 组件

注意:

  1. 请尽量保证GridOrigin_OpenCV的纵坐标(Y)与Center_HumanSpawn_CameraLookAt的纵坐标(Y)相同,否则可能会出现标定不准确的情况,这个问题可能会在后续工作中修复。
  2. 确保场景中供人物模型行走的平面携带有 NavMeshSurface 组件,并已完成烘焙,若您未在 Add Component 中找到这个组件,请前往安装 Package Manager -> Packages: Unity Registry -> AI Navigation,此处使用的版本是 1.1.1

供人物模型行走的平面携带有 NavMeshSurface 组件

Camera Manager

Camera Manager 管理并控制着相机相关的内容,您可以在这里配置将在场景运行多少帧后开始导出序列帧(Begin Frame Count)、相机的位置类型(自动生成 Ellipse_Auto 或者手动摆放 By Hand)、相机的自动生成参数 Ellipse_Auto Settings

Camera Place Type

若您希望程序自动生成相机,请使用Auto

若您希望手动放置相机,请使用 By Hand
并从菜单中添加相机,为这个场景添加相机预制体 Camera_Perception,并将预制体放在HandPlacedCameraParent下

为这个场景添加相机预制体

将相机预制体放在HandPlacedCameraParent下

Ellipse_Auto Settings

此处您可以配置相机的自动生成参数。

参数名 备注
Level 有几层相机
Nums Per Level 每层多少个相机
Height First Level 第一层离地(LookAt) 多少垂直高度(已经换算为了OpenCV下长度)
H Per Level 若有多层,每层层高(已经换算为了OpenCV下长度)
Major Axis 椭圆主轴长度 (已经换算为了OpenCV下长度)
Minor Axis 椭圆副轴长度 (已经换算为了OpenCV下长度)
Camera Prefab 将会被自动生成的相机的预制体

Pedestrians Manager

此处您可以配置人物生成的相关参数。

参数名 备注
Default Animator 人物模型使用的默认动画控制器
Add_human_count 每次敲击空格将会新生成几个人物模型
Preset_humans 场景初始化后生成多少个模型
Largest,Smallest,X,Y 规定初始化生成模型的区域(绿色矩形辅助线)以及行人的活动范围
Outter Bound Radius 人物模型回收边界,请设置大一些,务必使此边界不与 Grid 相交,否则可能出现Editor 卡死,这个问题会在后续工作中修复

AbstractPedestrianModelProvider

实现此类以能为 Pedestrians Manager 提供行人模型(将其拖拽到 Main Controller 的 Pedestrian Model Provider 属性槽中,默认为 LocalFilePedestrianModelProvider)

CalibrateTool

用于相机的标定,为 MultiviewX_Perception 提供数据,请见:CalibrateTool

Notes of the calibration of MultivewX_Perception(CalibrateTool)

WHAT IS NEW!!

支持利用数据集文件夹中 calibrations 中的标定数据与 datasetparameters.py 中的 NUM_CAM MAP_HEIGHT MAP_WIDTH OverlapUnitConvert OverlapGridOffset 参数给出其相机姿态和视野范围。

例如,当我们希望为 Wildtrack 数据集产生 Overlap view 时:

在命令行中输入 -view D:\Wildtrack ,注意需保证其calibrations文件夹下有extrinsicintrinsic文件夹(与Wildtrack格式一致)。

运行可得下列结果。

Camera 6

左图为本工具对 Wildtrack 的结果,右图(有一定变形)为参考

注意:请修改上述的五个参数以符合实际情况,MAP 使用的单位应当与其 calibration 使用的单位相同。Wildtrack 数据集工具声明其网格起点与世界原点并非同处,网格起点为(-300,-90,0)cm,似乎有误。此处使用的是网格起点为(-300,-900,0)cm

Args

MultiviewX_Perception可以接受命令行参数,从而用户可以快速高效地产生数据集。当未接收到相关参数时候,不会启用相关功能。

-a :Annotate and show the bbox on the first frame of each camera or not.

-s :Save the bbox on the first frame of each camera or not.

-k :Keep the remains of Perception dataset or not.

-f :Force calibrate and generate POM, regardless of perception.

-p n: Provide preview for the front n frames. ex. -p 5 will provide 5 frames to preview

-v :Generate Overlap view for the dataset

-view path :Generate Overlap view for the specified dataset, there should be folder calibrations in the given path. ex. -view D:\Wildtrack

例如,当只想借助CalibrateTool进行标定时,可以输入-f,程序会跳过处理percetion数据步骤,也不会进行后续标注的环节。

1
python run_all.py -f

Keep in Mind

CalibrateTool 现在是 WildPerception 的标定部分

Github 项目地址:MultiviewX_WildPerception

欢迎下载示例文件:sample.zip

对于场景:

  1. Unity长度(米)➗ Scaling = OpenCV长度(米)

  2. (Unity点坐标 - Unity中GridOrigin的Unity坐标)➗Scaling , 再交换Unity坐标中的y,z分量,可以得到OpenCV下点坐标。

  3. GridOrigin所在位置是OpenCV下的坐标原点

  4. 棋盘会在黄色辅助正方体内随机生成,辅助正方体的边长等于两倍的tRandomTransform,其中心是chessboardGenerateCenter

  5. 场景中全体markpoint_3dchessboardGenerateCenter的坐标加上一些预设的偏移得到。换言之,场景其实只有一份markpoints_3d,其中心为 chessboardGenerateCenter,均匀分布在水平面上。

    注意:Grid辅助线上标注的和辅助点markpoint_3d上标注的值已经是OpenCV下此点的坐标。

    如下图:

    image-20230322202441746

对于每个相机:

  1. 既然整个场景公用一份markpoints_3d,为什么每个相机下都有markpoints_3d.txt这么个文件呢?

    因为不是全体markpoint_3d都在此相机的视野范围内,需要针对每个相机进行剔除对应点。每个相机的 markpoints_3d.txtmarkpoints_2d.txt 共同得出了其外参。

  2. 务必保证Game View下的分辨率与CalibrateTool配置的分辨率相同,否则会直接退出运行并报错。

  3. tRandomTransform的选择推荐是,使得黄色辅助正方体大部分在所有相机的视野中。

Introduction

CalibrateTool是一个在Unity3D中为一个或多个相机,产生多个虚拟的不同角度朝向的棋盘格数据且给出待标定相机对应内外参的工具。其生成的虚拟棋盘数据等效于利用OpenCV中cv.findChessboardCorners所产生的结果。同时,CalibrateTool 可以完成一些运行 MultiviewX_Perception 所需要的设置,诸如设置地图大小、地图格点起始位置等。具体使用在 [Work with MultiviewX_Perception](# Work with MultiviewX_Perception) 标题下。

下列图片为标注环节的效果演示,此环节不在CalibrateTool能力范围内,是MultviewX_Perception的后续环节。此处贴上标注的图仅仅用来说明CalibrateTool的缩放、OpenCV坐标系的设置、标定是合理有效的。

Grid地图

bbox\_cam9

bbox\_cam8

Setup

CalibrateTool.unitypackage 是对应的Unity资产,其中包含了一个带有CalibrateTool组件的预制体和组件对应的代码。(面板可能因为版本不同略有出入,推荐总是使用最新的一个版本)

  1. unitypackage包导入完成后,我们可以将 CalibrateTool 拖入到需要标定的场景中:

    检视面板

  2. 根据自己项目的情况进行配置,点击加号➕,产生空槽,将场景中需要标定的相机拖入,一个或者多个均可,同时,此字段是公开的,可以利用脚本进行赋值:

    点击➕,拖入待标定相机

    利用脚本进行赋值

  3. 调整相机分辨率,点击Game,选择一个具体的分辨率,此处以1920*1080为例

    选择一个具体的分辨率

  4. 传入一个Transform,chessboardGenerateCenter,用来指示虚拟棋盘的产生位置,同时也规定了标定参照的水平面,这个 Transform 的位置最好能在所需标定的相机的屏幕中央附近(此处为了演示此位置,创建了一个cube,实际使用中只需要创建一个空物体,传入Transform即可,不必考虑其旋转,将被统一清零):

    位置最好能在所需标定的相机的屏幕中央附近

    传入一个Transform

  5. 给定目标文件夹,CalibrateTool会在此文件夹下产生一个 calib 文件夹用来保存数据。一般会填入MultiviewX所在文件夹

    给定目标文件夹

  6. 传入一个Transform,Grid Origin用来指示Grid格点的原点,同时也是OpenCV坐标系(右手坐标系)的原点,为了方便计算,应当将此点设置在标定参照的水平面上(其Unity坐标的Y值应该与chessboardGenerateCenter的Y值相同,我没有测试过不相同会如何)。

    Grid Origin

    正确配置后,Scene场景中会产生辅助线。此图中,蓝色箭头指示右手坐标系下Y轴的正反向,红色箭头指示右手坐标系下X轴的正方向

    指示Grid格点的原点

  7. 可以通过调节MAP_HEIGHTMAP_WIDTH 来调节格点图的大小,MultivewX只会标注脚底在格点图中的人。默认值16 与 25 是一个合理的值,一般不需要额外改动。

    例如,当MAP_HEIGHT = 16 ,MAP_WIDTH = 8 时,标注如图:

    MAP\_WIDTH = 8

    bbox\_cam7

    MAP_EXPAND可以理解成每个边长被额外划分多少份(小刻度),改动此项不会改变地图的大小。

    例如,当MAP_EXPAND = 40 时:

    MAP\_EXPAND = 40

  8. 缩放(Scaling)。很多时候,场景素材的地图尺寸和人物模型尺寸是不一样的,往往会存在人物模型与场景的不协调。 下图展示了这种差异,人物模型看起来很小,成年人看起来身高和儿童一样。

    地图尺寸和人物模型尺寸这就导致用户难以一站式完成CalibrateTool的使用,需要自己手动再去调整人物模型或者场景素材,而往往这种调整还牵扯到matchings(MultiviewX接受的一种输入)的坐标变换,每个人实现matchings的方法都不一样,这里提个醒,坐标变换的顺序必须是: 缩放->旋转->平移

    通过调整Scaling参数,CalibrateTool的辅助线与辅助模型(立方体)可以帮助用户很直观的找到一个合理的缩放值。辅助线的每格的边长为右手坐标系下1米。辅助模型的长宽为MAN_RADIUS*2,高为MAN_HEIGHT

    给与生成辅助线所需引用

    辅助线与模型

  9. 一般情况下,其余参数不需要额外设置。如果Python端报错,可以尝试调大Update Chessboard Interval参数,增加IO读写的时间。

  10. 运行。

Calibrate

拿到数据后,我们就可以进行标定了,应该会有如下结构:calib文件夹下有 C1 - Cn 子文件夹,每个子文件夹中,有得到的棋盘数据。

image-20230301221916504

运行calibrateCameraByChessboard.py,内外参数分别保存在calibration/intrinsiccalibration/extrinsic中。所输出的外参数(对于每一个虚拟的棋盘,都有一个外参负责对应的变换)为对第一个虚拟棋盘的变换,且生成的第一个虚拟棋盘总是与给定的Chessboard Generate Center同面

虚拟棋盘始终与给定的Chessboard Generate Center同面

一个疑惑 这种方法中,Python收到的棋盘格的世界坐标是给定的,如上图所示。(0,0,0)总是在左下角 往往在一些相对Chessboard Generate Center物体对称的物体,会有一个很相近的tvec。 因为在单个相机时,相对于该相机描述时,物体总是需要做同样的位移变换。但是在多个相机时,这种描述,依旧是相对单个接受标定的相机。

为了解决上述的疑问,尝试采用了cv2.solvePnP,和一组在待标定(水)平面上的静态的点来得到R与T,目前不支持相对斜面标定外参。

一组在待标定平面上的静态的点

在引入Grid格点的原点的概念时,遇到了一些问题。原思路是直接变换MarkPoints,使得solvePnP ”认识“目标坐标系,但是,经过实验得知,变换MarkPoints时候,应当保证最终被solvePnP获取的(OpenCV中)世界坐标的x,y值,保证其正方向与原 Unity 中x,z正方向保持一致或全部相反。否则会导致后续POM生成失败。猜测是左右手坐标系变换后OpenCV下Y正方向的问题。

Validate

通过参考Unity3d和OpenCV的相机模型左右手坐标系下三维位姿(旋转、平移)的转换旋转向量和旋转矩阵的互相转换 python cv2.Rodrigues()得知,默认的 Unity3D 相机组件是一个理想的针孔相机,其内外参可以通过调用Unity3D给予的相关参数计算得出。

GetNativeCalibrationByMath(),给出了这种方法,其结果基于Unity场景下的世界坐标系。经过比较这两个方法获得的值,误差很小,可以认为CalibrateTool是可以合理利用的。

提供了 vali.py,其利用单应性检验标定结果。

Preview

cam1\_frames

支持动图预览

  • 例如,在命令行中输入 python run_all.py -p 15 ,即可为前15帧生成带标注框的动图预览。

Work with MultiviewX_Perception

请 clone 一份 MultiviewX_Perception,可以参考Notes of MultiviewX_Perception进行后续工作。其将原calibdateCamera.py替换为了calibrateByChessboard.py,添加了一些动态容量的数组以适应不同的摄像头数,支持Scaling缩放,并且datasetParameters将由 CalibrateTool 根据Unity中Inspector面板处的参数自动生成,等等。

欢迎下载示例文件sample.zip,将其子文件夹calibperceptionmatchings,子文件datasetParameters.py拖入到 MultiviewX_Perception 文件夹下。

黄色字体即拖入的文件

运行run_all.py,参考Notes of MultiviewX_Perception,其给出了一些常用的命令行参数

1
python run_all.py 

当用户仅仅需要标定与生成POM时候(仅仅提供calibdatasetParameters.py),可以输入参数-f:

1
python run_all.py -f 

如果遇到WinError 32 报错,请检查是否有相关程序正在使用.pom,在PyCharm中,可能不小心打开了.pom的预览窗口,请关闭。

image-20230325105913670

示例 datasetParameters.py (for Wildtrack):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
GRID_ORIGIN = [-14.91,-1.51,-5.43]
NUM_CAM = 7
CHESSBOARD_COUNT = 50
MAP_WIDTH = 12
MAP_HEIGHT = 36
MAP_EXPAND = 40
IMAGE_WIDTH = 1280
IMAGE_HEIGHT = 720
MAN_HEIGHT = 1.8
MAN_RADIUS = 0.16
RJUST_WIDTH = 4
Scaling = 1
NUM_FRAMES = 0
DATASET_NAME = ''

# If you are using perception package: this should NOT be 'perception', output path of perception instead
PERCEPTION_PATH = 'D:/Test/WildPerception'

# The following is for -view configure only:

# Define how to convert your unit length to meter, if you are using cm, then 0.01
OverlapUnitConvert = 0.01
# Define how to translate cams to make the world origin and the grid origin is the same
OverlapGridOffset = (3., 9., 0.)