Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Udayraj123
GitHub Repository: Udayraj123/OMRChecker
Path: blob/master/src/utils/image.py
228 views
1
"""
2
3
OMRChecker
4
5
Author: Udayraj Deshmukh
6
Github: https://github.com/Udayraj123
7
8
"""
9
import cv2
10
import matplotlib.pyplot as plt
11
import numpy as np
12
13
from src.logger import logger
14
15
plt.rcParams["figure.figsize"] = (10.0, 8.0)
16
CLAHE_HELPER = cv2.createCLAHE(clipLimit=5.0, tileGridSize=(8, 8))
17
18
19
class ImageUtils:
20
"""A Static-only Class to hold common image processing utilities & wrappers over OpenCV functions"""
21
22
@staticmethod
23
def save_img(path, final_marked):
24
logger.info(f"Saving Image to '{path}'")
25
cv2.imwrite(path, final_marked)
26
27
@staticmethod
28
def resize_util(img, u_width, u_height=None):
29
if u_height is None:
30
h, w = img.shape[:2]
31
u_height = int(h * u_width / w)
32
return cv2.resize(img, (int(u_width), int(u_height)))
33
34
@staticmethod
35
def resize_util_h(img, u_height, u_width=None):
36
if u_width is None:
37
h, w = img.shape[:2]
38
u_width = int(w * u_height / h)
39
return cv2.resize(img, (int(u_width), int(u_height)))
40
41
@staticmethod
42
def grab_contours(cnts):
43
# source: imutils package
44
45
# if the length the contours tuple returned by cv2.findContours
46
# is '2' then we are using either OpenCV v2.4, v4-beta, or
47
# v4-official
48
if len(cnts) == 2:
49
cnts = cnts[0]
50
51
# if the length of the contours tuple is '3' then we are using
52
# either OpenCV v3, v4-pre, or v4-alpha
53
elif len(cnts) == 3:
54
cnts = cnts[1]
55
56
# otherwise OpenCV has changed their cv2.findContours return
57
# signature yet again and I have no idea WTH is going on
58
else:
59
raise Exception(
60
(
61
"Contours tuple must have length 2 or 3, "
62
"otherwise OpenCV changed their cv2.findContours return "
63
"signature yet again. Refer to OpenCV's documentation "
64
"in that case"
65
)
66
)
67
68
# return the actual contours array
69
return cnts
70
71
@staticmethod
72
def normalize_util(img, alpha=0, beta=255):
73
return cv2.normalize(img, alpha, beta, norm_type=cv2.NORM_MINMAX)
74
75
@staticmethod
76
def auto_canny(image, sigma=0.93):
77
# compute the median of the single channel pixel intensities
78
v = np.median(image)
79
80
# apply automatic Canny edge detection using the computed median
81
lower = int(max(0, (1.0 - sigma) * v))
82
upper = int(min(255, (1.0 + sigma) * v))
83
edged = cv2.Canny(image, lower, upper)
84
85
# return the edged image
86
return edged
87
88
@staticmethod
89
def adjust_gamma(image, gamma=1.0):
90
# build a lookup table mapping the pixel values [0, 255] to
91
# their adjusted gamma values
92
inv_gamma = 1.0 / gamma
93
table = np.array(
94
[((i / 255.0) ** inv_gamma) * 255 for i in np.arange(0, 256)]
95
).astype("uint8")
96
97
# apply gamma correction using the lookup table
98
return cv2.LUT(image, table)
99
100
@staticmethod
101
def four_point_transform(image, pts):
102
# obtain a consistent order of the points and unpack them
103
# individually
104
rect = ImageUtils.order_points(pts)
105
(tl, tr, br, bl) = rect
106
107
# compute the width of the new image, which will be the
108
width_a = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
109
width_b = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
110
111
max_width = max(int(width_a), int(width_b))
112
# max_width = max(int(np.linalg.norm(br-bl)), int(np.linalg.norm(tr-tl)))
113
114
# compute the height of the new image, which will be the
115
height_a = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
116
height_b = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
117
max_height = max(int(height_a), int(height_b))
118
# max_height = max(int(np.linalg.norm(tr-br)), int(np.linalg.norm(tl-br)))
119
120
# now that we have the dimensions of the new image, construct
121
# the set of destination points to obtain a "birds eye view",
122
# (i.e. top-down view) of the image, again specifying points
123
# in the top-left, top-right, bottom-right, and bottom-left
124
# order
125
dst = np.array(
126
[
127
[0, 0],
128
[max_width - 1, 0],
129
[max_width - 1, max_height - 1],
130
[0, max_height - 1],
131
],
132
dtype="float32",
133
)
134
135
transform_matrix = cv2.getPerspectiveTransform(rect, dst)
136
warped = cv2.warpPerspective(image, transform_matrix, (max_width, max_height))
137
138
# return the warped image
139
return warped
140
141
@staticmethod
142
def order_points(pts):
143
rect = np.zeros((4, 2), dtype="float32")
144
145
# the top-left point will have the smallest sum, whereas
146
# the bottom-right point will have the largest sum
147
s = pts.sum(axis=1)
148
rect[0] = pts[np.argmin(s)]
149
rect[2] = pts[np.argmax(s)]
150
diff = np.diff(pts, axis=1)
151
rect[1] = pts[np.argmin(diff)]
152
rect[3] = pts[np.argmax(diff)]
153
154
# return the ordered coordinates
155
return rect
156
157