Text Documents Skewness Correction using OpenCV

Netra Prasad Neupane
2 min readJan 5, 2023

In this tutorial, I will explain the different text skew correction methods. Text skew correction is the basic image pre-processing step of Optical Character Recognition(OCR) and is mostly used for text-based image Alignment. In most cases, the text is not aligned horizontally in the image, so it needs to be aligned properly to get accurate text output from the OCR engine. A few skew correction strategies are:

  • Calculating the skewed angle of text lines using the Probabilistic Houghline transform, which I have explained here.
  • Finding a minimum rotated rectangle that contains the entire text region and rotating inversely.

In this tutorial, I will explain the second method to align the image using text skewness correction.

Let’s read the image, convert the image foreground to white and background to black, and apply otsu thresholding.

fig: input image
image = cv2.imread("image.jpeg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.bitwise_not(gray) # flip image background
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]

Now, we need to grab the (x, y) coordinates of all pixel values greater than zero, and then use these coordinates to compute a rotated bounding box containing all coordinates.

coords = np.column_stack(np.where(thresh > 0)) # (x,y) coordinates of pixels > 0
angle = cv2.minAreaRect(coords)[-1] # angle of minimum rotated bounding box

The cv2.minAreaRectfunction returns values in the range [-90, 0). We need to add 90 degrees to the angle because as the rectangle rotates clockwise the returned angle tends to 0.

if angle < -45:
angle = -(90 + angle)
# otherwise, just take the inverse of the angle to make
else:
angle = -angle

Now rotate the image by calculating RotationMatrix and applying warp affine transform to correct the skewness of the image.

(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0) # get rotation matrix
rotated_image = cv2.warpAffine(image, M, (w, h),
flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)

This is our final rotated_image.

fig: output rotated_image

I hope that this will help you to correct the skewness of your document. Thank you!

--

--

Netra Prasad Neupane

Machine Learning Engineer with expertise in Computer Vision, Deep Learning, NLP and Generative AI. https://www.linkedin.com/in/netraneupane/