← Back to blog

wHash: The Fast Wavelet-Based Duplicate Finder for Large Image Collections

Sakarto's wHash (Wavelet Hash) algorithm finds duplicate photos and videos using a Haar Wavelet Transform—faster than pHash with near-identical accuracy. Perfect for large collections where speed matters. Free, browser-based, and 100% private.

Sakarto wHash duplicate finder interface showing wavelet-based grouping of images

When you have a library of 50,000 images, speed matters. pHash is reliable, but its DCT computation on a 32×32 canvas takes time. aHash is fast, but it misses duplicates that have been edited or re-compressed. What if you could have both—speed and accuracy?

That’s exactly what wHash (Wavelet Hash) delivers. It uses a Haar Wavelet Transform—a simpler mathematical operation than the DCT—to capture the same low‑frequency structural content that makes pHash so reliable, but on a smaller 16×16 canvas and with fewer computations. The result is an algorithm that finds nearly every duplicate pHash would catch, at 30–40% less CPU cost.

For large collections where every millisecond counts, wHash is the sweet spot.


What makes wHash different from pHash, aHash, and dHash?

All four algorithms produce a binary hash and compare using Hamming distance. But they use different mathematical transforms:

AlgorithmTransformCanvas SizeHash BitsSpeedBest for
aHashMean comparison16×16256FastestExact copies, large folders
dHashGradient comparison17×16256Very FastExposure-adjusted copies
pHashDCT (frequency)32×3264FastPrecision, edited copies
wHashHaar Wavelet16×1664Very FastSpeed + accuracy balance

The key insight: wHash is pHash without the computational overhead. The Haar wavelet transform is just averaging and subtracting adjacent pairs of values—no trigonometric functions, no matrix multiplications. It’s simpler than DCT but captures very similar low‑frequency structural information. For most photo deduplication tasks, wHash and pHash produce nearly identical groups, but wHash is noticeably faster.


How the algorithm works: a deep dive

Let’s walk through exactly what happens when you scan a folder with wHash.

Step 1: Resize to 16×16 pixels

Each image is drawn onto a 16×16 canvas. The canvas size must be a power of 2 for the Haar wavelet transform to work correctly—16×16 gives 256 pixels, enough information to capture broad perceptual structure while keeping computation extremely fast.

Fast Mode (enabled by default for JPEGs): Instead of decoding the full image, Sakarto reads the embedded EXIF thumbnail (typically 160×120 pixels). This makes JPEG scans 5–10× faster. Since wHash operates on a 16×16 canvas anyway, the thumbnail is more than large enough and produces an identical hash.

Step 2: Convert to grayscale

Each of the 16×16 = 256 pixels is converted to a single brightness value using the standard luminance formula: Gray = 0.299 × Red + 0.587 × Green + 0.114 × Blue

Colour information is discarded—wHash, like all hash algorithms in Sakarto, is colour‑blind.

Step 3: Apply the 1D Haar Wavelet Transform to each row

For each of the 16 rows, the 16‑element array is transformed by the Haar operation:

  • Adjacent pairs of pixels are averaged (stored in the first half of the result)
  • Adjacent pairs of pixels are differenced (stored in the second half)

The first half encodes a low‑frequency approximation of the row; the second half encodes the fine detail. This is the fundamental “split into averages and differences” step of the Haar wavelet.

Step 4: Apply the 1D Haar Wavelet Transform to each column

The same Haar operation is applied column‑wise to the result of step 3. After this separable 2D transform, the 16×16 matrix is divided into four 8×8 sub‑bands:

Sub‑bandNameContent
Top‑leftLLLow‑frequency approximation (both row and column averages)
Top‑rightLHHorizontal edges (row‑averaged, column‑differenced)
Bottom‑leftHLVertical edges (row‑differenced, column‑averaged)
Bottom‑rightHHDiagonal detail (both differenced)

Step 5: Extract the 8×8 LL sub‑band (64 values)

wHash keeps only the top‑left 8×8 = 64 wavelet coefficients—the LL sub‑band. This represents the broadest, most perceptually dominant structures in the image: overall brightness distribution, major edges, and dominant shapes. All high‑frequency detail (fine texture, noise, compression artifacts) is discarded.

Step 6: Compute the mean of the 64 coefficients

The mean (average) of the 64 LL sub‑band values is calculated, excluding the DC component at index 0 (which represents overall image brightness). Excluding the DC component makes the hash invariant to global brightness differences.

Step 7: Produce the 64‑bit hash

Each of the 64 LL sub‑band coefficients is compared to the mean. If a coefficient is above the mean, its bit is 1; if at or below, its bit is 0. The resulting 64‑bit binary string is the wHash fingerprint.

Step 8: Compare using Hamming distance

To compare two files, their 64‑bit hashes are XOR’d bit by bit. The number of positions where the bits differ is the Hamming distance. A distance of 0 means identical wavelet fingerprints. The threshold slider controls the maximum Hamming distance allowed for two files to be grouped. Lower = stricter.

An aspect‑ratio pre‑check first skips any pair where proportions differ by more than 10%. For videos, 3 frames are extracted at 1.5‑second intervals, each hashed individually, and combined by majority vote into one representative hash.


What wHash finds well

Type of duplicateHow well it worksWhy
Exact byte‑for‑byte copies✅ ExcellentThe hash will be identical.
Same photo at different resolutions✅ ExcellentResizing to 16×16 removes resolution differences.
Re‑saved copies in different formats (JPEG → PNG → WebP)✅ ExcellentFormat conversions affect pixels but not low‑frequency wavelet structure.
Re‑compressed JPEGs at moderate quality reductions✅ Very GoodWavelet LL sub‑band is stable across most compression levels.
Mild colour‑graded versions✅ GoodLuminance structure is largely preserved.
Lightly cropped versions✅ GoodAs long as major structure remains.
Videos with similar dominant visual content✅ GoodMultiple frames averaged together.
Heavily re‑compressed JPEGs (quality 1–5)⚠️ May missVery aggressive compression can affect the LL sub‑band.
Heavily cropped images (over 30% removed)⚠️ May missStructural content shifts too much.
Rotated or mirrored images❌ Won’t findWavelet transform is not rotation‑invariant. Use ORB.
Dramatic colour or contrast transformations⚠️ May missLuminance structure can change significantly. Try dHash or Color Signature.
Stylised versions (extreme filters)⚠️ May missExtreme filters change structural content.

Understanding the Hamming threshold slider

The threshold slider is the most important control in wHash. It determines how many of the 64 hash bits two images can differ on and still be grouped as duplicates.

Threshold rangeWhat it doesWhen to use
0–5 (Very strict)Only near‑identical wavelet fingerprints match. Very few false positives.Finding exact copies and direct re‑exports.
6–15 (Balanced)Catches resized, re‑compressed, and lightly edited copies.Default and recommended. The default of 10 is well‑calibrated for wHash’s 64‑bit hash space.
16–25 (Loose)Includes more approximate structural matches. More false positives.If you’re missing duplicates with significant edits.
30+ (Very loose)Groups images with broadly similar wavelet patterns.Only use for exploration. Expect false positives.

Tip: Because wHash uses a 64‑bit hash (like pHash), threshold values map similarly. A value of 10 on wHash is stricter than 10 on aHash (which is 256‑bit). Start at 8–10 and adjust from there.


How to use wHash: step by step

Step 1: Open the tool and select a folder

Go to the wHash duplicate finder page. Click 📁 Select Folder to Scan to open a native folder picker (Chrome/Edge). Or drag and drop a folder onto the page.

Tip: Make sure Fast Mode is checked. For JPEGs, this reads the embedded thumbnail instead of the full image—5–10× faster with near‑identical accuracy because wHash discards high‑frequency detail anyway.

Step 2: Wait for the scan to run

A progress bar shows how many files have been processed. wHash is one of the fastest algorithms in Sakarto—the Haar wavelet on a 16×16 canvas is extremely light. Duplicate groups appear live as they’re found—you don’t need to wait for the full scan to finish before reviewing results.

Step 3: Adjust the threshold

After the scan completes, use the Hamming Threshold slider (0–50) to tune matching strictness. Release the slider to re‑cluster all results instantly using the new value—no re‑scanning needed. A background Web Worker handles the re‑comparison.

Step 4: Review the duplicate groups

Results are shown in numbered groups. Each group contains files with similar wavelet structure.

  • Click a card to select it (blue border)
  • Ctrl+Click (Cmd on Mac) to add to the compare list (purple border)
  • Click the 🔍 icon on hover to preview full size
  • Right‑click any card for the context menu
  • Click & drag on empty space to box‑select multiple cards

Step 5: Use the Compare modal

Ctrl+Click two or more cards, then click ⚖️ Compare in the toolbar. A modal shows each file with:

  • Full metadata (dimensions, file size, format)
  • A similarity percentage
  • Copy, Move, and Delete buttons for each file
  • A pairwise similarity matrix for 3+ files

Step 6: Take action—Move, Delete, or Copy

Select files and use the toolbar buttons. With Queue Mode on (recommended), files are staged for review first:

  • 📋 Copy — copy filename(s) to clipboard
  • 📂 Move — stage for move to a named folder
  • 🗑️ Delete — stage for permanent deletion
  • ⚖️ Compare — view selected files side‑by‑side

Warning: Deletions are permanent. The File System Access API bypasses the recycle bin. Always use Queue Mode to review before executing.

Step 7: Execute queued actions

Switch to the Move Queue or Delete Queue tab in the sidebar to review staged files, remove any you changed your mind about, then execute when ready.


When to use wHash vs. the other 6 algorithms

Sakarto gives you seven visual algorithms for a reason—each one handles a different type of duplication problem. Here’s when to pick wHash over the others:

Color Signature — colour accuracy

Color Signature is the only algorithm that compares actual colour.

Use wHash instead: Your copies have been edited in ways that change colour but preserve luminance structure. wHash is colour‑blind and stable across luminance-preserving edits.

aHash (Average Hash) — speed above all else

aHash is the fastest algorithm—it reads individual pixels and compares them to the overall mean.

Use wHash instead: You need better accuracy than aHash but still want speed. wHash is only slightly slower than aHash but catches re‑compressed and lightly edited copies that aHash misses.

BlockHash — noise tolerance

BlockHash averages brightness over blocks, making it tolerant of compression noise.

Use wHash instead: You want fewer false positives than BlockHash. wHash’s wavelet encoding is more discriminating than block averaging.

dHash (Difference Hash) — brightness and exposure-adjusted copies

dHash encodes gradient directions and handles exposure shifts well.

Use wHash instead: Your copies have been edited in ways beyond just brightness changes. wHash is more broadly stable across a wider range of edits while still being very fast.

pHash (Perceptual Hash) — the precision choice

pHash uses the Discrete Cosine Transform on a 32×32 canvas—the most precise but most computationally intensive.

Use wHash instead: You have a very large collection (50,000+ images) and want pHash‑like accuracy with significantly better performance. wHash typically produces nearly identical results to pHash at 30–40% lower CPU cost.

ORB (Feature Matching) — rotation, cropping, and perspective

ORB is the only algorithm that handles rotation, cropping, and perspective warping.

Use wHash instead: Your copies are not rotated or heavily cropped. wHash is 100× faster than ORB and handles a wider range of edits that don’t involve geometric transformations.


Algorithm quick reference

AlgorithmBest forColour‑aware?Handles rotation?Handles re‑compression?SpeedAccuracy
Color SignatureSame colour palette, social media re‑uploads✅ Yes❌ No⚠️ ModerateFastHigh (colour)
aHashLarge folders, speed priority❌ No❌ No⚠️ ModerateFastestLow
BlockHashHeavily compressed JPEGs, noisy images❌ No❌ No✅ GoodVery FastMedium
dHashBrightness/exposure‑adjusted copies❌ No❌ No⚠️ ModerateVery FastMedium
pHashFormat conversions, watermarks, precision❌ No❌ No✅ ExcellentFastHighest
wHashLarge collections, speed + quality balance❌ No❌ No✅ GoodVery FastHigh
ORBRotated, cropped, perspective‑warped❌ No✅ Yes✅ GoodSlowerHigh

Privacy: your files never leave your device

Like every Sakarto tool, the wHash duplicate finder runs entirely in your browser:

  • Zero network activity after page load. Open DevTools → Network tab and verify: no outbound requests during any scan or file operation.
  • No accounts, no cookies, no analytics. The only localStorage data is your OS detection and checkbox preferences. No file names or scan results are ever saved.
  • Folder access is scoped and session‑only. Permission expires when you close the tab.
  • Purely static—no backend. Sakarto is HTML, CSS, and JavaScript. There is no server, no database, and no API receiving your data.

Frequently asked questions (wHash specific)

“How is wHash different from pHash, aHash, and dHash?”

All four produce a 64‑bit hash compared with Hamming distance, but they use different mathematical transforms. aHash simply compares pixels to a mean—the fastest but coarsest. dHash encodes brightness gradient directions—good for exposure‑adjusted copies. pHash applies a 2D Discrete Cosine Transform on 32×32 and extracts the 8×8 low‑frequency coefficients—the most precise but most computationally intensive. wHash applies a Haar Wavelet Transform on a 16×16 canvas and extracts the 8×8 LL (low‑low) sub‑band. Wavelets decompose the image into multiple frequency scales simultaneously, similar to how DCT works but in a different mathematical basis. The result is quality very close to pHash at lower CPU cost—making wHash the best balance of speed and accuracy when you want more precision than aHash but don’t need every last bit of pHash’s discrimination.

”When should I choose wHash over pHash?”

Choose wHash when you have a large collection and want good quality matching without pHash’s higher processing cost. In practice, for most photo deduplication tasks, wHash and pHash produce nearly identical groups—the difference only becomes noticeable at the boundaries of the threshold, where very similar but not identical images either match or don’t. Choose pHash over wHash when you’re looking for copies of photos that have been subtly edited (light retouching, slight colour adjustments, minor crops) and need the extra precision to distinguish real duplicates from near‑duplicates. wHash is also slightly better at handling images with local edits in one region of the image, because wavelet transforms capture spatial structure at multiple scales simultaneously.

”Two clearly different photos are being grouped together. How do I fix it?”

Lower the similarity threshold slider to 4–8. wHash’s 16×16 wavelet basis is coarser than pHash’s 32×32 DCT, so at loose thresholds it can group photos with broadly similar structural layouts. Use the Compare modal (Ctrl+Click two cards, then Compare) to verify before acting. If false positives persist at strict thresholds, try pHash for more discrimination, or Color Signature if the falsely‑grouped photos have different colour palettes that colour comparison could distinguish.

”I know two files are duplicates but wHash isn’t grouping them. What should I try?”

First, raise the threshold toward 15–20. Second, check aspect ratios—pairs differing by more than 10% are excluded by the pre‑check. Third, consider what kind of edit was applied: wHash handles re‑compression, format changes, and mild edits well. Like all hash algorithms, it fails for rotated images—use ORB for those. For very heavily cropped copies where more than a third of the image content was removed, the structural content shifts enough that the wavelet sub‑band changes significantly. Try ORB for cropped copies as well.

”What does Fast Mode do, and does it affect wHash accuracy?”

Fast Mode reads the EXIF thumbnail embedded in JPEG files instead of the full image. Since wHash operates on a 16×16 canvas, the EXIF thumbnail (typically 160×120 or similar) is many times larger than needed and produces an identical hash. Leave Fast Mode on. Turn it off only if you’re seeing suspicious groupings on JPEG files that disappear when Fast Mode is disabled—a sign that the EXIF thumbnails in those files were stripped or are stale (some editors update the image but not the embedded thumbnail).

”What is a Haar Wavelet Transform, explained simply?”

A Haar wavelet transform works by repeatedly averaging pairs of values and keeping the difference between them. Applied to an image row by row and then column by column, the result is four sub‑regions: LL (both averaged—the “thumbnail” of the image), LH (row‑averaged, column‑differenced—horizontal edges), HL (row‑differenced, column‑averaged—vertical edges), and HH (both differenced—diagonal detail). wHash uses only the LL sub‑band—the smoothed, low‑frequency overview of the image—and discards the edge/detail sub‑bands. This is conceptually similar to what pHash does with DCT, just using a different (and computationally cheaper) mathematical basis.

”Why does video scanning pause when I switch tabs?”

Browsers throttle video elements when a tab is hidden to save battery and CPU. Sakarto uses the Page Visibility API to detect this and pauses video frame extraction, resuming when you return. Image hashing runs in a background Web Worker that is not throttled by tab visibility—images continue scanning at full speed regardless of which tab you have open.

”Can I recover files after deleting them?”

No. The File System Access API’s remove() method permanently deletes files without using the OS Recycle Bin or Trash. Queue Mode is enabled by default to prevent accidental deletions: files are staged for review before execution. Use the preview icon and Compare modal to verify groups. When uncertain, Move to a “Sakarto‑Duplicates” subfolder rather than deleting—you can recover those files manually later.

”What file types are supported?”

Images: JPEG, PNG, GIF, WebP, BMP. Videos: MP4, WebM, MOV, MKV. Files over 40 MB are skipped. HEIC/HEIF, SVG, RAW formats, and TIFF are not supported due to browser decoder limitations. Convert these to JPEG or PNG in your photo editor before scanning.

”Does this work on Firefox or Safari?”

Scanning, wavelet computation, result display, and the Compare modal all work in Firefox and Safari. Move and Delete are the exception—they require the File System Access API (Chrome 86+ and Edge 86+ only). In other browsers, complete the scan, review groups, and use Download List to export a report for manual file management.


Final thoughts

wHash is the algorithm you reach for when you need the best balance of speed and accuracy. It’s not quite as fast as aHash, and it’s not quite as precise as pHash—but it’s close to both, making it the ideal choice for large collections where every millisecond counts.

It’s particularly effective for:

  • Large photo libraries. 50,000+ images where pHash would take noticeably longer.
  • First‑pass deduplication. Run wHash to find the obvious duplicates quickly, then use pHash for a second pass on the remaining groups.
  • Collections with mixed formats and mild edits. wHash handles re‑compression, format conversion, and light edits reliably.
  • Scenarios where you want pHash‑like results but your hardware is older. wHash’s lower computational cost makes it more usable on older machines.

Where wHash falls short—rotated, heavily cropped, or dramatically edited copies—other Sakarto algorithms fill the gap. Use ORB for geometric transforms, dHash for brightness shifts, or pHash for the most discriminating matching.

But for large collections where speed matters as much as accuracy, wHash is the algorithm that gives you the best of both worlds.

Ready to find duplicate images and videos with wHash?

May 27, 2026
⏱ 18 min read
🇬🇧 English