Add Sharpness/Blur Detection for Better Duplicate Selection #21
Labels
No labels
Kind/Bug
Kind/Feature
Priority/High
Priority/Medium
Reviewed/Confirmed
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ai-collab/bulk-image-organizer#21
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
When the perceptual hashing step identifies near-duplicate images (same resolution but different files), we currently rely primarily on file size to decide which version to keep.
Describe the solution you'd like
Consider adding Sharpness / Blur Detection using the variance of the Laplacian (via OpenCV) as a secondary quality metric.
Sample Implementation
Additional context
Benefits
Enhancement: Add Sharpness/Blur Detection for Better Duplicate Selectionto Add Sharpness/Blur Detection for Better Duplicate SelectionImplemented on branch
0.1.45/issue-21-57-67-dupe-workbench-depth(chained off the previous dev branch, not merged tomainyet) — with one substitution from the proposed implementation, recorded as DR-025 indocs/DECISIONS.md.This project's AGENTS.md lists "No OpenCV dependency by default" as an explicit non-goal, so the
cv2.Laplacian(...).var()approach in the issue couldn't be used as-is. Instead,core/dupe_detector.pygainedsharpness_score(path), using Pillow'sImageFilter.FIND_EDGES(also a discrete Laplacian-style edge kernel) on a grayscale copy plusImageStat.Statpixel variance — the same underlying idea (edge-variance sharpness), staying within the existing Pillow dependency.pick_keep_best_path()/keep_best_delete_paths()gained an optionalrootparameter: resolution (pixel count) is still the primary criterion exactly as before, but when multiple images in a group tie on resolution, sharpness now breaks that tie before falling back to date/path. Sharpness is only computed for the images actually tied on resolution, not the whole group, so the common case (one image with strictly more pixels) pays no extra cost.ui/main_window.py's Keep Best handler passesroot=self._current_rootso this is live.Bundled with #67 and #57 in the same branch/PR.
This needs a metric, rating, score, or indicator of some sort added to the meta data display below each images in the multi dupe view. Don't apply it only to the images with highest resolution, process the whole set.
Added, pushed to
0.1.47/issue-111-86-64-89-feedback-fixes(0.1.56).The sharpness score (same edge-variance metric from the original Keep Best tie-breaker) is now shown below every image in the Multi view's metadata row, next to resolution and file size — computed for the whole group, not just the images tied on highest resolution like Keep Best's internal use of it. The sharpest/blurriest image in the group gets the same green/red highlighting the other two metrics already use.
It's scored in the background per image (so it doesn't block opening a group), which means it can briefly show "Sharp —" right after a group loads before filling in — that's expected, not a bug.
One thing I want to flag honestly: I don't have a display in this environment, so I verified this through unit tests (real images, real background worker round-trip, not mocks) and an offscreen UI-exit smoke test, but I have not visually confirmed how it actually looks in a running window. Please give it a look and let me know if the layout/formatting needs any adjustment.
Closing as part of wrapping up this branch chain into PRs. One implementation note for the record: this was built without OpenCV (per AGENTS.md's no-OpenCV-by-default policy) —
sharpness_score()uses Pillow'sImageFilter.FIND_EDGES+ pixel variance instead ofcv2.Laplacian(...).var(), which is the same underlying idea (edge-detail variance) but without the extra dependency. See DR-025 for the substitution rationale and DR-032 for how the score got surfaced into the Multi view's UI for every image in a group, not just Keep Best's internal tiebreaker use of it.Shipped across PR #127 (original sharpness tiebreaker for Keep Best) and PR #129 (the UI display for every image, addressing your "process the whole set" follow-up comment). Reopen or file a new issue if the display needs adjustment once you've had a chance to look at it in a running build.