Skip to main content

Fast-deskew

CI PyPI Python License

A fast drop-in alternative to the excellent deskew library by sbrunner, using OpenCV instead of scikit-image for the heavy lifting. It estimates the skew angle of a document image so you can rotate it back to straight.

On sbrunner's own test set it returns the same angles while running ~9× faster (see Benchmark).

Before and after deskewing

Installation

  • Using pip:
pip install fast-deskew-cv
  • From source:
pip install git+https://git@github.com/HOZHENWAI/fast_deskew.git

Usage

import cv2
from deskew import determine_skew

image_grayscale = cv2.imread('input_image.png', cv2.IMREAD_GRAYSCALE)
skew_angle = determine_skew(image_grayscale)

determine_skew returns the skew angle in degrees (or None if no dominant orientation is found). To straighten the image, rotate it by +skew_angle:

import cv2
from deskew import determine_skew

image = cv2.imread('input_image.png')
grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

angle = determine_skew(grayscale)
if angle is not None:
    height, width = image.shape[:2]
    matrix = cv2.getRotationMatrix2D((width / 2, height / 2), angle, 1.0)
    deskewed = cv2.warpAffine(image, matrix, (width, height),
                              borderValue=(255, 255, 255))
    cv2.imwrite('output_image.png', deskewed)

How it works

The classical Hough-transform skew-detection pipeline:

  1. Blur the image (Gaussian) to suppress noise.
  2. Canny edge detection — thresholds are derived from a percentile of the image's gradient magnitude, so the same defaults work across document sizes and contrasts.
  3. Hough line transform to find straight edges.
  4. Fold every line orientation into a canonical interval (so text baselines and vertical strokes, which differ by ~90°, reinforce the same estimate) and return the most frequent (modal) angle from the strongest lines.

Parameters

Parameter Default Description
image_array 8-bit single-channel (grayscale) image.
sigma 3.0 Standard deviation of the Gaussian pre-blur.
num_peaks 20 Number of strongest Hough lines used to vote on the angle.
angle_pm_90 False Fold into [-90, 90) instead of [-45, 45).
min_angle / max_angle None Restrict the reported skew to a degree range.
min_deviation 1.0 Angular resolution in degrees (also the voting bin width).
gradient_percentile 99.0 Gradient-magnitude percentile used as the high Canny threshold when auto-deriving.
canny_threshold_low / canny_threshold_high None Explicit Canny thresholds; None auto-derives them from the gradient.
hough_rho 1.0 Distance resolution of the Hough accumulator (pixels).
hough_threshold 30 Minimum Hough votes for a line (a floor; peak selection stays relative via num_peaks).

Benchmark

fast-deskew vs the reference deskew (1.6.1) on the reference library's own 8 test images. Both libraries receive the same grayscale array; timing is the median of repeated calls and excludes image loading. Angles are compared against the ground-truth values from the reference test suite.

Image Size Ground truth deskew fast-deskew Speed-up
1 6172×4152 −1.0° −1.0° / 2781 ms −1.0° / 320 ms 8.7×
2 1748×1241 −2.0° −2.0° / 300 ms −2.0° / 31 ms 9.7×
3 1748×1241 −6.0° −6.0° / 286 ms −6.0° / 27 ms 10.5×
4 1748×1241 7.0° 7.0° / 238 ms 7.0° / 30 ms 7.9×
5 724×1198 3.0° 3.0° / 103 ms 3.0° / 10 ms 10.1×
6 1415×1120 −3.0° −3.0° / 209 ms −3.0° / 20 ms 10.6×
7 575×336 3.0° 3.0° / 28 ms 3.0° / 3.5 ms 7.9×
8 3089×2435 15.0° 15.0° / 702 ms 15.0° / 73 ms 9.6×

Accuracy: 8/8 angles identical to the reference. Speed: ~9× faster (median).

Measured on Python 3.14, OpenCV 4.13, scikit-image 0.26, AMD64. Absolute timings are hardware-dependent; the relative speed-up is the meaningful figure.

Notes & limitations

  • Input is expected to be an 8-bit grayscale image (convert color images with cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) first).
  • For skews beyond ±45°/±90°, fix the global page rotation first and use this library for the residual fine skew. angle_pm_90=True widens the fold range.

Development

pip install -e ".[dev]"
pytest

License

MIT — see LICENSE.

Acknowledgements

Algorithm and test images from sbrunner/deskew.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fast_deskew_cv-1.0.1.tar.gz (8.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fast_deskew_cv-1.0.1-py3-none-any.whl (6.8 kB view details)

Uploaded Python 3

File details

Details for the file fast_deskew_cv-1.0.1.tar.gz.

File metadata

  • Download URL: fast_deskew_cv-1.0.1.tar.gz
  • Upload date:
  • Size: 8.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for fast_deskew_cv-1.0.1.tar.gz
Algorithm Hash digest
SHA256 407d912cf41e08d8e2b855b10fd9f6ecb2ae53770cc8d725dbcaef23c80d393d
MD5 c93e4f6b55824e0842f6883a122cc1c2
BLAKE2b-256 3febbeb7daa32a1697c7eea85c463500460fe543fac3f55a018a470ba2a9e36e

See more details on using hashes here.

File details

Details for the file fast_deskew_cv-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: fast_deskew_cv-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 6.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for fast_deskew_cv-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 71b9e6cb0f06e700e1a436178296697ee449e72bb0bd434ac20339ff7e51280f
MD5 a2420987eb37b49690d08023cf8a3668
BLAKE2b-256 3927c1572692facb857c62daac4e30d211b037f78ab3443336647e93ad7b13d0

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 files

1.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page