Exemplo n.º 1
0
    def parse_exif_values(self, _path_file):
        # Disable exifread log
        logging.getLogger('exifread').setLevel(logging.CRITICAL)

        with open(_path_file, 'rb') as f:
            tags = exifread.process_file(f, details=False)

            try:
                if 'Image Make' in tags:
                    self.camera_make = tags['Image Make'].values.encode('utf8')
                if 'Image Model' in tags:
                    self.camera_model = tags['Image Model'].values.encode(
                        'utf8')
                if 'GPS GPSAltitude' in tags:
                    self.altitude = self.float_values(
                        tags['GPS GPSAltitude'])[0]
                    if 'GPS GPSAltitudeRef' in tags and self.int_values(
                            tags['GPS GPSAltitudeRef'])[0] > 0:
                        self.altitude *= -1
                if 'GPS GPSLatitude' in tags and 'GPS GPSLatitudeRef' in tags:
                    self.latitude = self.dms_to_decimal(
                        tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
                if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
                    self.longitude = self.dms_to_decimal(
                        tags['GPS GPSLongitude'], tags['GPS GPSLongitudeRef'])
            except IndexError as e:
                log.ODM_WARNING("Cannot read EXIF tags for %s: %s" %
                                (_path_file, e.message))

        if self.camera_make and self.camera_model:
            self.make_model = sensor_string(self.camera_make,
                                            self.camera_model)

        self.width, self.height = get_image_size.get_image_size(_path_file)
Exemplo n.º 2
0
    def parse_exif_values(self, _path_file):
        # Disable exifread log
        logging.getLogger('exifread').setLevel(logging.CRITICAL)

        with open(_path_file, 'rb') as f:
            tags = exifread.process_file(f, details=False)

            try:
                if 'Image Make' in tags:
                    self.camera_make = tags['Image Make'].values.encode('utf8')
                if 'Image Model' in tags:
                    self.camera_model = tags['Image Model'].values.encode('utf8')
                if 'GPS GPSAltitude' in tags:
                    self.altitude = self.float_values(tags['GPS GPSAltitude'])[0]
                    if 'GPS GPSAltitudeRef' in tags and self.int_values(tags['GPS GPSAltitudeRef'])[0] > 0:
                        self.altitude *= -1
                if 'GPS GPSLatitude' in tags and 'GPS GPSLatitudeRef' in tags:
                    self.latitude = self.dms_to_decimal(tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
                if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
                    self.longitude = self.dms_to_decimal(tags['GPS GPSLongitude'], tags['GPS GPSLongitudeRef'])
            except IndexError as e:
                log.ODM_WARNING("Cannot read EXIF tags for %s: %s" % (_path_file, e.message))

        if self.camera_make and self.camera_model:
            self.make_model = sensor_string(self.camera_make, self.camera_model)

        # needed to do that since sometimes metadata contains wrong data
        try:
            self.width, self.height = get_image_size.get_image_size(_path_file)
        except get_image_size.UnknownImageFormat:
            # Fallback to slower cv2
            img = cv2.imread(_path_file)
            self.width = img.shape[1]
            self.height = img.shape[0]
Exemplo n.º 3
0
    def parse_exif_values(self, _path_file):
        # Disable exifread log
        logging.getLogger('exifread').setLevel(logging.CRITICAL)

        with open(_path_file, 'rb') as f:
            tags = exifread.process_file(f, details=False)

            try:
                if 'Image Make' in tags:
                    self.camera_make = tags['Image Make'].values.encode('utf8')
                if 'Image Model' in tags:
                    self.camera_model = tags['Image Model'].values.encode('utf8')
                if 'GPS GPSAltitude' in tags:
                    self.altitude = self.float_values(tags['GPS GPSAltitude'])[0]
                    if 'GPS GPSAltitudeRef' in tags and self.int_values(tags['GPS GPSAltitudeRef'])[0] > 0:
                        self.altitude *= -1
                if 'GPS GPSLatitude' in tags and 'GPS GPSLatitudeRef' in tags:
                    self.latitude = self.dms_to_decimal(tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
                if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
                    self.longitude = self.dms_to_decimal(tags['GPS GPSLongitude'], tags['GPS GPSLongitudeRef'])
            except IndexError as e:
                log.ODM_WARNING("Cannot read EXIF tags for %s: %s" % (_path_file, e.message))

        if self.camera_make and self.camera_model:
            self.make_model = sensor_string(self.camera_make, self.camera_model)

        # needed to do that since sometimes metadata contains wrong data
        try:
            self.width, self.height = get_image_size.get_image_size(_path_file)
        except get_image_size.UnknownImageFormat:
            # Fallback to slower cv2
            img = cv2.imread(_path_file)
            self.width = img.shape[1]
            self.height = img.shape[0]
Exemplo n.º 4
0
def compute_cutline(orthophoto_file, crop_area_file, destination, max_concurrency=1, tmpdir=None, scale=1):
    if io.file_exists(orthophoto_file) and io.file_exists(crop_area_file):
        from opendm.grass_engine import grass
        log.ODM_DEBUG("Computing cutline")

        if tmpdir and not io.dir_exists(tmpdir):
            system.mkdir_p(tmpdir)

        scale = max(0.0001, min(1, scale))
        scaled_orthophoto = None

        if scale < 1:
            log.ODM_DEBUG("Scaling orthophoto to %s%% to compute cutline" % (scale * 100))

            scaled_orthophoto = os.path.join(tmpdir, os.path.basename(io.related_file_path(orthophoto_file, postfix=".scaled")))
            # Scale orthophoto before computing cutline
            system.run("gdal_translate -outsize {}% 0 "
                "-co NUM_THREADS={} "
                "--config GDAL_CACHEMAX {}% "
                "{} {}".format(
                scale * 100,
                max_concurrency,
                concurrency.get_max_memory(),
                orthophoto_file,
                scaled_orthophoto
            ))
            orthophoto_file = scaled_orthophoto

        try:
            ortho_width,ortho_height = get_image_size.get_image_size(orthophoto_file, fallback_on_error=False)
            log.ODM_DEBUG("Orthophoto dimensions are %sx%s" % (ortho_width, ortho_height))
            number_lines = int(max(8, math.ceil(min(ortho_width, ortho_height) / 256.0)))
        except:
            log.ODM_DEBUG("Cannot compute orthophoto dimensions, setting arbitrary number of lines.")
            number_lines = 32
        
        log.ODM_DEBUG("Number of lines: %s" % number_lines)

        gctx = grass.create_context({'auto_cleanup' : False, 'tmpdir': tmpdir})
        gctx.add_param('orthophoto_file', orthophoto_file)
        gctx.add_param('crop_area_file', crop_area_file)
        gctx.add_param('number_lines', number_lines)
        gctx.add_param('max_concurrency', max_concurrency)
        gctx.add_param('memory', int(concurrency.get_max_memory_mb(300)))
        gctx.set_location(orthophoto_file)

        cutline_file = gctx.execute(os.path.join("opendm", "grass", "compute_cutline.grass"))
        if cutline_file != 'error':
            if io.file_exists(cutline_file):
                shutil.move(cutline_file, destination)
                log.ODM_INFO("Generated cutline file: %s --> %s" % (cutline_file, destination))
                gctx.cleanup()
                return destination
            else:
                log.ODM_WARNING("Unexpected script result: %s. No cutline file has been generated." % cutline_file)
        else:
            log.ODM_WARNING("Could not generate orthophoto cutline. An error occured when running GRASS. No orthophoto will be generated.")
    else:
        log.ODM_WARNING("We've been asked to compute cutline, but either %s or %s is missing. Skipping..." % (orthophoto_file, crop_area_file))
Exemplo n.º 5
0
def compute_cutline(orthophoto_file,
                    crop_area_file,
                    destination,
                    max_concurrency=1,
                    tmpdir=None):
    if io.file_exists(orthophoto_file) and io.file_exists(crop_area_file):
        from opendm.grass_engine import grass
        log.ODM_DEBUG("Computing cutline")

        if tmpdir and not io.dir_exists(tmpdir):
            system.mkdir_p(tmpdir)

        try:
            ortho_width, ortho_height = get_image_size.get_image_size(
                orthophoto_file)
            log.ODM_DEBUG("Orthophoto dimensions are %sx%s" %
                          (ortho_width, ortho_height))
            number_lines = int(
                max(8, math.ceil(min(ortho_width, ortho_height) / 256.0)))
        except get_image_size.UnknownImageFormat:
            log.ODM_DEBUG(
                "Cannot compute orthophoto dimensions, setting arbitrary number of lines."
            )
            number_lines = 32

        log.ODM_DEBUG("Number of lines: %s" % number_lines)

        gctx = grass.create_context({'auto_cleanup': False, 'tmpdir': tmpdir})
        gctx.add_param('orthophoto_file', orthophoto_file)
        gctx.add_param('crop_area_file', crop_area_file)
        gctx.add_param('number_lines', number_lines)
        gctx.add_param('max_concurrency', max_concurrency)
        gctx.add_param('memory', int(concurrency.get_max_memory_mb(300)))
        gctx.set_location(orthophoto_file)

        cutline_file = gctx.execute(
            os.path.join("opendm", "grass", "compute_cutline.grass"))
        if cutline_file != 'error':
            if io.file_exists(cutline_file):
                shutil.move(cutline_file, destination)
                log.ODM_INFO("Generated cutline file: %s --> %s" %
                             (cutline_file, destination))
                gctx.cleanup()
                return destination
            else:
                log.ODM_WARNING(
                    "Unexpected script result: %s. No cutline file has been generated."
                    % cutline_file)
        else:
            log.ODM_WARNING(
                "Could not generate orthophoto cutline. An error occured when running GRASS. No orthophoto will be generated."
            )
    else:
        log.ODM_WARNING(
            "We've been asked to compute cutline, but either %s or %s is missing. Skipping..."
            % (orthophoto_file, crop_area_file))
Exemplo n.º 6
0
Arquivo: photo.py Projeto: wzdk123/ODM
    def parse_exif_values(self, _path_file):
        # Disable exifread log
        logging.getLogger('exifread').setLevel(logging.CRITICAL)

        with open(_path_file, 'rb') as f:
            tags = exifread.process_file(f, details=False)
            try:
                if 'Image Make' in tags:
                    try:
                        self.camera_make = tags['Image Make'].values
                    except UnicodeDecodeError:
                        log.ODM_WARNING("EXIF Image Make might be corrupted")
                        self.camera_make = "unknown"
                if 'Image Model' in tags:
                    try:
                        self.camera_model = tags['Image Model'].values
                    except UnicodeDecodeError:
                        log.ODM_WARNING("EXIF Image Model might be corrupted")
                        self.camera_model = "unknown"
                if 'GPS GPSAltitude' in tags:
                    self.altitude = self.float_value(tags['GPS GPSAltitude'])
                    if 'GPS GPSAltitudeRef' in tags and self.int_value(
                            tags['GPS GPSAltitudeRef']) > 0:
                        self.altitude *= -1
                if 'GPS GPSLatitude' in tags and 'GPS GPSLatitudeRef' in tags:
                    self.latitude = self.dms_to_decimal(
                        tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
                if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
                    self.longitude = self.dms_to_decimal(
                        tags['GPS GPSLongitude'], tags['GPS GPSLongitudeRef'])
            except IndexError as e:
                log.ODM_WARNING("Cannot read basic EXIF tags for %s: %s" %
                                (_path_file, str(e)))

            try:
                if 'Image Tag 0xC61A' in tags:
                    self.black_level = self.list_values(
                        tags['Image Tag 0xC61A'])
                elif 'BlackLevel' in tags:
                    self.black_level = self.list_values(tags['BlackLevel'])

                if 'EXIF ExposureTime' in tags:
                    self.exposure_time = self.float_value(
                        tags['EXIF ExposureTime'])

                if 'EXIF FNumber' in tags:
                    self.fnumber = self.float_value(tags['EXIF FNumber'])

                if 'EXIF ISOSpeed' in tags:
                    self.iso_speed = self.int_value(tags['EXIF ISOSpeed'])
                elif 'EXIF PhotographicSensitivity' in tags:
                    self.iso_speed = self.int_value(
                        tags['EXIF PhotographicSensitivity'])
                elif 'EXIF ISOSpeedRatings' in tags:
                    self.iso_speed = self.int_value(
                        tags['EXIF ISOSpeedRatings'])

                if 'Image BitsPerSample' in tags:
                    self.bits_per_sample = self.int_value(
                        tags['Image BitsPerSample'])
                if 'EXIF DateTimeOriginal' in tags:
                    str_time = tags['EXIF DateTimeOriginal'].values
                    utc_time = datetime.strptime(str_time, "%Y:%m:%d %H:%M:%S")
                    subsec = 0
                    if 'EXIF SubSecTime' in tags:
                        subsec = self.int_value(tags['EXIF SubSecTime'])
                    negative = 1.0
                    if subsec < 0:
                        negative = -1.0
                        subsec *= -1.0
                    subsec = float('0.{}'.format(int(subsec)))
                    subsec *= negative
                    ms = subsec * 1e3
                    utc_time += timedelta(milliseconds=ms)
                    timezone = pytz.timezone('UTC')
                    epoch = timezone.localize(datetime.utcfromtimestamp(0))
                    self.utc_time = (timezone.localize(utc_time) -
                                     epoch).total_seconds() * 1000.0
            except Exception as e:
                log.ODM_WARNING("Cannot read extended EXIF tags for %s: %s" %
                                (_path_file, str(e)))

            # Extract XMP tags
            f.seek(0)
            xmp = self.get_xmp(f)

            for tags in xmp:
                try:
                    band_name = self.get_xmp_tag(
                        tags, ['Camera:BandName', '@Camera:BandName'])
                    if band_name is not None:
                        self.band_name = band_name.replace(" ", "")

                    self.set_attr_from_xmp_tag(
                        'band_index',
                        tags,
                        [
                            'DLS:SensorId',  # Micasense RedEdge
                            '@Camera:RigCameraIndex',  # Parrot Sequoia, Sentera 21244-00_3.2MP-GS-0001
                            'Camera:RigCameraIndex',  # MicaSense Altum
                        ])
                    self.set_attr_from_xmp_tag(
                        'radiometric_calibration', tags, [
                            'MicaSense:RadiometricCalibration',
                        ])

                    self.set_attr_from_xmp_tag('vignetting_center', tags, [
                        'Camera:VignettingCenter',
                        'Sentera:VignettingCenter',
                    ])

                    self.set_attr_from_xmp_tag('vignetting_polynomial', tags, [
                        'Camera:VignettingPolynomial',
                        'Sentera:VignettingPolynomial',
                    ])

                    self.set_attr_from_xmp_tag('horizontal_irradiance', tags,
                                               ['Camera:HorizontalIrradiance'],
                                               float)

                    self.set_attr_from_xmp_tag(
                        'irradiance_scale_to_si', tags,
                        ['Camera:IrradianceScaleToSIUnits'], float)

                    self.set_attr_from_xmp_tag('sun_sensor', tags, [
                        'Camera:SunSensor',
                    ], float)

                    self.set_attr_from_xmp_tag('spectral_irradiance', tags, [
                        'Camera:SpectralIrradiance',
                        'Camera:Irradiance',
                    ], float)

                    # Phantom 4 RTK
                    if '@drone-dji:RtkStdLon' in tags:
                        y = float(
                            self.get_xmp_tag(tags, '@drone-dji:RtkStdLon'))
                        x = float(
                            self.get_xmp_tag(tags, '@drone-dji:RtkStdLat'))
                        self.gps_xy_stddev = max(x, y)

                        if '@drone-dji:RtkStdHgt' in tags:
                            self.gps_z_stddev = float(
                                self.get_xmp_tag(tags, '@drone-dji:RtkStdHgt'))
                    else:
                        self.set_attr_from_xmp_tag(
                            'gps_xy_stddev', tags,
                            ['@Camera:GPSXYAccuracy', 'GPSXYAccuracy'], float)
                        self.set_attr_from_xmp_tag(
                            'gps_z_stddev', tags,
                            ['@Camera:GPSZAccuracy', 'GPSZAccuracy'], float)

                    if 'DLS:Yaw' in tags:
                        self.set_attr_from_xmp_tag('dls_yaw', tags,
                                                   ['DLS:Yaw'], float)
                        self.set_attr_from_xmp_tag('dls_pitch', tags,
                                                   ['DLS:Pitch'], float)
                        self.set_attr_from_xmp_tag('dls_roll', tags,
                                                   ['DLS:Roll'], float)
                except Exception as e:
                    log.ODM_WARNING("Cannot read XMP tags for %s: %s" %
                                    (_path_file, str(e)))

                # self.set_attr_from_xmp_tag('center_wavelength', tags, [
                #     'Camera:CentralWavelength'
                # ], float)

                # self.set_attr_from_xmp_tag('bandwidth', tags, [
                #     'Camera:WavelengthFWHM'
                # ], float)

        self.width, self.height = get_image_size.get_image_size(_path_file)
        # Sanitize band name since we use it in folder paths
        self.band_name = re.sub('[^A-Za-z0-9]+', '', self.band_name)
Exemplo n.º 7
0
    def parse_exif_values(self, _path_file):
        # Disable exifread log
        logging.getLogger('exifread').setLevel(logging.CRITICAL)

        try:
            self.width, self.height = get_image_size.get_image_size(_path_file)
        except Exception as e:
            raise PhotoCorruptedException(str(e))

        tags = {}
        xtags = {}

        with open(_path_file, 'rb') as f:
            tags = exifread.process_file(f,
                                         details=True,
                                         extract_thumbnail=False)
            try:
                if 'Image Make' in tags:
                    try:
                        self.camera_make = tags['Image Make'].values
                        self.camera_make = self.camera_make.strip()
                    except UnicodeDecodeError:
                        log.ODM_WARNING("EXIF Image Make might be corrupted")
                        self.camera_make = "unknown"
                if 'Image Model' in tags:
                    try:
                        self.camera_model = tags['Image Model'].values
                        self.camera_model = self.camera_model.strip()
                    except UnicodeDecodeError:
                        log.ODM_WARNING("EXIF Image Model might be corrupted")
                        self.camera_model = "unknown"
                if 'GPS GPSAltitude' in tags:
                    self.altitude = self.float_value(tags['GPS GPSAltitude'])
                    if 'GPS GPSAltitudeRef' in tags and self.int_value(
                            tags['GPS GPSAltitudeRef']
                    ) is not None and self.int_value(
                            tags['GPS GPSAltitudeRef']) > 0:
                        self.altitude *= -1
                if 'GPS GPSLatitude' in tags and 'GPS GPSLatitudeRef' in tags:
                    self.latitude = self.dms_to_decimal(
                        tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
                elif 'GPS GPSLatitude' in tags:
                    log.ODM_WARNING(
                        "GPS position for %s might be incorrect, GPSLatitudeRef tag is missing (assuming N)"
                        % self.filename)
                    self.latitude = self.dms_to_decimal(
                        tags['GPS GPSLatitude'], GPSRefMock('N'))
                if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
                    self.longitude = self.dms_to_decimal(
                        tags['GPS GPSLongitude'], tags['GPS GPSLongitudeRef'])
                elif 'GPS GPSLongitude' in tags:
                    log.ODM_WARNING(
                        "GPS position for %s might be incorrect, GPSLongitudeRef tag is missing (assuming E)"
                        % self.filename)
                    self.longitude = self.dms_to_decimal(
                        tags['GPS GPSLongitude'], GPSRefMock('E'))
                if 'Image Orientation' in tags:
                    self.orientation = self.int_value(
                        tags['Image Orientation'])
            except (IndexError, ValueError) as e:
                log.ODM_WARNING("Cannot read basic EXIF tags for %s: %s" %
                                (self.filename, str(e)))

            try:
                if 'Image Tag 0xC61A' in tags:
                    self.black_level = self.list_values(
                        tags['Image Tag 0xC61A'])
                elif 'BlackLevel' in tags:
                    self.black_level = self.list_values(tags['BlackLevel'])

                if 'EXIF ExposureTime' in tags:
                    self.exposure_time = self.float_value(
                        tags['EXIF ExposureTime'])

                if 'EXIF FNumber' in tags:
                    self.fnumber = self.float_value(tags['EXIF FNumber'])

                if 'EXIF ISOSpeed' in tags:
                    self.iso_speed = self.int_value(tags['EXIF ISOSpeed'])
                elif 'EXIF PhotographicSensitivity' in tags:
                    self.iso_speed = self.int_value(
                        tags['EXIF PhotographicSensitivity'])
                elif 'EXIF ISOSpeedRatings' in tags:
                    self.iso_speed = self.int_value(
                        tags['EXIF ISOSpeedRatings'])

                if 'Image BitsPerSample' in tags:
                    self.bits_per_sample = self.int_value(
                        tags['Image BitsPerSample'])
                if 'EXIF DateTimeOriginal' in tags:
                    str_time = tags['EXIF DateTimeOriginal'].values
                    utc_time = datetime.strptime(str_time, "%Y:%m:%d %H:%M:%S")
                    subsec = 0
                    if 'EXIF SubSecTime' in tags:
                        subsec = self.int_value(tags['EXIF SubSecTime'])
                    negative = 1.0
                    if subsec < 0:
                        negative = -1.0
                        subsec *= -1.0
                    subsec = float('0.{}'.format(int(subsec)))
                    subsec *= negative
                    ms = subsec * 1e3
                    utc_time += timedelta(milliseconds=ms)
                    timezone = pytz.timezone('UTC')
                    epoch = timezone.localize(datetime.utcfromtimestamp(0))
                    self.utc_time = (timezone.localize(utc_time) -
                                     epoch).total_seconds() * 1000.0

                if 'MakerNote SpeedX' in tags and \
                    'MakerNote SpeedY' in tags and \
                    'MakerNote SpeedZ' in tags:
                    self.speed_x = self.float_value(tags['MakerNote SpeedX'])
                    self.speed_y = self.float_value(tags['MakerNote SpeedY'])
                    self.speed_z = self.float_value(tags['MakerNote SpeedZ'])

            except Exception as e:
                log.ODM_WARNING("Cannot read extended EXIF tags for %s: %s" %
                                (self.filename, str(e)))

            # Warn if GPS coordinates are suspiciously wrong
            if self.latitude is not None and self.latitude == 0 and \
                self.longitude is not None and self.longitude == 0:
                log.ODM_WARNING(
                    "%s has GPS position (0,0), possibly corrupted" %
                    self.filename)

            # Extract XMP tags
            f.seek(0)
            xmp = self.get_xmp(f)

            for xtags in xmp:
                try:
                    band_name = self.get_xmp_tag(
                        xtags, ['Camera:BandName', '@Camera:BandName'])
                    if band_name is not None:
                        self.band_name = band_name.replace(" ", "")

                    self.set_attr_from_xmp_tag(
                        'band_index',
                        xtags,
                        [
                            'DLS:SensorId',  # Micasense RedEdge
                            '@Camera:RigCameraIndex',  # Parrot Sequoia, Sentera 21244-00_3.2MP-GS-0001
                            'Camera:RigCameraIndex',  # MicaSense Altum
                        ])

                    self.set_attr_from_xmp_tag(
                        'radiometric_calibration', xtags, [
                            'MicaSense:RadiometricCalibration',
                        ])

                    self.set_attr_from_xmp_tag('vignetting_center', xtags, [
                        'Camera:VignettingCenter',
                        'Sentera:VignettingCenter',
                    ])

                    self.set_attr_from_xmp_tag(
                        'vignetting_polynomial', xtags, [
                            'Camera:VignettingPolynomial',
                            'Sentera:VignettingPolynomial',
                        ])

                    self.set_attr_from_xmp_tag('horizontal_irradiance', xtags,
                                               ['Camera:HorizontalIrradiance'],
                                               float)

                    self.set_attr_from_xmp_tag(
                        'irradiance_scale_to_si', xtags,
                        ['Camera:IrradianceScaleToSIUnits'], float)

                    self.set_attr_from_xmp_tag('sun_sensor', xtags, [
                        'Camera:SunSensor',
                    ], float)

                    self.set_attr_from_xmp_tag('spectral_irradiance', xtags, [
                        'Camera:SpectralIrradiance',
                        'Camera:Irradiance',
                    ], float)

                    self.set_attr_from_xmp_tag(
                        'capture_uuid',
                        xtags,
                        [
                            '@drone-dji:CaptureUUID',  # DJI
                            'MicaSense:CaptureId',  # MicaSense Altum
                            '@Camera:ImageUniqueID',  # sentera 6x
                        ])

                    # Camera make / model for some cameras is stored in the XMP
                    if self.camera_make == '':
                        self.set_attr_from_xmp_tag('camera_make', xtags,
                                                   ['@tiff:Make'])
                    if self.camera_model == '':
                        self.set_attr_from_xmp_tag('camera_model', xtags,
                                                   ['@tiff:Model'])

                    # DJI GPS tags
                    self.set_attr_from_xmp_tag('longitude', xtags,
                                               ['@drone-dji:Longitude'], float)
                    self.set_attr_from_xmp_tag('latitude', xtags,
                                               ['@drone-dji:Latitude'], float)
                    self.set_attr_from_xmp_tag('altitude', xtags,
                                               ['@drone-dji:AbsoluteAltitude'],
                                               float)

                    # Phantom 4 RTK
                    if '@drone-dji:RtkStdLon' in xtags:
                        y = float(
                            self.get_xmp_tag(xtags, '@drone-dji:RtkStdLon'))
                        x = float(
                            self.get_xmp_tag(xtags, '@drone-dji:RtkStdLat'))
                        self.gps_xy_stddev = max(x, y)

                        if '@drone-dji:RtkStdHgt' in xtags:
                            self.gps_z_stddev = float(
                                self.get_xmp_tag(xtags,
                                                 '@drone-dji:RtkStdHgt'))
                    else:
                        self.set_attr_from_xmp_tag(
                            'gps_xy_stddev', xtags,
                            ['@Camera:GPSXYAccuracy', 'GPSXYAccuracy'], float)
                        self.set_attr_from_xmp_tag(
                            'gps_z_stddev', xtags,
                            ['@Camera:GPSZAccuracy', 'GPSZAccuracy'], float)

                    # DJI Speed tags
                    if '@drone-dji:FlightXSpeed' in xtags and \
                       '@drone-dji:FlightYSpeed' in xtags and \
                       '@drone-dji:FlightZSpeed' in xtags:
                        self.set_attr_from_xmp_tag('speed_x', xtags,
                                                   ['@drone-dji:FlightXSpeed'],
                                                   float)
                        self.set_attr_from_xmp_tag('speed_y', xtags, [
                            '@drone-dji:FlightYSpeed',
                        ], float)
                        self.set_attr_from_xmp_tag('speed_z', xtags, [
                            '@drone-dji:FlightZSpeed',
                        ], float)

                    # Account for over-estimation
                    if self.gps_xy_stddev is not None:
                        self.gps_xy_stddev *= 2.0
                    if self.gps_z_stddev is not None:
                        self.gps_z_stddev *= 2.0

                    if 'DLS:Yaw' in xtags:
                        self.set_attr_from_xmp_tag('dls_yaw', xtags,
                                                   ['DLS:Yaw'], float)
                        self.set_attr_from_xmp_tag('dls_pitch', xtags,
                                                   ['DLS:Pitch'], float)
                        self.set_attr_from_xmp_tag('dls_roll', xtags,
                                                   ['DLS:Roll'], float)

                    camera_projection = self.get_xmp_tag(
                        xtags, ['@Camera:ModelType', 'Camera:ModelType'])
                    if camera_projection is not None:
                        camera_projection = camera_projection.lower()
                        if camera_projection in projections:
                            self.camera_projection = camera_projection

                    # OPK
                    self.set_attr_from_xmp_tag('yaw', xtags, [
                        '@drone-dji:FlightYawDegree', '@Camera:Yaw',
                        'Camera:Yaw'
                    ], float)
                    self.set_attr_from_xmp_tag('pitch', xtags, [
                        '@drone-dji:GimbalPitchDegree', '@Camera:Pitch',
                        'Camera:Pitch'
                    ], float)
                    self.set_attr_from_xmp_tag('roll', xtags, [
                        '@drone-dji:GimbalRollDegree', '@Camera:Roll',
                        'Camera:Roll'
                    ], float)

                    # Normalize YPR conventions (assuming nadir camera)
                    # Yaw: 0 --> top of image points north
                    # Yaw: 90 --> top of image points east
                    # Yaw: 270 --> top of image points west
                    # Pitch: 0 --> nadir camera
                    # Pitch: 90 --> camera is looking forward
                    # Roll: 0 (assuming gimbal)
                    if self.has_ypr():
                        if self.camera_make.lower() in ['dji', 'hasselblad']:
                            self.pitch = 90 + self.pitch

                        if self.camera_make.lower() == 'sensefly':
                            self.roll *= -1

                except Exception as e:
                    log.ODM_WARNING("Cannot read XMP tags for %s: %s" %
                                    (self.filename, str(e)))

                # self.set_attr_from_xmp_tag('center_wavelength', xtags, [
                #     'Camera:CentralWavelength'
                # ], float)

                # self.set_attr_from_xmp_tag('bandwidth', xtags, [
                #     'Camera:WavelengthFWHM'
                # ], float)

        # Sanitize band name since we use it in folder paths
        self.band_name = re.sub('[^A-Za-z0-9]+', '', self.band_name)

        self.compute_focal(tags, xtags)
        self.compute_opk()
Exemplo n.º 8
0
    def parse_exif_values(self, _path_file):
        # Disable exifread log
        logging.getLogger('exifread').setLevel(logging.CRITICAL)

        with open(_path_file, 'rb') as f:
            tags = exifread.process_file(f, details=False)

            try:
                if 'Image Make' in tags:
                    self.camera_make = tags['Image Make'].values.encode('utf8')
                if 'Image Model' in tags:
                    self.camera_model = tags['Image Model'].values.encode(
                        'utf8')
                if 'GPS GPSAltitude' in tags:
                    self.altitude = self.float_values(
                        tags['GPS GPSAltitude'])[0]
                    if 'GPS GPSAltitudeRef' in tags and self.int_values(
                            tags['GPS GPSAltitudeRef'])[0] > 0:
                        self.altitude *= -1
                if 'GPS GPSLatitude' in tags and 'GPS GPSLatitudeRef' in tags:
                    self.latitude = self.dms_to_decimal(
                        tags['GPS GPSLatitude'], tags['GPS GPSLatitudeRef'])
                if 'GPS GPSLongitude' in tags and 'GPS GPSLongitudeRef' in tags:
                    self.longitude = self.dms_to_decimal(
                        tags['GPS GPSLongitude'], tags['GPS GPSLongitudeRef'])
            except IndexError as e:
                log.ODM_WARNING("Cannot read EXIF tags for %s: %s" %
                                (_path_file, e.message))

            # Extract XMP tags
            f.seek(0)
            xmp = self.get_xmp(f)

            # Find band name and camera index (if available)
            camera_index_tags = [
                'DLS:SensorId',  # Micasense RedEdge
                '@Camera:RigCameraIndex',  # Parrot Sequoia
                'Camera:RigCameraIndex',  # MicaSense Altum
            ]

            for tags in xmp:
                if 'Camera:BandName' in tags:
                    cbt = tags['Camera:BandName']
                    band_name = None

                    if isinstance(cbt, string_types):
                        band_name = str(tags['Camera:BandName'])
                    elif isinstance(cbt, dict):
                        items = cbt.get('rdf:Seq', {}).get('rdf:li', {})
                        if items:
                            band_name = " ".join(items)

                    if band_name is not None:
                        self.band_name = band_name.replace(" ", "")
                    else:
                        log.ODM_WARNING(
                            "Camera:BandName tag found in XMP, but we couldn't parse it. Multispectral bands might be improperly classified."
                        )

                for cit in camera_index_tags:
                    if cit in tags:
                        self.band_index = int(tags[cit])

        self.width, self.height = get_image_size.get_image_size(_path_file)

        # Sanitize band name since we use it in folder paths
        self.band_name = re.sub('[^A-Za-z0-9]+', '', self.band_name)