Skip to main content

FocusWeave

Focus stacking via Laplacian pyramid fusion. Takes a set of images captured at different focus distances and combines them into a single image where the entire subject is sharp.

Download

Pre-built archives for Windows, macOS and Linux are on the releases tab, alongside Python wheels. FocusWeave can also be installed via

pip install FocusWeave

Basic usage

Point focusweave at a folder of images and it will produce stacked.jpg inside that folder:

focusweave path/to/images/

To output to a specific file, format it as so.

focusweave path/to/images/ --output result.tiff

Command-line options

Output options

--output PATH           Output file path, supports JPG, PNG, TIFF, and WebP images.
--quality N             JPEG output quality 1–95 (default: 95).

Alignment options
--no-align              Skip alignment entirely. Use when images are already registered.
--reference N           Index of the image to align all others to (default: middle image).
--global-align          Align every image directly to the reference instead of
                        chaining through neighbours. More robust when images are not
                        ordered by similarity.
--full-res              Run the fine alignment pass at full resolution instead of the
                        default 1024px cap. More accurate but significantly slower.
--min-shift PIXELS      Minimum shift in pixels before alignment is applied (default: 5.0).
--no-rotation           Suppress rotation correction during alignment.
--no-scale              Suppress scale correction during alignment.
--no-shear              Suppress shear correction during alignment.
--no-translation        Suppress translation correction during alignment.

Canvas options
--keep-size             Keep the output the same size as the inputs; warps are applied
                        in-place rather than expanding the canvas.
--crop                  Crop the output to the intersection of all image extents —
                        removes all border regions but produces a smaller result.
--no-fill               Fill border regions with black instead of reflecting edge pixels.
                        Pairs naturally with --crop to trim the borders away.

Stacking options
--levels N              Laplacian pyramid levels (default: auto from image size).
--sharpness EXPONENT    Weight sharpness exponent (default: 4.0). Higher values favour
                        the sharpest image more aggressively at each pixel, approaching
                        a hard winner-take-all selection. Useful range is roughly
                        1.0 (soft blend) to 8.0 (near-hard selection).
--workers N             Number of frames fused concurrently. The default is automatic:
                        one per core, capped so the workers' buffers fit in free
                        memory. Each worker costs roughly 110 MB per megapixel of
                        output (160 MB for 16-bit sources). Pass a number to
                        override it.

Culling options
--cull [THRESHOLD]      Remove wholly out-of-focus images before stacking. Each frame
                        is scored by the high- to low-frequency energy ratio of its
                        Tenengrad response; frames scoring below THRESHOLD are dropped.
                        The threshold is absolute, not relative to the sharpest frame.
                        THRESHOLD defaults to 0.6 when --cull is given without a value.
                        At least the two sharpest frames are always retained.

Slabbing options

Slabbing splits a large image set into overlapping sub-stacks, stacks each one independently, then fuses the results. This can improve quality by reducing the number of images competing in each fusion pass.

--slab SIZE OVERLAP     Enable slabbing. SIZE is images per sub-stack; OVERLAP is how
                        many images adjacent slabs share. Example: --slab 20 5
--output-steps          Save each intermediate slab result to a focusweave_slabs/
                        folder inside the output directory. Requires --slab.
--only-slab             Stop after producing slabs; skip the final fusion. Implies
                        --output-steps. Requires --slab.
--recursive-slab        If the layer-1 slab results still outnumber SIZE, apply
                        slabbing again as layer 2, and so on, until the count fits in
                        a single stack pass.
--slab-format EXT       File format for slab output images (e.g. tiff, png, jpg).
                        Defaults to tiff. Requires --output-steps or --only-slab.

Batch options

Batch mode stacks a folder of folders, treating each subfolder as its own set:

focusweave --batch path/to/shoot/
focusweave --batch path/to/shoot/ --output path/to/results/

--batch FOLDER          Stack each subfolder of FOLDER separately. Results are
                        named after their subfolder and written into FOLDER,
                        or into --output, which is then a folder rather than a
                        file. Every other option applies to each set. A set that
                        fails is reported and the rest carry on.
--batch-format EXT      Format for batch results: inherit (the default), or an
                        extension such as tiff, png or jpg. inherit uses the
                        most common extension among each set's images, so a set
                        of 16-bit TIFFs comes out as a 16-bit TIFF.

Other

--timings               Print how long each stage took.
--version, -V           Show the version number and exit.
--opencv-version        Show the version of the OpenCV library in use and exit.
--formats               List the supported image extensions and exit.
--help                  Displays the list of commands

Memory usage

Peak memory is roughly 110 MB per megapixel of output per worker, or 160 MB for 16-bit sources. The worker count defaults to one per core, capped so those buffers fit in free memory. To cut memory to the minimum at the cost of processing time, set workers to 1:

focusweave path/to/images/ --workers 1

Python API

focusweave can be installed into your environment directly via pip:

pip install focusweave

Installing from git builds from source, so it needs the prerequisites listed under Building from source.

All public symbols are importable from the top-level focusweave package. Only numpy is required at runtime. The main entry point is FocusStackConfig and run:

from pathlib import Path
from focusweave import FocusStackConfig, run

cfg = FocusStackConfig(images=Path("path/to/images/"))
result = run(cfg)

# result.image is a uint8 (or uint16) RGB numpy array

Images can be supplied as a folder path, a list of Path objects, or a list of pre-loaded numpy arrays:

import numpy as np
from focusweave import FocusStackConfig, run

images: list[np.ndarray] = [...]  # pre-loaded uint8 RGB arrays
cfg = FocusStackConfig(images=images, workers=4)
result = run(cfg)

A progress callback can be passed to run to receive stage-by-stage updates:

from pathlib import Path
from focusweave import FocusStackConfig, run

def on_progress(fraction: float, stage: str, message: str) -> None:
    print(f"[{stage}] {fraction * 100:.1f}%  {message}")

cfg = FocusStackConfig(images=Path("path/to/images/"))
result = run(cfg, progress=on_progress)

Long-running stacks can be cancelled by supplying an interrupt callback in the config. If it returns True at any checkpoint, Interrupted is raised:

from pathlib import Path
from focusweave import FocusStackConfig, Interrupted, run

cancelled = False

cfg = FocusStackConfig(
    images=Path("path/to/images/"),
    interrupt=lambda: cancelled,
)

try:
    result = run(cfg)
except Interrupted:
    print("Stack cancelled.")

Images can be read and written without pulling in another imaging library:

from pathlib import Path
from focusweave import load_image, save_image

frame = load_image(Path("frame_00.tiff"))   # uint8 or uint16 RGB
save_image(result.image, Path("stacked.tiff"))

See python/focusweave/api_example.py for a more complete example, or run it:

python -m focusweave.api_example path/to/images/ --streaming

Building from source

A Rust toolchain (1.82 or newer) is required, plus OpenCV 4 development files and libclang, which the opencv crate compiles and links against. Python 3.10 or newer if you want the bindings.

sudo apt-get install libopencv-dev libclang-dev   # Debian, Ubuntu
brew install opencv llvm                          # macOS
choco install llvm opencv                         # Windows, plus the
                                                  # environment variables in
                                                  # RUNNING.md

Command line binary:

cargo build --release -p focusweave-cli
./target/release/focusweave --help

Python package, via maturin:

pip install maturin
maturin develop --release

Once installed, the focusweave command is available on your PATH and is the same CLI as the native binary.

RUNNING.md walks through building, running and troubleshooting in more detail. docs/PORTING-NOTES.md records how the Rust implementation relates to the original Python one, including where the two deliberately differ.

Testing

cargo test --workspace

covers the parts that stand alone from image data. The port was validated against the original Python implementation until the two were meant to diverge; the last commit with that comparison is 638c5f0.

Algorithms

The focus stacking algorithm is based on Laplacian pyramid fusion as described in:

Wang, W., & Chang, F. (2011). A Multi-focus Image Fusion Method Based on Laplacian Pyramid. Journal of Computers.

Image alignment uses a custom coarse-to-fine pipeline built on an enhanced correlation coefficient solver (Evangelidis & Psarakis, 2008), implemented here. It seeds ECC with a phase-correlation translation estimate, applies CLAHE normalisation and a focus-aware pixel mask to concentrate the optimisation on sharp, informative regions, then validates the result against the seed to reject false minima. Warps are composed mathematically through a neighbour chain so interpolation error does not accumulate across the stack.

Release files for focusweave 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for focusweave 2.0.0
File Size Uploaded
focusweave-2.0.0.tar.gz 72.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for focusweave 2.0.0
File Interpreter ABI Platform
focusweave-2.0.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
focusweave-2.0.0-cp310-abi3-manylinux_2_28_x86_64.whl CPython 3.10 abi3 Linux glibc 2.28+ x86-64 Details
focusweave-2.0.0-cp310-abi3-macosx_26_0_arm64.whl CPython 3.10 abi3 macOS 26.0+ ARM64 Details

Total release size: 15.3 MB

Release files / focusweave-2.0.0.tar.gz

Download URL focusweave-2.0.0.tar.gz
Size 72.2 kB
Tags Source
SHA-256 checksum
How to use checksums
5d31d48200f24879da87ac1e965166ce7125c61b3d2c82ad2232b71260cec2cd
BLAKE2b-256 checksum
How to use checksums
bea0085abbb0b9db93a36c7dbd2d74202e1a57aec791ca2c1a198d033cb9bc30
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / focusweave-2.0.0-cp310-abi3-win_amd64.whl

Download URL focusweave-2.0.0-cp310-abi3-win_amd64.whl
Size 5.4 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
bd249f964334a84e94652cd556326f03a033cbe0dff214ac88b14bf9991d935d
BLAKE2b-256 checksum
How to use checksums
366d002e8eabdc5844b3eb67482875db29d0964cdcef4fa2f268edf29191065f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / focusweave-2.0.0-cp310-abi3-manylinux_2_28_x86_64.whl

Download URL focusweave-2.0.0-cp310-abi3-manylinux_2_28_x86_64.whl
Size 6.0 MB
Tags CPython 3.10 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
c9060d866a76ad8d70cb9d1cad27be5471ffea495e1b8e0ebecb5e1924a946fd
BLAKE2b-256 checksum
How to use checksums
1857e693bd1d41f372102882f52e3419b6d74b5e806fa9bd20af1ffa98f6036f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / focusweave-2.0.0-cp310-abi3-macosx_26_0_arm64.whl

Download URL focusweave-2.0.0-cp310-abi3-macosx_26_0_arm64.whl
Size 3.8 MB
Tags CPython 3.10 abi3 macOS 26.0+ ARM64
SHA-256 checksum
How to use checksums
dc47e3ec641922c84e430242885ec639c0e4d01edd0e33dc040b8311962be376
BLAKE2b-256 checksum
How to use checksums
3d4d60cca427d5f70aa414b586f47f92f3c9e602176482eea16bc69f7ba46860
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2.0.0 This release

4 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page