├── pc_compressing_description.pdf ├── LICENSE ├── README └── pccomp_oct.py /pc_compressing_description.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/szppaks/pccomp_oct/HEAD/pc_compressing_description.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ################################################################### 2 | This Source Code Form is subject to the terms of the Mozilla Public 3 | License, v. 2.0. If a copy of the MPL was not distributed with this 4 | file, You can obtain one at https://mozilla.org/MPL/2.0/. 5 | 6 | copyright (c) 2020, Peter Szutor 7 | 8 | @author: Peter Szutor, Hungary, szppaks@gmail.com 9 | Created on Wed Feb 26 17:23:24 2020 10 | ################################################################### 11 | 12 | 13 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | ## Octree-based lossy point-cloud compression with open3d and numpy 2 | 3 | Average compressing rate (depends on octreee depth setting parameter): 0.012 - 0.1 4 | 5 | (Original article: Szutor Péter: Ipari pontfelhők tömörítése, 6 | Dr. Balázs Boglárka (szerk.) Az elmélet és a gyakorlat találkozása a térinformatikában VIII. Theory meets practice in GIS Debrecen, Magyarország 7 | Debreceni Egyetemi Kiadó, (2017) pp. 349-355) 8 | 9 | Input formats: You can get a list of supported formats from : http://www.open3d.org/docs/release/tutorial/Basic/file_io.html#point-cloud 10 | (xyz,pts,ply,pcd) 11 | 12 | Usage: 13 | 14 | Dependencies: Open3D, Numpy (You can install theese modules: pip install open3d, pip install numpy) 15 | 16 | Compress a point cloud: 17 | 18 | octreezip(,) -> 19 | : (str) Point Cloud file name. Saved file name: [filename without ext]_ocz.npz (Yes, it's a numpy array file) 20 | : (str) Octree depth. You can try 11-16 for best result. Bigger depht results higher precision and bigger compressed file size. 21 | : (str) If the compressing was success you get: "Compressed into:[comp.file name] | Storing resolution:0.003445". Storing resolution means the precision. 22 | The PC file is missing or bad: "PC is empty, bad, or missing" 23 | Other error: "Error: [error message]" 24 | 25 | 26 | Uncompressing: 27 | octreeunzip() -> 28 | : (str) Zipped Point Cloud file name (npz). Saved file name: [filename].xyz (standard XYZ text file) 29 | : (str) If the compressing was success you get: "Saved: [filename].xyz" 30 | Other error: "Error: [error message]" 31 | -------------------------------------------------------------------------------- /pccomp_oct.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | ################################################################### 5 | This Source Code Form is subject to the terms of the Mozilla Public 6 | License, v. 2.0. If a copy of the MPL was not distributed with this 7 | file, You can obtain one at https://mozilla.org/MPL/2.0/. 8 | 9 | copyright (c) 2020, Peter Szutor 10 | 11 | @author: Peter Szutor, Hungary, szppaks@gmail.com 12 | Created on Wed Feb 26 17:23:24 2020 13 | ################################################################### 14 | 15 | 16 | 17 | Octree-based lossy point-cloud compression with open3d and numpy 18 | Average compressing rate (depends on octreee depth setting parameter): 0.012 - 0.1 19 | 20 | 21 | Input formats: You can get a list of supported formats from : http://www.open3d.org/docs/release/tutorial/Basic/file_io.html#point-cloud 22 | (xyz,pts,ply,pcd) 23 | 24 | Usage: 25 | 26 | Dependencies: Open3D, Numpy (You can install theese modules: pip install open3d, pip install numpy) 27 | 28 | Compress a point cloud: 29 | 30 | octreezip(,) -> 31 | : (str) Point Cloud file name. Saved file name: [filename without ext]_ocz.npz (Yes, it's a numpy array file) 32 | : (str) Octree depth. You can try 11-16 for best result. Bigger depht results higher precision and bigger compressed file size. 33 | : (str) If the compressing was success you get: "Compressed into:[comp.file name] | Storing resolution:0.003445". Storing resolution means the precision. 34 | The PC file is missing or bad: "PC is empty, bad, or missing" 35 | Other error: "Error: [error message]" 36 | 37 | 38 | Uncompressing: 39 | octreeunzip() -> 40 | : (str) Zipped Point Cloud file name (npz). Saved file name: [filename].xyz (standard XYZ text file) 41 | : (str) If the compressing was success you get: "Saved: [filename].xyz" 42 | Other error: "Error: [error message]" 43 | 44 | 45 | 46 | """ 47 | import numpy as np 48 | import os 49 | import open3d as o3d 50 | 51 | def d1halfing_fast(pmin,pmax,pdepht): 52 | return np.linspace(pmin,pmax,2**int(pdepht)+1) 53 | 54 | def octreecodes(ppoints,pdepht): 55 | minx=np.amin(ppoints[:,0]) 56 | maxx=np.amax(ppoints[:,0]) 57 | miny=np.amin(ppoints[:,1]) 58 | maxy=np.amax(ppoints[:,1]) 59 | minz=np.amin(ppoints[:,2]) 60 | maxz=np.amax(ppoints[:,2]) 61 | xletra=d1halfing_fast(minx,maxx,pdepht) 62 | yletra=d1halfing_fast(miny,maxy,pdepht) 63 | zletra=d1halfing_fast(minz,maxz,pdepht) 64 | otcodex=np.searchsorted(xletra,ppoints[:,0],side='right')-1 65 | otcodey=np.searchsorted(yletra,ppoints[:,1],side='right')-1 66 | otcodez=np.searchsorted(zletra,ppoints[:,2],side='right')-1 67 | ki=otcodex*(2**(pdepht*2))+otcodey*(2**pdepht)+otcodez 68 | return (ki,minx,maxx,miny,maxy,minz,maxz) 69 | 70 | def octreezip(pfilename,pdepht): 71 | try: 72 | pcd = o3d.io.read_point_cloud(pfilename,format='auto') 73 | ppoints=np.asarray(pcd.points) 74 | if len(ppoints)>0: 75 | occ=octreecodes(ppoints,pdepht) 76 | occsorted=np.sort(occ[0]) 77 | prec=np.amax(np.asarray([occ[2]-occ[1],occ[4]-occ[3],occ[6]-occ[5]])/(2**pdepht)) 78 | paramarr=np.asarray([pdepht,occ[1],occ[2],occ[3],occ[4],occ[5],occ[6]]) #depth and boundary 79 | np.savez_compressed(os.path.splitext(pfilename)[0]+'_ocz',points=occsorted,params=paramarr) 80 | retmessage='Compressed into:'+str(os.path.splitext(pfilename)[0])+'.ocz | Storing resolution:'+str(prec) 81 | else: 82 | retmessage='PC is empty, bad, or missing' 83 | except Exception as e: 84 | retmessage='Error:'+str(e) 85 | return retmessage 86 | 87 | def octreeunzip(pfilename): 88 | try: 89 | pc=np.load(pfilename) 90 | pcpoints=pc['points'] 91 | pcparams=pc['params'] 92 | pdepht=(pcparams[0]) 93 | minx=(pcparams[1]) 94 | maxx=(pcparams[2]) 95 | miny=(pcparams[3]) 96 | maxy=(pcparams[4]) 97 | minz=(pcparams[5]) 98 | maxz=(pcparams[6]) 99 | xletra=d1halfing_fast(minx,maxx,pdepht) 100 | yletra=d1halfing_fast(miny,maxy,pdepht) 101 | zletra=d1halfing_fast(minz,maxz,pdepht) 102 | occodex=(pcpoints/(2**(pdepht*2))).astype(int) 103 | occodey=((pcpoints-occodex*(2**(pdepht*2)))/(2**pdepht)).astype(int) 104 | occodez=(pcpoints-occodex*(2**(pdepht*2))-occodey*(2**pdepht)).astype(int) 105 | koorx=xletra[occodex] 106 | koory=yletra[occodey] 107 | koorz=zletra[occodez] 108 | points=np.array([koorx,koory,koorz]).T 109 | np.savetxt(os.path.splitext(pfilename)[0]+'.xyz',points,fmt='%.4f') 110 | retmessage='Saved:'+os.path.splitext(pfilename)[0]+'.xyz' 111 | except Exception as e: 112 | retmessage='Error:'+str(e) 113 | return retmessage 114 | 115 | 116 | 117 | --------------------------------------------------------------------------------