-
Notifications
You must be signed in to change notification settings - Fork 0
/
functions.py
executable file
·119 lines (93 loc) · 3.26 KB
/
functions.py
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# --------------------Image--------------
#
# |-------------> x-axis
# | $ $ $ $ $--------------------------------------------------------> (x, y)
# | $ $ $ $ $
# | $ $ $ $ $
# |
# y-axis
# --------------------numpy array--------------
#
# |-------------> x-axis
# | $ $ $ $ $--------------------------------------------------------> (y, x)
# | $ $ $ $ $
# | $ $ $ $ $
# |
# y-axis
import sys
import cv2 as cv
import numpy as np
from pathlib import Path
def read(path):
img = cv.imread(path, 0)
if type(img) == type(None):
sys.exit("Error!, Invalid path")
else:
return img
def resize(img, width=600):
b = width
a = b / img.shape[1]
return cv.resize(img, (b, int(img.shape[0] * a)), interpolation=cv.INTER_AREA)
def show(img, name='image'):
cv.imshow(name, img)
k = cv.waitKey(0) & 0xFF
cv.destroyAllWindows()
def apply_thresh(img):
return cv.adaptiveThreshold(img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 155, 20) # 155, 15
def get_box_coords(cnts):
boxes = np.zeros((len(cnts), 4), dtype='uint8')
for i, cnt in enumerate(cnts):
x, y, w, h = cv.boundingRect(cnt)
boxes[i] = x, y, w, h
return boxes
def get_area_wise_order(cnts):
def f(box):
return box[2] * box[3]
vfunc = np.vectorize(lambda cnt: f(cv.boundingRect(cnt)))
areas = vfunc(cnts)
order = np.argsort(areas)
return order
def squarify(img):
axis_0, axis_1 = img.shape
diff = np.abs(axis_0 - axis_1)
pad_1 = diff // 2
pad_2 = pad_1 + (diff % 2)
if axis_0 > axis_1:
return np.pad(img, ((0, 0), (pad_1, pad_2)), mode='constant', constant_values=255)
else:
return np.pad(img, ((pad_1, pad_2), (0, 0)), mode='constant', constant_values=255)
def save_all_masks(img, show_boxes, path):
cnts, _ = cv.findContours(255 - img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # 1st stage contour
pad_x = 2
pad_y = 2
mask = np.ones(img.shape, np.uint8) * 255
for cnt in cnts:
cv.drawContours(mask, [cnt], 0, (0, 0, 0), -1)
cnts, _ = cv.findContours(255 - mask, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # 2nd stage contour
cnts = np.asarray(cnts)
sizes = np.zeros(len(cnts))
max_size = 0
for i, cnt in enumerate(cnts):
size = cv.contourArea(cnt)
max_size = np.maximum(size, max_size)
sizes[i] = size
order = get_area_wise_order(cnts)
cnts = cnts[order]
sizes = sizes[order]
temp = img.copy()
for i, cnt in enumerate(cnts):
size = sizes[i]
if size > max_size / 20:
x, y, w, h = cv.boundingRect(cnt)
target = temp[y: y + h, x: x + w]
target = np.pad(target, (2, 2), mode='constant', constant_values=255)
target = squarify(target)
temp[y: y + h, x: x + w] = 255
img = cv.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 1)
cv.imwrite(str(path / f'{i}.png'), target)
else:
x, y, w, h = cv.boundingRect(cnt) # box enclosing given contour
temp[y: y + h, x: x + w] = 255
cv.imwrite(str(path / 'image_with_boxes.png'), img)
if show_boxes == True:
show(img)