dibahadie commited on
Commit
681cbb8
1 Parent(s): 9adda2a

Upload 3 files

Browse files
Files changed (3) hide show
  1. predict_database.py +13 -0
  2. segment_key.py +344 -0
  3. test.py +82 -0
predict_database.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from segment_key import final_features
4
+
5
+ image_dir = '../augmentation/testing/3'
6
+
7
+ for filename in os.listdir(image_dir):
8
+ if filename.endswith('.jpg'):
9
+ image_path = os.path.join(image_dir, filename)
10
+ features = final_features(image_path)
11
+ with open('./prediction/database.txt', 'a+') as f:
12
+ f.write(filename + ';' + str(features) + '\n')
13
+ print('successfully predicted ' + filename)
segment_key.py ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+
3
+ import cv2
4
+ import imutils
5
+ import numpy as np
6
+ from sklearn.preprocessing import MinMaxScaler
7
+ from ultralytics import YOLO
8
+
9
+ from models.birefnet import BiRefNet
10
+ from util.utils import check_state_dict
11
+ from PIL import Image
12
+ import torch
13
+ from torchvision import transforms
14
+ from openvino.runtime import Core
15
+
16
+ model = BiRefNet(bb_pretrained=False)
17
+ state_dict = torch.load('models/weights/BiRefNet-general-epoch_244.pth', map_location='cpu')
18
+ state_dict = check_state_dict(state_dict)
19
+ model.load_state_dict(state_dict)
20
+
21
+ # Input Data
22
+ transform_image = transforms.Compose([
23
+ transforms.Resize((1024, 1024)),
24
+ transforms.ToTensor(),
25
+ transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
26
+ ])
27
+
28
+ import torch
29
+ from PIL import Image
30
+ import torchvision.transforms as transforms
31
+
32
+
33
+ def export_to_onnx(model, dummy_input, onnx_path='model.onnx'):
34
+ # Export the PyTorch model to ONNX format
35
+ torch.onnx.export(model, dummy_input, onnx_path, verbose=True, input_names=['input'], output_names=['output'])
36
+
37
+
38
+ image = Image.open('./examples/img.jpg')
39
+ dummy_input = torch.randn(1, 3, 224, 224) # Adjust input size to match your model
40
+ export_to_onnx(model, image)
41
+
42
+
43
+ def pred_segmentation(image, box=[-1, -1, -1, -1]):
44
+ core = Core()
45
+ model_path = 'model_ir/model.xml'
46
+ compiled_model = core.compile_model(model_path, device_name='GPU') # Use "GPU" to target Intel GPU
47
+ print('predicting segmentation...')
48
+
49
+ # box: left, top, right, bottom
50
+ w, h = image.size[:2]
51
+
52
+ # Adjust box coordinates if necessary
53
+ for idx_coord_value, coord_value in enumerate(box):
54
+ if coord_value == -1:
55
+ box[idx_coord_value] = [0, 0, w, h][idx_coord_value]
56
+
57
+ # Crop the image based on the box
58
+ image_crop = image.crop(box)
59
+
60
+ # Transform the image
61
+ input_image = transform_image(image_crop)
62
+ input_image = np.expand_dims(input_image, axis=0) # Add batch dimension
63
+
64
+ # Run inference
65
+ infer_request = compiled_model.create_infer_request()
66
+ result = infer_request.infer(inputs={'input': input_image})
67
+
68
+ pred = result['output'][0] # Adjust if output name is different
69
+
70
+ # Post-process predictions
71
+ canvas = np.zeros_like(pred)
72
+
73
+ # Calculate the bounding box to place the result back on the canvas
74
+ box_to_canvas = [
75
+ int(round(coord_value * (canvas.shape[-1] / w, canvas.shape[-2] / h)[idx_coord_value % 2]))
76
+ for idx_coord_value, coord_value in enumerate(box)
77
+ ]
78
+
79
+ pred = np.resize(pred, (box_to_canvas[3] - box_to_canvas[1], box_to_canvas[2] - box_to_canvas[0]))
80
+
81
+ canvas[box_to_canvas[1]:box_to_canvas[3], box_to_canvas[0]:box_to_canvas[2]] = pred
82
+
83
+ # Convert the canvas to PIL image for visualization
84
+ pred_pil = Image.fromarray((canvas * 255).astype(np.uint8)) # Rescale to [0, 255] for visualization
85
+
86
+ return pred_pil
87
+
88
+
89
+ def pred_bbox(image_path):
90
+ print('predicting bounding box...')
91
+ image = cv2.imread(image_path)
92
+ model = YOLO('models/weights/yolo_finetuned.pt')
93
+
94
+ # Perform prediction
95
+ results = model(image)
96
+ boxes = results[0].boxes.xyxy.cpu().numpy()[0]
97
+
98
+ # Extract the bounding box coordinates
99
+ x1, y1, x2, y2 = map(int, list(boxes))
100
+ return [x1, y1, x2, y2]
101
+
102
+
103
+ def get_kps_from_pil(pil_image):
104
+ print('converting keypoints...')
105
+ image_array = np.array(pil_image)
106
+
107
+ # Find contours using OpenCV
108
+ contours, _ = cv2.findContours(image_array, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
109
+
110
+ # Find the largest contour by area
111
+ largest_contour = max(contours, key=cv2.contourArea)
112
+ largest_contour = np.array(largest_contour)
113
+ contour = []
114
+ for i in range(len(largest_contour)):
115
+ contour.append(largest_contour[i][0])
116
+ scaler = MinMaxScaler()
117
+ kps = scaler.fit_transform(contour)
118
+ kps = np.array(kps)
119
+ kps = kps * 299
120
+ kps = np.int32(kps)
121
+ return kps
122
+
123
+
124
+ def get_features_up(contour):
125
+ feature = []
126
+ for i in range(0, 300):
127
+ position = 0
128
+ unsorted_features = []
129
+ for j in range(len(contour)):
130
+ point = contour[j]
131
+ prev_point = point
132
+ if j != 0:
133
+ prev_point = contour[j - 1]
134
+ if point[0] > i and position == 0:
135
+ position = 1
136
+ elif point[0] < i and position == 0:
137
+ position = -1
138
+ elif point[0] > i and position == -1:
139
+ unsorted_features.append((point[1] + prev_point[1]) // 2)
140
+ position = 1
141
+ elif point[0] < i and position == 1:
142
+ position = -1
143
+ unsorted_features.append((point[1] + prev_point[1]) // 2)
144
+ elif point[0] == i and position == 1:
145
+ unsorted_features.append(point[1])
146
+ position = -1
147
+ elif point[0] == i and position == -1:
148
+ unsorted_features.append(point[1])
149
+ position = 1
150
+ elif point[0] == i and position == 0:
151
+ position = 1
152
+
153
+ if len(unsorted_features) != 0:
154
+ if len(unsorted_features) == 1:
155
+ unsorted_features.append((contour[0][1] + contour[-1][1]) // 2)
156
+ unsorted_features.sort()
157
+ feature.append(max(unsorted_features))
158
+ else:
159
+ feature.append(-1)
160
+
161
+ return feature
162
+
163
+
164
+ def get_features_down(contour):
165
+ feature = []
166
+ for i in range(0, 300):
167
+ position = 0
168
+ unsorted_features = []
169
+ for j in range(len(contour)):
170
+ point = contour[j]
171
+ prev_point = point
172
+ if j != 0:
173
+ prev_point = contour[j - 1]
174
+ if point[0] > i and position == 0:
175
+ position = 1
176
+ elif point[0] < i and position == 0:
177
+ position = -1
178
+ elif point[0] > i and position == -1:
179
+ unsorted_features.append((point[1] + prev_point[1]) // 2)
180
+ position = 1
181
+ elif point[0] < i and position == 1:
182
+ position = -1
183
+ unsorted_features.append((point[1] + prev_point[1]) // 2)
184
+ elif point[0] == i and position == 1:
185
+ unsorted_features.append(point[1])
186
+ position = -1
187
+ elif point[0] == i and position == -1:
188
+ unsorted_features.append(point[1])
189
+ position = 1
190
+ elif point[0] == i and position == 0:
191
+ position = 1
192
+
193
+ if len(unsorted_features) != 0:
194
+ if len(unsorted_features) == 1:
195
+ unsorted_features.append((contour[0][1] + contour[-1][1]) // 2)
196
+ unsorted_features.sort()
197
+ feature.append(min(unsorted_features))
198
+ else:
199
+ feature.append(-1)
200
+
201
+ return feature
202
+
203
+
204
+ def get_features_right(contour):
205
+ feature = []
206
+ for i in range(0, 300):
207
+ position = 0
208
+ unsorted_features = []
209
+ for j in range(len(contour)):
210
+ point = contour[j]
211
+ prev_point = point
212
+ if j != 0:
213
+ prev_point = contour[j - 1]
214
+ if point[1] > i and position == 0:
215
+ position = 1
216
+ elif point[1] < i and position == 0:
217
+ position = -1
218
+ elif point[1] > i and position == -1:
219
+ unsorted_features.append((point[0] + prev_point[0]) // 2)
220
+ position = 1
221
+ elif point[1] < i and position == 1:
222
+ position = -1
223
+ unsorted_features.append((point[0] + prev_point[0]) // 2)
224
+ elif point[1] == i and position == 1:
225
+ unsorted_features.append(point[0])
226
+ position = -1
227
+ elif point[1] == i and position == -1:
228
+ unsorted_features.append(point[0])
229
+ position = 1
230
+ elif point[1] == i and position == 0:
231
+ position = 1
232
+
233
+ if len(unsorted_features) != 0:
234
+ if len(unsorted_features) == 1:
235
+ unsorted_features.append((contour[0][0] + contour[-1][0]) // 2)
236
+ unsorted_features.sort()
237
+ feature.append(min(unsorted_features))
238
+ else:
239
+ feature.append(-1)
240
+
241
+ return feature
242
+
243
+
244
+ def get_features_left(contour):
245
+ feature = []
246
+ for i in range(0, 300):
247
+ position = 0
248
+ unsorted_features = []
249
+ for j in range(len(contour)):
250
+ point = contour[j]
251
+ prev_point = point
252
+ if j != 0:
253
+ prev_point = contour[j - 1]
254
+ if point[1] > i and position == 0:
255
+ position = 1
256
+ elif point[1] < i and position == 0:
257
+ position = -1
258
+ elif point[1] > i and position == -1:
259
+ unsorted_features.append((point[0] + prev_point[0]) // 2)
260
+ position = 1
261
+ elif point[1] < i and position == 1:
262
+ position = -1
263
+ unsorted_features.append((point[0] + prev_point[0]) // 2)
264
+ elif point[1] == i and position == 1:
265
+ unsorted_features.append(point[0])
266
+ position = -1
267
+ elif point[1] == i and position == -1:
268
+ unsorted_features.append(point[0])
269
+ position = 1
270
+ elif point[1] == i and position == 0:
271
+ position = 1
272
+
273
+ if len(unsorted_features) != 0:
274
+ if len(unsorted_features) == 1:
275
+ unsorted_features.append((contour[0][0] + contour[-1][0]) // 2)
276
+ unsorted_features.sort()
277
+ feature.append(max(unsorted_features))
278
+ else:
279
+ feature.append(-1)
280
+
281
+ return feature
282
+
283
+
284
+ def extract_features(contour):
285
+ print('extracting features...')
286
+ return get_features_down(contour) + get_features_up(contour) + get_features_right(contour) + get_features_left(contour)
287
+
288
+
289
+ def final_features(image_path):
290
+ image = Image.open(image_path)
291
+ image = rotate_image(image)
292
+ pil_image = pred_segmentation(image, pred_bbox(image_path))
293
+ contour = get_kps_from_pil(pil_image)
294
+ return extract_features(contour)
295
+
296
+
297
+ def predict_kps(image):
298
+ model = YOLO('models/weights/yolo_finetuned.pt')
299
+ # Perform prediction
300
+ results = model(image)
301
+ kps = results[0].masks.xy[0]
302
+ return kps
303
+
304
+
305
+ def calculate_angle(p1, p2):
306
+ delta_y = p2[1] - p1[1]
307
+ delta_x = p2[0] - p1[0]
308
+ return math.degrees(np.arctan2(delta_y, delta_x))
309
+
310
+
311
+ # Function to rotate points by a given angle
312
+ def calculate_square(img):
313
+ np_image = np.array(img)
314
+ # Convert RGB (PIL) to BGR (OpenCV)
315
+ if np_image.ndim == 3: # Check if the image is colored
316
+ cv_image = cv2.cvtColor(np_image, cv2.COLOR_RGB2BGR)
317
+ else:
318
+ # For grayscale images, no conversion is needed
319
+ cv_image = np_image
320
+
321
+ rect = cv2.minAreaRect(predict_kps(cv_image))
322
+ box = cv2.boxPoints(rect)
323
+ box = np.int32(box)
324
+ return box
325
+
326
+
327
+ def rotate_image(image):
328
+ square = calculate_square(image)
329
+ # Calculate the lengths of the sides
330
+ side_lengths = [np.linalg.norm(square[i] - square[i + 1]) for i in range(len(square) - 1)]
331
+
332
+ # Find the indices of the larger side
333
+ max_index = np.argmax(side_lengths)
334
+
335
+ # Find the two points that form the largest side
336
+ p1, p2 = square[max_index], square[max_index + 1]
337
+
338
+ # Calculate the angle between this side and the horizontal axis
339
+ angle = calculate_angle(p1, p2)
340
+
341
+ # Rotate the square to align the largest side with the horizontal axis
342
+ rotated_image = image.rotate(angle)
343
+
344
+ return rotated_image
test.py ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from ast import literal_eval
3
+
4
+ from segment_key import *
5
+ from matplotlib import pyplot as plt
6
+
7
+
8
+ def show_kps(contour):
9
+ list1 = range(0, 310)
10
+ list2 = list(zip(get_features_right(contour), list1))
11
+
12
+ x_coords = [point[0] for point in list2]
13
+ y_coords = [point[1] for point in list2]
14
+ plt.scatter(x_coords, y_coords, c='red', marker='o', label='Keypoints')
15
+
16
+ list2 = list(zip(get_features_left(contour), list1))
17
+ x_coords = [point[0] for point in list2]
18
+ y_coords = [point[1] for point in list2]
19
+ plt.scatter(x_coords, y_coords, c='red', marker='o', label='Keypoints')
20
+
21
+ list2 = list(zip(list1, get_features_up(contour)))
22
+ x_coords = [point[0] for point in list2]
23
+ y_coords = [point[1] for point in list2]
24
+ plt.scatter(x_coords, y_coords, c='red', marker='o', label='Keypoints')
25
+
26
+ list2 = list(zip(list1, get_features_down(contour)))
27
+ x_coords = [point[0] for point in list2]
28
+ y_coords = [point[1] for point in list2]
29
+ plt.scatter(x_coords, y_coords, c='red', marker='o', label='Keypoints')
30
+
31
+ plt.show()
32
+
33
+
34
+ def get_all_features():
35
+ contours = []
36
+ with open('prediction/database.txt', 'r') as file:
37
+ lines = file.readlines()
38
+ for line in lines:
39
+ results = (line.split(';')[1])
40
+ results = results.replace(",,", ",'',")
41
+ results = literal_eval(results)
42
+ results = np.array(results)
43
+ contours.append((line.split(';')[0], results))
44
+
45
+ return contours
46
+
47
+
48
+ def cos_similarity(feature1, feature2):
49
+ return np.dot(feature1, feature2) / (np.linalg.norm(feature1) * np.linalg.norm(feature2))
50
+
51
+
52
+ def predict_match(image_path):
53
+ main_name = os.path.basename(image_path)[:-11] + '.jpg'
54
+ main_feature = final_features(image_path)
55
+ contours = get_all_features()
56
+
57
+ l = []
58
+
59
+ for image in contours:
60
+ feature = image[1]
61
+ feature_similarity = 1 - cos_similarity(feature, main_feature)
62
+
63
+ l.append([image[0], feature_similarity])
64
+
65
+ l.sort(key=lambda x: x[1])
66
+
67
+ print(l)
68
+ print(l[0])
69
+ index_in_list = -1
70
+ for i in range(len(l)):
71
+ if l[i][0] == main_name:
72
+ index_in_list = i
73
+ return l[0][0], l[0][1], index_in_list
74
+
75
+
76
+ # for image_file in os.listdir('../augmentation/testing/3'):
77
+ # image_path = os.path.join('../augmentation/testing/3', image_file)
78
+ # best_image_name, best_match_value, index = predict_match(image_path)
79
+ # with open('performance/performance_results.txt', 'a+') as file:
80
+ # file.write(image_file + ';' + best_image_name + ';' + str(best_match_value) + ';' + str(index) + '\n')
81
+
82
+ predict_match('./examples/img.jpg')