-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathimpurity_extract.py
More file actions
200 lines (163 loc) · 6.87 KB
/
impurity_extract.py
File metadata and controls
200 lines (163 loc) · 6.87 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
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
import warnings
with warnings.catch_warnings():
warnings.filterwarnings("ignore",category=FutureWarning)
import os
import numpy as np
import cv2 as cv
from data_preparation import rescale_and_write_normalized_impurity
from shape_anomaly import get_circle_impurity_score
from utils import num_threads
import ray
import time
from absl import app
def get_markers(img, min_threshold, img_name):
"""
Get the impurities arranged with unique indices from an image (img).
Applies image processing.
"""
image = img.copy()
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(gray, min_threshold, 255, cv.THRESH_BINARY_INV)
# noise removal
kernel = np.ones((3, 3), np.uint8)
opening = cv.morphologyEx(thresh, cv.MORPH_CLOSE, kernel, iterations=1)
# sure background area
sure_bg = cv.dilate(opening, kernel, iterations=3)
sure_fg = opening
# Finding unknown region
sure_fg = np.uint8(sure_fg)
unknown = cv.subtract(sure_bg, sure_fg)
# Marker labelling
ret, markers = cv.connectedComponents(sure_fg)
# Add one to all labels so that sure background is not 0, but 1
markers = markers + 1
# Now, mark the region of unknown with zero
markers[unknown == 255] = 0
markers = cv.watershed(image, markers)
image[markers == -1] = [0, 0, 255]
print(img_name + ", number of impurities: " + str(ret))
return ret, markers
def bbox(img):
"""
Get the bounding box of an impurity in an image such that all of it is blank but the impurity itself.
"""
rows = np.any(img, axis=1)
cols = np.any(img, axis=0)
imp_rows = np.where(rows)[0]
imp_cols = np.where(cols)[0]
if len(imp_rows) > 0 and len(imp_cols):
rmin, rmax = imp_rows[[0, -1]]
cmin, cmax = imp_cols[[0, -1]]
cmin -= 1
rmin -= 1
cmax += 1
rmax += 1
else:
rmin, rmax, cmin, cmax = 0, 0, 0, 0
return int(rmin), int(rmax), int(cmin), int(cmax)
@ray.remote
def save_boxes_single(markers, impurities_list):
boxes = np.zeros((len(impurities_list), 4)) # impurities_num-1 elements, each with 4 features
for i in range(len(impurities_list)):
indx = markers == impurities_list[i]
rmin, rmax, cmin, cmax = bbox(indx)
boxes[i, :] = rmin, rmax, cmin, cmax
return boxes
def save_boxes(markers, impurities_num):
"""
Saves the bounding boxes
boxes[i-2] := (rmin, rmax, cmin, cmax) of impurity i
"""
start = time.time()
boxes = np.zeros((impurities_num - 1, 4)) # impurities_num-1 elements, each with 4 features
impurities_list = range(2, impurities_num + 1)
impurities_chunks = np.array_split(impurities_list, num_threads)
tasks = list()
for i in range(num_threads):
tasks.append(save_boxes_single.remote(markers, impurities_chunks[i]))
for i in range(num_threads):
task_out = ray.get(tasks[i])
boxes[impurities_chunks[i] - 2, :] = task_out[:, :]
end = time.time()
print("time save_boxes parallel: " + str(end - start))
return boxes
def save_boxes_not_parallel(markers, impurities_num):
"""
Saves the bounding boxes
boxes[i-2] := (rmin, rmax, cmin, cmax) of impurity i
"""
start = time.time()
boxes = np.zeros((impurities_num - 1, 4)) # impurities_num-1 elements, each with 4 features
for impurity in range(2, impurities_num + 1):
indx = markers == impurity
rmin, rmax, cmin, cmax = bbox(indx)
boxes[impurity - 2, :] = rmin, rmax, cmin, cmax
end = time.time()
print("time save_boxes not parallel: " + str(end - start))
return boxes
@ray.remote
def get_impurity_areas_and_significant_indices_single(markers, impurities_chunks, min_area):
imp_area = np.zeros(len(impurities_chunks))
indices = []
for i in range(len(impurities_chunks)):
impurity = impurities_chunks[i]
impurity_shape = np.argwhere(markers == impurity + 2)
area = impurity_shape.shape[0]
imp_area[i] = area
if area > min_area:
indices.append(impurity)
return imp_area, indices
def get_impurity_areas_and_significant_indices(imp_boxes, markers, min_area=3):
start = time.time()
imp_area = np.zeros(imp_boxes.shape[0])
indices = []
impurities_chunks = np.array_split(range(imp_boxes.shape[0]), num_threads)
tasks = list()
for i in range(num_threads):
tasks.append(get_impurity_areas_and_significant_indices_single.remote(markers, impurities_chunks[i], min_area))
for i in range(num_threads):
task_out_areas, task_out_indices = ray.get(tasks[i])
imp_area[impurities_chunks[i]] = task_out_areas[:] # order is important
indices.extend(task_out_indices) # order is not important
end = time.time()
print("time get_impurity_areas_and_significant_indices parallel: " + str(end - start))
return imp_area, indices
def get_impurity_areas_and_significant_indices_not_parallel(imp_boxes, markers, min_area=3):
start = time.time()
imp_area = []
indices = []
for impurity in range(imp_boxes.shape[0]):
impurity_shape = np.argwhere(markers == impurity + 2)
area = impurity_shape.shape[0]
imp_area.append(area)
if area > min_area:
indices.append(impurity)
end = time.time()
print("time get_impurity_areas_and_significant_indices not parallel: " + str(end - start))
return imp_area, indices
def normalize_all_impurities(dir_path):
scans_dir = os.listdir(dir_path)
for img_path in scans_dir:
img_name = os.path.splitext(os.path.basename(img_path))[0]
img = cv.imread(dir_path + img_path)
ret, markers = get_markers(img)
imp_boxes = save_boxes(markers, ret)
areas, indices = get_impurity_areas_and_significant_indices(imp_boxes, markers)
scores = get_circle_impurity_score(markers, imp_boxes, areas, indices)
rescale_and_write_normalized_impurity(img, markers, imp_boxes, areas, indices, scores, scan_name=img_name,
dest_path_normal="./data/rescaled_extended/normal/",
dest_path_anomaly="./data/rescaled_extended/anomaly/"
)
def extract_impurities(img_path, use_ray, min_threshold=0, black_background=True):
img = cv.imread(img_path)
if black_background:
img = 255 - img
img_name = os.path.splitext(os.path.basename(img_path))[0]
ret, markers = get_markers(img, min_threshold, img_name)
if use_ray:
imp_boxes = save_boxes(markers, ret)
areas, indices = get_impurity_areas_and_significant_indices(imp_boxes, markers)
else:
imp_boxes = save_boxes_not_parallel(markers, ret)
areas, indices = get_impurity_areas_and_significant_indices_not_parallel(imp_boxes, markers)
return img, ret, markers, imp_boxes, areas, indices