├── README.md ├── environment_open3d.yml ├── fragment.ply ├── main.py ├── open3d-0.11.1-cp38-cp38-linux_x86_64.whl ├── open3d-0.11.1-cp38-cp38-win_amd64.whl ├── screenshot_depth.png ├── screenshot_image.png ├── view_point.json └── visualization.py /README.md: -------------------------------------------------------------------------------- 1 | # render_depthmap_example 2 | 3 | This is an example of the Open3D PR: 4 | https://github.com/intel-isl/Open3D/pull/2564 5 | 6 | For pyvista (VTK), check `pyvista` branch 7 | https://github.com/pablospe/render_depthmap_example/tree/pyvista 8 | 9 | ## How to run the example? 10 | 11 | # creat environment 12 | conda env create -f environment_open3d.yml 13 | conda activate open3d 14 | 15 | # install package (check platform) 16 | pip install open3d-0.11.1-cp38-cp38-win_amd64.whl (in windows) 17 | pip install open3d-0.11.1-cp38-cp38-linux_x86_64.whl (in linux) 18 | 19 | # run example 20 | python main.py 21 | 22 | 23 | #### Capture the screen 24 | 25 | ![Capture the screen](screenshot_image.png) 26 | 27 | #### Capture depth 28 | 29 | ![Capture depth](screenshot_depth.png) 30 | -------------------------------------------------------------------------------- /environment_open3d.yml: -------------------------------------------------------------------------------- 1 | name: open3d 2 | channels: 3 | - defaults 4 | dependencies: 5 | - astroid=2.4.2 6 | - backcall=0.2.0 7 | - backports=1.0 8 | - backports.functools_lru_cache=1.6.1 9 | - backports.tempfile=1.0 10 | - backports.weakref=1.0.post1 11 | - beautifulsoup4=4.9.3 12 | - blas=1.0 13 | - bzip2=1.0.8 14 | - ca-certificates=2020.10.14 15 | - certifi=2020.6.20 16 | - cffi=1.14.0 17 | - chardet=3.0.4 18 | - click=7.1.2 19 | - conda=4.9.1 20 | - conda-build=3.20.5 21 | - conda-package-handling=1.6.1 22 | - conda-verify=3.4.2 23 | - cryptography=2.9.2 24 | - cycler=0.10.0 25 | - decorator=4.4.2 26 | - expat=2.2.10 27 | - filelock=3.0.12 28 | - freetype=2.10.4 29 | - future=0.18.2 30 | - glob2=0.7 31 | - icu=58.2 32 | - idna=2.9 33 | - intel-openmp=2020.2 34 | - ipython=7.18.1 35 | - ipython_genutils=0.2.0 36 | - isort=5.6.4 37 | - jedi=0.17.2 38 | - jinja2=2.11.2 39 | - jpeg=9b 40 | - kiwisolver=1.3.0 41 | - lazy-object-proxy=1.4.3 42 | - lcms2=2.11 43 | - libarchive=3.4.2 44 | - liblief=0.10.1 45 | - libpng=1.6.37 46 | - libtiff=4.1.0 47 | - libxml2=2.9.10 48 | - lz4-c=1.9.2 49 | - markupsafe=1.1.1 50 | - matplotlib=3.3.2 51 | - matplotlib-base=3.3.2 52 | - mccabe=0.6.1 53 | - mkl=2020.2 54 | - mkl-service=2.3.0 55 | - mkl_fft=1.2.0 56 | - mkl_random=1.1.1 57 | - numpy=1.19.2 58 | - numpy-base=1.19.2 59 | - olefile=0.46 60 | - openssl=1.1.1h 61 | - parso=0.7.0 62 | - pcre=8.44 63 | - pexpect=4.8.0 64 | - pickleshare=0.7.5 65 | - pillow=8.0.1 66 | - pip=20.0.2 67 | - pkginfo=1.6.0 68 | - prompt-toolkit=3.0.8 69 | - psutil=5.7.2 70 | - py-lief=0.10.1 71 | - pycosat=0.6.3 72 | - pycparser=2.20 73 | - pygments=2.7.2 74 | - pylint=2.6.0 75 | - pyopenssl=19.1.0 76 | - pyparsing=2.4.7 77 | - pyqt=5.9.2 78 | - pysocks=1.7.1 79 | - python=3.8.3 80 | - python-dateutil=2.8.1 81 | - python-libarchive-c=2.9 82 | - pytz=2020.1 83 | - pyyaml=5.3.1 84 | - qt=5.9.7 85 | - requests=2.23.0 86 | - ripgrep=12.1.1 87 | - ruamel_yaml=0.15.87 88 | - setuptools=46.4.0 89 | - sip=4.19.13 90 | - six=1.14.0 91 | - soupsieve=2.0.1 92 | - sqlite=3.31.1 93 | - tk=8.6.8 94 | - toml=0.10.1 95 | - tornado=6.0.4 96 | - tqdm=4.46.0 97 | - traitlets=5.0.5 98 | - urllib3=1.25.8 99 | - wcwidth=0.2.5 100 | - wheel=0.34.2 101 | - wrapt=1.11.2 102 | - xz=5.2.5 103 | - yaml=0.1.7 104 | - zlib=1.2.11 105 | - zstd=1.4.5 106 | - pip: 107 | - argon2-cffi==20.1.0 108 | - async-generator==1.10 109 | - attrs==20.2.0 110 | - bleach==3.2.1 111 | - defusedxml==0.6.0 112 | - entrypoints==0.3 113 | - ipykernel==5.3.4 114 | - ipywidgets==7.5.1 115 | - jsonschema==3.2.0 116 | - jupyter-client==6.1.7 117 | - jupyter-core==4.6.3 118 | - jupyterlab-pygments==0.1.2 119 | - mistune==0.8.4 120 | - nbclient==0.5.1 121 | - nbconvert==6.0.7 122 | - nbformat==5.0.8 123 | - nest-asyncio==1.4.2 124 | - notebook==6.1.4 125 | - packaging==20.4 126 | - pandocfilters==1.4.3 127 | - prometheus-client==0.8.0 128 | - pyrsistent==0.17.3 129 | - pyzmq==19.0.2 130 | - send2trash==1.5.0 131 | - terminado==0.9.1 132 | - testpath==0.4.4 133 | - webencodings==0.5.1 134 | - widgetsnbextension==3.5.1 135 | -------------------------------------------------------------------------------- /fragment.ply: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablospe/render_depthmap_example/dbd53b33ae13a78514b8307416bd7d4651d38cb5/fragment.ply -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import open3d 2 | from visualization import VisOpen3D 3 | 4 | 5 | def main(): 6 | w = 1024 7 | h = 768 8 | 9 | pcd = open3d.io.read_point_cloud("fragment.ply") 10 | 11 | # create window 12 | window_visible = True 13 | vis = VisOpen3D(width=w, height=h, visible=window_visible) 14 | 15 | # point cloud 16 | vis.add_geometry(pcd) 17 | 18 | # update view 19 | # vis.update_view_point(intrinsic, extrinsic) 20 | 21 | # save view point to file 22 | # vis.save_view_point("view_point.json") 23 | vis.load_view_point("view_point.json") 24 | 25 | 26 | # capture images 27 | depth = vis.capture_depth_float_buffer(show=True) 28 | image = vis.capture_screen_float_buffer(show=True) 29 | 30 | # save to file 31 | vis.capture_screen_image("capture_screen_image.png") 32 | vis.capture_depth_image("capture_depth_image.png") 33 | 34 | 35 | # draw camera 36 | if window_visible: 37 | vis.load_view_point("view_point.json") 38 | intrinsic = vis.get_view_point_intrinsics() 39 | extrinsic = vis.get_view_point_extrinsics() 40 | vis.draw_camera(intrinsic, extrinsic, scale=0.5, color=[0.8, 0.2, 0.8]) 41 | # vis.update_view_point(intrinsic, extrinsic) 42 | 43 | if window_visible: 44 | vis.load_view_point("view_point.json") 45 | vis.run() 46 | 47 | del vis 48 | 49 | 50 | if __name__ == "__main__": 51 | main() 52 | -------------------------------------------------------------------------------- /open3d-0.11.1-cp38-cp38-linux_x86_64.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablospe/render_depthmap_example/dbd53b33ae13a78514b8307416bd7d4651d38cb5/open3d-0.11.1-cp38-cp38-linux_x86_64.whl -------------------------------------------------------------------------------- /open3d-0.11.1-cp38-cp38-win_amd64.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablospe/render_depthmap_example/dbd53b33ae13a78514b8307416bd7d4651d38cb5/open3d-0.11.1-cp38-cp38-win_amd64.whl -------------------------------------------------------------------------------- /screenshot_depth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablospe/render_depthmap_example/dbd53b33ae13a78514b8307416bd7d4651d38cb5/screenshot_depth.png -------------------------------------------------------------------------------- /screenshot_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pablospe/render_depthmap_example/dbd53b33ae13a78514b8307416bd7d4651d38cb5/screenshot_image.png -------------------------------------------------------------------------------- /view_point.json: -------------------------------------------------------------------------------- 1 | { 2 | "class_name" : "PinholeCameraParameters", 3 | "extrinsic" : 4 | [ 5 | 0.9503879347691897, 6 | -0.12228840479714526, 7 | 0.28602153677183806, 8 | 0.0, 9 | 0.095412504779002483, 10 | 0.98976322388070337, 11 | 0.10613771518679699, 12 | 0.0, 13 | -0.29607301021361471, 14 | -0.073581972693359823, 15 | 0.95232686926160104, 16 | 0.0, 17 | -1.8429529140825325, 18 | -1.2214317950963878, 19 | 0.6428005992092698, 20 | 1.0 21 | ], 22 | "intrinsic" : 23 | { 24 | "height" : 768, 25 | "intrinsic_matrix" : 26 | [ 27 | 665.1075101064489, 28 | 0.0, 29 | 0.0, 30 | 0.0, 31 | 665.1075101064489, 32 | 0.0, 33 | 511.5, 34 | 383.5, 35 | 1.0 36 | ], 37 | "width" : 1024 38 | }, 39 | "version_major" : 1, 40 | "version_minor" : 0 41 | } -------------------------------------------------------------------------------- /visualization.py: -------------------------------------------------------------------------------- 1 | import open3d 2 | import numpy as np 3 | import matplotlib.pyplot as plt 4 | 5 | 6 | class VisOpen3D: 7 | 8 | def __init__(self, width=1920, height=1080, visible=True): 9 | self.__vis = open3d.visualization.Visualizer() 10 | self.__vis.create_window(width=width, height=height, visible=visible) 11 | self.__width = width 12 | self.__height = height 13 | 14 | if visible: 15 | self.poll_events() 16 | self.update_renderer() 17 | 18 | def __del__(self): 19 | self.__vis.destroy_window() 20 | 21 | def render(self): 22 | self.__vis.poll_events() 23 | self.__vis.update_renderer() 24 | self.__vis.run() 25 | 26 | def poll_events(self): 27 | self.__vis.poll_events() 28 | 29 | def update_renderer(self): 30 | self.__vis.update_renderer() 31 | 32 | def run(self): 33 | self.__vis.run() 34 | 35 | def destroy_window(self): 36 | self.__vis.destroy_window() 37 | 38 | def add_geometry(self, data): 39 | self.__vis.add_geometry(data) 40 | 41 | def update_view_point(self, intrinsic, extrinsic): 42 | ctr = self.__vis.get_view_control() 43 | param = self.convert_to_open3d_param(intrinsic, extrinsic) 44 | ctr.convert_from_pinhole_camera_parameters(param, allow_arbitrary=True) 45 | self.__vis.update_renderer() 46 | 47 | def get_view_point_intrinsics(self): 48 | ctr = self.__vis.get_view_control() 49 | param = ctr.convert_to_pinhole_camera_parameters() 50 | intrinsic = param.intrinsic.intrinsic_matrix 51 | return intrinsic 52 | 53 | def get_view_point_extrinsics(self): 54 | ctr = self.__vis.get_view_control() 55 | param = ctr.convert_to_pinhole_camera_parameters() 56 | extrinsic = param.extrinsic 57 | return extrinsic 58 | 59 | def get_view_control(self): 60 | return self.__vis.get_view_control() 61 | 62 | def save_view_point(self, filename): 63 | ctr = self.__vis.get_view_control() 64 | param = ctr.convert_to_pinhole_camera_parameters() 65 | open3d.io.write_pinhole_camera_parameters(filename, param) 66 | 67 | def load_view_point(self, filename): 68 | param = open3d.io.read_pinhole_camera_parameters(filename) 69 | intrinsic = param.intrinsic.intrinsic_matrix 70 | extrinsic = param.extrinsic 71 | self.update_view_point(intrinsic, extrinsic) 72 | 73 | def convert_to_open3d_param(self, intrinsic, extrinsic): 74 | param = open3d.camera.PinholeCameraParameters() 75 | param.intrinsic = open3d.camera.PinholeCameraIntrinsic() 76 | param.intrinsic.intrinsic_matrix = intrinsic 77 | param.extrinsic = extrinsic 78 | return param 79 | 80 | def capture_screen_float_buffer(self, show=False): 81 | image = self.__vis.capture_screen_float_buffer(do_render=True) 82 | 83 | if show: 84 | plt.imshow(image) 85 | plt.show() 86 | 87 | return image 88 | 89 | def capture_screen_image(self, filename): 90 | self.__vis.capture_screen_image(filename, do_render=True) 91 | 92 | def capture_depth_float_buffer(self, show=False): 93 | depth = self.__vis.capture_depth_float_buffer(do_render=True) 94 | 95 | if show: 96 | plt.imshow(depth) 97 | plt.show() 98 | 99 | return depth 100 | 101 | def capture_depth_image(self, filename): 102 | self.__vis.capture_depth_image(filename, do_render=True) 103 | 104 | # to read the saved depth image file use: 105 | # depth = open3d.io.read_image(filename) 106 | # plt.imshow(depth) 107 | # plt.show() 108 | 109 | def draw_camera(self, intrinsic, extrinsic, scale=1, color=None): 110 | # intrinsics 111 | K = intrinsic 112 | 113 | # convert extrinsics matrix to rotation and translation matrix 114 | extrinsic = np.linalg.inv(extrinsic) 115 | R = extrinsic[0:3,0:3] 116 | t = extrinsic[0:3,3] 117 | 118 | width = self.__width 119 | height = self.__height 120 | 121 | geometries = draw_camera(K, R, t, width, height, scale, color) 122 | for g in geometries: 123 | self.add_geometry(g) 124 | 125 | def draw_points3D(self, points3D, color=None): 126 | geometries = draw_points3D(points3D, color) 127 | for g in geometries: 128 | self.add_geometry(g) 129 | 130 | # 131 | # Auxiliary funcions 132 | # 133 | def draw_camera(K, R, t, width, height, scale=1, color=None): 134 | """ Create axis, plane and pyramid geometries in Open3D format 135 | : param K : calibration matrix (camera intrinsics) 136 | : param R : rotation matrix 137 | : param t : translation 138 | : param width : image width 139 | : param height: image height 140 | : param scale : camera model scale 141 | : param color : color of the image plane and pyramid lines 142 | : return : camera model geometries (axis, plane and pyramid) 143 | """ 144 | 145 | # default color 146 | if color is None: 147 | color = [0.8, 0.2, 0.8] 148 | 149 | # camera model scale 150 | s = 1 / scale 151 | 152 | # intrinsics 153 | Ks = np.array([[K[0, 0] * s, 0, K[0,2]], 154 | [ 0, K[1, 1] * s, K[1,2]], 155 | [ 0, 0, K[2,2]]]) 156 | Kinv = np.linalg.inv(Ks) 157 | 158 | # 4x4 transformation 159 | T = np.column_stack((R, t)) 160 | T = np.vstack((T, (0, 0, 0, 1))) 161 | 162 | # axis 163 | axis = create_coordinate_frame(T, scale=scale*0.5) 164 | 165 | # points in pixel 166 | points_pixel = [ 167 | [0, 0, 0], 168 | [0, 0, 1], 169 | [width, 0, 1], 170 | [0, height, 1], 171 | [width, height, 1], 172 | ] 173 | 174 | # pixel to camera coordinate system 175 | points = [scale * Kinv @ p for p in points_pixel] 176 | 177 | # image plane 178 | width = abs(points[1][0]) + abs(points[3][0]) 179 | height = abs(points[1][1]) + abs(points[3][1]) 180 | plane = open3d.geometry.TriangleMesh.create_box(width, height, depth=1e-6) 181 | plane.paint_uniform_color(color) 182 | plane.transform(T) 183 | plane.translate(R @ [points[1][0], points[1][1], scale]) 184 | 185 | # pyramid 186 | points_in_world = [(R @ p + t) for p in points] 187 | lines = [ 188 | [0, 1], 189 | [0, 2], 190 | [0, 3], 191 | [0, 4], 192 | ] 193 | colors = [color for i in range(len(lines))] 194 | line_set = open3d.geometry.LineSet( 195 | points=open3d.utility.Vector3dVector(points_in_world), 196 | lines=open3d.utility.Vector2iVector(lines)) 197 | line_set.colors = open3d.utility.Vector3dVector(colors) 198 | 199 | # return as list in Open3D format 200 | return [axis, plane, line_set] 201 | 202 | 203 | def create_coordinate_frame(T, scale=0.25): 204 | frame = open3d.geometry.TriangleMesh.create_coordinate_frame(size=scale) 205 | frame.transform(T) 206 | return frame 207 | 208 | 209 | def draw_points3D(points3D, color=None): 210 | # color: default value 211 | if color is None: 212 | color = [0.8, 0.2, 0.8] 213 | 214 | geometries = [] 215 | for pt in points3D: 216 | sphere = open3d.geometry.TriangleMesh.create_sphere(radius=0.01, 217 | resolution=20) 218 | sphere.translate(pt) 219 | sphere.paint_uniform_color(np.array(color)) 220 | geometries.append(sphere) 221 | 222 | return geometries 223 | --------------------------------------------------------------------------------