shunk031 commited on
Commit
a999bbc
·
1 Parent(s): b3850a5

deploy: 63a85616f5fc427cf1e1e7b425293131f2fce2b8

Browse files
Files changed (3) hide show
  1. README.md +152 -1
  2. layout-occlusion.py +16 -3
  3. requirements.txt +136 -89
README.md CHANGED
@@ -9,4 +9,155 @@ app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  pinned: false
10
  ---
11
 
12
+ # Layout Occlusion
13
+
14
+ ## Description
15
+
16
+ The Layout Occlusion metric evaluates how much layout elements occlude or cover important visual regions in the background canvas. This metric is particularly important for content-aware layout generation where background imagery should remain visible and not be blocked by poorly placed elements.
17
+
18
+ ## What It Measures
19
+
20
+ This metric computes the average saliency (visual importance) of canvas regions covered by layout elements:
21
+
22
+ - **Visual importance coverage**: How much salient (visually important) content is blocked by elements
23
+ - **Element placement quality**: Whether elements are placed on less important background regions
24
+ - **Content-awareness**: How well the layout respects the underlying visual content
25
+
26
+ Lower occlusion scores indicate better placement where elements avoid covering important background content.
27
+
28
+ ## Metric Details
29
+
30
+ - Uses saliency maps to identify visually important regions in the canvas
31
+ - Computes average saliency values in areas covered by elements
32
+ - Combines two saliency maps for robust evaluation
33
+ - From PosterLayout (Hsu et al., CVPR 2023) for content-aware poster design
34
+ - Lower scores mean elements are placed on less salient (less important) regions
35
+
36
+ ## Usage
37
+
38
+ ### Installation
39
+
40
+ ```bash
41
+ pip install evaluate
42
+ ```
43
+
44
+ ### Basic Example
45
+
46
+ ```python
47
+ import evaluate
48
+ import numpy as np
49
+
50
+ # Load the metric with canvas dimensions
51
+ metric = evaluate.load(
52
+ "creative-graphic-design/layout-occlusion",
53
+ canvas_width=360,
54
+ canvas_height=504
55
+ )
56
+
57
+ # Prepare data
58
+ predictions = np.random.rand(1, 25, 4)
59
+ gold_labels = np.random.randint(0, 4, size=(1, 25))
60
+ # Paths to saliency map images (grayscale, 0-255)
61
+ saliency_maps_1 = ["path/to/saliency_map_1.png"]
62
+ saliency_maps_2 = ["path/to/saliency_map_2.png"]
63
+
64
+ score = metric.compute(
65
+ predictions=predictions,
66
+ gold_labels=gold_labels,
67
+ saliency_maps_1=saliency_maps_1,
68
+ saliency_maps_2=saliency_maps_2
69
+ )
70
+ print(score)
71
+ ```
72
+
73
+ ### Batch Processing Example
74
+
75
+ ```python
76
+ import evaluate
77
+
78
+ # Load the metric
79
+ metric = evaluate.load(
80
+ "creative-graphic-design/layout-occlusion",
81
+ canvas_width=360,
82
+ canvas_height=504
83
+ )
84
+
85
+ # Batch processing
86
+ batch_size = 128
87
+ predictions = np.random.rand(batch_size, 25, 4)
88
+ gold_labels = np.random.randint(0, 4, size=(batch_size, 25))
89
+ saliency_maps_1 = [f"path/to/saliency_{i}_1.png" for i in range(batch_size)]
90
+ saliency_maps_2 = [f"path/to/saliency_{i}_2.png" for i in range(batch_size)]
91
+
92
+ score = metric.compute(
93
+ predictions=predictions,
94
+ gold_labels=gold_labels,
95
+ saliency_maps_1=saliency_maps_1,
96
+ saliency_maps_2=saliency_maps_2
97
+ )
98
+ print(score)
99
+ ```
100
+
101
+ ## Parameters
102
+
103
+ ### Initialization Parameters
104
+
105
+ - **canvas_width** (`int`, required): Width of the canvas in pixels
106
+ - **canvas_height** (`int`, required): Height of the canvas in pixels
107
+
108
+ ### Computation Parameters
109
+
110
+ - **predictions** (`list` of `lists` of `float`): Normalized bounding boxes in ltrb format
111
+ - **gold_labels** (`list` of `lists` of `int`): Class labels for each element (0 = padding)
112
+ - **saliency_maps_1** (`list` of `str`): File paths to first set of saliency map images
113
+ - **saliency_maps_2** (`list` of `str`): File paths to second set of saliency map images
114
+
115
+ **Note**: Saliency maps should be grayscale images (0-255) where brighter regions indicate more visually important areas. They will be automatically resized to match canvas dimensions if needed.
116
+
117
+ ## Returns
118
+
119
+ Returns a `float` value representing the average saliency of occluded regions (range: 0.0 to 1.0).
120
+
121
+ ## Interpretation
122
+
123
+ - **Lower is better** (range: 0.0 to 1.0)
124
+ - **Value ~0.0**: Elements placed on unimportant background regions (ideal)
125
+ - **Value ~0.5**: Elements partially cover moderately important regions
126
+ - **Value ~1.0**: Elements heavily occlude highly salient background content (problematic)
127
+
128
+ ### Use Cases
129
+
130
+ - **Content-aware layout generation**: Evaluate if generated layouts respect background imagery
131
+ - **Poster/flyer design**: Ensure text and graphics don't block important visual elements
132
+ - **Advertisement layout**: Place call-to-action elements without covering key visuals
133
+ - **Magazine/presentation layouts**: Balance element placement with background content
134
+
135
+ ### Key Insights
136
+
137
+ - **Good layouts** minimize occlusion of salient background regions
138
+ - **Background-aware models** should achieve lower occlusion scores
139
+ - **Trade-off**: Sometimes covering salient regions is necessary for design needs
140
+ - **Use with other metrics**: Combine with validity and alignment for comprehensive evaluation
141
+
142
+ ## Citations
143
+
144
+ ```bibtex
145
+ @inproceedings{hsu2023posterlayout,
146
+ title={Posterlayout: A new benchmark and approach for content-aware visual-textual presentation layout},
147
+ author={Hsu, Hsiao Yuan and He, Xiangteng and Peng, Yuxin and Kong, Hao and Zhang, Qing},
148
+ booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},
149
+ pages={6018--6026},
150
+ year={2023}
151
+ }
152
+ ```
153
+
154
+ ## References
155
+
156
+ - **Paper**: [PosterLayout (Hsu et al., CVPR 2023)](https://arxiv.org/abs/2303.15937)
157
+ - **Reference Implementation**: [PosterLayout eval.py](https://github.com/PKU-ICST-MIPL/PosterLayout-CVPR2023/blob/main/eval.py#L144-L171)
158
+
159
+ ## Related Metrics
160
+
161
+ - [Layout Utility](../layout_utility/): Measures how well suitable space is utilized
162
+ - [Layout Unreadability](../layout_unreadability/): Evaluates text placement on non-flat regions
163
+ - [Layout Validity](../layout_validity/): Checks basic validity constraints
layout-occlusion.py CHANGED
@@ -5,6 +5,7 @@ import datasets as ds
5
  import evaluate
6
  import numpy as np
7
  import numpy.typing as npt
 
8
  from PIL import Image
9
 
10
  _DESCRIPTION = r"""\
@@ -12,7 +13,18 @@ Computes the average pixel value of areas covered by elements in S.
12
  """
13
 
14
  _KWARGS_DESCRIPTION = """\
15
- FIXME
 
 
 
 
 
 
 
 
 
 
 
16
  """
17
 
18
  _CITATION = """\
@@ -26,6 +38,7 @@ _CITATION = """\
26
  """
27
 
28
 
 
29
  class LayoutOcculusion(evaluate.Metric):
30
  def __init__(
31
  self,
@@ -64,10 +77,10 @@ class LayoutOcculusion(evaluate.Metric):
64
  filepath = filepath[0]
65
 
66
  map_pil = Image.open(filepath) # type: ignore
67
- map_pil = map_pil.convert("L")
68
 
69
  if map_pil.size != (self.canvas_width, self.canvas_height):
70
- map_pil = map_pil.resize((self.canvas_width, self.canvas_height))
71
 
72
  map_arr = np.array(map_pil)
73
  map_arr = map_arr / 255.0
 
5
  import evaluate
6
  import numpy as np
7
  import numpy.typing as npt
8
+ from evaluate.utils.file_utils import add_start_docstrings
9
  from PIL import Image
10
 
11
  _DESCRIPTION = r"""\
 
13
  """
14
 
15
  _KWARGS_DESCRIPTION = """\
16
+ Args:
17
+ predictions (`list` of `lists` of `float`): A list of lists of floats representing bounding boxes.
18
+ gold_labels (`list` of `lists` of `int`): A list of lists of integers representing class labels.
19
+ saliency_maps_1 (`list` of `str`): A list of strings representing path to saliency maps 1.
20
+ saliency_maps_2 (`list` of `str`): A list of strings representing path to saliency maps 2.
21
+
22
+ Returns:
23
+ float: Average saliency of areas covered by elements. Lower values are generally better (in 0.0 - 1.0 range).
24
+
25
+ Examples:
26
+ Examples 1: Single processing
27
+ >>> metric = evaluate.load("creative-graphic-design/layout-occlusion")
28
  """
29
 
30
  _CITATION = """\
 
38
  """
39
 
40
 
41
+ @add_start_docstrings(_DESCRIPTION, _KWARGS_DESCRIPTION)
42
  class LayoutOcculusion(evaluate.Metric):
43
  def __init__(
44
  self,
 
77
  filepath = filepath[0]
78
 
79
  map_pil = Image.open(filepath) # type: ignore
80
+ map_pil = map_pil.convert("L") # type: ignore
81
 
82
  if map_pil.size != (self.canvas_width, self.canvas_height):
83
+ map_pil = map_pil.resize((self.canvas_width, self.canvas_height)) # type: ignore
84
 
85
  map_arr = np.array(map_pil)
86
  map_arr = map_arr / 255.0
requirements.txt CHANGED
@@ -1,89 +1,136 @@
1
- aiofiles==23.2.1 ; python_version >= "3.9" and python_version < "4.0"
2
- aiohttp==3.9.3 ; python_version >= "3.9" and python_version < "4.0"
3
- aiosignal==1.3.1 ; python_version >= "3.9" and python_version < "4.0"
4
- altair==5.2.0 ; python_version >= "3.9" and python_version < "4.0"
5
- annotated-types==0.6.0 ; python_version >= "3.9" and python_version < "4.0"
6
- anyio==4.2.0 ; python_version >= "3.9" and python_version < "4.0"
7
- arrow==1.3.0 ; python_version >= "3.9" and python_version < "4.0"
8
- async-timeout==4.0.3 ; python_version >= "3.9" and python_version < "3.11"
9
- attrs==23.2.0 ; python_version >= "3.9" and python_version < "4.0"
10
- binaryornot==0.4.4 ; python_version >= "3.9" and python_version < "4.0"
11
- certifi==2024.2.2 ; python_version >= "3.9" and python_version < "4.0"
12
- chardet==5.2.0 ; python_version >= "3.9" and python_version < "4.0"
13
- charset-normalizer==3.3.2 ; python_version >= "3.9" and python_version < "4.0"
14
- click==8.1.7 ; python_version >= "3.9" and python_version < "4.0"
15
- colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0"
16
- contourpy==1.2.0 ; python_version >= "3.9" and python_version < "4.0"
17
- cookiecutter==2.5.0 ; python_version >= "3.9" and python_version < "4.0"
18
- cycler==0.12.1 ; python_version >= "3.9" and python_version < "4.0"
19
- datasets==2.17.0 ; python_version >= "3.9" and python_version < "4.0"
20
- dill==0.3.8 ; python_version >= "3.9" and python_version < "4.0"
21
- evaluate[template]==0.4.1 ; python_version >= "3.9" and python_version < "4.0"
22
- exceptiongroup==1.2.0 ; python_version >= "3.9" and python_version < "3.11"
23
- fastapi==0.109.2 ; python_version >= "3.9" and python_version < "4.0"
24
- ffmpy==0.3.1 ; python_version >= "3.9" and python_version < "4.0"
25
- filelock==3.13.1 ; python_version >= "3.9" and python_version < "4.0"
26
- fonttools==4.48.1 ; python_version >= "3.9" and python_version < "4.0"
27
- frozenlist==1.4.1 ; python_version >= "3.9" and python_version < "4.0"
28
- fsspec==2023.10.0 ; python_version >= "3.9" and python_version < "4.0"
29
- fsspec[http]==2023.10.0 ; python_version >= "3.9" and python_version < "4.0"
30
- gradio-client==0.10.0 ; python_version >= "3.9" and python_version < "4.0"
31
- gradio==4.18.0 ; python_version >= "3.9" and python_version < "4.0"
32
- h11==0.14.0 ; python_version >= "3.9" and python_version < "4.0"
33
- httpcore==1.0.2 ; python_version >= "3.9" and python_version < "4.0"
34
- httpx==0.26.0 ; python_version >= "3.9" and python_version < "4.0"
35
- huggingface-hub==0.20.3 ; python_version >= "3.9" and python_version < "4.0"
36
- idna==3.6 ; python_version >= "3.9" and python_version < "4.0"
37
- importlib-resources==6.1.1 ; python_version >= "3.9" and python_version < "4.0"
38
- jinja2==3.1.3 ; python_version >= "3.9" and python_version < "4.0"
39
- jsonschema-specifications==2023.12.1 ; python_version >= "3.9" and python_version < "4.0"
40
- jsonschema==4.21.1 ; python_version >= "3.9" and python_version < "4.0"
41
- kiwisolver==1.4.5 ; python_version >= "3.9" and python_version < "4.0"
42
- markdown-it-py==3.0.0 ; python_version >= "3.9" and python_version < "4.0"
43
- markupsafe==2.1.5 ; python_version >= "3.9" and python_version < "4.0"
44
- matplotlib==3.8.2 ; python_version >= "3.9" and python_version < "4.0"
45
- mdurl==0.1.2 ; python_version >= "3.9" and python_version < "4.0"
46
- multidict==6.0.5 ; python_version >= "3.9" and python_version < "4.0"
47
- multiprocess==0.70.16 ; python_version >= "3.9" and python_version < "4.0"
48
- numpy==1.26.4 ; python_version >= "3.9" and python_version < "4.0"
49
- orjson==3.9.13 ; python_version >= "3.9" and python_version < "4.0"
50
- packaging==23.2 ; python_version >= "3.9" and python_version < "4.0"
51
- pandas==2.2.0 ; python_version >= "3.9" and python_version < "4.0"
52
- pillow==10.2.0 ; python_version >= "3.9" and python_version < "4.0"
53
- pyarrow-hotfix==0.6 ; python_version >= "3.9" and python_version < "4.0"
54
- pyarrow==15.0.0 ; python_version >= "3.9" and python_version < "4.0"
55
- pydantic-core==2.16.2 ; python_version >= "3.9" and python_version < "4.0"
56
- pydantic==2.6.1 ; python_version >= "3.9" and python_version < "4.0"
57
- pydub==0.25.1 ; python_version >= "3.9" and python_version < "4.0"
58
- pygments==2.17.2 ; python_version >= "3.9" and python_version < "4.0"
59
- pyparsing==3.1.1 ; python_version >= "3.9" and python_version < "4.0"
60
- python-dateutil==2.8.2 ; python_version >= "3.9" and python_version < "4.0"
61
- python-multipart==0.0.9 ; python_version >= "3.9" and python_version < "4.0"
62
- python-slugify==8.0.4 ; python_version >= "3.9" and python_version < "4.0"
63
- pytz==2024.1 ; python_version >= "3.9" and python_version < "4.0"
64
- pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "4.0"
65
- referencing==0.33.0 ; python_version >= "3.9" and python_version < "4.0"
66
- requests==2.31.0 ; python_version >= "3.9" and python_version < "4.0"
67
- responses==0.18.0 ; python_version >= "3.9" and python_version < "4.0"
68
- rich==13.7.0 ; python_version >= "3.9" and python_version < "4.0"
69
- rpds-py==0.17.1 ; python_version >= "3.9" and python_version < "4.0"
70
- ruff==0.2.1 ; python_version >= "3.9" and python_version < "4.0"
71
- semantic-version==2.10.0 ; python_version >= "3.9" and python_version < "4.0"
72
- shellingham==1.5.4 ; python_version >= "3.9" and python_version < "4.0"
73
- six==1.16.0 ; python_version >= "3.9" and python_version < "4.0"
74
- sniffio==1.3.0 ; python_version >= "3.9" and python_version < "4.0"
75
- starlette==0.36.3 ; python_version >= "3.9" and python_version < "4.0"
76
- text-unidecode==1.3 ; python_version >= "3.9" and python_version < "4.0"
77
- tomlkit==0.12.0 ; python_version >= "3.9" and python_version < "4.0"
78
- toolz==0.12.1 ; python_version >= "3.9" and python_version < "4.0"
79
- tqdm==4.66.2 ; python_version >= "3.9" and python_version < "4.0"
80
- typer[all]==0.9.0 ; python_version >= "3.9" and python_version < "4.0"
81
- types-python-dateutil==2.8.19.20240106 ; python_version >= "3.9" and python_version < "4.0"
82
- typing-extensions==4.9.0 ; python_version >= "3.9" and python_version < "4.0"
83
- tzdata==2024.1 ; python_version >= "3.9" and python_version < "4.0"
84
- urllib3==2.2.0 ; python_version >= "3.9" and python_version < "4.0"
85
- uvicorn==0.27.1 ; python_version >= "3.9" and python_version < "4.0"
86
- websockets==11.0.3 ; python_version >= "3.9" and python_version < "4.0"
87
- xxhash==3.4.1 ; python_version >= "3.9" and python_version < "4.0"
88
- yarl==1.9.4 ; python_version >= "3.9" and python_version < "4.0"
89
- zipp==3.17.0 ; python_version >= "3.9" and python_version < "3.10"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file was autogenerated by uv via the following command:
2
+ # uv export --package layout_occlusion --no-dev --no-hashes --format requirements-txt
3
+ aiohappyeyeballs==2.6.1
4
+ # via aiohttp
5
+ aiohttp==3.13.2
6
+ # via fsspec
7
+ aiosignal==1.4.0
8
+ # via aiohttp
9
+ anyio==4.12.0
10
+ # via httpx
11
+ attrs==25.4.0
12
+ # via aiohttp
13
+ certifi==2025.11.12
14
+ # via
15
+ # httpcore
16
+ # httpx
17
+ # requests
18
+ charset-normalizer==3.4.4
19
+ # via requests
20
+ click==8.3.1
21
+ # via typer-slim
22
+ colorama==0.4.6 ; sys_platform == 'win32'
23
+ # via
24
+ # click
25
+ # tqdm
26
+ datasets==4.4.2
27
+ # via evaluate
28
+ dill==0.4.0
29
+ # via
30
+ # datasets
31
+ # evaluate
32
+ # multiprocess
33
+ evaluate==0.4.6
34
+ # via layout-occlusion
35
+ filelock==3.20.1
36
+ # via
37
+ # datasets
38
+ # huggingface-hub
39
+ frozenlist==1.8.0
40
+ # via
41
+ # aiohttp
42
+ # aiosignal
43
+ fsspec==2025.10.0
44
+ # via
45
+ # datasets
46
+ # evaluate
47
+ # huggingface-hub
48
+ h11==0.16.0
49
+ # via httpcore
50
+ hf-xet==1.2.0 ; platform_machine == 'AMD64' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'arm64' or platform_machine == 'x86_64'
51
+ # via huggingface-hub
52
+ httpcore==1.0.9
53
+ # via httpx
54
+ httpx==0.28.1
55
+ # via
56
+ # datasets
57
+ # huggingface-hub
58
+ huggingface-hub==1.2.3
59
+ # via
60
+ # datasets
61
+ # evaluate
62
+ idna==3.11
63
+ # via
64
+ # anyio
65
+ # httpx
66
+ # requests
67
+ # yarl
68
+ multidict==6.7.0
69
+ # via
70
+ # aiohttp
71
+ # yarl
72
+ multiprocess==0.70.18
73
+ # via
74
+ # datasets
75
+ # evaluate
76
+ numpy==2.2.6
77
+ # via
78
+ # datasets
79
+ # evaluate
80
+ # pandas
81
+ packaging==25.0
82
+ # via
83
+ # datasets
84
+ # evaluate
85
+ # huggingface-hub
86
+ pandas==2.3.3
87
+ # via
88
+ # datasets
89
+ # evaluate
90
+ pillow==12.0.0
91
+ # via layout-occlusion
92
+ propcache==0.4.1
93
+ # via
94
+ # aiohttp
95
+ # yarl
96
+ pyarrow==22.0.0
97
+ # via datasets
98
+ python-dateutil==2.9.0.post0
99
+ # via pandas
100
+ pytz==2025.2
101
+ # via pandas
102
+ pyyaml==6.0.3
103
+ # via
104
+ # datasets
105
+ # huggingface-hub
106
+ requests==2.32.5
107
+ # via
108
+ # datasets
109
+ # evaluate
110
+ shellingham==1.5.4
111
+ # via huggingface-hub
112
+ six==1.17.0
113
+ # via python-dateutil
114
+ tqdm==4.67.1
115
+ # via
116
+ # datasets
117
+ # evaluate
118
+ # huggingface-hub
119
+ typer-slim==0.21.0
120
+ # via huggingface-hub
121
+ typing-extensions==4.15.0
122
+ # via
123
+ # aiosignal
124
+ # anyio
125
+ # huggingface-hub
126
+ # typer-slim
127
+ tzdata==2025.3
128
+ # via pandas
129
+ urllib3==2.6.2
130
+ # via requests
131
+ xxhash==3.6.0
132
+ # via
133
+ # datasets
134
+ # evaluate
135
+ yarl==1.22.0
136
+ # via aiohttp