Auto Rotate on Edges
Automatically rotate an image so its dominant straight edges become vertical and/or horizontal.
Automatically deskew an image by finding the rotation angle that best aligns the image's dominant straight edges (e.g. the sides of a document, package, panel, or shelf) to the vertical axis, the horizontal axis, or whichever of the two is closest, then rotating the full-resolution image by that angle with an automatically expanded canvas so nothing is cropped.
How This Block Works
This block estimates the rotation angle from the image's dominant gradient orientation, then applies that rotation to the image. The block:
Converts the image to grayscale (color images are converted with
BGR2GRAY)Downscales a working copy so its largest dimension is at most
internal_resolutionpixels (default 1000, for speed; the detected angle is scale-invariant and is later applied to the full-resolution original)Checks for a flat/low-texture image (very low pixel standard deviation) and, if found, skips processing and returns the image unchanged with
angle = 0.0Enhances local contrast with CLAHE and applies a light Gaussian blur to reduce noise sensitivity, producing a float32 image used only for scoring candidate angles
Computes Sobel gradients once and builds a magnitude-weighted histogram of gradient orientations (mod 180 degrees): gradients of the dominant lines point perpendicular to the lines themselves, so vertical lines concentrate the histogram around 0 degrees and horizontal lines around 90 degrees
Rejects indistinct histograms (no clearly dominant orientation) and returns the image unchanged
Refines the histogram's dominant mode with a doubled-angle weighted circular mean over nearby orientations for sub-degree precision, and normalizes the correction into
(-90, 90]degrees forvertical/horizontalor(-45, 45]degrees foreitherIf the final angle is smaller in magnitude than
skip_below_degrees, returns the image unchanged withangle = 0.0(avoids unnecessary re-encoding/resampling for already-straight images). Likewise, if the final angle is larger in magnitude thanmax_correction_degrees, the image is returned unchanged withangle = 0.0- a correction beyond the plausible skew range usually means the search aligned to a different dominant structure (e.g. a long object silhouette) rather than the lines of interestOtherwise rotates the full-resolution original image by the final angle around its center, automatically expanding the output canvas so the entire rotated image is preserved (matching the canvas-expansion behavior of
roboflow_core/image_preprocessing@v1's rotate task)
The block outputs both the deskewed image (with expanded canvas) and the applied rotation angle in degrees. Angles follow OpenCV's convention: positive angles rotate counter-clockwise.
Common Use Cases
Document and Label Scanning: Straighten photographed documents, labels, or packaging before OCR or downstream detection, improving text and barcode reading accuracy
Fixed-Camera Inspection: Correct small mounting-induced tilts in fixed-position industrial cameras so downstream measurement blocks (e.g. size or distance measurement) operate on axis-aligned imagery
Conveyor and Shelf Alignment: Align images of conveyors, shelving, or panels whose edges should be vertical or horizontal, improving the reliability of downstream line/edge-based analysis
Pre-processing for Detection Models: Straighten input images before running object detection or classification models that are sensitive to rotation
Connecting to Other Blocks
This block receives an image and produces a deskewed image plus the applied angle:
Before detection or classification models to straighten images prior to inference, enabling more reliable model outputs on tilted source imagery
Before measurement blocks (e.g. distance or size measurement) that assume an axis-aligned scene
With downstream coordinate mapping - the
angleoutput (together with the original image's dimensions) fully determines the applied transform, so detections made on the rotated image can be mapped back into the original image's coordinate space by inverting the rotation matrix built bybuild_auto_rotate_matrix
Type identifier
Use the following identifier in step "type" field: roboflow_core/auto_rotate_on_edges@v1 to add the block as a step in your workflow.
Properties
Name
Type
Description
Refs
name
str
Enter a unique identifier for this step..
❌
target_orientation
str
Which edge direction the image's dominant straight lines should be aligned to. 'vertical' searches for the rotation that makes the dominant lines vertical, 'horizontal' searches for the rotation that makes the dominant lines horizontal, and 'either' aligns to whichever of the two is closest (search is limited to a +/-45 degree range around the nearest right angle)..
✅
skip_below_degrees
float
If the detected correction angle's absolute value is smaller than this threshold (in degrees), the block returns the input image unchanged (identity passthrough) with angle = 0.0, avoiding unnecessary re-encoding/resampling of images that are already sufficiently straight..
✅
max_correction_degrees
float
If the best correction angle found exceeds this cap (in absolute degrees), the block returns the input image unchanged (identity passthrough) with angle = 0.0. Set this when the plausible skew range of your imagery is known (e.g. parts photographed at most ~40 degrees off-axis) so that a different dominant structure in the image (e.g. a long object silhouette instead of the lines of interest) cannot cause a wild, incorrect rotation. The default of 90.0 disables the cap..
✅
internal_resolution
int
The rotation-angle search runs on a working copy of the image downscaled so that its longest side is at most this many pixels; the full-resolution image is only used for the final rotation. Lower values make the search faster but can blur very thin lines; higher values preserve fine-line detail at the cost of search time..
✅
The Refs column marks possibility to parametrise the property with dynamic values available in workflow runtime. See Bindings for more info.
Input and Output Bindings
The available connections depend on its binding kinds. Check what binding kinds Auto Rotate on Edges in version v1 has.
Input and output bindings
input
image(image): Input image (color or grayscale) to deskew. Color images are automatically converted to grayscale for angle detection; the detected rotation angle is applied to the full-resolution original image. The output includes both the rotated image (with an automatically expanded canvas) and the appliedanglein degrees..target_orientation(string): Which edge direction the image's dominant straight lines should be aligned to. 'vertical' searches for the rotation that makes the dominant lines vertical, 'horizontal' searches for the rotation that makes the dominant lines horizontal, and 'either' aligns to whichever of the two is closest (search is limited to a +/-45 degree range around the nearest right angle)..skip_below_degrees(float): If the detected correction angle's absolute value is smaller than this threshold (in degrees), the block returns the input image unchanged (identity passthrough) withangle = 0.0, avoiding unnecessary re-encoding/resampling of images that are already sufficiently straight..max_correction_degrees(float): If the best correction angle found exceeds this cap (in absolute degrees), the block returns the input image unchanged (identity passthrough) withangle = 0.0. Set this when the plausible skew range of your imagery is known (e.g. parts photographed at most ~40 degrees off-axis) so that a different dominant structure in the image (e.g. a long object silhouette instead of the lines of interest) cannot cause a wild, incorrect rotation. The default of 90.0 disables the cap..internal_resolution(integer): The rotation-angle search runs on a working copy of the image downscaled so that its longest side is at most this many pixels; the full-resolution image is only used for the final rotation. Lower values make the search faster but can blur very thin lines; higher values preserve fine-line detail at the cost of search time..
Last updated
Was this helpful?