A fast deskew using hough line transform
Project description
Fast-deskew
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).
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:
- Blur the image (Gaussian) to suppress noise.
- 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.
- Hough line transform to find straight edges.
- 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=Truewidens the fold range.
Development
pip install -e ".[dev]"
pytest
License
MIT — see LICENSE.
Acknowledgements
Algorithm and test images from sbrunner/deskew.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
407d912cf41e08d8e2b855b10fd9f6ecb2ae53770cc8d725dbcaef23c80d393d
|
|
| MD5 |
c93e4f6b55824e0842f6883a122cc1c2
|
|
| BLAKE2b-256 |
3febbeb7daa32a1697c7eea85c463500460fe543fac3f55a018a470ba2a9e36e
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71b9e6cb0f06e700e1a436178296697ee449e72bb0bd434ac20339ff7e51280f
|
|
| MD5 |
a2420987eb37b49690d08023cf8a3668
|
|
| BLAKE2b-256 |
3927c1572692facb857c62daac4e30d211b037f78ab3443336647e93ad7b13d0
|