shunk031 commited on
Commit
3ba4e49
·
verified ·
1 Parent(s): 5a3810e

Delete layout_maximum_iou.py

Browse files
Files changed (1) hide show
  1. layout_maximum_iou.py +0 -246
layout_maximum_iou.py DELETED
@@ -1,246 +0,0 @@
1
- from collections import defaultdict
2
- from itertools import chain
3
- from typing import Dict, List, Tuple, TypedDict
4
-
5
- import datasets as ds
6
- import evaluate
7
- import numpy as np
8
- import numpy.typing as npt
9
- from scipy.optimize import linear_sum_assignment
10
-
11
-
12
- class Layout(TypedDict):
13
- bboxes: npt.NDArray[np.float64]
14
- categories: npt.NDArray[np.int64]
15
-
16
-
17
- _DESCRIPTION = """\
18
- Compute the maximum IoU between two sets of layouts.
19
- """
20
-
21
- _KWARGS_DESCRIPTION = """\
22
- Args:
23
- layouts1 (`list` of `dict`): A list of dictionaries representing layouts including `list` of `bboxes` (float) and `list` of `categories` (int).
24
- layouts2 (`list` of `dict`): A list of dictionaries representing layouts including `list` of `bboxes` (float) and `list` of `categories` (int).
25
-
26
- Returns:
27
- float: The maximum IoU score.
28
-
29
- Examples:
30
-
31
- Example 1: Single processing
32
- >>> metric = evaluate.load("pytorch-layout-generation/layout-maximum-iou")
33
- >>> num_samples, num_categories = 24, 4
34
- >>> layout1 = {
35
- >>> "bboxes": np.random.rand(num_samples, num_categories),
36
- >>> "categories": np.random.randint(0, num_categories, size=(num_samples,)),
37
- >>> }
38
- >>> layout2 = {
39
- >>> "bboxes": np.random.rand(num_samples, num_categories),
40
- >>> "categories": np.random.randint(0, num_categories, size=(num_samples,)),
41
- >>> }
42
- >>> metric.add(layouts1=layout1, layouts2=layout2)
43
- >>> print(metric.compute())
44
-
45
- Example 2: Batch processing
46
- >>> metric = evaluate.load("pytorch-layout-generation/layout-maximum-iou")
47
- >>> batch_size, num_samples, num_categories = 512, 24, 4
48
- >>> layouts1 = [
49
- >>> {
50
- >>> "bboxes": np.random.rand(num_samples, num_categories),
51
- >>> "categories": np.random.randint(0, num_categories, size=(num_samples,)),
52
- >>> }
53
- >>> for _ in range(batch_size)
54
- >>> ]
55
- >>> layouts2 = [
56
- >>> {
57
- >>> "bboxes": np.random.rand(num_samples, num_categories),
58
- >>> "categories": np.random.randint(0, num_categories, size=(num_samples,)),
59
- >>> }
60
- >>> for _ in range(batch_size)
61
- >>> ]
62
- >>> metric.add_batch(layouts1=layouts1, layouts2=layouts2)
63
- >>> print(metric.compute())
64
- """
65
-
66
- _CITATION = """\
67
- @inproceedings{kikuchi2021constrained,
68
- title={Constrained graphic layout generation via latent optimization},
69
- author={Kikuchi, Kotaro and Simo-Serra, Edgar and Otani, Mayu and Yamaguchi, Kota},
70
- booktitle={Proceedings of the 29th ACM International Conference on Multimedia},
71
- pages={88--96},
72
- year={2021}
73
- }
74
- """
75
-
76
-
77
- def convert_xywh_to_ltrb(
78
- batch_bbox: npt.NDArray[np.float64],
79
- ) -> Tuple[
80
- npt.NDArray[np.float64],
81
- npt.NDArray[np.float64],
82
- npt.NDArray[np.float64],
83
- npt.NDArray[np.float64],
84
- ]:
85
- xc, yc, w, h = batch_bbox
86
- x1 = xc - w / 2
87
- y1 = yc - h / 2
88
- x2 = xc + w / 2
89
- y2 = yc + h / 2
90
- return (x1, y1, x2, y2)
91
-
92
-
93
- def _compute_iou(
94
- bbox1: npt.NDArray[np.float64],
95
- bbox2: npt.NDArray[np.float64],
96
- generalized: bool = False,
97
- ):
98
- # shape: bbox1 (N, 4), bbox2 (N, 4)
99
- assert bbox1.shape[0] == bbox2.shape[0]
100
- assert bbox1.shape[1] == bbox1.shape[1] == 4
101
-
102
- l1, t1, r1, b1 = convert_xywh_to_ltrb(bbox1.T)
103
- l2, t2, r2, b2 = convert_xywh_to_ltrb(bbox2.T)
104
- a1, a2 = (r1 - l1) * (b1 - t1), (r2 - l2) * (b2 - t2)
105
-
106
- # intersection
107
- l_max = np.maximum(l1, l2)
108
- r_min = np.minimum(r1, r2)
109
- t_max = np.maximum(t1, t2)
110
- b_min = np.minimum(b1, b2)
111
- cond = (l_max < r_min) & (t_max < b_min)
112
- ai = np.where(cond, (r_min - l_max) * (b_min - t_max), np.zeros_like(a1[0]))
113
-
114
- au = a1 + a2 - ai
115
- iou = ai / au
116
-
117
- if not generalized:
118
- return iou
119
-
120
- # outer region
121
- l_min = np.minimum(l1, l2)
122
- r_max = np.maximum(r1, r2)
123
- t_min = np.minimum(t1, t2)
124
- b_max = np.maximum(b1, b2)
125
- ac = (r_max - l_min) * (b_max - t_min)
126
-
127
- giou = iou - (ac - au) / ac
128
-
129
- return giou
130
-
131
-
132
- def _compute_maximum_iou_for_layout(layout1: Layout, layout2: Layout):
133
- score = 0.0
134
- bi, ci = layout1["bboxes"], layout1["categories"]
135
- bj, cj = layout2["bboxes"], layout2["categories"]
136
- N = len(bi)
137
-
138
- for c in list(set(ci.tolist())):
139
- _bi = bi[np.where(ci == c)]
140
- _bj = bj[np.where(cj == c)]
141
- n = len(_bi)
142
- ii, jj = np.meshgrid(range(n), range(n))
143
- ii, jj = ii.flatten(), jj.flatten()
144
- iou = _compute_iou(_bi[ii], _bj[jj]).reshape(n, n)
145
- # Note: maximize is supported only when scipy >= 1.4
146
- ii, jj = linear_sum_assignment(iou, maximize=True)
147
- score += iou[ii, jj].sum().item()
148
- return score / N
149
-
150
-
151
- def _compute_maximum_iou(
152
- layouts_1_and_2: Tuple[List[Layout], List[Layout]]
153
- ) -> npt.NDArray[np.float64]:
154
- assert len(layouts_1_and_2) == 2
155
- layouts1, layouts2 = layouts_1_and_2
156
-
157
- N, M = len(layouts1), len(layouts2)
158
- ii, jj = np.meshgrid(range(N), range(M))
159
- ii, jj = ii.flatten(), jj.flatten()
160
- scores = np.asarray(
161
- [
162
- _compute_maximum_iou_for_layout(layouts1[i], layouts2[j])
163
- for i, j in zip(ii, jj)
164
- ]
165
- )
166
- scores = scores.reshape(N, M)
167
- ii, jj = linear_sum_assignment(scores, maximize=True)
168
- return scores[ii, jj]
169
-
170
-
171
- def _get_cond_to_layouts(layouts: List[Layout]) -> Dict[str, List[Layout]]:
172
- out = defaultdict(list)
173
-
174
- for layout in layouts:
175
- bboxes = layout["bboxes"]
176
- categories = layout["categories"]
177
-
178
- # e.g., [18, 2, 1, 20, 0, 0, 0, 0, 0, 9, 9, 5, 0, 5, 0, 0]
179
- # -> "[0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 5, 5, 9, 9, 18, 20]"
180
- cond_key = str(sorted(categories))
181
-
182
- categories = np.array(categories)
183
- layout_dict: Layout = {
184
- "bboxes": np.asarray(bboxes),
185
- "categories": np.asarray(categories),
186
- }
187
- out[cond_key].append(layout_dict)
188
-
189
- return out
190
-
191
-
192
- def compute_maximum_iou(args):
193
- return [_compute_maximum_iou(a) for a in args]
194
-
195
-
196
- class LayoutMaximumIoU(evaluate.Metric):
197
-
198
- def _info(self) -> evaluate.EvaluationModuleInfo:
199
- return evaluate.EvaluationModuleInfo(
200
- description=_DESCRIPTION,
201
- citation=_CITATION,
202
- inputs_description=_KWARGS_DESCRIPTION,
203
- features=ds.Features(
204
- {
205
- "layouts1": {
206
- "bboxes": ds.Sequence(ds.Sequence((ds.Value("float64")))),
207
- "categories": ds.Sequence(ds.Value("int64")),
208
- },
209
- "layouts2": {
210
- "bboxes": ds.Sequence(ds.Sequence((ds.Value("float64")))),
211
- "categories": ds.Sequence(ds.Value("int64")),
212
- },
213
- }
214
- ),
215
- codebase_urls=[
216
- "https://github.com/CyberAgentAILab/layout-dm/blob/main/src/trainer/trainer/helpers/metric.py#L206-L247",
217
- "https://github.com/CyberAgentAILab/layout-dm/blob/main/src/trainer/trainer/helpers/metric.py#L250-L297",
218
- "https://github.com/CyberAgentAILab/layout-dm/blob/main/src/trainer/trainer/helpers/metric.py#L300-L314",
219
- "https://github.com/CyberAgentAILab/layout-dm/blob/main/src/trainer/trainer/helpers/metric.py#L317-L329",
220
- "https://github.com/CyberAgentAILab/layout-dm/blob/main/src/trainer/trainer/helpers/metric.py#L332-L340",
221
- "https://github.com/CyberAgentAILab/layout-dm/blob/main/src/trainer/trainer/helpers/metric.py#L343-L371",
222
- ],
223
- )
224
-
225
- def _compute(
226
- self,
227
- *,
228
- layouts1: List[Layout],
229
- layouts2: List[Layout],
230
- ) -> float:
231
- c2bl_1 = _get_cond_to_layouts(layouts1)
232
- keys_1 = set(c2bl_1.keys())
233
- c2bl_2 = _get_cond_to_layouts(layouts2)
234
- keys_2 = set(c2bl_2.keys())
235
- keys = list(keys_1.intersection(keys_2))
236
- args = [(c2bl_1[key], c2bl_2[key]) for key in keys]
237
-
238
- # to check actual number of layouts for evaluation
239
- # ans = 0
240
- # for x in args:
241
- # ans += len(x[0])
242
-
243
- scores = compute_maximum_iou(args)
244
- scores = np.asarray(list(chain.from_iterable(scores)))
245
-
246
- return scores.mean().item() if len(scores) != 0 else 0.0