Skip to content

AIFrontiersLab/ScanPhoto

Repository files navigation

Photo Selector — Pick best photos with AI

A desktop and command-line app that reads images from a folder, sends them in batches to the OpenAI Vision model to pick the best photos (sharpness, focus, lighting, composition, no duplicates, best aesthetic), then moves the selected photos to a destination folder and can send an SMS when the job is complete.

Contents: User interface · Requirements · Install · Configuration · Usage · Project structure

User interface

The Photo Selector app (Tauri Mac app or browser UI) presents a single screen with:

Element Description
Title Photo Selector — Pick best photos with AI at the top of the window.
OpenAI API Key A required field (masked) for your OpenAI API key. Placeholder: sk-....
Folder with photos (source) Full path to the folder that contains your images. Hint: Full path to the folder containing your images.
Folder for selected photos (destination) Full path where the 20 selected photos will be moved. Hint: Full path where the 20 selected photos will be moved.
Phone number to notify when done Optional. E.g. +15551234567. Hint: Optional. Set Twilio credentials in .env or leave blank.
Run photo selection A single blue button that starts the AI photo selection. While running, a progress line and bar show batch progress and how many photos were selected.
Status / log area A large area below the button that shows status messages, progress (e.g. photos in folder, batches, batch N of M, photos selected), and any errors or logs from the Python script.

After you click Run photo selection, the app scans the source folder, runs the AI in batches, and moves the chosen photos to the destination folder. Use a full path for both folders (e.g. /Users/you/Pictures/Photos).

Requirements

  • Python 3.10+
  • OpenAI API key
  • (Optional) Twilio account for SMS notifications

Install dependencies

From the project folder (e.g. the app folder you copied this into):

# Create a virtual environment (recommended)
python3 -m venv venv
source venv/bin/activate   # On macOS/Linux

# Install packages
pip install -r requirements.txt

Configuration

  1. Copy the sample environment file and add your keys:

    cp .env.example .env
  2. Edit .env and set at least:

    • OPENAI_API_KEY – required for AI selection
    • Optionally: SOURCE_FOLDER (default source folder)
    • Optionally: Twilio variables for SMS (TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_FROM_NUMBER, TWILIO_TO_NUMBER)

Setting the key (Mac / server only):

  • Recommended: Use a .env file (as above). The app loads it automatically; no export needed.
  • Shell (temporary):
    export OPENAI_API_KEY=your_actual_api_key_here
    (No spaces around =, no quotes unless the value contains spaces.)

See .env.example for the full list and format.

Security: API key and iPhone app

Do not put OPENAI_API_KEY inside an iPhone (or any mobile) app. Keys in the app can be extracted from the binary. Use one of these patterns instead:

  1. Backend proxy (recommended for iPhone): Run a small server (e.g. the api_server.py in this repo) on your Mac or a cloud host. Store OPENAI_API_KEY only in that server’s environment or .env. The iPhone app calls your server over HTTPS; the server calls OpenAI with the key. The key never leaves the server.
  2. Mac-only workflow: If the script runs only on your Mac (e.g. from Terminal or Shortcuts), keep the key in .env on the Mac. The iPhone never needs the key.

Usage

Mac app (Tauri — native .app)

You can build a standalone Mac app (.app bundle) with Tauri. The app window has the same form (API key, source path, destination path, phone number) and runs the Python script under the hood.

Requirements: Node.js (npm), Rust (rustup), Python 3 with dependencies installed (pip install -r requirements.txt), and system python3 on your PATH.

# Install Node deps and Tauri CLI
npm install

# Development: opens the app window (uses dev server for frontend)
npm run dev

# Build the Mac .app bundle
npm run build

The built app is in src-tauri/target/release/bundle/macos/Photo Selector.app. You can drag it to Applications and run it like any Mac app. The first time you run the built app, ensure Python 3 is installed and the packages from requirements.txt are available to that Python (e.g. install them in the user environment or in a venv that’s on PATH).

To add or change the app icon, run: npx tauri icon path/to/your/icon.png (creates/updates src-tauri/icons/), then run npm run build again.

If the app icon doesn't update (you still see the old or generic icon):

  1. Use the new build – Run the app from src-tauri/target/release/bundle/macos/Photo Selector.app, or drag that .app into Applications and replace the old one when prompted.
  2. Quit Photo Selector completely (Cmd+Q), then remove it from the Dock (right-click → Options → Remove from Dock).
  3. Refresh macOS icon cache – In Terminal run: killall Dock. If the icon still doesn't change, run: sudo rm -rf /Library/Caches/com.apple.iconservices.store then killall Dock. Open Photo Selector again from the new build and add it back to the Dock.

Mac app (GUI — other options)

Option A — Browser UI (no extra install)
Works with any Python that has Flask (already in requirements):

source venv/bin/activate
python main_web.py

Then open http://127.0.0.1:5000 in your browser. Enter API key, source folder path, destination folder path, and optional phone number, then click Run photo selection.

Option B — Desktop window (Tkinter)
If your Python has Tkinter (e.g. python.org installer), you can run:

python main_gui.py

If you get ModuleNotFoundError: No module named '_tkinter' (common with Homebrew Python), either install Tk with brew install [email protected] (match your Python version) or use the browser UI above.

In either UI you can set:

  1. OpenAI API key (required)
  2. Folder with photos (source path)
  3. Folder for selected photos (destination path)
  4. Phone number for “job complete” SMS (optional; Twilio credentials in .env for SMS)

Command line

# Use default source folder (from config / SOURCE_FOLDER env)
python main.py

# Or specify folder path
python main.py /path/to/your/photos

The script will:

  1. Read images from the given folder
  2. Send them to the OpenAI Vision model in batches of 10
  3. Ask the AI to return only the best photo filenames in JSON: {"selected": ["IMG_1234.jpg", ...]}
  4. Append those filenames to selected_photos.txt in the same folder
  5. Move selected photos into a subfolder named Selected
  6. Send an SMS when the job is complete (if Twilio is configured)

Example prompt sent to OpenAI

The app sends a prompt like this (plus the images):

You are a professional photo curator. Look at the images provided.

For each image you receive, consider:
- Sharpness: Is the image sharp and clear (not blurry)?
- Focus: Is the subject in focus?
- Lighting: Is the lighting flattering and well-balanced?
- Composition: Is the framing and composition strong (rule of thirds, balance, no cut-off subjects)?
- No duplicates: If two images are nearly identical, pick only the better one.
- Best overall aesthetic: Which images would you keep in a final album?

Your task: From the images in this batch, select ONLY the best photos. Return the filenames of selected photos only.

You MUST respond with valid JSON only, no other text. Use this exact format:
{
  "selected": ["filename1.jpg", "filename2.jpg"]
}
...
Return ONLY the JSON object. No markdown, no explanation, no code block.

Project structure

  • main.py – Entry point; runs the full workflow
  • ai_selector.py – Calls OpenAI Vision and returns selected filenames (JSON)
  • file_handler.pyget_images, batch_images, move_selected_images, append to selected_photos.txt
  • notifier.pysend_sms via Twilio (env-based)
  • config.py – Paths, batch size, model name
  • requirements.txt – Dependencies
  • .env.example – Sample environment variables
  • api_server.py – Optional backend for iPhone app (keeps API key on server)
  • main_gui.py – Desktop GUI (requires Tkinter)
  • main_web.py – Browser GUI (no Tkinter; run then open http://127.0.0.1:5000)
  • Tauri apppackage.json, index.html, src/main.js, vite.config.js, src-tauri/ (Rust + config). Run npm run dev or npm run build for a native Mac .app.

Using from an iPhone app (backend API)

To call the photo-selection logic from an iPhone app without embedding the API key:

  1. On your Mac (or a server), set OPENAI_API_KEY in .env or the environment.
  2. Start the API server:
    python api_server.py
  3. From the iPhone app, send POST /select with a JSON body: {"images": [{"filename": "a.jpg", "base64": "<base64 data>"}, ...]}.
    Response: {"selected": ["a.jpg", ...]}.

The API key stays on the machine running api_server.py; the iPhone app never sees it.

Notes

  • Uses pathlib for paths and shutil for moving files.
  • API calls use retry logic (see config.OPENAI_MAX_RETRIES).
  • If Twilio is not configured, the app still runs and only skips the SMS.
  • Supported image extensions: .jpg, .jpeg, .png, .gif, .webp, .heic, .bmp, .tiff, .tif.

About

PhotoSelector based on the image

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors