def interpolate_with_anchors(anchors, angle_offset): ''' Interpolate gps position and compass angle given a list of anchors anchor: lat: latitude lon: longitude alt: altitude datetime: date time of the anchor (datetime object) num_image: number of images in between two anchors ''' points = [ (a['datetime'], a['lat'], a['lon'], a.get('alt', 0)) for a in anchors] inter_points = [] for i, (a1, a2) in enumerate(zip(points[:], points[1:])): t1 = a1[0] t2 = a2[0] num_image = anchors[i]['num_image'] delta = (t2-t1).total_seconds()/float(num_image+1) inter_points.append(points[i]+(0.0,)) for ii in xrange(num_image): t = t1 + datetime.timedelta(seconds=(ii+1)*delta) p = interpolate_lat_lon(points, t) inter_points.append((t,)+p) inter_points.append(points[-1]+(0,0,)) # get angles bearings = [offset_bearing(compute_bearing(ll1[1], ll1[2], ll2[1], ll2[2]), angle_offset) for ll1, ll2 in zip(inter_points, inter_points[1:])] bearings.append(bearings[-1]) inter_points = [ (p[0], p[1], p[2], p[4], bearing) for p, bearing in zip(inter_points, bearings)] return inter_points
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 add_exif_using_timestamp(filename, time, points, offset_time=0, offset_angle=0): ''' Find lat, lon and bearing of filename and write to EXIF. ''' metadata = pyexiv2.ImageMetadata(filename) metadata.read() # subtract offset in s beween gpx time and exif time t = time - datetime.timedelta(seconds=offset_time) try: lat, lon, bearing, elevation, speed = interpolate_lat_lon(points, t) lat_deg = decimal_to_dms(lat, ["S", "N"]) lon_deg = decimal_to_dms(lon, ["W", "E"]) # convert decimal coordinates into degrees, minutes and seconds as fractions for EXIF exiv_lat = (make_fraction(lat_deg[0], 1), make_fraction(int(lat_deg[1]), 1), make_fraction(int(lat_deg[2] * 1000000), 1000000)) exiv_lon = (make_fraction(lon_deg[0], 1), make_fraction(int(lon_deg[1]), 1), make_fraction(int(lon_deg[2] * 1000000), 1000000)) # convert direction into fraction bearing = offset_bearing(bearing, offset_angle) exiv_bearing = make_fraction(int(bearing * 100), 100) # add to exif metadata["Exif.GPSInfo.GPSLatitude"] = exiv_lat metadata["Exif.GPSInfo.GPSLatitudeRef"] = lat_deg[3] metadata["Exif.GPSInfo.GPSLongitude"] = exiv_lon metadata["Exif.GPSInfo.GPSLongitudeRef"] = lon_deg[3] metadata["Exif.Image.GPSTag"] = 654 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" if elevation is not None: exiv_elevation = make_fraction(abs(int(elevation * 10)), 10) metadata["Exif.GPSInfo.GPSAltitude"] = exiv_elevation metadata[ "Exif.GPSInfo.GPSAltitudeRef"] = '0' if elevation >= 0 else '1' metadata.write() print("Added geodata to {}: {}, {:.6f}, {:.6f}, {:.1f}".format( os.path.basename(filename), time, lat, lon, bearing)) if (speed is not None and speed < 0.6): move_into_dir(filename, os.path.dirname(filename) + "\S0") except ValueError, e: print("Skipping {0}: {1}".format(filename, e))
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 = pyexiv2.ImageMetadata(filename) metadata.read() print(time) print(datetime.timedelta(seconds=offset_time)) #print(points) # 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) lat_deg = decimal_to_dms(lat, ["S", "N"]) lon_deg = decimal_to_dms(lon, ["W", "E"]) # convert decimal coordinates into degrees, minutes and seconds as fractions for EXIF exiv_lat = (make_fraction(lat_deg[0],1), make_fraction(int(lat_deg[1]),1), make_fraction(int(lat_deg[2]*1000000),1000000)) exiv_lon = (make_fraction(lon_deg[0],1), make_fraction(int(lon_deg[1]),1), make_fraction(int(lon_deg[2]*1000000),1000000)) corrected_bearing = (bearing + offset_bearing) % 360 # convert direction into fraction exiv_bearing = make_fraction(int(corrected_bearing*100),100) # add to exif metadata["Exif.GPSInfo.GPSLatitude"] = exiv_lat metadata["Exif.GPSInfo.GPSLatitudeRef"] = lat_deg[3] metadata["Exif.GPSInfo.GPSLongitude"] = exiv_lon metadata["Exif.GPSInfo.GPSLongitudeRef"] = lon_deg[3] metadata["Exif.Image.GPSTag"] = 654 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" if elevation is not None: exiv_elevation = make_fraction(abs(int(elevation*10)),10) metadata["Exif.GPSInfo.GPSAltitude"] = exiv_elevation metadata["Exif.GPSInfo.GPSAltitudeRef"] = '0' if elevation >= 0 else '1' 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 geotag_from_gpx(piclists, gpx_file, offset_time=0, offset_bearings=0, offset_distance=0): """This function will try to find the location (lat lon) for each pictures in each list, compute the direction of the pictures with an offset if given, and offset the location with a distance if given. Then, these coordinates will be added in the New_Picture_infos namedtuple. :param piclists: a list of of list of New_Picture_infos namedtuple :param gpx_file: a gpx or nmea file path :param offset_time: time offset between the gpx/nmea file, and the image's timestamp :param offset_bearings: the offset angle to add to the direction of the images (for side camera) :param offset_distance: a distance (in meter) to move the image from the computed location. (Use this setting to not have all the images from a multicam setup at the same exact location :return: nothing, the function update the New_Picture_infos namedtuple inside the lists""" now = datetime.datetime.now(tzlocal()) print("Your local timezone is {0}, if this is not correct, your geotags will be wrong.".format( now.strftime('%Y-%m-%d %H:%M:%S %z'))) # read gpx file to get track locations if gpx_file.lower().endswith(".gpx"): gpx = get_lat_lon_time_from_gpx(gpx_file) elif gpx_file.lower().endswith(".nmea"): gpx = get_lat_lon_time_from_nmea(gpx_file) else: print("\nWrong gnss file! It should be a .gpx or .nmea file.") sys.exit() for piclist, offset_bearing in zip(piclists, offset_bearings): start_time = time.time() print("===\nStarting geotagging of {0} images using {1}.\n===".format(len(piclist), gpx_file)) # for filepath, filetime in zip(piclist.path, piclist.New_DateTimeOriginal): for i, pic in enumerate(piclist): # add_exif_using_timestamp(filepath, filetime, gpx, time_offset, bearing_offset) # metadata = ExifEdit(filename) t = pic.New_DateTimeOriginal - datetime.timedelta(seconds=offset_time) try: lat, lon, bearing, elevation = interpolate_lat_lon(gpx, t) corrected_bearing = (bearing + offset_bearing) % 360 # Apply offset to the coordinates if distance_offset exists if offset_distance != 0: new_Coords = LatLon(lat, lon).offset(corrected_bearing, offset_distance / 1000) lat = new_Coords.lat.decimal_degree lon = new_Coords.lon.decimal_degree # Add coordinates, elevation and bearing to the New_Picture_infos namedtuple piclist[i] = pic._replace(Longitude=lon, Latitude=lat, Ele=elevation, ImgDirection=corrected_bearing) except ValueError, e: print("Skipping {0}: {1}".format(pic.path, e)) print("Done geotagging {0} images in {1:.1f} seconds.".format(len(piclist), time.time() - start_time))
sample_video(video_file, image_path, sample_interval, video_type) # Add EXIF data to sample images image_list = list_images(image_path) print "Adding EXIF to {} images".format(len(image_list)) missing_gps = 0 for i, im in enumerate(image_list): io.progress(i, len(image_list)) timestamp = timestamp_from_filename(os.path.basename(im), sample_interval, start_time, video_duration, time_offset, duration_ratio) try: lat, lon, bearing, altitude = geo.interpolate_lat_lon( points, timestamp) data = { "lat": lat, "lon": lon, "altitude": altitude, "capture_time": timestamp, "bearing": (bearing + args.offset_angle) % 360, "make": make, "model": model } exifedit.add_exif_data(os.path.join(image_path, im), data) except Exception as e: print "Image {} timestamp out of range. Skipping".format(im) missing_gps += 1 print "{} image samples with {} images missing gps".format(
# Add EXIF data to sample images image_list = list_images(image_path) print "Adding EXIF to {} images".format(len(image_list)) missing_gps = 0 for i, im in enumerate(image_list): io.progress(i, len(image_list)) timestamp = timestamp_from_filename(os.path.basename(im), sample_interval, start_time, video_duration, time_offset) try: lat, lon, bearing, altitude = geo.interpolate_lat_lon(points, timestamp) data = { "lat": lat, "lon": lon, "altitude": altitude, "capture_time": timestamp, "bearing": bearing, "make": make, "model": model } exifedit.add_exif_data(os.path.join(image_path, im), data) except Exception as e: print e print "Image {} timestamp out of range. Skipping".format(im) missing_gps += 1