Spaces:
Sleeping
Sleeping
import streamlit as st | |
from PIL import Image | |
import exifread | |
from geopy.geocoders import Nominatim | |
import io | |
import datetime | |
def get_exif_data(image_bytes): | |
try: | |
tags = exifread.process_file(image_bytes) | |
gps_latitude = tags.get('GPS GPSLatitude') | |
gps_latitude_ref = tags.get('GPS GPSLatitudeRef') | |
gps_longitude = tags.get('GPS GPSLongitude') | |
gps_longitude_ref = tags.get('GPS GPSLongitudeRef') | |
timestamp = tags.get('EXIF DateTimeOriginal') | |
return tags, gps_latitude, gps_longitude, timestamp, gps_latitude_ref, gps_longitude_ref | |
except Exception as e: | |
st.error(f"Error processing image: {e}") | |
return None, None, None, None, None, None | |
def convert_to_degrees(value, ref): | |
try: | |
if isinstance(value, exifread.classes.IfdTag): | |
values = value.values # Extract the tuple (degrees, minutes, seconds) | |
d = float(values[0].num) / float(values[0].den) | |
m = float(values[1].num) / float(values[1].den) | |
s = float(values[2].num) / float(values[2].den) | |
degrees = d + (m / 60.0) + (s / 3600.0) | |
if ref in ['S', 'W']: | |
degrees = -degrees | |
return degrees | |
return None | |
except Exception as e: | |
st.error(f"Error converting GPS data: {e}") | |
return None | |
def get_location(lat, lon): | |
try: | |
geolocator = Nominatim(user_agent="photo_app") | |
location = geolocator.reverse((lat, lon)) | |
return location.address | |
except Exception as e: | |
st.error(f"Error getting location: {e}") | |
return "Location not found" | |
st.title("πΈ Photo Inspection App") | |
# β **User Instructions for GPS & Location Services** | |
st.markdown(""" | |
### πΉ **Before You Start: Enable Location for Accurate GPS Data** | |
To ensure your photos contain GPS location data, please: | |
1. **Enable "Location Tags" in your Camera settings** (on Android, iPhone, or DSLR). | |
2. **Turn on "Location Services" in your device settings**. | |
3. Ensure your device **has GPS access while taking the photo**. | |
4. Take a new photo **outdoors** for better GPS accuracy. | |
If your image doesn't contain GPS data, the location will **not** be displayed. | |
""") | |
option = st.selectbox("Choose an option", ("Take a photo", "Upload a photo")) | |
if option == "Take a photo": | |
uploaded_file = st.camera_input("Take a photo") | |
else: | |
uploaded_file = st.file_uploader("Upload a photo", type=["jpg", "jpeg", "png"]) | |
if uploaded_file is not None: | |
try: | |
image = Image.open(uploaded_file) | |
img_bytes = io.BytesIO(uploaded_file.getvalue()) | |
tags, gps_latitude, gps_longitude, timestamp, gps_latitude_ref, gps_longitude_ref = get_exif_data(img_bytes) | |
if gps_latitude and gps_longitude and timestamp and gps_latitude_ref and gps_longitude_ref: | |
lat = convert_to_degrees(gps_latitude, gps_latitude_ref) | |
lon = convert_to_degrees(gps_longitude, gps_longitude_ref) | |
st.write(f"**π Latitude:** {lat}") | |
st.write(f"**π Longitude:** {lon}") | |
try: | |
timestamp_str = timestamp.printable # Convert IfdTag to string | |
date_time_obj = datetime.datetime.strptime(timestamp_str, '%Y:%m:%d %H:%M:%S') | |
# β **No timezone conversion needed, just reformat the date & time** | |
formatted_date = date_time_obj.strftime("%m-%d-%Y") # MM-DD-YYYY | |
formatted_time = date_time_obj.strftime("%I:%M:%S %p") # 12-hour format with AM/PM | |
st.write(f"**π Date Taken:** {formatted_date}") | |
st.write(f"**β° Time Taken:** {formatted_time}") | |
except ValueError: | |
st.write(f"**Timestamp:** {timestamp} (Could not format - Check format)") | |
st.write("**Date Taken:** Unknown") | |
st.write("**Time Taken:** Unknown") | |
address = get_location(lat, lon) | |
st.write(f"**π Location:** {address}") | |
google_maps_url = f"https://www.google.com/maps/place/{lat},{lon}" | |
st.markdown(f"[π View on Google Maps]({google_maps_url})") | |
else: | |
st.warning("β οΈ **No GPS data found!** Make sure location tagging is enabled on your camera.") | |
except Exception as e: | |
st.error(f"An error occurred: {e}") | |