Install deskew via pip
masterYou can install the deskew library directly from PyPI using pip. To upgrade to a newer version, use the -U flag.
python3 -m pip install deskew
# Or to upgrade
python3 -m pip install -U deskewrepository·master·Indexed 17 days ago
https://github.com/sbrunner/deskewA Python library for detecting and correcting skew (rotation) in images containing text. It provides the `determine_skew` function to calculate rotation angles, a CLI for angle estimation and image correction, and debugging tools via `determine_skew_debug_images` to visualize the Hough transform process. The library integrates with scikit-image and OpenCV for applying image rotations.
You can install the deskew library directly from PyPI using pip. To upgrade to a newer version, use the -U flag.
python3 -m pip install deskew
# Or to upgrade
python3 -m pip install -U deskewIf the detected skew angle is incorrect, you can generate debug images to inspect the detection process.
pip install deskew[debug_images]determine_skew_debug_images to generate visual aids.num_peaks (default is 20; try increasing this first)angle_pm_90min_anglemax_anglemin_deviationsigmaTo deskew an image using OpenCV, use determine_skew on a grayscale version of the image. Because OpenCV's standard rotation might crop the image, you may need a custom rotation function (like the one provided in the example below) that calculates the new bounding box dimensions to accommodate the rotated content.
import math
import cv2
import numpy as np
from typing import Tuple, Union
from deskew import determine_skew
def rotate(
image: np.ndarray, angle: float, background: Union[int, Tuple[int, int, int]]
) -> np.ndarray:
old_width, old_height = image.shape[:2]
angle_radian = math.radians(angle)
width = abs(np.sin(angle_radian) * old_height) + abs(np.cos(angle_radian) * old_width)
height = abs(np.sin(angle_radian) * old_width) + abs(np.cos(angle_radian) * old_height)
image_center = tuple(np.array(image.shape[1::-1]) / 2)
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
rot_mat[1, 2] += (width - old_width) / 2
rot_mat[0, 2] += (height - old_height) / 2
return cv2.warpAffine(image, rot_mat, (int(round(height)), int(round(width))), borderValue=background)
image = cv2.imread('input.png')
grayscale = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
angle = determine_skew(grayscale)
rotated = rotate(image, angle, (0, 0, 0))
cv2.imwrite('output.png', rotated)To deskew an image using scikit-image, use determine_skew to find the angle and skimage.transform.rotate to apply the correction. Note that when rotating, you should set resize=True to ensure the image content is not cropped.
import numpy as np
from skimage import io
from skimage.color import rgb2gray
from skimage.transform import rotate
from deskew import determine_skew
image = io.imread('input.png')
grayscale = rgb2gray(image)
angle = determine_skew(grayscale)
# Rotate and rescale to prevent cropping
rotated = rotate(image, angle, resize=True) * 255
io.imsave('output.png', rotated.astype(np.uint8))The core function determine_skew calculates the skew angle of an image containing text. It typically expects a grayscale image as input.
By default, the returned angle is between -45 and 45 degrees to prevent arbitrary changes to image orientation. If you require an angle between -90 and 90 degrees, set the angle_pm_90 argument to True.
from deskew import determine_skew
from skimage import io
from skimage.color import rgb2gray
image = io.imread('input.png')
grayscale = rgb2gray(image)
angle = determine_skew(grayscale)
print(f"Detected angle: {angle}")The deskew command-line interface allows you to either detect the skew angle of an image or perform the deskewing operation directly.
# Get the skew angle
deskew input.png
# Deskew an image and save to a specific output file
deskew --output output.png input.pngUse determine_skew_debug_images() to visualize the internal steps of the skew detection process. This is useful for troubleshooting why a specific angle was chosen or why no angle was detected.
Returns:
Returns a tuple (angle_deg, debug_images) where:
angle_deg: float | None (the detected angle in degrees).debug_images: A list of tuples (name, image_array) containing:"hough_transform": A visualization of the Hough transform space."detected_lines": The original image with detected lines overlaid."polar_angles": Polar plots showing original and corrected angle frequencies.Note: This function requires cv2 (OpenCV) and matplotlib to be installed. It also attempts to use gm (GraphicsMagick) to flatten transparent backgrounds in the generated plots.
Parameters:
Identical to determine_skew(), but min_angle and max_angle are treated as degrees and converted to radians internally.
from deskew import determine_skew_debug_images
angle, debug_imgs = determine_skew_debug_images(image)
for name, img in debug_imgs:
print(f"Displaying debug image: {name}")
# Use cv2.imshow or similar to view 'img'Use determine_skew() to find the rotation angle (in degrees) of text within an image. This is the primary high-level function for skew detection.
Parameters:
image: Input image as a NumPy array (ImageType).sigma: Standard deviation of the Gaussian filter used for edge detection (default: 3.0).num_peaks: Number of peaks to detect in the Hough transform (default: 20).num_angles: (Deprecated) Number of angles to consider. Use min_deviation instead.angle_pm_90: If True, considers angles in the range [-180, 180] instead of [-90, 90].min_angle: Minimum angle to consider (in degrees).max_angle: Maximum angle to consider (in degrees).min_deviation: Minimum deviation between angles (in degrees, default: 1.0).Returns:
float: The detected skew angle in degrees.None: If no skew is detected.import numpy as np
from deskew import determine_skew
# Load your image as a numpy array
image = np.array(your_image_data)
# Calculate the skew angle
angle = determine_skew(image, sigma=3.0, min_angle=-10, max_angle=10)
if angle is not None:
print(f"Detected skew angle: {angle} degrees")
else:
print("No skew detected")Use determine_skew_dev() when you need more than just the final angle. It returns the angle in radians along with a detailed tuple containing the raw Hough transform data, peak data, and frequency distributions of detected angles.
Returns:
Returns a tuple (angle, data) where:
angle: np.float64 | None (the detected angle in radians).data: A nested tuple containing:hough_line_out: (hspace, angles, distances) from skimage.transform.hough_line.hough_line_peaks_out: (hspace, angles_peaks, dists) from skimage.feature.hough_line_peaks.all_freqs: (freqs_original, freqs) where both are dict[np.float64, int] mapping angles to their occurrence frequency.from deskew import determine_skew_dev
angle_rad, data = determine_skew_dev(image)
if angle_rad is not None:
print(f"Angle in radians: {angle_rad}")
# Access raw Hough data for custom analysis
hspace, angles, distances = data[0]The following flags are available when using the deskew command line interface:
| Flag | Default | Description |
|---|---|---|
-o, --output | None | Output file path for the corrected image. |
--sigma | 3.0 | Blur strength (Gaussian sigma). Higher values reduce noise but may miss fine details. |
--num-peaks | 20 | Number of peaks to detect. More peaks can improve accuracy but increase processing time. |
--num-angles | 180 | The number of angles to check (search precision). Higher values provide better precision but are slower. |
--background | None | Background color for rotated image corners. Use a single value for grayscale or comma-separated RGB values (e.g., 255,255,255). |
input | (Required) | The input file name. |
# Example with custom parameters
deskew input.jpg --output out.jpg --sigma 2.0 --num-peaks 30 --background 255,255,255The deskew CLI allows you to either estimate the skew angle of a tilted image or save a corrected (rotated) version of that image.
By default, if no output file is specified, the tool prints the estimated angle to the console. If an output path is provided via --output, the tool saves the rotated image.
# Estimate the angle and print to console
deskew input_image.png
# Rotate the image and save to a file
deskew input_image.png --output corrected_image.pngdeskew input_image.png --output corrected_image.png