|
| 1 | +import numpy as np |
| 2 | +import argparse |
| 3 | +import cv2 |
| 4 | + |
| 5 | +# construct the argument parse and parse the arguments |
| 6 | +ap = argparse.ArgumentParser() |
| 7 | +ap.add_argument("-i", "--image", required=True, help="path to input image file") |
| 8 | +args = vars(ap.parse_args()) |
| 9 | + |
| 10 | +# load the image from disk |
| 11 | +image = cv2.imread(args["image"]) |
| 12 | + |
| 13 | +# convert the image to grayscale and flip the foreground |
| 14 | +# and background to ensure foreground is now "white" and |
| 15 | +# the background is "black" |
| 16 | +gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) |
| 17 | +gray = cv2.bitwise_not(gray) |
| 18 | + |
| 19 | +# threshold the image, setting all foreground pixels to |
| 20 | +# 255 and all background pixels to 0 |
| 21 | +thresh = cv2.threshold(gray, 0, 255, |
| 22 | + cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1] |
| 23 | + |
| 24 | +# grab the (x, y) coordinates of all pixel values that |
| 25 | +# are greater than zero, then use these coordinates to |
| 26 | +# compute a rotated bounding box that contains all |
| 27 | +# coordinates |
| 28 | +coords = np.column_stack(np.where(thresh > 0)) |
| 29 | +angle = cv2.minAreaRect(coords)[-1] |
| 30 | + |
| 31 | +# the `cv2.minAreaRect` function returns values in the |
| 32 | +# range [-90, 0); as the rectangle rotates clockwise the |
| 33 | +# returned angle trends to 0 -- in this special case we |
| 34 | +# need to add 90 degrees to the angle |
| 35 | +if angle < -45: |
| 36 | + angle = -(90 + angle) |
| 37 | + |
| 38 | +# otherwise, just take the inverse of the angle to make |
| 39 | +# it positive |
| 40 | +else: |
| 41 | + angle = -angle |
| 42 | + |
| 43 | +# rotate the image to deskew it |
| 44 | +(h, w) = image.shape[:2] |
| 45 | +center = (w // 2, h // 2) |
| 46 | +M = cv2.getRotationMatrix2D(center, angle, 1.0) |
| 47 | +rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE) |
| 48 | + |
| 49 | +# draw the correction angle on the image so we can validate it |
| 50 | +cv2.putText(rotated, "Angle: {:.2f} degrees".format(angle),(10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) |
| 51 | + |
| 52 | +# show the output image |
| 53 | +print("[INFO] angle: {:.3f}".format(angle)) |
| 54 | +cv2.imshow("Input", image) |
| 55 | +cv2.imshow("Rotated", rotated) |
| 56 | +cv2.waitKey(0) |
0 commit comments