Esempio n. 1
0
    def create_utm_copy(self,
                        gcp_file_output,
                        filenames=None,
                        rejected_entries=None,
                        include_extras=True):
        """
        Creates a new GCP file from an existing GCP file
        by optionally including only filenames and reprojecting each point to
        a UTM CRS. Rejected entries can recorded by passing a list object to
        rejected_entries.
        """
        if os.path.exists(gcp_file_output):
            os.remove(gcp_file_output)

        output = [self.wgs84_utm_zone()]
        target_srs = location.parse_srs_header(output[0])
        transformer = location.transformer(self.srs, target_srs)

        for entry in self.iter_entries():
            if filenames is None or entry.filename in filenames:
                entry.x, entry.y, entry.z = transformer.TransformPoint(
                    entry.x, entry.y, entry.z)
                if not include_extras:
                    entry.extras = ''
                output.append(str(entry))
            elif isinstance(rejected_entries, list):
                rejected_entries.append(entry)

        with open(gcp_file_output, 'w') as f:
            f.write('\n'.join(output) + '\n')

        return gcp_file_output
Esempio n. 2
0
    def make_micmac_copy(self,
                         output_dir,
                         precisionxy=0.01,
                         precisionz=0.01,
                         utm_zone=None):
        """
        Convert this GCP file in a format compatible with MicMac.
        :param output_dir directory where to save the two MicMac GCP files. The directory must exist.
        :param utm_zone UTM zone to use for output coordinates (UTM string, PROJ4 or EPSG definition).
            If one is not specified, the nearest UTM zone will be selected.
        :param precisionxy horizontal precision of GCP measurements in meters.
        :param precisionz vertical precision of GCP measurements in meters.
        """
        if not os.path.isdir(output_dir):
            raise IOError("{} does not exist.".format(output_dir))
        if not isinstance(precisionxy, float) and not isinstance(
                precisionxy, int):
            raise AssertionError("precisionxy must be a number")
        if not isinstance(precisionz, float) and not isinstance(
                precisionz, int):
            raise AssertionError("precisionz must be a number")

        gcp_3d_file = os.path.join(output_dir, '3d_gcp.txt')
        gcp_2d_file = os.path.join(output_dir, '2d_gcp.txt')

        if os.path.exists(gcp_3d_file):
            os.remove(gcp_3d_file)
        if os.path.exists(gcp_2d_file):
            os.remove(gcp_2d_file)

        if utm_zone is None:
            utm_zone = self.wgs84_utm_zone()

        target_srs = location.parse_srs_header(utm_zone)
        transformer = location.transformer(self.srs, target_srs)

        gcps = {}
        for entry in self.iter_entries():
            utm_x, utm_y, utm_z = transformer.TransformPoint(
                entry.x, entry.y, entry.z)
            k = "{} {} {}".format(utm_x, utm_y, utm_z)
            if not k in gcps:
                gcps[k] = [entry]
            else:
                gcps[k].append(entry)

        with open(gcp_3d_file, 'w') as f3:
            with open(gcp_2d_file, 'w') as f2:
                gcp_n = 1
                for k in gcps:
                    f3.write("GCP{} {} {} {}\n".format(gcp_n, k, precisionxy,
                                                       precisionz))

                    for entry in gcps[k]:
                        f2.write("GCP{} {} {} {}\n".format(
                            gcp_n, entry.filename, entry.px, entry.py))

                    gcp_n += 1

        return (gcp_3d_file, gcp_2d_file)
Esempio n. 3
0
    def __init__(self, geo_path):
        self.geo_path = geo_path
        self.entries = {}
        self.srs = None

        with open(self.geo_path, 'r') as f:
            contents = f.read().strip()

        lines = list(map(str.strip, contents.split('\n')))
        if lines:
            self.raw_srs = lines[0]  # SRS
            self.srs = location.parse_srs_header(self.raw_srs)
            longlat = CRS.from_epsg("4326")

            for line in lines[1:]:
                if line != "" and line[0] != "#":
                    parts = line.split()
                    if len(parts) >= 3:
                        i = 3
                        filename = parts[0]
                        x, y = [float(p) for p in parts[1:3]]
                        z = float(parts[3]) if len(parts) >= 4 else None

                        # Always convert coordinates to WGS84
                        if z is not None:
                            x, y, z = location.transform3(
                                self.srs, longlat, x, y, z)
                        else:
                            x, y = location.transform2(self.srs, longlat, x, y)

                        omega = phi = kappa = None

                        if len(parts) >= 7:
                            omega, phi, kappa = [float(p) for p in parts[4:7]]
                            i = 7

                        horizontal_accuracy = vertical_accuracy = None
                        if len(parts) >= 9:
                            horizontal_accuracy, vertical_accuracy = [
                                float(p) for p in parts[7:9]
                            ]
                            i = 9

                        extras = " ".join(parts[i:])
                        self.entries[filename] = GeoEntry(
                            filename, x, y, z, omega, phi, kappa,
                            horizontal_accuracy, vertical_accuracy, extras)
                    else:
                        logger.warning("Malformed geo line: %s" % line)
Esempio n. 4
0
    def FromCoordsFile(coords_file):
        # check for coordinate file existence
        if not io.file_exists(coords_file):
            log.ODM_WARNING('Could not find file %s' % coords_file)
            return

        srs = None

        with open(coords_file) as f:
            # extract reference system and utm zone from first line.
            # We will assume the following format:
            # 'WGS84 UTM 17N' or 'WGS84 UTM 17N \n'
            line = f.readline().rstrip()
            srs = location.parse_srs_header(line)

        return ODM_GeoRef(srs)
Esempio n. 5
0
    def read(self):
        if self.exists():
            with open(self.gcp_path, 'r') as f:
                contents = f.read().decode('utf-8-sig').encode('utf-8').strip()

            lines = map(str.strip, contents.split('\n'))
            if lines:
                self.raw_srs = lines[0]  # SRS
                self.srs = location.parse_srs_header(self.raw_srs)

                for line in lines[1:]:
                    if line != "" and line[0] != "#":
                        parts = line.split()
                        if len(parts) >= 6:
                            self.entries.append(line)
                        else:
                            log.MM_WARNING("Malformed GCP line: %s" % line)
Esempio n. 6
0
    def FromCoordsFile(coords_file):
        # check for coordinate file existence
        if not io.file_exists(coords_file):
            log.ODM_WARNING('Could not find file %s' % coords_file)
            return

        with open(coords_file) as f:
            # extract reference system and utm zone from first line.
            # We will assume the following format:
            # 'WGS84 UTM 17N' or 'WGS84 UTM 17N \n'
            line = f.readline().rstrip()
            srs = location.parse_srs_header(line)

            # second line is a northing/easting offset
            line = f.readline().rstrip()
            utm_east_offset, utm_north_offset = map(float, line.split(" "))

        return ODM_GeoRef(srs, utm_east_offset, utm_north_offset)
Esempio n. 7
0
    def read(self):
        if self.exists():
            with open(self.gcp_path, 'r') as f:
                contents = f.read().strip()

            # Strip eventual BOM characters
            contents = contents.replace('\ufeff', '')

            lines = list(map(str.strip, contents.split('\n')))
            if lines:
                self.raw_srs = lines[0]  # SRS
                self.srs = location.parse_srs_header(self.raw_srs)

                for line in lines[1:]:
                    if line != "" and line[0] != "#":
                        parts = line.split()
                        if len(parts) >= 6:
                            self.entries.append(line)
                        else:
                            log.ODM_WARNING("Malformed GCP line: %s" % line)
Esempio n. 8
0
    def process(self, args, outputs):

        georeferenced_point_cloud_file = os.path.join(
            args.project_path, 'odm_georeferencing',
            'odm_georeferenced_model.laz')

        with open(outputs["utm_coords_file"], 'r') as f:
            srs_header = f.readline()
            outputs["utm_offset"] = list(map(float, f.readline().split(" ")))
            outputs["utm_srs"] = parse_srs_header(srs_header)

        if not os.path.exists(georeferenced_point_cloud_file) or self.rerun():
            # Easy-peasy with PDAL
            # Point cloud is already georegistered, but it's just offset
            offset_x, offset_y = outputs["utm_offset"]

            kwargs = {
                'input': quote(outputs["point_cloud_ply_file"]),
                'output': quote(georeferenced_point_cloud_file),
                'a_srs': "EPSG:%s" % outputs["utm_srs"].to_epsg(),
                'offset_x': offset_x,
                'offset_y': offset_y,
                'offset_z': 0,
            }

            system.run(
                'pdal translate --input {input} --output {output} '
                '--writers.las.offset_x={offset_x} '
                '--writers.las.offset_y={offset_y} '
                '--writers.las.offset_z={offset_z} '
                '--writers.las.a_srs="{a_srs}" '
                '--filters.transformation.matrix="1 0 0 {offset_x} 0 1 0 {offset_y} 0 0 1 {offset_z} 0 0 0 1" '
                'transformation'.format(**kwargs))
        else:
            log.ODM_WARNING("Found existing georeferenced point cloud: %s" %
                            georeferenced_point_cloud_file)

        outputs[
            "georeferenced_point_cloud_file"] = georeferenced_point_cloud_file