Repository
doc-dewarping
Document Image Dewarping Using Text Lines and Line Segments via Classical Methods Only (Without Machine Learning)
- Input
- Debug
- Option
- Description
- --proc-size N
- Maximum image side used for feature extraction and optimization
- --render-grid N
- Resolution per side of the inverse-mapping grid
Specs
- InputDebug
- OptionDescription
- --proc-size NMaximum image side used for feature extraction and optimization
- --render-grid NResolution per side of the inverse-mapping grid
- --interp {linear,cubic,lanczos}Output interpolation method
- --max-nfev NMaximum number of residual evaluations during optimization
- --outlier-iter NNumber of outlier-removal iterations
- --no-exifIgnore an EXIF focal length
- --f-scanTry focal-length initializations corresponding to several fields of view when EXIF is unavailable
- --no-page-boundaryDisable automatic refinement from a trusted, fully visible rectangular paper boundary
- PathPurpose
- src/dewarping/textline.pyText binarization, connected components, text lines, and blocks
- src/dewarping/linesegs.pyLSD line-segment detection and preprocessing
- src/dewarping/saliency.pySalient-object detection used by --scene
- src/dewarping/model.pyGCS geometry, back-projection, and image mappings
- src/dewarping/optimize.pyCost function, alignment classification, and iterative optimization
- src/dewarping/lsq.pyNumPy-only bounded Levenberg-Marquardt solver
- src/dewarping/dewarp.pyEnd-to-end pipeline and rendering
- src/dewarping/options.pyQuality presets and EXIF focal-length handling
- src/dewarping/cli.pyCommand-line interface
README
Document Image Dewarping
Document image dewarping using text lines and line segments, implemented with classical computer-vision and numerical-optimization methods only. No machine learning model or model weights are required.
| Input | Debug | Output |
|---|---|---|
| <img width="3024" height="4032" alt="for_dewarping" src="https://github.com/user-attachments/assets/be2d27e9-cc0e-477b-bb8b-9e92e823d8f7" /> | <img width="1650" height="2200" alt="for_dewarping_dewarped_debug" src="https://github.com/user-attachments/assets/5023e70c-8542-45b2-a079-fc243393ec9b" /> | <img width="1596" height="2200" alt="for_dewarping_dewarped" src="https://github.com/user-attachments/assets/8436e695-f0c6-4656-8fee-b2af0dc115ca" /> |
Features
- Generalized cylindrical surface (GCS) model for curved pages
- Text-line extraction from connected components of both dark and light text
- Text and line-segment detection restricted to the detected paper region
- Structural text-line filtering to keep illustration strokes out of geometry fitting
- Automatic paper-boundary refinement for text-free page regions
- Joint optimization of surface shape, camera pose, and focal length
- Analytical Jacobian and a NumPy-only bounded Levenberg-Marquardt solver
- Iterative outlier removal for text lines and line segments
- EXIF-based focal-length initialization for JPEG images
- Optional real-world curved-object mode for bottles, cans, cups, and labels
- Configurable processing and rendering quality
Requirements
- Python 3.12 or later
- uv for the recommended setup
The only runtime dependencies are NumPy and OpenCV Headless. SciPy is not required; nonlinear least-squares optimization is implemented in src/dewarping/lsq.py.
Installation
From a checkout of this repository, create the environment:
git clone https://github.com/PINTO0309/doc-dewarping.git && cd doc-dewarping
curl -LsSf https://astral.sh/uv/install.sh | sh
uv sync
source .venv/bin/activate
To display the available command-line options:
uv run dewarping --help
Command-line usage
The positional arguments follow the original executable:
dewarping INPUT OUTPUT [FLAG1] [FLAG2] [OPTIONS]
For example:
uv run dewarping input.jpg output.jpg 1 0
FLAG1 and FLAG2 were not documented by the original implementation. This package uses the following inferred behavior:
FLAG1:1includes the line-segment terms from the full Kil 2017 method;0uses text lines only, similar to the Kim 2015 method. The default is1.FLAG2:1writes<output_stem>_debug.png. Final text inliers are green, rejected text candidates are gray, geometry-supported line segments are red, and sampled paper sides use distinct colors. The default is0.
The flags are optional, so the shortest invocation is:
uv run dewarping input.jpg output.jpg
Quality presets
uv run dewarping input.jpg output.jpg 1 0 --quality high
| Preset | Processing side | Render grid | Interpolation | Max evaluations | Outlier iterations | Focal-length scan |
|---|---|---|---|---|---|---|
fast |
1200 px | 65 | linear | 300 | 2 | No |
default |
1600 px | 129 | linear | 600 | 3 | No |
high |
2200 px | 257 | cubic | 1200 | 4 | Yes |
Individual settings can override a preset:
| Option | Description |
|---|---|
--proc-size N |
Maximum image side used for feature extraction and optimization |
--render-grid N |
Resolution per side of the inverse-mapping grid |
--interp {linear,cubic,lanczos} |
Output interpolation method |
--max-nfev N |
Maximum number of residual evaluations during optimization |
--outlier-iter N |
Number of outlier-removal iterations |
--no-exif |
Ignore an EXIF focal length |
--f-scan |
Try focal-length initializations corresponding to several fields of view when EXIF is unavailable |
--no-page-boundary |
Disable automatic refinement from a trusted, fully visible rectangular paper boundary |
For JPEG images containing FocalLengthIn35mmFilm, the value is used by default to initialize the focal length and narrow its optimization range. It is not fixed because EXIF focal lengths are not assumed to be exact.
Curved-object scene mode
Use --scene to flatten labels or text on curved objects in real-world scenes:
uv run dewarping bottle.jpg bottle_flat.png 1 0 --scene
Scene mode detects a salient object using a SLIC-like segmentation and the graph-based manifold-ranking method of Yang et al., CVPR 2013. Text and line-segment extraction are restricted to the detected object. The surface model, optimization, and rendering stages are shared with document dewarping.
Python API
The pipeline can also be called directly with an OpenCV image:
import cv2
from dewarping.dewarp import dewarp_image
from dewarping.options import make_options
image = cv2.imread("input.jpg", cv2.IMREAD_COLOR)
if image is None:
raise FileNotFoundError("input.jpg")
options = make_options("high")
result = dewarp_image(
image,
use_line_term=True,
debug=False,
opts=options,
)
if not cv2.imwrite("output.jpg", result.rectified):
raise RuntimeError("Failed to write output.jpg")
dewarp_image returns a DewarpOutput containing:
rectified: the dewarped imagedebug_image: the optional feature visualizationparams: the estimated surface and camera parameters, or no estimate when the input contains no usable features
Tests
Run the NumPy/OpenCV unit tests, including page-boundary extraction and the
analytical boundary Jacobian check, with:
uv run python -m unittest discover -s tests -v
How it works
- Resize the image to a stable feature-extraction resolution.
- Detect text connected components, assemble them into text lines and blocks, reject weak illustration-like line candidates when enough strong text is present, and detect line segments with LSD. With a trusted page boundary, retain only segments near strong text or the paper perimeter for geometry fitting.
- Estimate a generalized cylindrical surface by minimizing text straightness, line spacing, block alignment, and line-segment orientation residuals.
- Reclassify inliers and repeat bounded nonlinear least-squares optimization.
- When all four paper sides are detected reliably, refine the text-first solution with page-boundary straightness constraints and retain it only if text alignment is preserved.
- Apply a small residual deskew/warp correction and render the rectified image through an inverse map with OpenCV.
Package structure
| Path | Purpose |
|---|---|
src/dewarping/textline.py |
Text binarization, connected components, text lines, and blocks |
src/dewarping/linesegs.py |
LSD line-segment detection and preprocessing |
src/dewarping/saliency.py |
Salient-object detection used by --scene |
src/dewarping/model.py |
GCS geometry, back-projection, and image mappings |
src/dewarping/optimize.py |
Cost function, alignment classification, and iterative optimization |
src/dewarping/lsq.py |
NumPy-only bounded Levenberg-Marquardt solver |
src/dewarping/dewarp.py |
End-to-end pipeline and rendering |
src/dewarping/options.py |
Quality presets and EXIF focal-length handling |
src/dewarping/cli.py |
Command-line interface |
Limitations
- Pixel-identical output to the original executable is not guaranteed. In particular, its text-line extractor was replaced with a practical connected-component implementation because the original source is unavailable.
- The method depends on detectable text lines or line segments. Images with few usable structural features may be returned unchanged or produce a weak estimate.
- Highly irregular, folded, or non-cylindrical surfaces are outside the primary GCS model. A low-order residual warp can correct only small remaining errors.
- Boundary refinement requires a complete, approximately upright rectangular page. Cropped, torn, strongly non-convex, or scene-mode objects fall back to the text/line-segment result.
- Runtime depends on image complexity and the selected quality preset.
highquality can be substantially slower, especially when it scans multiple focal lengths.
License
This project is licensed under the MIT License.
Referenced
- Taeho Kil, Wonkyo Seo, Hyung Il Koo and Nam Ik Cho, "Robust Document Image Dewarping Using Text-Line and Line Segments", ICDAR 2017.
@article{Kil2017RobustDI, title={Robust Document Image Dewarping Method Using Text-Lines and Line Segments}, author={Tae Ho Kil and Wonkyo Seo and Hyung Il Koo and Nam Ik Cho}, journal={2017 14th IAPR International Conference on Document Analysis and Recognition (ICDAR)}, year={2017}, volume={01}, pages={865-870}, url={https://s-space.snu.ac.kr/handle/10371/136804} } - DocRes: A Generalist Model Toward Unifying Document Image Restoration Tasks.
@inproceedings{zhangdocres2024, Author={Jiaxin Zhang, Dezhi Peng, Chongyu Liu , Peirong Zhang and Lianwen Jin}, Booktitle={In Proceedings of the IEEE/CV Conference on Computer Vision and Pattern Recognition}, Title={{DocRes: A Generalist Model Toward Unifying Document Image Restoration Tasks}}, Year={2024} }