Пример #1
0
    def process(self, inputs, outputs):

        # find a file in the root directory
        def find(file, dir):
            for root, dirs, files in os.walk(dir):
                return '/'.join((root, file)) if file in files else None

        # Benchmarking
        start_time = system.now_raw()

        log.ODM_INFO('Running ODM Georeferencing Cell')

        # get inputs
        args = self.inputs.args
        tree = self.inputs.tree
        gcpfile = io.join_paths(tree.root_path, self.params.gcp_file) \
            if self.params.gcp_file else find('gcp_list.txt', tree.root_path)
        geocreated = True
        verbose = '-verbose' if self.params.verbose else ''

        # define paths and create working directories
        system.mkdir_p(tree.odm_georeferencing)

        # in case a gcp file it's not provided, let's try to generate it using
        # images metadata. Internally calls jhead.
        log.ODM_DEBUG(self.params.gcp_file)
        if not self.params.gcp_file:  # and \
            #   not io.file_exists(tree.odm_georeferencing_coords):

            log.ODM_WARNING('No coordinates file. '
                            'Generating coordinates file: %s' %
                            tree.odm_georeferencing_coords)

            # odm_georeference definitions
            kwargs = {
                'bin': context.odm_modules_path,
                'imgs': tree.dataset_resize,
                'imgs_list': tree.opensfm_bundle_list,
                'coords': tree.odm_georeferencing_coords,
                'log': tree.odm_georeferencing_utm_log,
                'verbose': verbose
            }

            # run UTM extraction binary
            extract_utm = system.run_and_return(
                '{bin}/odm_extract_utm -imagesPath {imgs}/ '
                '-imageListFile {imgs_list} -outputCoordFile {coords} {verbose} '
                '-logFile {log}'.format(**kwargs))

            if extract_utm != '':
                log.ODM_WARNING('Could not generate coordinates file. '
                                'Ignore if there is a GCP file. Error: %s' %
                                extract_utm)

        # check if we rerun cell or not
        rerun_cell = (args.rerun is not None and
                      args.rerun == 'odm_georeferencing') or \
                     (args.rerun_all) or \
                     (args.rerun_from is not None and
                      'odm_georeferencing' in args.rerun_from)

        if not io.file_exists(tree.odm_georeferencing_model_obj_geo) or \
           not io.file_exists(tree.odm_georeferencing_model_ply_geo) or rerun_cell:

            # odm_georeference definitions
            kwargs = {
                'bin': context.odm_modules_path,
                'bundle': tree.opensfm_bundle,
                'imgs': tree.dataset_resize,
                'imgs_list': tree.opensfm_bundle_list,
                'model': tree.odm_textured_model_obj,
                'log': tree.odm_georeferencing_log,
                'coords': tree.odm_georeferencing_coords,
                'pc_geo': tree.odm_georeferencing_model_ply_geo,
                'geo_sys': tree.odm_georeferencing_model_txt_geo,
                'model_geo': tree.odm_georeferencing_model_obj_geo,
                'size': self.params.img_size,
                'gcp': gcpfile,
                'verbose': verbose
            }
            if not args.use_pmvs:
                kwargs['pc'] = tree.opensfm_model
            else:
                kwargs['pc'] = tree.pmvs_model

            # Check to see if the GCP file exists

            if not self.params.use_exif and (self.params.gcp_file or find(
                    'gcp_list.txt', tree.root_path)):
                log.ODM_INFO('Found %s' % gcpfile)
                try:
                    system.run(
                        '{bin}/odm_georef -bundleFile {bundle} -imagesPath {imgs} -imagesListPath {imgs_list} '
                        '-bundleResizedTo {size} -inputFile {model} -outputFile {model_geo} '
                        '-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} {verbose} '
                        '-logFile {log} -georefFileOutputPath {geo_sys} -gcpFile {gcp} '
                        '-outputCoordFile {coords}'.format(**kwargs))
                except Exception:
                    log.ODM_EXCEPTION('Georeferencing failed. ')
                    return ecto.QUIT
            elif io.file_exists(tree.odm_georeferencing_coords):
                log.ODM_INFO(
                    'Running georeferencing with generated coords file.')
                system.run(
                    '{bin}/odm_georef -bundleFile {bundle} -inputCoordFile {coords} '
                    '-inputFile {model} -outputFile {model_geo} '
                    '-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} {verbose} '
                    '-logFile {log} -georefFileOutputPath {geo_sys}'.format(
                        **kwargs))
            else:
                log.ODM_WARNING('Georeferencing failed. Make sure your '
                                'photos have geotags in the EXIF or you have '
                                'provided a GCP file. ')
                geocreated = False  # skip the rest of the georeferencing

            if geocreated:
                # update images metadata
                geo_ref = types.ODM_GeoRef()
                geo_ref.parse_coordinate_system(tree.odm_georeferencing_coords)

                for idx, photo in enumerate(self.inputs.photos):
                    geo_ref.utm_to_latlon(tree.odm_georeferencing_latlon,
                                          photo, idx)

                # convert ply model to LAS reference system
                geo_ref.convert_to_las(tree.odm_georeferencing_model_ply_geo,
                                       tree.odm_georeferencing_pdal)

                # XYZ point cloud output
                log.ODM_INFO(
                    "Creating geo-referenced CSV file (XYZ format, can be used with GRASS to create DEM)"
                )
                with open(tree.odm_georeferencing_xyz_file, "wb") as csvfile:
                    csvfile_writer = csv.writer(csvfile, delimiter=",")
                    reachedpoints = False
                    with open(tree.odm_georeferencing_model_ply_geo) as f:
                        for lineNumber, line in enumerate(f):
                            if reachedpoints:
                                tokens = line.split(" ")
                                csv_line = [
                                    float(tokens[0]) + geo_ref.utm_east_offset,
                                    float(tokens[1]) +
                                    geo_ref.utm_north_offset, tokens[2]
                                ]
                                csvfile_writer.writerow(csv_line)
                            if line.startswith("end_header"):
                                reachedpoints = True
                csvfile.close()

        else:
            log.ODM_WARNING('Found a valid georeferenced model in: %s' %
                            tree.odm_georeferencing_model_ply_geo)

        if args.time:
            system.benchmark(start_time, tree.benchmarking, 'Georeferencing')

        log.ODM_INFO('Running ODM Georeferencing Cell - Finished')
        return ecto.OK if args.end_with != 'odm_georeferencing' else ecto.QUIT
Пример #2
0
    def process(self, inputs, outputs):

        # Benchmarking
        start_time = system.now_raw()

        log.ODM_INFO('Running ODM Orthophoto Cell')

        # get inputs
        args = self.inputs.args
        tree = self.inputs.tree
        verbose = '-verbose' if self.params.verbose else ''

        # define paths and create working directories
        system.mkdir_p(tree.odm_orthophoto)

        # check if we rerun cell or not
        rerun_cell = (args.rerun is not None and
                      args.rerun == 'odm_orthophoto') or \
                     (args.rerun_all) or \
                     (args.rerun_from is not None and
                      'odm_orthophoto' in args.rerun_from)

        if not io.file_exists(tree.odm_orthophoto_file) or rerun_cell:

            # odm_orthophoto definitions
            kwargs = {
                'bin': context.odm_modules_path,
                'log': tree.odm_orthophoto_log,
                'ortho': tree.odm_orthophoto_file,
                'corners': tree.odm_orthophoto_corners,
                'res': self.params.resolution,
                'verbose': verbose
            }

            # Have geo coordinates?
            if io.file_exists(tree.odm_georeferencing_coords):
                if args.use_25dmesh:
                    kwargs['model_geo'] = os.path.join(
                        tree.odm_25dtexturing,
                        tree.odm_georeferencing_model_obj_geo)
                else:
                    kwargs['model_geo'] = os.path.join(
                        tree.odm_texturing,
                        tree.odm_georeferencing_model_obj_geo)
            else:
                if args.use_25dmesh:
                    kwargs['model_geo'] = os.path.join(
                        tree.odm_25dtexturing, tree.odm_textured_model_obj)
                else:
                    kwargs['model_geo'] = os.path.join(
                        tree.odm_texturing, tree.odm_textured_model_obj)

            # run odm_orthophoto
            system.run(
                '{bin}/odm_orthophoto -inputFile {model_geo} '
                '-logFile {log} -outputFile {ortho} -resolution {res} {verbose} '
                '-outputCornerFile {corners}'.format(**kwargs))

            if not io.file_exists(tree.odm_georeferencing_coords):
                log.ODM_WARNING('No coordinates file. A georeferenced raster '
                                'will not be created')
            else:
                # Create georeferenced GeoTiff
                geotiffcreated = False
                georef = types.ODM_GeoRef()
                # creates the coord refs # TODO I don't want to have to do this twice- after odm_georef
                georef.parse_coordinate_system(tree.odm_georeferencing_coords)

                if georef.epsg and georef.utm_east_offset and georef.utm_north_offset:
                    ulx = uly = lrx = lry = 0.0
                    with open(tree.odm_orthophoto_corners) as f:
                        for lineNumber, line in enumerate(f):
                            if lineNumber == 0:
                                tokens = line.split(' ')
                                if len(tokens) == 4:
                                    ulx = float(tokens[0]) + \
                                        float(georef.utm_east_offset)
                                    lry = float(tokens[1]) + \
                                        float(georef.utm_north_offset)
                                    lrx = float(tokens[2]) + \
                                        float(georef.utm_east_offset)
                                    uly = float(tokens[3]) + \
                                        float(georef.utm_north_offset)
                    log.ODM_INFO('Creating GeoTIFF')

                    kwargs = {
                        'ulx':
                        ulx,
                        'uly':
                        uly,
                        'lrx':
                        lrx,
                        'lry':
                        lry,
                        'tiled':
                        '' if self.params.no_tiled else '-co TILED=yes ',
                        'compress':
                        self.params.compress,
                        'predictor':
                        '-co PREDICTOR=2 '
                        if self.params.compress in ['LZW', 'DEFLATE'] else '',
                        'epsg':
                        georef.epsg,
                        't_srs':
                        self.params.t_srs or "EPSG:{0}".format(georef.epsg),
                        'bigtiff':
                        self.params.bigtiff,
                        'png':
                        tree.odm_orthophoto_file,
                        'tiff':
                        tree.odm_orthophoto_tif,
                        'log':
                        tree.odm_orthophoto_tif_log
                    }

                    system.run(
                        'gdal_translate -a_ullr {ulx} {uly} {lrx} {lry} '
                        '{tiled} '
                        '-co BIGTIFF={bigtiff} '
                        '-co COMPRESS={compress} '
                        '{predictor} '
                        '-co BLOCKXSIZE=512 '
                        '-co BLOCKYSIZE=512 '
                        '-co NUM_THREADS=ALL_CPUS '
                        '-a_srs \"EPSG:{epsg}\" '
                        '{png} {tiff} > {log}'.format(**kwargs))

                    if self.params.build_overviews:
                        log.ODM_DEBUG("Building Overviews")
                        kwargs = {
                            'orthophoto': tree.odm_orthophoto_tif,
                            'log': tree.odm_orthophoto_gdaladdo_log
                        }
                        # Run gdaladdo
                        system.run(
                            'gdaladdo -ro -r average '
                            '--config BIGTIFF_OVERVIEW IF_SAFER '
                            '--config COMPRESS_OVERVIEW JPEG '
                            '{orthophoto} 2 4 8 16 > {log}'.format(**kwargs))

                    geotiffcreated = True
                if not geotiffcreated:
                    log.ODM_WARNING(
                        'No geo-referenced orthophoto created due '
                        'to missing geo-referencing or corner coordinates.')

        else:
            log.ODM_WARNING('Found a valid orthophoto in: %s' %
                            tree.odm_orthophoto_file)

        if args.time:
            system.benchmark(start_time, tree.benchmarking, 'Orthophoto')

        log.ODM_INFO('Running ODM OrthoPhoto Cell - Finished')
        return ecto.OK if args.end_with != 'odm_orthophoto' else ecto.QUIT
Пример #3
0
class ODMGeoreferencingCell(ecto.Cell):
    def declare_params(self, params):
        params.declare(
            "gcp_file", 'path to the file containing the ground control '
            'points used for georeferencing.The file needs to '
            'be on the following line format: \neasting '
            'northing height pixelrow pixelcol imagename', 'gcp_list.txt')
        params.declare("use_gcp",
                       'set to true for enabling GCPs from the file above',
                       False)
        params.declare("img_size", 'image size used in calibration', 2400)

    def declare_io(self, params, inputs, outputs):
        inputs.declare("tree", "Struct with paths", [])
        inputs.declare("args", "The application arguments.", {})
        inputs.declare("photos", "list of ODMPhoto's", [])
        inputs.declare("reconstruction", "list of ODMReconstructions", [])
        outputs.declare("reconstruction", "list of ODMReconstructions", [])

    def process(self, inputs, outputs):
        # Benchmarking
        start_time = system.now_raw()

        log.ODM_INFO('Running ODM Georeferencing Cell')

        # get inputs
        args = self.inputs.args
        tree = self.inputs.tree
        gcpfile = io.join_paths(tree.root_path, self.params.gcp_file)

        # define paths and create working directories
        system.mkdir_p(tree.odm_georeferencing)

        # in case a gcp file it's not provided, let's try to generate it using
        # images metadata. Internally calls jhead.
        if not self.params.use_gcp and \
           not io.file_exists(tree.odm_georeferencing_coords):

            log.ODM_WARNING('Warning: No coordinates file. '
                            'Generating coordinates file in: %s' %
                            tree.odm_georeferencing_coords)
            try:
                # odm_georeference definitions
                kwargs = {
                    'bin': context.odm_modules_path,
                    'imgs': tree.dataset_raw,
                    'imgs_list': tree.opensfm_bundle_list,
                    'coords': tree.odm_georeferencing_coords,
                    'log': tree.odm_georeferencing_utm_log
                }

                # run UTM extraction binary
                system.run(
                    '{bin}/odm_extract_utm -imagesPath {imgs}/ '
                    '-imageListFile {imgs_list} -outputCoordFile {coords} '
                    '-logFile {log}'.format(**kwargs))

            except Exception, e:
                log.ODM_ERROR(
                    'Could not generate GCP file from images metadata.'
                    'Consider rerunning with argument --odm_georeferencing-useGcp'
                    ' and provide a proper GCP file')
                log.ODM_ERROR(e)
                return ecto.QUIT

        # check if we rerun cell or not
        rerun_cell = (args.rerun is not None and
                      args.rerun == 'odm_georeferencing') or \
                     (args.rerun_all) or \
                     (args.rerun_from is not None and
                      'odm_georeferencing' in args.rerun_from)

        if not io.file_exists(tree.odm_georeferencing_model_obj_geo) or \
           not io.file_exists(tree.odm_georeferencing_model_ply_geo) or rerun_cell:

            # odm_georeference definitions
            kwargs = {
                'bin': context.odm_modules_path,
                'bundle': tree.opensfm_bundle,
                'imgs': tree.dataset_raw,
                'imgs_list': tree.opensfm_bundle_list,
                'model': tree.odm_textured_model_obj,
                'pc': tree.pmvs_model,
                'log': tree.odm_georeferencing_log,
                'coords': tree.odm_georeferencing_coords,
                'pc_geo': tree.odm_georeferencing_model_ply_geo,
                'geo_sys': tree.odm_georeferencing_model_txt_geo,
                'model_geo': tree.odm_georeferencing_model_obj_geo,
                'size': self.params.img_size,
                'gcp': gcpfile,
            }

            if self.params.use_gcp and \
               io.file_exists(gcpfile):

                system.run(
                    '{bin}/odm_georef -bundleFile {bundle} -imagesPath {imgs} -imagesListPath {imgs_list} '
                    '-bundleResizedTo {size} -inputFile {model} -outputFile {model_geo} '
                    '-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} '
                    '-logFile {log} -georefFileOutputPath {geo_sys} -gcpFile {gcp} '
                    '-outputCoordFile {coords}'.format(**kwargs))
            else:
                system.run(
                    '{bin}/odm_georef -bundleFile {bundle} -inputCoordFile {coords} '
                    '-inputFile {model} -outputFile {model_geo} '
                    '-inputPointCloudFile {pc} -outputPointCloudFile {pc_geo} '
                    '-logFile {log} -georefFileOutputPath {geo_sys}'.format(
                        **kwargs))

            # update images metadata
            geo_ref = types.ODM_GeoRef()
            geo_ref.parse_coordinate_system(tree.odm_georeferencing_coords)

            for idx, photo in enumerate(self.inputs.photos):
                geo_ref.utm_to_latlon(tree.odm_georeferencing_latlon, photo,
                                      idx)

            # convert ply model to LAS reference system
            geo_ref.convert_to_las(tree.odm_georeferencing_model_ply_geo,
                                   tree.odm_georeferencing_pdal)

            # XYZ point cloud output
            log.ODM_INFO(
                "Creating geo-referenced CSV file (XYZ format, can be used with GRASS to create DEM)"
            )
            with open(tree.odm_georeferencing_xyz_file, "wb") as csvfile:
                csvfile_writer = csv.writer(csvfile, delimiter=",")
                reachedpoints = False
                with open(tree.odm_georeferencing_model_ply_geo) as f:
                    for lineNumber, line in enumerate(f):
                        if reachedpoints:
                            tokens = line.split(" ")
                            csv_line = [
                                float(tokens[0]) + geo_ref.utm_east_offset,
                                float(tokens[1]) + geo_ref.utm_north_offset,
                                tokens[2]
                            ]
                            csvfile_writer.writerow(csv_line)
                        if line.startswith("end_header"):
                            reachedpoints = True
            csvfile.close()

        else:
            log.ODM_WARNING('Found a valid georeferenced model in: %s' %
                            tree.odm_georeferencing_model_ply_geo)

        if args.time:
            system.benchmark(start_time, tree.benchmarking, 'Georeferencing')

        log.ODM_INFO('Running ODM Georeferencing Cell - Finished')
        return ecto.OK if args.end_with != 'odm_georeferencing' else ecto.QUIT
Пример #4
0
    def process(self, inputs, outputs):

        # Benchmarking
        start_time = system.now_raw()

        log.ODM_INFO('Running OMD OrthoPhoto Cell')

        # get inputs
        args = self.inputs.args
        tree = self.inputs.tree

        # define paths and create working directories
        system.mkdir_p(tree.odm_orthophoto)

        # check if we rerun cell or not
        rerun_cell = (args.rerun is not None and
                      args.rerun == 'odm_orthophoto') or \
                     (args.rerun_all) or \
                     (args.rerun_from is not None and
                      'odm_orthophoto' in args.rerun_from)

        if not io.file_exists(tree.odm_orthophoto_file) or rerun_cell:

            # odm_orthophoto definitions
            kwargs = {
                'bin': context.odm_modules_path,
                'model_geo': tree.odm_georeferencing_model_obj_geo,
                'log': tree.odm_orthophoto_log,
                'ortho': tree.odm_orthophoto_file,
                'corners': tree.odm_orthophoto_corners,
                'res': self.params.resolution
            }

            # run odm_orthophoto
            system.run('{bin}/odm_orthophoto -inputFile {model_geo} '
                       '-logFile {log} -outputFile {ortho} -resolution {res} '
                       '-outputCornerFile {corners}'.format(**kwargs))

            # Create georeferenced GeoTiff
            geotiffcreated = False
            georef = types.ODM_GeoRef()
            # creates the coord refs # TODO I don't want to have to do this twice- after odm_georef
            georef.parse_coordinate_system(tree.odm_georeferencing_coords)

            if georef.epsg and georef.utm_east_offset and georef.utm_north_offset:
                ulx = uly = lrx = lry = 0.0
                with open(tree.odm_orthophoto_corners) as f:
                    for lineNumber, line in enumerate(f):
                        if lineNumber == 0:
                            tokens = line.split(' ')
                            if len(tokens) == 4:
                                ulx = float(tokens[0]) + \
                                    float(georef.utm_east_offset)
                                lry = float(tokens[1]) + \
                                    float(georef.utm_north_offset)
                                lrx = float(tokens[2]) + \
                                    float(georef.utm_east_offset)
                                uly = float(tokens[3]) + \
                                    float(georef.utm_north_offset)
                log.ODM_INFO('Creating GeoTIFF')

                kwargs = {
                    'ulx': ulx,
                    'uly': uly,
                    'lrx': lrx,
                    'lry': lry,
                    'epsg': georef.epsg,
                    'png': tree.odm_orthophoto_file,
                    'tiff': tree.odm_orthophoto_tif,
                    'log': tree.odm_orthophoto_tif_log
                }

                system.run('gdal_translate -a_ullr {ulx} {uly} {lrx} {lry} '
							'-co TILED=yes '
							'-co COMPRESS=DEFLATE '
							'-co PREDICTOR=2 '
							'-co BLOCKXSIZE=512 '
							'-co BLOCKYSIZE=512 '
							'-co NUM_THREADS=ALL_CPUS '
                           '-a_srs \"EPSG:{epsg}\" {png} {tiff} > {log}'.format(**kwargs))
                geotiffcreated = True
            if not geotiffcreated:
                log.ODM_WARNING('No geo-referenced orthophoto created due '
                                'to missing geo-referencing or corner coordinates.')

        else:
            log.ODM_WARNING('Found a valid orthophoto in: %s' % tree.odm_orthophoto_file)

        if args.time:
            system.benchmark(start_time, tree.benchmarking, 'Orthophoto')

        log.ODM_INFO('Running ODM OrthoPhoto Cell - Finished')
        return ecto.OK if args.end_with != 'odm_orthophoto' else ecto.QUIT