2019-04-22 19:14:39 +00:00
import os
2019-04-03 18:47:06 +00:00
from opendm import log
from opendm import io
from opendm import system
from opendm import context
from opendm import point_cloud
2019-04-22 19:14:39 +00:00
from opendm import types
2021-10-13 17:54:16 +00:00
from opendm import gsd
from opendm . boundary import boundary_offset , compute_boundary_from_shots
2019-04-03 18:47:06 +00:00
2019-04-22 19:14:39 +00:00
class ODMFilterPoints ( types . ODM_Stage ) :
def process ( self , args , outputs ) :
tree = outputs [ ' tree ' ]
reconstruction = outputs [ ' reconstruction ' ]
2019-04-03 18:47:06 +00:00
if not os . path . exists ( tree . odm_filterpoints ) : system . mkdir_p ( tree . odm_filterpoints )
2022-07-10 16:40:33 +00:00
inputPointCloud = " "
2019-04-03 18:47:06 +00:00
# check if reconstruction was done before
2019-04-22 19:14:39 +00:00
if not io . file_exists ( tree . filtered_point_cloud ) or self . rerun ( ) :
2019-04-03 18:47:06 +00:00
if args . fast_orthophoto :
inputPointCloud = os . path . join ( tree . opensfm , ' reconstruction.ply ' )
else :
2020-10-27 21:10:10 +00:00
inputPointCloud = tree . openmvs_model
2019-04-03 18:47:06 +00:00
2021-10-13 17:54:16 +00:00
# Check if we need to compute boundary
if args . auto_boundary :
if reconstruction . is_georeferenced ( ) :
if not ' boundary ' in outputs :
2022-07-15 01:42:16 +00:00
boundary_distance = None
if args . auto_boundary_distance > 0 :
boundary_distance = args . auto_boundary_distance
else :
avg_gsd = gsd . opensfm_reconstruction_average_gsd ( tree . opensfm_reconstruction )
if avg_gsd is not None :
boundary_distance = avg_gsd * 20 # 20 is arbitrary
if boundary_distance is not None :
outputs [ ' boundary ' ] = compute_boundary_from_shots ( tree . opensfm_reconstruction , boundary_distance , reconstruction . get_proj_offset ( ) )
2022-07-10 16:21:31 +00:00
if outputs [ ' boundary ' ] is None :
2022-07-19 22:07:12 +00:00
log . ODM_WARNING ( " Cannot compute boundary from camera shots " )
2022-07-10 16:21:31 +00:00
else :
log . ODM_WARNING ( " Cannot compute boundary (GSD cannot be estimated) " )
2021-10-13 17:54:16 +00:00
else :
log . ODM_WARNING ( " --auto-boundary set but so is --boundary, will use --boundary " )
else :
log . ODM_WARNING ( " Not a georeferenced reconstruction, will ignore --auto-boundary " )
2023-02-20 04:28:34 +00:00
point_cloud . filter ( inputPointCloud , tree . filtered_point_cloud , tree . filtered_point_cloud_stats ,
2019-10-28 13:53:46 +00:00
standard_deviation = args . pc_filter ,
sample_radius = args . pc_sample ,
2021-10-12 20:43:42 +00:00
boundary = boundary_offset ( outputs . get ( ' boundary ' ) , reconstruction . get_proj_offset ( ) ) ,
2020-07-07 18:20:57 +00:00
max_concurrency = args . max_concurrency )
2020-03-30 14:32:21 +00:00
2021-10-13 17:54:16 +00:00
# Quick check
info = point_cloud . ply_info ( tree . filtered_point_cloud )
if info [ " vertex_count " ] == 0 :
extra_msg = ' '
if ' boundary ' in outputs :
extra_msg = ' . Also, since you used a boundary setting, make sure that the boundary polygon you specified covers the reconstruction area correctly. '
raise system . ExitException ( " Uh oh! We ended up with an empty point cloud. This means that the reconstruction did not succeed. Have you followed best practices for data acquisition? See https://docs.opendronemap.org/flying/ %s " % extra_msg )
2019-04-03 18:47:06 +00:00
else :
log . ODM_WARNING ( ' Found a valid point cloud file in: %s ' %
tree . filtered_point_cloud )
2020-03-30 14:32:21 +00:00
2021-06-15 14:04:17 +00:00
if args . optimize_disk_space and inputPointCloud :
if os . path . isfile ( inputPointCloud ) :
os . remove ( inputPointCloud )