Document image dewarping library using a cubic sheet model.
Python 3 library for page dewarping and thresholding, available on PyPI.
A managed web version, Page Dewarp Web, is also available for use from any device with a browser, with an API for programmatic web access.
To install from PyPI, optionally using uv (recommended), run:
uv pip install page-dewarpTo install with JAX autodiff for ~11x faster optimisation on single images and ~33x faster for batches (CPU only), add the jax extra:
uv pip install page-dewarp[jax]To install with support for GPU execution instead of only CPU, choose one of:
uv pip install page-dewarp[jax-cuda12] # CUDA 12
uv pip install page-dewarp[jax-cuda13] # CUDA 13 (requires Python 3.11+)Note: CPU execution is the default
DEVICEand can be faster than GPU for this workload, but this may vary depending on your relative CPU/GPU horsepower (cores, RAM, VRAM, etc.)
When the JAX backend is available, default behaviour when given multiple images is to use batch mode. Performance benchmark on 40 images (via #139):
| Device | Serial | Batch | Speedup |
|---|---|---|---|
| CPU | 36s | 8.7s | 4.1x |
| GPU | 53s | 11.2s | 4.7x |
Python 3.10+ and NumPy, SciPy, SymPy, Matplotlib, OpenCV, and msgspec are required to run page-dewarp.
See the docs site for full details, including a How It Works walkthrough of the algorithm and a configuration reference.
- See config docs for a table of options
usage: page-dewarp [-h] [-d {0,1,2,3}] [-dd {file,screen,both}]
[-o OUTPUT_DIR] [-f OUTPUT_FORMAT] [-j OUTPUT_JSON]
[-it OPT_MAX_ITER] [-m OPT_METHOD] [-dev DEVICE]
[-b USE_BATCH] [-vw SCREEN_MAX_W] [-vh SCREEN_MAX_H]
[-x PAGE_MARGIN_X] [-y PAGE_MARGIN_Y] [-tw TEXT_MIN_WIDTH]
[-th TEXT_MIN_HEIGHT] [-ta TEXT_MIN_ASPECT]
[-tk TEXT_MAX_THICKNESS] [-tm TEXT_MORPH_OPS]
[-lm LINE_MORPH_OPS] [-wz ADAPTIVE_WINSZ] [-ri RVEC_IDX]
[-ti TVEC_IDX] [-ci CUBIC_IDX] [-sw SPAN_MIN_WIDTH]
[-sp SPAN_PX_PER_STEP] [-eo EDGE_MAX_OVERLAP]
[-el EDGE_MAX_LENGTH] [-ec EDGE_ANGLE_COST]
[-ea EDGE_MAX_ANGLE] [-fl FOCAL_LENGTH] [-z OUTPUT_ZOOM]
[-dpi OUTPUT_DPI] [-nb NO_BINARY] [-sh SHEAR_COST]
[-mc MAX_CORR] [-s REMAP_DECIMATE]
IMAGE_FILE_OR_FILES [IMAGE_FILE_OR_FILES ...]
positional arguments:
IMAGE_FILE_OR_FILES One or more images to process
options:
-h, --help show this help message and exit
-d, --debug-level {0,1,2,3}
(type: int, default: 0)
-dd, --debug-dest {file,screen,both}
(type: str, default: file)
-o, --output-dir OUTPUT_DIR
Directory for output and debug images (type: str,
default: .)
-f, --output-format OUTPUT_FORMAT
Output image format (e.g. png, tiff, bmp, jpeg) (type:
str, default: png)
-j, --json OUTPUT_JSON
Write JSON sidecar with dewarp parameters (type: int,
default: 0)
-it, --max-iter OPT_MAX_ITER
Maximum optimisation iterations (type: int, default:
600000)
-m, --method OPT_METHOD
Name of the JAX/SciPy optimisation method to use.
(type: str, default: auto)
-dev, --device DEVICE
Compute device to select for optimisation. (type: str,
default: auto)
-b, --batch USE_BATCH
Whether to batch process images (JAX backend only).
(type: str, default: auto)
-vw, --max-screen-width SCREEN_MAX_W
Viewing screen max width (for resizing to screen)
(type: int, default: 1280)
-vh, --max-screen-height SCREEN_MAX_H
Viewing screen max height (for resizing to screen)
(type: int, default: 700)
-x, --x-margin PAGE_MARGIN_X
Reduced px to ignore near L/R edge (type: int,
default: 50)
-y, --y-margin PAGE_MARGIN_Y
Reduced px to ignore near T/B edge (type: int,
default: 20)
-tw, --min-text-width TEXT_MIN_WIDTH
Min reduced px width of detected text contour (type:
int, default: 15)
-th, --min-text-height TEXT_MIN_HEIGHT
Min reduced px height of detected text contour (type:
int, default: 2)
-ta, --min-text-aspect TEXT_MIN_ASPECT
Filter out text contours below this w/h ratio (type:
float, default: 1.5)
-tk, --max-text-thickness TEXT_MAX_THICKNESS
Max reduced px thickness of detected text contour
(type: int, default: 10)
-tm, --text-morph TEXT_MORPH_OPS
Morphological ops for text mask (e.g. d_9_1,e_1_3)
(type: str, default: d_9_1,e_1_3)
-lm, --line-morph LINE_MORPH_OPS
Morphological ops for line mask (e.g. e_3_1_3,d_8_2)
(type: str, default: e_3_1_3,d_8_2)
-wz, --adaptive-winsz ADAPTIVE_WINSZ
Window size for adaptive threshold in reduced px
(type: int, default: 55)
-ri, --rotation-vec-param-idx RVEC_IDX
Index of rvec in params vector (slice: pair of values)
(type: tuple[int, int], default: (0, 3))
-ti, --translation-vec-param-idx TVEC_IDX
Index of tvec in params vector (slice: pair of values)
(type: tuple[int, int], default: (3, 6))
-ci, --cubic-slope-param-idx CUBIC_IDX
Index of cubic slopes in params vector (slice: pair of
values) (type: tuple[int, int], default: (6, 8))
-sw, --min-span-width SPAN_MIN_WIDTH
Minimum reduced px width for span (type: int, default:
30)
-sp, --span-spacing SPAN_PX_PER_STEP
Reduced px spacing for sampling along spans (type:
int, default: 20)
-eo, --max-edge-overlap EDGE_MAX_OVERLAP
Max reduced px horiz. overlap of contours in span
(type: float, default: 1.0)
-el, --max-edge-length EDGE_MAX_LENGTH
Max reduced px length of edge connecting contours
(type: float, default: 100.0)
-ec, --edge-angle-cost EDGE_ANGLE_COST
Cost of angles in edges (tradeoff vs. length) (type:
float, default: 10.0)
-ea, --max-edge-angle EDGE_MAX_ANGLE
Maximum change in angle allowed between contours
(type: float, default: 7.5)
-fl, --focal-length FOCAL_LENGTH
Normalized focal length of camera (type: float,
default: 1.2)
-z, --output-zoom OUTPUT_ZOOM
How much to zoom output relative to *original* image
(type: float, default: 1.0)
-dpi, --output-dpi OUTPUT_DPI
Just affects stated DPI of PNG, not appearance (type:
int, default: 300)
-nb, --no-binary NO_BINARY
Disable output conversion to binary thresholded image
(type: int, default: 0)
-sh, --shear-cost SHEAR_COST
Penalty against camera tilt (shear distortion). (type:
float, default: 0.0)
-mc, --max-corrections MAX_CORR
Maximum corrections used to approximate the inverse
Hessian. (type: int, default: 100)
-s, --shrink REMAP_DECIMATE
Downscaling factor for remapping image (type: int,
default: 16)
To try out an example image:
git clone https://github.com/lmmx/page-dewarp
cd page-dewarp
mkdir results && cd results
page-dewarp ../example_input/boston_cooking_a.jpgSee page-dewarp --help for the full list of options.
This library was renovated from the original (2016) Python 2 script
by Matt Zucker. A book on a flat surface can be modelled as a cubic curve fixed to zero at its endpoints (see Matt's original writeup and derive_cubic.py for the derivation).