-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrotation_utils.py
More file actions
82 lines (65 loc) · 2.73 KB
/
Copy pathrotation_utils.py
File metadata and controls
82 lines (65 loc) · 2.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# rotations_utils.py
import cv2 as cv
import numpy as np
import logging
from utils import display_image
def order_points(pts):
"""
Order points in the following order:
top-left, top-right, bottom-right, bottom-left.
"""
rect = np.zeros((4, 2), dtype="float32")
# The top-left point has the smallest sum,
# the bottom-right has the largest sum.
s = pts.sum(axis=1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
# The top-right has the smallest difference,
# the bottom-left has the largest difference.
diff = np.diff(pts, axis=1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
return rect
def rotate_plate(plate_image):
if plate_image is None:
raise ValueError("Image not found or could not be loaded.")
# Convert to grayscale and apply preprocessing
gray = cv.cvtColor(plate_image, cv.COLOR_BGR2GRAY)
blurred = cv.medianBlur(gray, 5)
high_contrast = cv.convertScaleAbs(blurred, alpha=2, beta=-50)
_, thresholded = cv.threshold(high_contrast, 200, 255, cv.THRESH_BINARY)
dilated = cv.dilate(thresholded, None, iterations=1)
# Find the largest contour
contours, _ = cv.findContours(dilated, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
if not contours:
raise ValueError("No contours found in the image.")
max_contour = max(contours, key=cv.contourArea)
if max_contour is None:
raise ValueError("No valid contour found in the image.")
# Obtain the bounding box from the minimum area rectangle
rect = cv.minAreaRect(max_contour)
box = cv.boxPoints(rect)
box = np.array(box, dtype="float32")
# Order the points: top-left, top-right, bottom-right, bottom-left
ordered_box = order_points(box)
(tl, tr, br, bl) = ordered_box
# Compute the width of the new image (max of top or bottom side)
widthA = np.linalg.norm(br - bl)
widthB = np.linalg.norm(tr - tl)
maxWidth = int(max(widthA, widthB))
# Compute the height of the new image (max of left or right side)
heightA = np.linalg.norm(tr - br)
heightB = np.linalg.norm(tl - bl)
maxHeight = int(max(heightA, heightB))
# Define destination points for perspective transform using computed dimensions
dst_pts = np.array([
[0, 0],
[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],
[0, maxHeight - 1]
], dtype="float32")
# Get the perspective transform matrix and warp the image
M = cv.getPerspectiveTransform(ordered_box, dst_pts)
corrected_perspective = cv.warpPerspective(plate_image, M, (maxWidth, maxHeight))
display_image(corrected_perspective, title="Corrected Perspective")
return corrected_perspective