Skip to content

Repository files navigation

🧠 ImageAnalyzerAI by UgurkanTech

ImageAnalyzerAI is a high-performance desktop application that leverages local multimodal AI models to generate rich image descriptions and semantic embeddings. Designed for power users and researchers, it supports fast batch processing, semantic search, and database-backed storage — all wrapped in a sleek PyQt5 GUI.

Visitors

▶️ Demo

Analyze and search images locally using AI-powered descriptions and semantic embeddings — perfect for organizing memes, emotes, or any large image collection.

Demo preview

🚀 Features

  • Any OpenAI-compatible Server: Talks to the standard /v1 API, so it works with Ollama, llama.cpp, llama-swap, vLLM, and LM Studio using models like LLaVA, Qwen-VL, Moondream, Nomic, and BGE.
  • Adjustable Concurrency: Choose how many captioning requests run at once (1–256) to match what your server can batch. Embedding requests are pooled separately.
  • Hybrid Search: Fuses semantic (embedding) and full-text (FTS5) ranking, so both "guy looking at another woman" and "distracted_boyfriend" find the same image.
  • Database Management: One SQLite file per model pair holding images, descriptions, and embeddings together.
  • Dark Mode UI: Built with PyQt5 and styled for low-light environments.
  • Clipboard Support: Copy image previews directly from the search results.
  • Model Detection: Automatically sorts the server's model list into vision and embedding dropdowns by name.

🖥️ UI Overview

Panel Description
Left Panel Directory selection, server address, model dropdowns, processing controls
Right Panel Search interface with image previews, descriptions, and timestamps
Tabs Switch between database preview and search views

🛠️ Requirements

To run ImageAnalyzerAI, make sure the following are installed and properly configured:

  • Python 3.9+ — Recommended for compatibility with PyQt5 and multithreading.
  • An OpenAI-compatible server exposing /v1/models, /v1/chat/completions, and /v1/embeddings, serving at least one vision model and one embedding model. Tested shapes include Ollama, llama.cpp's llama-server, llama-swap, vLLM, and LM Studio.
  • Python packages:
    • PyQt5 — For the graphical user interface.
    • NumPy — For handling embedding vectors and similarity calculations.
    • Requests — For communicating with the /v1 API.

Install all required packages using: pip install -r requirements.txt

Choosing a server

The app defaults to http://localhost:11434/v1, which is Ollama's port. To point it anywhere else, set the IMAGE_ANALYZER_BASE_URL environment variable before launching:

# llama.cpp / llama-swap
set IMAGE_ANALYZER_BASE_URL=http://localhost:8080/v1
# vLLM
set IMAGE_ANALYZER_BASE_URL=http://localhost:8000/v1
# LM Studio
set IMAGE_ANALYZER_BASE_URL=http://localhost:1234/v1

The /v1 suffix is optional — it is appended automatically if you leave it off.

Because /v1/models reports only model ids, the vision and embedding dropdowns are filled by matching names against keyword lists (llava, -vl, moondream, embed, bge, nomic, and so on). Models whose names carry no such hint will not appear in either dropdown.

A PyInstaller build script is included to generate a compact standalone .exe for portable distribution without requiring Python on the target system.

📂 Usage

  1. Start your inference server and ensure that at least one vision model and one embedding model are available.
    These models are required for generating image descriptions and semantic embeddings. With Ollama you can pull them using ollama pull <model-name>; with llama.cpp, llama-swap, or vLLM they are whatever your server is configured to serve.

  2. Launch the application by running python main.py.

  3. First Run:

    • Select a directory containing images.
    • Choose a vision model and an embedding model from the dropdowns. Both list every model your server reports — /v1/models does not say what a model can do, so nothing is filtered out and the choice is yours.
    • Click Process to generate image descriptions and semantic embeddings.
    • These results are saved locally in a database and embedding file for future use.
  4. Subsequent Runs:

    • Previously processed data is automatically loaded.
    • You can immediately perform semantic or keyword-based searches without reprocessing.
    • Reprocessing is only needed if you change models or add new images to the directory.

📦 Portable Build

A PyInstaller build script is included to generate a compact standalone .exe version of the application.
This allows ImageAnalyzerAI to run as a portable app without requiring Python or external dependencies on the target system.

  • The build is optimized for minimal size.
  • All required assets and dependencies are bundled.
  • Ideal for distributing the app as a single executable.

🧪 Search Logic

Search is hybrid — every query runs two independent searches and merges them:

  • Meaning: cosine similarity between the query embedding and every stored vector.
  • Text: SQLite FTS5 (bm25) over descriptions and filenames. Wrap a phrase in "quotes" to require it verbatim.

The two are combined with Reciprocal Rank Fusion, which merges by position rather than by score. Cosine similarity and bm25 aren't on comparable scales, so this avoids any per-model tuning — and an image found by either half still surfaces.

There is no similarity threshold. Results are always ranked best-first and capped by Max Results, so a query can't silently come back empty because a cutoff was set slightly too high.

The Match column shows why each row matched: a cosine score (0.82), a full-text hit (text), or both (0.82 + text).

If the embedding server is unreachable, the text half still works on its own.

🗄️ Storage

Each vision/embedding model pair gets one SQLite file in data/, with three tables:

Table Holds
images image bytes, name, MD5 hash, byte size — keyed by path, independent of any model
descriptions one caption per image, with the prompt and vision model used
embeddings one float32 vector per image, with its dimension and embedding model

descriptions and embeddings reference images with ON DELETE CASCADE, so removing an image removes everything derived from it. Because images stands on its own, images can be added without a description — leaving room for a bulk import later.

⚙️ Notes

  • Embeddings are batched/v1/embeddings is called with several descriptions per request. If your server rejects array input, or returns fewer vectors than asked for, the app retries the missing ones individually.
  • Missing embeddings are backfilled — a description whose embedding failed (server offline, run stopped) is picked up on the next run without re-captioning the image.
  • Failed images are retried in parallel, up to 3 passes.
  • Context size is configured on the server, not in the app. The /v1 API has no num_ctx equivalent — llama.cpp and vLLM fix context at startup, and Ollama's /v1 endpoint ignores it.
  • Images are re-processed when the prompt changes; otherwise already-described images are skipped.

📜 License

See the LICENSE file in the repository for usage terms

About

Analyze and search images locally using AI-powered descriptions and semantic embeddings.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Contributors

Languages