BenjiELCA commited on
Commit
98b1103
·
1 Parent(s): e7657c7

align box in multiple function

Browse files
Files changed (1) hide show
  1. modules/toXML.py +125 -111
modules/toXML.py CHANGED
@@ -16,131 +16,145 @@ def find_position(pool_index, BPMN_id):
16
 
17
  return position
18
 
19
- def align_boxes(pred, size):
20
- modified_pred = copy.deepcopy(pred) # Make a deep copy of the prediction
21
-
22
- # Step 1: Calculate the center of each bounding box and group them by pool
23
  pool_groups = {}
24
  for pool_index, element_indices in pred['pool_dict'].items():
25
  pool_groups[pool_index] = []
26
  for i in element_indices:
27
- if i >= len(modified_pred['labels']):
28
- continue
29
- if class_dict[modified_pred['labels'][i]] != 'dataObject' or class_dict[modified_pred['labels'][i]] != 'dataStore':
30
- x1, y1, x2, y2 = modified_pred['boxes'][i]
31
  center = [(x1 + x2) / 2, (y1 + y2) / 2]
32
  pool_groups[pool_index].append((center, i))
33
-
34
- # Function to group centers within a specified range
35
- def group_centers(centers, axis, range_=50):
36
- groups = []
37
- while centers:
38
- center, idx = centers.pop(0)
39
- group = [(center, idx)]
40
- for other_center, other_idx in centers[:]:
41
- if abs(center[axis] - other_center[axis]) <= range_:
42
- group.append((other_center, other_idx))
43
- centers.remove((other_center, other_idx))
44
- groups.append(group)
45
- return groups
46
-
47
- # Step 2: Align the elements within each pool
 
 
48
  for pool_index, centers in pool_groups.items():
49
- # Group bounding boxes by checking if their centers are within ±50 pixels on the y-axis
50
  y_groups = group_centers(centers.copy(), axis=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
52
- # Align the y-coordinates of the centers of grouped bounding boxes
53
- for group in y_groups:
54
- avg_y = sum([c[0][1] for c in group]) / len(group) # Calculate the average y-coordinate
55
- for (center, idx) in group:
56
- label = class_dict[modified_pred['labels'][idx]]
57
- if label in size:
58
- new_center = (center[0], avg_y) # Align the y-coordinate
59
- modified_pred['boxes'][idx] = [
60
- new_center[0] - size[label][0] / 2,
61
- new_center[1] - size[label][1] / 2,
62
- new_center[0] + size[label][0] / 2,
63
- new_center[1] + size[label][1] / 2
64
- ]
65
-
66
- # Recalculate centers after vertical alignment
67
- centers = []
68
- for group in y_groups:
69
- for center, idx in group:
70
- x1, y1, x2, y2 = modified_pred['boxes'][idx]
71
- center = [(x1 + x2) / 2, (y1 + y2) / 2]
72
- centers.append((center, idx))
73
 
74
- # Group bounding boxes by checking if their centers are within ±50 pixels on the x-axis
75
- x_groups = group_centers(centers.copy(), axis=0)
 
 
76
 
77
- # Align the x-coordinates of the centers of grouped bounding boxes
78
- for group in x_groups:
79
- avg_x = sum([c[0][0] for c in group]) / len(group) # Calculate the average x-coordinate
80
- for (center, idx) in group:
81
- label = class_dict[modified_pred['labels'][idx]]
82
- if label in size:
83
- new_center = (avg_x, center[1]) # Align the x-coordinate
84
- modified_pred['boxes'][idx] = [
85
- new_center[0] - size[label][0] / 2,
86
- modified_pred['boxes'][idx][1],
87
- new_center[0] + size[label][0] / 2,
88
- modified_pred['boxes'][idx][3]
89
- ]
90
-
91
- # Step 3: Expand the pool bounding boxes to fit the aligned elements
92
- if len(pred['pool_dict'])>1:
93
- for idx, (pool_index, keep_elements) in enumerate(modified_pred['pool_dict'].items()):
94
- size_elements = get_size_elements(st.session_state.size_scale)
95
- if len(keep_elements) != 0:
96
- marge = 50
97
- else:
98
- marge = 0
99
-
100
- position = find_position(pool_index, modified_pred['BPMN_id'])
101
-
102
- if keep_elements == [] or position is None:
103
- min_x, min_y, max_x, max_y = modified_pred['boxes'][position]
104
- else:
105
- size_elements = get_size_elements(st.session_state.size_scale)
106
- min_x, min_y, max_x, max_y = calculate_pool_bounds(modified_pred['boxes'], modified_pred['labels'], keep_elements, size_elements)
107
-
108
- pool_width = max_x - min_x
109
- pool_height = max_y - min_y
110
- if pool_width < 300 or pool_height < 30:
111
- error("The pool is maybe too small, please add more elements or increase the scale by zooming on the image.")
112
- continue
113
 
114
- modified_pred['boxes'][position] = [min_x -marge, min_y-marge//2, min_x+pool_width+marge, min_y+pool_height+marge//2]
115
-
116
- min_left,max_right = 0, 0
117
- for pool_index, element_indices in pred['pool_dict'].items():
118
- position = find_position(pool_index, modified_pred['BPMN_id'])
119
- if position >= len(modified_pred['boxes']):
120
- print(f"Problem with the index {pool_index} with a length of {len(modified_pred['boxes'])}")
121
- continue
122
- x1, y1, x2, y2 = modified_pred['boxes'][position]
123
- left = x1
124
- right = x2
125
- if left < min_left:
126
- min_left = left
127
- if right > max_right:
128
- max_right = right
129
-
130
- for pool_index, element_indices in pred['pool_dict'].items():
131
- position = find_position(pool_index, modified_pred['BPMN_id'])
132
- if position >= len(modified_pred['boxes']):
133
- #print(f"Problem with the index {pool_index} with a length of {len(modified_pred['boxes'])}")
134
- continue
135
- x1, y1, x2, y2 = modified_pred['boxes'][position]
136
- if x1 > min_left:
137
- x1 = min_left
138
- if x2 < max_right:
139
- x2 = max_right
140
- modified_pred['boxes'][position] = [x1, y1, x2, y2]
141
 
142
  return modified_pred['boxes']
143
 
 
144
  # Function to create a BPMN XML file from prediction results
145
  def create_XML(full_pred, text_mapping, size_scale, scale):
146
  namespaces = {
@@ -184,7 +198,7 @@ def create_XML(full_pred, text_mapping, size_scale, scale):
184
  bpmnplane = ET.SubElement(bpmndi, 'bpmndi:BPMNPlane', id='BPMNPlane_1', bpmnElement='collaboration_1')
185
 
186
  full_pred['boxes'] = rescale_boxes(scale, old_boxes['boxes'])
187
- full_pred['boxes'] = align_boxes(full_pred, size_elements)
188
 
189
 
190
  # Add diagram elements for each pool
 
16
 
17
  return position
18
 
19
+ # Calculate the center of each bounding box and group them by pool
20
+ def calculate_centers_and_group_by_pool(pred, class_dict):
 
 
21
  pool_groups = {}
22
  for pool_index, element_indices in pred['pool_dict'].items():
23
  pool_groups[pool_index] = []
24
  for i in element_indices:
25
+ if i >= len(pred['labels']):
26
+ continue
27
+ if class_dict[pred['labels'][i]] not in ['dataObject', 'dataStore']:
28
+ x1, y1, x2, y2 = pred['boxes'][i]
29
  center = [(x1 + x2) / 2, (y1 + y2) / 2]
30
  pool_groups[pool_index].append((center, i))
31
+ return pool_groups
32
+
33
+ # Group centers within a specified range
34
+ def group_centers(centers, axis, range_=50):
35
+ groups = []
36
+ while centers:
37
+ center, idx = centers.pop(0)
38
+ group = [(center, idx)]
39
+ for other_center, other_idx in centers[:]:
40
+ if abs(center[axis] - other_center[axis]) <= range_:
41
+ group.append((other_center, other_idx))
42
+ centers.remove((other_center, other_idx))
43
+ groups.append(group)
44
+ return groups
45
+
46
+ # Align the elements within each pool
47
+ def align_elements_within_pool(modified_pred, pool_groups, class_dict, size):
48
  for pool_index, centers in pool_groups.items():
 
49
  y_groups = group_centers(centers.copy(), axis=1)
50
+ align_y_coordinates(modified_pred, y_groups, class_dict, size)
51
+
52
+ centers = recalculate_centers(modified_pred, y_groups)
53
+ x_groups = group_centers(centers.copy(), axis=0)
54
+ align_x_coordinates(modified_pred, x_groups, class_dict, size)
55
+
56
+ # Align the y-coordinates of the centers of grouped bounding boxes
57
+ def align_y_coordinates(modified_pred, y_groups, class_dict, size):
58
+ for group in y_groups:
59
+ avg_y = sum([c[0][1] for c in group]) / len(group)
60
+ for (center, idx) in group:
61
+ label = class_dict[modified_pred['labels'][idx]]
62
+ if label in size:
63
+ new_center = (center[0], avg_y)
64
+ modified_pred['boxes'][idx] = [
65
+ new_center[0] - size[label][0] / 2,
66
+ new_center[1] - size[label][1] / 2,
67
+ new_center[0] + size[label][0] / 2,
68
+ new_center[1] + size[label][1] / 2
69
+ ]
70
+
71
+ # Recalculate centers after alignment
72
+ def recalculate_centers(modified_pred, groups):
73
+ centers = []
74
+ for group in groups:
75
+ for center, idx in group:
76
+ x1, y1, x2, y2 = modified_pred['boxes'][idx]
77
+ center = [(x1 + x2) / 2, (y1 + y2) / 2]
78
+ centers.append((center, idx))
79
+ return centers
80
+
81
+ # Align the x-coordinates of the centers of grouped bounding boxes
82
+ def align_x_coordinates(modified_pred, x_groups, class_dict, size):
83
+ for group in x_groups:
84
+ avg_x = sum([c[0][0] for c in group]) / len(group)
85
+ for (center, idx) in group:
86
+ label = class_dict[modified_pred['labels'][idx]]
87
+ if label in size:
88
+ new_center = (avg_x, center[1])
89
+ modified_pred['boxes'][idx] = [
90
+ new_center[0] - size[label][0] / 2,
91
+ modified_pred['boxes'][idx][1],
92
+ new_center[0] + size[label][0] / 2,
93
+ modified_pred['boxes'][idx][3]
94
+ ]
95
+
96
+ # Expand the pool bounding boxes to fit the aligned elements
97
+ def expand_pool_bounding_boxes(modified_pred, pred, size_elements):
98
+ for idx, (pool_index, keep_elements) in enumerate(modified_pred['pool_dict'].items()):
99
+ if len(keep_elements) != 0:
100
+ marge = 50
101
+ else:
102
+ marge = 0
103
 
104
+ position = find_position(pool_index, modified_pred['BPMN_id'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
+ if keep_elements == [] or position is None:
107
+ min_x, min_y, max_x, max_y = modified_pred['boxes'][position]
108
+ else:
109
+ min_x, min_y, max_x, max_y = calculate_pool_bounds(modified_pred['boxes'], modified_pred['labels'], keep_elements, size_elements)
110
 
111
+ pool_width = max_x - min_x
112
+ pool_height = max_y - min_y
113
+ if pool_width < 300 or pool_height < 30:
114
+ error("The pool is maybe too small, please add more elements or increase the scale by zooming on the image.")
115
+ continue
116
+
117
+ modified_pred['boxes'][position] = [min_x - marge, min_y - marge // 2, min_x + pool_width + marge, min_y + pool_height + marge // 2]
118
+
119
+ # Adjust left and right boundaries of all pools
120
+ def adjust_pool_boundaries(modified_pred, pred):
121
+ min_left, max_right = 0, 0
122
+ for pool_index, element_indices in pred['pool_dict'].items():
123
+ position = find_position(pool_index, modified_pred['BPMN_id'])
124
+ if position >= len(modified_pred['boxes']):
125
+ continue
126
+ x1, y1, x2, y2 = modified_pred['boxes'][position]
127
+ left = x1
128
+ right = x2
129
+ if left < min_left:
130
+ min_left = left
131
+ if right > max_right:
132
+ max_right = right
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
+ for pool_index, element_indices in pred['pool_dict'].items():
135
+ position = find_position(pool_index, modified_pred['BPMN_id'])
136
+ if position >= len(modified_pred['boxes']):
137
+ continue
138
+ x1, y1, x2, y2 = modified_pred['boxes'][position]
139
+ if x1 > min_left:
140
+ x1 = min_left
141
+ if x2 < max_right:
142
+ x2 = max_right
143
+ modified_pred['boxes'][position] = [x1, y1, x2, y2]
144
+
145
+ # Main function to align boxes
146
+ def align_boxes(pred, size, class_dict):
147
+ modified_pred = copy.deepcopy(pred)
148
+ pool_groups = calculate_centers_and_group_by_pool(pred, class_dict)
149
+ align_elements_within_pool(modified_pred, pool_groups, class_dict, size)
150
+
151
+ if len(pred['pool_dict']) > 1:
152
+ expand_pool_bounding_boxes(modified_pred, pred, size)
153
+ adjust_pool_boundaries(modified_pred, pred)
 
 
 
 
 
 
 
154
 
155
  return modified_pred['boxes']
156
 
157
+
158
  # Function to create a BPMN XML file from prediction results
159
  def create_XML(full_pred, text_mapping, size_scale, scale):
160
  namespaces = {
 
198
  bpmnplane = ET.SubElement(bpmndi, 'bpmndi:BPMNPlane', id='BPMNPlane_1', bpmnElement='collaboration_1')
199
 
200
  full_pred['boxes'] = rescale_boxes(scale, old_boxes['boxes'])
201
+ full_pred['boxes'] = align_boxes(full_pred, size_elements, class_dict)
202
 
203
 
204
  # Add diagram elements for each pool