A comprehensive Python application for viewing and editing EXIF/IPTC/XMP metadata of images in a directory, with advanced geotagging capabilities and reverse geocoding.
Note
This application is a tribute to GeoSetter (https://geosetter.de/en/main-en/) and is not affiliated with or endorsed by the original GeoSetter project.
This is a light clone, written in Python, focusing on core geotagging features with additional AI-powered functionalities. The triggering reason was the lack of a macOS version of GeoSetter along with the desire to experiment with AI models for photo processing.
- Image List View: Display all JPEG, PNG, and HEIF/HEIC images from a directory with comprehensive metadata columns
- Image Viewer: View selected images in a resizable panel with thumbnail support
- Interactive Map: Display all images with GPS coordinates on an OpenStreetMap with visual distinction for selected images
- Active Marker: Click anywhere on the map to set an active marker for batch GPS updates
- GPS Coordinate Management: Update multiple images with GPS coordinates from the active marker
- 3-Pane Resizable Layout: Image list (top-left), image viewer (bottom-left), and map with toolbar (right)
- Metadata Editor: Edit EXIF/IPTC/XMP metadata for single or multiple images with namespace display
- Batch Operations: Apply metadata changes to multiple images at once
- Inline Editing: Edit metadata directly in the table with specialized editors for different field types
- File Renaming: Pattern-based batch file renaming with metadata tokens and counters
- Reverse Geocoding: Automatically determine country and city from GPS coordinates using OpenStreetMap Nominatim API
- Smart Country Picker: Searchable dropdown with 195+ countries using 3-letter ISO codes (ISO 3166-1 alpha-3)
- Timezone Management: Automatic timezone offset calculation with DST support
- Date/Time Management: Comprehensive date handling with Taken Date, Created Date, and GPS Date (UTC)
- Keywords Auto-Update: Automatically add country code and country name to keywords
- Metadata Repair: Fix/repair corrupted metadata with ExifTool's repair function
- Photo Similarity Detection: Find duplicate or similar photos using ResNet-based deep learning
- Configurable similarity threshold (0.0-1.0)
- Groups similar photos with similarity scores
- Batch deletion of similar photos
- Runs locally with lightweight models
- Geolocation Prediction: Predict GPS coordinates for photos without location data
- Uses CLIP-based vision-language model
- SQLite database with 1000+ world locations (cities, landmarks, natural features)
- Location data loaded from
data/world_locations.csv(easy to update/extend) - Provides top 5 location predictions with confidence scores
- Automatic reverse geocoding for predicted locations
- Batch GPS coordinate updates
- Runs entirely offline after initial model download
- Database auto-initializes on first run from CSV file
- To rebuild database: delete
locations.dband restart app - To add locations: edit
world_locations.csvdirectly
3-pane layout with image list, image viewer, and interactive map
Edit EXIF/IPTC/XMP metadata with filtering and tag management
Find and manage duplicate or similar photos
Predict GPS coordinates for photos without location data
- Python 3.12.9 or higher
- ExifTool installed on your system
macOS:
brew install exiftoolLinux (Debian/Ubuntu):
sudo apt-get install libimage-exiftool-perlWindows: Download from https://exiftool.org
- Install dependencies using uv (recommended) or pip:
# Using uv
uv sync
# Or using pip
pip install -e .Simply run the application without arguments to open a file picker:
uv run python main.pyProvide a path to an image file:
uv run python main.py /path/to/your/image.jpgThe application will display all images in the same directory as the provided file.
The application features a flexible 3-pane layout with resizable borders:
-
Top-Left Panel: Table showing all images with the following columns:
- Filename (read-only, resizable) - Use File β Rename Photos for batch renaming
- Taken Date (editable) - EXIF:DateTimeOriginal, XMP-exif:DateTimeOriginal
- TZ Offset (editable) - Timezone offset with DST support (e.g., "+05:00")
- GPS Coordinates (display only) - Latitude and Longitude
- City (editable) - IPTC:City, XMP-photoshop:City
- Sublocation (editable) - IPTC:Sub-location, XMP-iptcCore:Location
- Headline (editable) - IPTC:Headline, XMP-photoshop:Headline
- Camera Model (editable) - EXIF:Model
- Size (read-only) - File size in KB/MB
- GPS Date (editable, UTC) - EXIF:GPSDateStamp + GPSTimeStamp
- Country (dropdown picker) - 3-letter ISO code with searchable country list
- Keywords (editable) - Semicolon-separated display, auto-includes country info
- Created Date (editable) - EXIF:CreateDate, XMP-exif:DateTimeDigitized (auto-set from Taken Date)
-
Bottom-Left Panel: Image viewer showing the first selected image
-
Right Panel: Interactive OpenStreetMap with toolbar displaying:
- All Images: Gray markers for all images with GPS coordinates
- Selected Images: Blue markers for currently selected images
- Active Marker: Red marker set by clicking on the map
- Marker Tooltips: Click markers to see image thumbnails and filenames
- Toolbar Icons (left to right):
- Update GPS (red pin β images): Update selected images with active marker coordinates
- Set Marker (image β red pin): Set active marker from selected image GPS coordinates
- ππ Reverse Geocoding (toggle): Auto-determine country and city from GPS coordinates
- Set Taken Date (file β calendar): Initialize Taken Date from file creation date
- Set GPS Date (calendar β GPS): Initialize GPS Date from Taken Date (converted to UTC)
- Repair Metadata (medical cross): Fix/repair metadata using ExifTool
- Leaflet-based map with OpenStreetMap tiles
- Scale control
- Automatic zoom and centering based on markers
- Smart bounds fitting for multiple markers
All three panes can be resized by dragging the borders between them.
Image List:
- Left Click: Select an image to view it in the bottom-left panel. Selected images are highlighted in blue on the map
- Multi-Select: Use Ctrl/Cmd + Click or Shift + Click to select multiple images. The first image will be displayed in the viewer
- Right Click: Open context menu with:
- "Edit Metadata" - Opens full metadata editor dialog (works for single or multiple selections)
- "Quick Edit (Basic Fields)" - Opens simplified batch editor for common fields (only appears when 2+ images selected)
- Double-Click Cell:
- Filename cell: Opens Edit Metadata dialog
- other cells: Edit metadata directly in the table (country uses dropdown picker, dates use date picker)
- Delete/Backspace: Clear cell values (deletes corresponding metadata tags)
- Rename Files: Use File β Rename Photos for pattern-based batch renaming
Map:
- Click on Map: Set an active marker (red) at the clicked location. Map viewport (center and zoom) is preserved - no auto-fitting occurs
- Click on Marker: View popup with image thumbnail and filename
- Select Image: Centers map on selected image's marker, preserving current zoom level
- Deselect All: Fits map bounds to show all markers
AI Tools Menu:
- Find Similar Photos: Analyze all loaded images to find similar/duplicate photos
- Progress dialog shows AI processing status
- Results dialog displays groups of similar photos with thumbnails
- Select photos for deletion with checkboxes
- Batch delete similar photos with confirmation
- Predict Locations: Predict GPS coordinates for images without location data
- Only processes images without GPS coordinates
- Shows top 5 predictions per image with confidence scores
- Displays location names via reverse geocoding
- Select which predictions to apply
- Batch GPS coordinate updates
- Settings: Configure AI feature parameters
- Similarity threshold slider (0.0-1.0)
- Model cache directory selection
- Reset to defaults option
Panes:
- Resize Panes: Drag the borders between panes to adjust their sizes
The metadata editor allows you to:
- View all EXIF/IPTC/XMP tags from the selected image(s) with namespace prefixes (e.g., XMP-iptcCore, XMP-photoshop)
- Edit existing metadata values
- Delete tags by selecting them and pressing Delete/Backspace or using right-click context menu
- Add new EXIF/IPTC/XMP tags using the "Add New Tag" button
- Apply changes to all selected images
When editing multiple images:
- The editor shows metadata from the first selected image
- Changes are applied to all selected images
- Empty values will not overwrite existing metadata
The application handles multiple date fields with timezone awareness:
- Taken Date: When the photo was taken (local time at destination)
- Created Date: Auto-set from Taken Date if not present
- GPS Date: Always stored and displayed in UTC
- TZ Offset: Timezone offset with automatic DST handling
Timezone Offset Behavior:
- Select timezone from picker (shows zone ID, offset, and cities)
- Automatically calculates correct offset based on Taken Date (handles DST)
- Updates XMP date tags with timezone offset (e.g., "2024:11:26 10:30:00+05:00")
- Recalculates GPS Date to UTC when offset changes
Keywords are automatically managed:
- Storage Format: Asterisk-separated (
*) in IPTC:Keywords and XMP-dc:Subject - Display Format: Semicolon-separated (
;) in table - Auto-Update: When country is set, country code and country name are automatically added
- Preservation: Existing keywords are preserved when adding country information
geotag/
βββ main.py # Application entry point
βββ data/ # Data files
β βββ world_locations.csv # World locations database (1000+ locations)
βββ geosetter_lite/ # Main package
βββ ui/ # User interface components
β βββ main_window.py # Main application window (3-pane layout)
β βββ map_panel.py # Map panel with toolbar and icons
β βββ map_widget.py # Map widget with Leaflet/OpenStreetMap
β βββ metadata_editor.py # Metadata editor dialog with tag deletion and filtering
β βββ batch_edit_dialog.py # Batch metadata editing dialog
β βββ geocoding_dialog.py # Reverse geocoding results dialog
β βββ geolocation_dialog.py # Geolocation prediction results dialog
β βββ similarity_dialog.py # Similar photos results dialog
β βββ settings_dialog.py # AI settings configuration dialog
β βββ progress_dialog.py # Progress dialog for long-running operations
β βββ rename_dialog.py # Pattern-based batch file renaming dialog
β βββ table_delegates.py # Custom cell editors (country, date, timezone)
βββ services/ # External service integrations
β βββ exiftool_service.py # ExifTool wrapper with backup management
β βββ reverse_geocoding_service.py # Nominatim API integration
β βββ ai_service.py # AI services (similarity detection, geolocation prediction)
β βββ file_scanner.py # Directory scanner with auto-initialization
β βββ location_database.py # SQLite database for world locations
βββ models/ # Data models
β βββ image_model.py # Image data model with metadata fields
βββ core/ # Core utilities
βββ config.py # Configuration management for AI settings
βββ utils.py # Utility functions (formatting, etc.)
- PySide6: Qt-based GUI framework (includes QtWebEngineWidgets for map display)
- Pillow: Image loading, manipulation, and thumbnail generation
- requests: HTTP library for reverse geocoding API calls
External Requirements:
- ExifTool: Must be installed on your system for reading/writing EXIF/IPTC/XMP metadata
External APIs:
- OpenStreetMap Nominatim: Free reverse geocoding service (no API key required)
The application writes to multiple metadata standards for maximum compatibility:
| Category | Field | Metadata Tags | Notes |
|---|---|---|---|
| Location | Country | XMP-photoshop:CountryIPTC:Country-PrimaryLocationName |
Country name |
| Location | Country Code | XMP-iptcCore:CountryCodeIPTC:Country-PrimaryLocationCode |
3-letter ISO 3166-1 alpha-3 |
| Location | City | XMP-photoshop:CityIPTC:City |
City name |
| Location | Sublocation | XMP-iptcCore:LocationIPTC:Sub-location |
Specific location within city |
| GPS | Coordinates | EXIF:GPSLatitudeEXIF:GPSLongitude |
Decimal degrees |
| GPS | GPS Date/Time | EXIF:GPSDateStampEXIF:GPSTimeStampXMP-exif:GPSDateTime |
UTC time |
| GPS | GPS DateTime (Composite) | Composite:GPSDateTime |
Read-only, calculated by ExifTool |
| Date/Time | Taken Date | EXIF:DateTimeOriginalXMP-exif:DateTimeOriginal |
With timezone offset |
| Date/Time | Created Date | EXIF:CreateDateXMP-exif:DateTimeDigitized |
With timezone offset |
| Date/Time | Timezone Offset | EXIF:TimeZoneOffsetEXIF:OffsetTimeEXIF:OffsetTimeOriginalEXIF:OffsetTimeDigitized |
Decimal hours or "+HH:MM" format |
| Other | Headline | IPTC:HeadlineXMP-photoshop:Headline |
Image headline/title |
| Other | Keywords | IPTC:KeywordsXMP-dc:Subject |
Asterisk-separated |
| Other | Camera Model | EXIF:Model |
Camera make/model |
- ExifTool creates backup files with
_originalsuffix by default - Backup files are automatically renamed when you rename the original file
- Original file creation dates are preserved; only modification dates change
- Always set Taken Date first, then set TZ Offset
- TZ Offset automatically handles Daylight Saving Time based on Taken Date
- GPS Date is automatically recalculated to UTC when TZ Offset changes
- Keywords automatically include country code and country name when country is set
- Use semicolons (
;) when editing keywords in the table - Keywords are stored with asterisks (
*) in metadata for compatibility
- Enable reverse geocoding (ππ) before updating GPS coordinates
- Review and edit the suggested country/city before applying
- Uses OpenStreetMap Nominatim API (respects usage policy with proper User-Agent)
- Has 10-second timeout to prevent hanging
- Select multiple images to apply changes to all at once
- Use Ctrl/Cmd+Click for non-contiguous selection
- Use Shift+Click for range selection
- Edit Metadata: Full metadata editor works with multiple images - changes apply to all selected
- Quick Edit: Right-click menu option for batch editing of common fields (TZ Offset, Country, City, Headline) when 2+ images are selected
- Empty values won't overwrite existing metadata
- First Use: Models will be downloaded automatically on first use (~1.2GB total)
- Model Storage: Models are cached in
~/.cache/geosetter_liteby default (configurable in settings) - Location Database:
- Source data:
data/world_locations.csv(1000+ locations in CSV format) - SQLite database:
~/.cache/geosetter_lite/locations.db(auto-created from CSV) - To add locations: Edit
world_locations.csvdirectly (can use Excel, Google Sheets, or text editor) - To rebuild database: Delete
locations.dband restart the app - Includes major cities, landmarks, natural features across all continents
- CSV format:
latitude,longitude,description,country,city,category
- Source data:
- Memory Usage: AI features use less than 4GB of RAM
- Offline Operation: After initial download, all AI features work offline
- Similarity Threshold: Start with 0.85 (85%) and adjust based on results
- Higher values (0.90-0.95): Only very similar photos
- Lower values (0.70-0.80): More groups, less strict matching
- Geolocation Accuracy: Predictions work best for photos with:
- Recognizable landmarks or architecture
- Distinct geographic features (mountains, coastlines, etc.)
- Urban scenes with visible signs or buildings
- May not work well for abstract or indoor photos
Build a distributable package of the application:
make packageThis will create the following types of packages in the dist/ directory:
- Python wheel
- macOS App Bundle (via PyInstaller)
The wheel includes:
- All source code from the
geosetter_litepackage - Data files from the
data/directory (world_locations.csv) - Entry point script:
geosetter-lite
The app bundle includes:
- All Python dependencies (PySide6, PyTorch, etc.)
- Data files (world_locations.csv)
- Self-contained Python runtime
# Install the wheel
pip install dist/geosetter_lite-<VERSION>-py3-none-any.whl
# Run the application
geosetter-lite /path/to/image.jpgRun directly: Double-click dist/GeoSetter Lite.app
Customizing the build: Edit geosetter_lite.spec to:
- Include additional data files
- Configure hidden imports
- Adjust bundle settings
Note: The app requires ExifTool to be installed separately on the system:
brew install exiftoolThis project is licensed under the Apache License 2.0.
This project uses the following third-party libraries:
- PySide6 (LGPL v3): Qt for Python - dynamically linked as a dependency
- Pillow (HPND License): Python Imaging Library
- requests (Apache 2.0): HTTP library
- PyYAML (MIT License): YAML parser and emitter
- PyTorch (BSD-style License): Deep learning framework
- torchvision (BSD License): Computer vision models and utilities
- transformers (Apache 2.0): Hugging Face transformers library
- Leaflet (BSD 2-Clause): JavaScript library for interactive maps (loaded from CDN)
- OpenStreetMap (ODbL): Map tiles and data
- Nominatim (GPL v2): Reverse geocoding service (used as web service, not linked)
The use of PySide6 under LGPL v3 is compatible with Apache 2.0 licensing as long as PySide6 remains dynamically linked (installed as a separate package), which is the case in this project.
- ExifTool by Phil Harvey - Comprehensive metadata reading/writing tool
- OpenStreetMap Contributors - Map data and tiles
- Nominatim - Reverse geocoding service
- Leaflet - Interactive map library
- PyTorch - Deep learning framework
- Hugging Face - Pre-trained models (ResNet, CLIP)
- OpenAI - CLIP model architecture
