← Projects
03 / 05

Desktop application · 2026

TwinPhoto

A desktop product combining perceptual hashing, an incremental SQLite index, parallel processing and a native Rust bridge to review and safely remove duplicates—even from USB-connected phones.

1. Project overview

TwinPhoto is a desktop application for finding visually similar photographs in local folders and, on Windows, in public galleries on USB-connected devices. It is intended for people who want to review large collections and find duplicates or variants before deciding what to keep. Its main contribution is to combine perceptual comparison, cache reuse and visual review with an explicit deletion action, so analysis does not modify the originals.

2. Problem and objectives

Photo collections accumulate resized, recompressed or edited copies that cannot be detected by comparing names or file sizes. Reviewing them one by one takes time, and automatic deletion based only on similarity can discard an image the user wanted to keep. On mobile devices, MTP access can be slow and depends on what Windows exposes.

The objective was to group images by appearance, make them easier to review and leave the final decision to the user. Repeated analyses reuse results, and mobile access keeps temporary copies and an inventory. The scope is a desktop application for Windows and local folders.

3. Solution and architecture

The user chooses a folder or device and sets a similarity threshold. For folders, the analyzer consults SQLite; for mobile devices, the integration enumerates public content through WPD and prepares a local cache. The same engine calculates hashes, searches for candidates and forms groups. The interface displays thumbnails for review and selection. Deletion requires confirmation and, on mobile devices, is verified with the device before the cache is updated.

TwinPhoto architectureLocal folders or the mobile cache feed an inventory. Perceptual hashes and the index form groups for review. Selected deletion requires confirmation and targets the local file or the WPD device.Review and controlData and perceptual analysisconfirmlocal folderUSBpublic imagesgroupsdevicelocal fileUserDesktop interfaceSelected deletionWPD bridgeLocal mobile cacheImage inventorySQLite hashcachePerceptual hash: pHashAnalysed folderCandidate indexand grouping

4. Development and technical decisions

The core is implemented in Python. Pillow decodes and normalizes images, NumPy performs numerical calculations, and pillow-heif adds support for HEIF/HEIC formats. The code applies EXIF orientation, converts each image to grayscale, reduces it to 32 × 32 pixels and calculates a discrete cosine transform. It generates a 64-bit pHash from the low-frequency coefficients; comparison between two images uses the Hamming distance between their hashes. Similarity is therefore perceptual: a maximum score means identical hashes, not byte-for-byte identity.

The available levels are 80%, 90%, 95% and 100%. Each level maps to a maximum distance in differing bits. To avoid exhaustively comparing every image with every other image, the engine splits hashes into fragments and queries a candidate index; it then verifies the exact distance before joining two images. Grouping uses a disjoint-set structure, so transitive relationships also connect items in the same group. Thus, two images belonging to the same group does not necessarily mean that their pair directly meets the threshold.

The initial hash calculation is distributed across processes. SQLite stores metadata and hashes and reuses them when file size and modification time have not changed. New images can be added to the index; changes, deletions or threshold adjustments require rebuilding groups because they may split previous sets. Tkinter keeps analysis and thumbnail loading off the GUI thread, shows progress, and provides summary and detail views. Thresholds are comparison parameters, not model training.

The mobile integration is separate from the similarity engine. A native bridge written in Rust uses the Windows Portable Devices (WPD) interfaces to detect devices, traverse accessible content, copy images to a temporary cache and operate on persistent identifiers when deleting. A Windows Shell compatibility path is retained for older installations or inventories. The system skips Android areas that are usually unavailable through MTP, so coverage depends on the permissions and content exposed by the phone.

The documentation describes the index against exhaustive search, but provides no comparisons of algorithms or reasons for rejecting other approaches. It does not document tests of deep-learning models or other hashes.

5. Challenges and solutions

The fragment index reduces the candidate set, and Hamming distance verifies each candidate before grouping. SQLite stores hashes and metadata to avoid repeating work; it also records unreadable files so they are not decoded again while unchanged.

For MTP, the cache and manifest of persistent identifiers allow unchanged images to be reused and the inventory to be refreshed when needed. The phone must remain powered on, unlocked and connected during import or deletion. The interface applies group updates at navigation points that preserve the current review.

6. Evaluation and results

The documented tests compare the index with exhaustive search at all four thresholds and cover caching, the mobile manifest, batch deletion and compatibility. The demonstrable result is a packaged application with analysis, review, hash reuse and WPD integration with caching. There are no corroborated metrics: the guide publishes no timings, memory use, corpus size, precision or recall, so performance and detection against a ground truth cannot be quantified.

7. Current status and future improvements

The version includes a graphical interface, folder analysis, configurable thresholds, perceptual groups, caching, thumbnails, confirmed deletion, a WPD bridge and a Windows distribution. Analysis does not modify files; deletion is permanent. On mobile devices, coverage is limited to what WPD/MTP exposes.

The limitations are the Windows dependency for mobile access, partial coverage of protected galleries and the lack of a public evaluation on reference collections. One improvement would be to measure precision, recall and performance on a controlled dataset. Semantic search or a cross-platform version are possibilities, not current features.