def add_exif_using_timestamp(filename, time, points, offset_time=0, offset_bearing=0): ''' Find lat, lon and bearing of filename and write to EXIF. ''' metadata = ExifEdit(filename) # subtract offset in s beween gpx time and exif time t = time - datetime.timedelta(seconds=offset_time) try: lat, lon, bearing, elevation = interpolate_lat_lon(points, t) corrected_bearing = (bearing + offset_bearing) % 360 metadata.add_lat_lon(lat, lon) metadata.add_direction(corrected_bearing) if elevation is not None: metadata.add_altitude(elevation) metadata.write() print( "Added geodata to: {} time {} lat {} lon {} alt {} bearing {}" .format(filename, time, lat, lon, elevation, exiv_bearing)) except ValueError, e: print("Skipping {0}: {1}".format(filename, e))
def test_load_and_dump_corrupt_exif_2(self): corrupt_exifedit = ExifEdit(CORRUPT_EXIF_FILE_2) error_raised = False try: corrupt_exifedit.write(FIXED_EXIF_FILE_2) except: error_raised = True self.assertFalse(error_raised, 'EXIF load and dump back failed')
def write_direction_to_image(filename, direction): ''' Write the direction to the exif tag of the photograph. @param filename: photograph filename @param direction: direction of view in degrees ''' exif = ExifEdit(filename) try: exif.add_direction(direction, precision=10) exif.write() print("Added direction to: {0} ({1} degrees)".format(filename, float(direction))) except ValueError, e: print("Skipping {0}: {1}".format(filename, e))
def write_exif(filename, coordinates): ''' Write Lat Lon Direction ''' metadata = metadata = ExifEdit(filename) #metadata.read() try: # convert decimal coordinates into degrees, minutes and seconds as fractions for EXIF #exiv_lat = (make_fraction(48,1), make_fraction(58,1), make_fraction(int(52.69876547*1000000),1000000)) #exiv_lat = (make_fraction(int(coordinates[0]),1), make_fraction(int(coordinates[1]),1), make_fraction(int(float(coordinates[2])*1000000),1000000)) #exiv_lon = (make_fraction(int(coordinates[4]),1), make_fraction(int(coordinates[5]),1), make_fraction(int(float(coordinates[6])*1000000),1000000)) # convert direction into fraction #exiv_bearing = make_fraction(int(coordinates[8]*10),10) # add to exif #metadata["Exif.GPSInfo.GPSLatitude"] = exiv_lat #metadata["Exif.GPSInfo.GPSLatitudeRef"] = coordinates[3] #metadata["Exif.GPSInfo.GPSLongitude"] = exiv_lon #metadata["Exif.GPSInfo.GPSLongitudeRef"] = coordinates[7] #metadata["Exif.GPSInfo.GPSMapDatum"] = "WGS-84" #metadata["Exif.GPSInfo.GPSVersionID"] = '2 0 0 0' #metadata["Exif.GPSInfo.GPSImgDirection"] = exiv_bearing #metadata["Exif.GPSInfo.GPSImgDirectionRef"] = "T" metadata.add_lat_lon(coordinates.lat.decimal_degree, coordinates.lon.decimal_degree) metadata.write() print("Added geodata to: {0}".format(filename)) except ValueError, e: print("Skipping {0}: {1}".format(filename, e))
def create_mapillary_description( filename, username, email, upload_hash, sequence_uuid, interpolated_heading=0.0, verbose=False ): """ Check that image file has the required EXIF fields. Incompatible files will be ignored server side. """ # read exif exif = EXIF(filename) if not verify_exif(filename): return False # write the mapillary tag mapillary_description = {} mapillary_description["MAPLongitude"], mapillary_description["MAPLatitude"] = exif.extract_lon_lat() # required date format: 2015_01_14_09_37_01_000 mapillary_description["MAPCaptureTime"] = datetime.datetime.strftime( exif.extract_capture_time(), "%Y_%m_%d_%H_%M_%S_%f" )[:-3] mapillary_description["MAPOrientation"] = exif.extract_orientation() heading = exif.extract_direction() heading = normalize_bearing(interpolated_heading) if heading is None else normalize_bearing(heading) mapillary_description["MAPCompassHeading"] = {"TrueHeading": heading, "MagneticHeading": heading} mapillary_description["MAPSettingsUploadHash"] = upload_hash mapillary_description["MAPSettingsEmail"] = email mapillary_description["MAPSettingsUsername"] = username settings_upload_hash = hashlib.sha256("%s%s%s" % (upload_hash, email, base64.b64encode(filename))).hexdigest() mapillary_description["MAPSettingsUploadHash"] = settings_upload_hash mapillary_description["MAPPhotoUUID"] = str(uuid.uuid4()) mapillary_description["MAPSequenceUUID"] = str(sequence_uuid) mapillary_description["MAPDeviceModel"] = exif.extract_model() mapillary_description["MAPDeviceMake"] = exif.extract_make() # write to file json_desc = json.dumps(mapillary_description) if verbose: print "tag: {0}".format(json_desc) metadata = ExifEdit(filename) metadata.add_image_description(json_desc) metadata.write()
def add_orientation_general(test_obj, filename): test_orientation = 2 empty_exifedit = ExifEdit(filename) empty_exifedit.add_orientation(test_orientation) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() test_obj.assertEqual(test_orientation, exif_data[EXIF_PRIMARY_TAGS_DICT['Orientation']])
def create_mapillary_description(filename, username, email, upload_hash, sequence_uuid, interpolated_heading=0.0, verbose=False): ''' Check that image file has the required EXIF fields. Incompatible files will be ignored server side. ''' # read exif exif = EXIF(filename) if not verify_exif(filename): return False # write the mapillary tag mapillary_description = {} mapillary_description["MAPLongitude"], mapillary_description[ "MAPLatitude"] = exif.extract_lon_lat() #required date format: 2015_01_14_09_37_01_000 mapillary_description["MAPCaptureTime"] = datetime.datetime.strftime( exif.extract_capture_time(), "%Y_%m_%d_%H_%M_%S_%f")[:-3] mapillary_description["MAPOrientation"] = exif.extract_orientation() heading = exif.extract_direction() heading = normalize_bearing( interpolated_heading) if heading is None else normalize_bearing( heading) mapillary_description["MAPCompassHeading"] = { "TrueHeading": heading, "MagneticHeading": heading } mapillary_description["MAPSettingsUploadHash"] = upload_hash mapillary_description["MAPSettingsEmail"] = email mapillary_description["MAPSettingsUsername"] = username settings_upload_hash = hashlib.sha256( "%s%s%s" % (upload_hash, email, base64.b64encode(filename))).hexdigest() mapillary_description['MAPSettingsUploadHash'] = settings_upload_hash mapillary_description['MAPPhotoUUID'] = str(uuid.uuid4()) mapillary_description['MAPSequenceUUID'] = str(sequence_uuid) mapillary_description['MAPDeviceModel'] = exif.extract_model() mapillary_description['MAPDeviceMake'] = exif.extract_make() # write to file json_desc = json.dumps(mapillary_description) if verbose: print "tag: {0}".format(json_desc) metadata = ExifEdit(filename) metadata.add_image_description(json_desc) metadata.write()
def add_date_time_original_general(test_obj, filename): test_datetime = datetime.datetime(2016, 8, 31, 8, 29, 26, 249000) empty_exifedit = ExifEdit(filename) empty_exifedit.add_date_time_original(test_datetime) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() test_obj.assertEqual( test_datetime.strftime('%Y:%m:%d %H:%M:%S.%f')[:-3], exif_data[EXIF_PRIMARY_TAGS_DICT['DateTimeOriginal']])
def test_write_to_non_existing_file(self): test_datetime = datetime.datetime(2016, 8, 31, 8, 29, 26, 249000) empty_exifedit = ExifEdit(EMPTY_EXIF_FILE_TEST) empty_exifedit.add_date_time_original(test_datetime) empty_exifedit.write(NON_EXISTING_FILE) exif_data = load_exif(NON_EXISTING_FILE) self.assertEqual( test_datetime.strftime('%Y:%m:%d %H:%M:%S.%f')[:-3], exif_data[EXIF_PRIMARY_TAGS_DICT['DateTimeOriginal']])
def write_direction_to_image(filename, direction): ''' Write the direction to the exif tag of the photograph. @param filename: photograph filename @param direction: direction of view in degrees ''' exif = ExifEdit(filename) try: exif.add_direction(direction, precision=10) exif.write() print("Added direction to: {0} ({1} degrees)".format( filename, float(direction))) except ValueError, e: print("Skipping {0}: {1}".format(filename, e))
def add_camera_make_model_general(test_obj, filename): test_make = "test_make" test_model = "test_model" empty_exifedit = ExifEdit(filename) empty_exifedit.add_camera_make_model(test_make, test_model) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() test_obj.assertEqual((test_make, test_model), (exif_data[EXIF_PRIMARY_TAGS_DICT['Make']], exif_data[EXIF_PRIMARY_TAGS_DICT['Model']]))
def add_dop_general(test_obj, filename): test_dop = 10.5 test_dop_precision = 100 empty_exifedit = ExifEdit(filename) empty_exifedit.add_dop(test_dop, test_dop_precision) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() test_obj.assertEqual((test_dop * test_dop_precision, test_dop_precision), exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSDOP']])
def add_altitude_general(test_obj, filename): test_altitude = 15.5 test_altitude_precision = 100 empty_exifedit = ExifEdit(filename) empty_exifedit.add_altitude(test_altitude, test_altitude_precision) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() test_obj.assertEqual( (test_altitude * test_altitude_precision, test_altitude_precision), exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSAltitude']])
def add_direction_general(test_obj, filename): test_direction = 1 test_direction_ref = "T" test_direction_precision = 100 empty_exifedit = ExifEdit(filename) empty_exifedit.add_direction(test_direction, test_direction_ref, test_direction_precision) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() test_obj.assertEqual( (test_direction * test_direction_precision, test_direction_precision), exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSImgDirection']])
def add_exif_using_timestamp(filename, start_time, offset_time): ''' Add timestamp to EXIF given start time and offset time. ''' exif = ExifEdit(filename) t = start_time + datetime.timedelta(seconds=offset_time) print("setting {0} time to {1} due to offset {2}".format( filename, t, offset_time)) try: exif.add_date_time_original(t) exif.write() print("Added timestamp {} to {}.".format(filename, t.strftime(time_format))) except ValueError, e: print("Skipping {0}: {1}".format(filename, e))
def add_image_description_general(test_obj, filename): test_dictionary = { "key_numeric": 1, "key_string": "one", "key_list": [1, 2], "key_dict": { "key_dict1": 1, "key_dict2": 2 } } empty_exifedit = ExifEdit(filename) empty_exifedit.add_image_description(test_dictionary) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() test_obj.assertEqual( str(test_dictionary), str(exif_data[EXIF_PRIMARY_TAGS_DICT['ImageDescription']]).replace( '"', '\''))
def test_add_negative_lat_lon(self): test_latitude = -50.5 test_longitude = -15.5 precision = 1e7 empty_exifedit = ExifEdit(EMPTY_EXIF_FILE_TEST) empty_exifedit.add_lat_lon(test_latitude, test_longitude, precision) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() self.assertEqual( (decimal_to_dms(abs(test_latitude), precision), decimal_to_dms(abs(test_longitude), precision), "S", "W"), (exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSLatitude']], exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSLongitude']], exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSLatitudeRef']], exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSLongitudeRef']]))
def add_lat_lon_general(test_obj, filename): test_latitude = 50.5475894785 test_longitude = 15.595866685 precision = 1e7 empty_exifedit = ExifEdit(filename) empty_exifedit.add_lat_lon(test_latitude, test_longitude, precision) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() test_obj.assertEqual( (decimal_to_dms(abs(test_latitude), precision), decimal_to_dms(abs(test_longitude), precision), "N", "E"), (exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSLatitude']], exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSLongitude']], exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSLatitudeRef']], exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSLongitudeRef']]))
def test_run(image_path): ''' Test run for images ''' s = Sequence(image_path, check_exif=False) file_list = s.get_file_list(image_path) num_image = len(file_list) t1 = datetime.datetime.strptime('2000_09_03_12_00_00', '%Y_%m_%d_%H_%M_%S') t2 = datetime.datetime.strptime('2000_09_03_12_30_00', '%Y_%m_%d_%H_%M_%S') p1 = point(0.5, 0.5, 0.2, t1, num_image-2) p2 = point(0.55, 0.55, 0.0, t2, 0) inter_points = interpolate_with_anchors([p1, p2], angle_offset=-90.0) save_path = os.path.join(image_path, 'processed') lib.io.mkdir_p(save_path) assert(len(inter_points)==len(file_list)) for f, p in zip(file_list, inter_points): meta = ExifEdit(f) meta.add_lat_lon(p[1], p[2]) meta.add_altitude(p[3]) meta.add_date_time_original(p[0]) meta.add_orientation(1) meta.add_direction(p[4]) meta.write()
bearings = s.interpolate_direction() for filename in s.get_file_list(args.path): stat = os.stat(filename) exifRead = EXIF(filename) mapillaryTag = json.loads(exifRead.extract_image_description()) if args.interpolate: bearing = bearings[filename] else: bearing = exifRead.extract_direction() if args.offset: bearing = offset_bearing(bearing, args.offset) exifEdit = ExifEdit(filename) if args.interpolate or args.offset: exifEdit.add_direction(bearing, precision=10) if (args.backup): if 'backup' not in mapillaryTag: mapillaryTag['backup'] = {} if 'MAPCompassHeading' not in mapillaryTag['backup']: mapillaryTag['backup']['MAPCompassHeading'] = {} mapillaryTag['backup']['MAPCompassHeading'][ 'TrueHeading'] = mapillaryTag['MAPCompassHeading'][ 'TrueHeading'] mapillaryTag['MAPCompassHeading']['TrueHeading'] = round( bearing, 1) if args.orientation is not None: exifEdit.add_orientation(exifOrientation)
try: capture_time = exif.extract_capture_time() except Exception as e: print "Datetime error '{}' for image {}. Skipping".format(e, photo_file) shutil.move(photo_file, os.path.join(failed_folder, os.path.basename(photo_file))) num_exif_error += 1 continue if capture_time == 0: # Use upload time + 12:00:00 instead upload_time = p["upload_date"] + " 12:00:00" capture_time = datetime.datetime.strptime(upload_time, "%d %B %Y %H:%M:%S") print("Image {} missing time stamp. Using update date instead.".format(photo_file)) num_missing_date += 1 exifedit = ExifEdit(photo_file) exifedit.add_lat_lon(p["latitude"], p["longitude"]) exifedit.add_altitude(p.get("altitude", 0)) exifedit.add_date_time_original(capture_time) exifedit.write() valid_files.append(photo_file) # Sequence Cut s = sequence.Sequence(image_path, skip_subfolders=True) sequences = s.split(move_files=False, cutoff_distance=100) sequence_ids = {} for s in sequences: sequence_uuid = str(uuid.uuid4()) for im in s: sequence_ids[im] = sequence_uuid
sys.exit() if path.lower().endswith(".jpg"): # single file file_list = [path] else: # folder(s) file_list = [] for root, sub_folders, files in os.walk(path): file_list += [ os.path.join(root, filename) for filename in files if filename.lower().endswith(".jpg") ] num_file = len(file_list) for i, filepath in enumerate(file_list): exif = EXIF(filepath) description_ = exif.extract_image_description() exif_edit = ExifEdit(filepath) try: description_ = json.loads(description_) except: description_ = {} if 'MAPSettingsProject' not in description_ or overwrite: description_['MAPSettingsProject'] = project_key description_ = {} exif_edit.add_image_description(description_) exif_edit.write() print("Done, processed %s files" % len(file_list))
def test_add_time_original_to_existing_exif(self): test_altitude = 15.5 test_altitude_precision = 100 empty_exifedit = ExifEdit(EMPTY_EXIF_FILE_TEST) empty_exifedit.add_altitude(test_altitude, test_altitude_precision) empty_exifedit.write(EMPTY_EXIF_FILE_TEST) test_datetime = datetime.datetime(2016, 9, 30, 8, 29, 26, 249000) not_empty_exifedit = ExifEdit(EMPTY_EXIF_FILE_TEST) not_empty_exifedit.add_date_time_original(test_datetime) not_empty_exifedit.write(EMPTY_EXIF_FILE_TEST) exif_data = load_exif() self.assertEqual( (test_altitude * test_altitude_precision, test_altitude_precision), exif_data[EXIF_PRIMARY_TAGS_DICT['GPSInfo']][ EXIF_GPS_TAGS_DICT['GPSAltitude']])
def write_metadata(image_lists): """ Write the exif metadata in the jpeg file :param image_lists : A list in list of New_Picture_infos namedtuple """ for image_list in image_lists: for image in image_list: # metadata = pyexiv2.ImageMetadata(image.path) metadata = ExifEdit(image.path) # metadata.read() metadata.add_date_time_original(image.New_DateTimeOriginal) # metadata.add_subsec_time_original(image.New_SubSecTimeOriginal) metadata.add_lat_lon(image.Latitude, image.Longitude) metadata.add_direction(image.ImgDirection) if image.Ele is not None: metadata.add_altitude(image.Ele) metadata.write() print('Writing new timestamp to ', image.path)
photo_file, os.path.join(failed_folder, os.path.basename(photo_file))) num_exif_error += 1 continue if capture_time == 0: # Use upload time + 12:00:00 instead upload_time = p["upload_date"] + " 12:00:00" capture_time = datetime.datetime.strptime( upload_time, "%d %B %Y %H:%M:%S") print( "Image {} missing time stamp. Using update date instead.". format(photo_file)) num_missing_date += 1 exifedit = ExifEdit(photo_file) exifedit.add_lat_lon(p["latitude"], p["longitude"]) exifedit.add_altitude(p.get("altitude", 0)) exifedit.add_date_time_original(capture_time) exifedit.write() valid_files.append(photo_file) # Sequence Cut s = sequence.Sequence(image_path, skip_subfolders=True) sequences = s.split(move_files=False, cutoff_distance=100) sequence_ids = {} for s in sequences: sequence_uuid = str(uuid.uuid4()) for im in s: sequence_ids[im] = sequence_uuid
for filename in s.get_file_list(args.path): stat = os.stat(filename) exifRead = EXIF(filename) mapillaryTag = json.loads(exifRead.tags['Image ImageDescription'].values) # print filename, exifRead.extract_orientation(), mapillaryTag['MAPCameraRotation'] if args.interpolate: bearing = bearings[filename]; else: bearing = exifRead.extract_direction(); if args.offset: bearing = offset_bearing(bearing, args.offset) exifEdit = ExifEdit(filename) if args.interpolate or args.offset: exifEdit.add_direction(bearing, precision=10) if (args.backup): if 'backup' not in mapillaryTag: mapillaryTag['backup'] = {} if 'MAPCompassHeading' not in mapillaryTag['backup']: mapillaryTag['backup']['MAPCompassHeading'] = {} mapillaryTag['backup']['MAPCompassHeading']['TrueHeading'] = mapillaryTag['MAPCompassHeading']['TrueHeading'] mapillaryTag['MAPCompassHeading']['TrueHeading'] = round(bearing, 1) if args.orientation is not None: exifEdit.add_orientation(exifOrientation) if (args.backup and (mapillaryTag['MAPCameraRotation'] != str(args.orientation))): if 'backup' not in mapillaryTag: mapillaryTag['backup'] = {} mapillaryTag['backup']['MAPCameraRotation'] = mapillaryTag['MAPCameraRotation']