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)
| File | Size | Uploaded | |
|---|---|---|---|
| focusweave-2.0.0.tar.gz | 72.2 kB | Details |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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 logRelease 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 logRelease 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