0%

轻量型视觉数据生成

1. 1 问题描述

为了给训练模型提供大量不同背景和姿态的训练数据,基于相机模型和Open3D的渲染生成数据,输入模型、背景和相机的姿态(或者模型的姿态),输出RGB图和深度图

2. 2 方法步骤

主要依赖两个库

  • Open3D:提供读取模型(.obj .mtl .jpg)以及渲染模型的作用,生成具有真实感的模型图片
  • 虚拟相机模型virtual_camera:提供生成mask的作用,也就是获取模型在图片中的位置

Pipeline:

  1. 读取模型
  2. 初始化相机模型,计算相机内参、外参
  3. 获取mask(起到抠图的作用)
  4. 读取模型的顶点和mesh信息
  5. 将顶点通过相机模型映射到像素平面
  6. 根据mesh信息将对应的三角形涂上颜色
  7. 最终根据颜色信息获取mask
  8. 渲染模型
  9. 初始化一个Open3D的render
  10. 定义render中的相机位置、模型材质、环境光照信息
  11. 渲染模型的深度图和RGB图
  12. 背景融合
  13. 读取背景图片
  14. 根据3中获取的mask信息读取4中RGB图相应位置的点,赋值给背景图图片,获得融合后的RGB图
  15. 根据4中获取的深度图,重新计算,映射到0-255范围,获得可视化良好的深度图

3. 3 代码实现

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import open3d as o3d
import open3d.visualization.rendering as rendering
import matplotlib.pyplot as plt
import numpy as np
from virtual_camera import VirtualCamera
import cv2

## Read the Data (From obj file)
bpa_mesh = o3d.io.read_triangle_mesh('BigConnecter.obj',True)
tri=np.asarray(bpa_mesh.triangles)
points_raw=np.asarray(bpa_mesh.vertices)
center_p=np.sum(points_raw,0)/len(points_raw)
rx=-np.pi/2
ry=0
rz=np.pi/2
R=o3d.geometry.get_rotation_matrix_from_xyz([rx,ry,rz])
bpa_mesh.rotate(R,center_p)
o3d.visualization.draw_geometries([bpa_mesh])

## Setup a camera
rx=0
ry=np.pi
rz=0
x=1
y=1
z=570
W,H=2048,2048
focal=1024
tic=time.time()
cam = VirtualCamera(rx, ry, rz,x, y, z, focal*3.45e-6, [W, H])

## Create Mask
# Get the triangle relationship
points=points_raw
print(points)
points=points.reshape(-1,3)
ans,cp = cam.project_world_to_pixel(points)
ans=ans.astype(int)
mask_bg=np.zeros((W,H,3))
mask_bg[:,:,:]=0
ans=ans[:,0:2]
for i in range(len(tri)):
pt1=ans[tri[i][0]]
pt2=ans[tri[i][1]]
pt3=ans[tri[i][2]]
tri_set=np.asarray([pt1,pt2,pt3])
tri_set=tri_set.astype(int)
tri_set=tri_set.reshape(-1,2)
cv2.fillPoly(mask_bg,[tri_set],(0,255,0))
# Calculate the mask
kernel = np.ones((3,3),np.uint8)
fushi = cv2.erode(mask_bg,kernel,iterations = 1)
mask=np.where(fushi[:,:,1]==255)

## Render model
camera_intrinsics=o3d.camera.PinholeCameraIntrinsic()
camera_intrinsics.set_intrinsics(W,H,focal,focal,W/2,H/2)
extrinsics=cam.RT_world_in_camera

render = rendering.OffscreenRenderer(2048, 2048)
material = rendering.Material()
material.base_color = [1, 1, 1, 1.0]
material.shader = "defaultLit"
material.albedo_img=o3d.io.read_image('BigConnectSilver.jpg')
material.base_metallic=1.0
render.scene.add_geometry("pcd",bpa_mesh,material)
render.setup_camera(camera_intrinsics,extrinsics)
render.scene.scene.set_sun_light([0, 0.0, -1], [1, 1,1],
3e6)
render.scene.scene.enable_sun_light(True)

## Read RGB and Depth image from open3d
img = np.asarray(render.render_to_image())
depth_img=np.asarray(render.render_to_depth_image())
depth_img=1-depth_img
depth_img=depth_img/np.amax(depth_img)*255
depth_img=depth_img.astype(int)
cv2.imwrite('render_depth.png',255-depth_img)

img= cv2.cvtColor(img,cv2.COLOR_RGB2BGR)
bg=cv2.imread('WechatIMG1313.jpeg')
bg=cv2.resize(bg,(2048,2048))
bg[mask[0],mask[1]]=img[mask[0],mask[1]]

cv2.imwrite('render_rgb.jpg',bg)
plt.imshow(cv2.cvtColor(bg,cv2.COLOR_BGR2RGB))

4. 4 实验结果

实验结果