RE_UPLOAD-REBUILD-RESTART
Browse files- utils/get_features.py +123 -0
utils/get_features.py
ADDED
@@ -0,0 +1,123 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import layoutparser as lp
|
2 |
+
from PIL import Image
|
3 |
+
import tensorflow as tf
|
4 |
+
import numpy as np
|
5 |
+
import torch
|
6 |
+
import torchvision.ops.boxes as box_ops
|
7 |
+
from typing import List, Tuple
|
8 |
+
from .split_image import split_image
|
9 |
+
from .get_unique_values import get_unique_values
|
10 |
+
|
11 |
+
def get_vectors(*,
|
12 |
+
predicted_bboxes: List[Tuple[int, int, int, int]],
|
13 |
+
predicted_scores: List[float],
|
14 |
+
predicted_labels: List[str],
|
15 |
+
label_names: List[str],
|
16 |
+
sub_images_bboxes: List[Tuple[int, int, int, int]],
|
17 |
+
index_start: int = 0.17,
|
18 |
+
index_end: int = 1,
|
19 |
+
weighted_jaccard_index = False):
|
20 |
+
bboxes_tensor: torch.Tensor = torch.tensor(predicted_bboxes)
|
21 |
+
labels_nonce = { value:key for key, value in zip(get_unique_values(start = index_start, end = index_end, count = len(label_names)), list(label_names)) }
|
22 |
+
|
23 |
+
def get_vector(bbox: Tuple[int, int, int, int], region_nonce: int):
|
24 |
+
# bbox: Expected to be in ``(x1, y1, x2, y2)`` format with ``0 <= x1 < x2`` and ``0 <= y1 < y2``.
|
25 |
+
bbox_tensor: torch.Tensor = torch.tensor([bbox])
|
26 |
+
[jaccard_indexes] = box_ops.box_iou(bbox_tensor, bboxes_tensor)
|
27 |
+
'''
|
28 |
+
Either get the index of bounding box with largest jaccard_index (Intersection Over Union) or
|
29 |
+
get the index of bounding box with largest jaccard_index (Intersection Over Union) multiplied by the score.
|
30 |
+
By doing this we strike a balance between accuracy and relative position.
|
31 |
+
'''
|
32 |
+
index_of_jaccard_index = jaccard_indexes.argmax() if not weighted_jaccard_index else np.multiply(jaccard_indexes, predicted_scores).argmax()
|
33 |
+
jaccard_index = jaccard_indexes[index_of_jaccard_index]
|
34 |
+
jaccard_index_bbox_label__nonce = labels_nonce[predicted_labels[index_of_jaccard_index]]
|
35 |
+
jaccard_index_bbox_score = predicted_scores[index_of_jaccard_index]
|
36 |
+
vector = region_nonce * jaccard_index * jaccard_index_bbox_label__nonce * jaccard_index_bbox_score
|
37 |
+
return vector.item()
|
38 |
+
sub_images_nonces = get_unique_values(start = index_start, end = index_end, count = len(sub_images_bboxes))
|
39 |
+
for sub_image_bbox, region_nonce in zip(sub_images_bboxes, sub_images_nonces):
|
40 |
+
yield get_vector(sub_image_bbox, region_nonce)
|
41 |
+
|
42 |
+
def get_predictions(
|
43 |
+
image: Image.Image,
|
44 |
+
model: lp.Detectron2LayoutModel,
|
45 |
+
predictions_reducer = lambda *args: args):
|
46 |
+
layout_predicted = model.detect(image)
|
47 |
+
if len(layout_predicted) > 0:
|
48 |
+
predicted_bboxes = [block.coordinates for block in layout_predicted]
|
49 |
+
predicted_scores = [block.score for block in layout_predicted]
|
50 |
+
predicted_labels = [block.type for block in layout_predicted]
|
51 |
+
[predicted_bboxes, predicted_scores, predicted_labels] = predictions_reducer(
|
52 |
+
predicted_bboxes,
|
53 |
+
predicted_scores,
|
54 |
+
predicted_labels)
|
55 |
+
return {
|
56 |
+
'predicted_bboxes': predicted_bboxes,
|
57 |
+
'predicted_scores': predicted_scores,
|
58 |
+
'predicted_labels': predicted_labels,
|
59 |
+
}
|
60 |
+
else:
|
61 |
+
return {
|
62 |
+
'predicted_bboxes': [],
|
63 |
+
'predicted_scores': [],
|
64 |
+
'predicted_labels': [],
|
65 |
+
}
|
66 |
+
|
67 |
+
def predictions_reducer(
|
68 |
+
predicted_bboxes: List[Tuple[int, int, int, int]],
|
69 |
+
predicted_scores: List[float],
|
70 |
+
predicted_labels: List[str]):
|
71 |
+
selected_indices = tf.image.non_max_suppression(
|
72 |
+
boxes = predicted_bboxes,
|
73 |
+
scores = predicted_scores ,
|
74 |
+
max_output_size = len(predicted_bboxes),
|
75 |
+
iou_threshold = 0.01)
|
76 |
+
return {
|
77 |
+
'predicted_bboxes': tf.gather(predicted_bboxes, selected_indices).numpy().tolist(), # List[List[int, int, int, int]]
|
78 |
+
'predicted_scores': tf.gather(predicted_scores, selected_indices).numpy().astype(float).tolist(),
|
79 |
+
'predicted_labels': tf.gather(predicted_labels, selected_indices).numpy().astype(str).tolist()
|
80 |
+
}
|
81 |
+
|
82 |
+
def get_features(image: Image.Image, model: lp.Detectron2LayoutModel, label_names: List[str], width_parts = 100, height_parts = 100):
|
83 |
+
predictions = get_predictions(image, model)
|
84 |
+
reduced_predictions = predictions_reducer(**predictions)
|
85 |
+
sub_images_bboxes = list(split_image(np.array(image), width_parts, height_parts, result = 'bboxes'))
|
86 |
+
|
87 |
+
vectors = get_vectors(
|
88 |
+
sub_images_bboxes = sub_images_bboxes,
|
89 |
+
label_names = label_names,
|
90 |
+
weighted_jaccard_index = False,
|
91 |
+
**predictions)
|
92 |
+
|
93 |
+
weighted_vectors = get_vectors(
|
94 |
+
sub_images_bboxes = sub_images_bboxes,
|
95 |
+
label_names = label_names,
|
96 |
+
weighted_jaccard_index = True,
|
97 |
+
**predictions)
|
98 |
+
|
99 |
+
reduced_vectors = get_vectors(
|
100 |
+
sub_images_bboxes = sub_images_bboxes,
|
101 |
+
label_names = label_names,
|
102 |
+
weighted_jaccard_index = False,
|
103 |
+
**reduced_predictions)
|
104 |
+
|
105 |
+
reduced_weighted_vectors = get_vectors(
|
106 |
+
sub_images_bboxes = sub_images_bboxes,
|
107 |
+
label_names = label_names,
|
108 |
+
weighted_jaccard_index = True,
|
109 |
+
**reduced_predictions)
|
110 |
+
|
111 |
+
return {
|
112 |
+
'predicted_bboxes': predictions['predicted_bboxes'],
|
113 |
+
'predicted_scores': predictions['predicted_scores'],
|
114 |
+
'predicted_labels': predictions['predicted_labels'],
|
115 |
+
'vectors': list(vectors),
|
116 |
+
'weighted_vectors': list(weighted_vectors),
|
117 |
+
|
118 |
+
'reduced_predicted_bboxes': reduced_predictions['predicted_bboxes'],
|
119 |
+
'reduced_predicted_scores': reduced_predictions['predicted_scores'],
|
120 |
+
'reduced_predicted_labels': reduced_predictions['predicted_labels'],
|
121 |
+
'reduced_vectors': list(reduced_vectors),
|
122 |
+
'reduced_weighted_vectors': list(reduced_weighted_vectors),
|
123 |
+
}
|