creative-graphic-design/layout-validity
0
1from typing import List, Union2 3import datasets as ds4import evaluate5import numpy as np6import numpy.typing as npt7from evaluate.utils.file_utils import add_start_docstrings8 9_DESCRIPTION = r"""\10Computes the ratio of valid elements to all elements in the layout, where the area within the canvas of a valid element must be greater than 0.1% of the canvas.11"""12 13_KWARGS_DESCRIPTION = """\14Args:15 predictions (`list` of `list` of `float`): A list of lists of floats representing normalized `ltrb`-format bounding boxes.16 gold_labels (`list` of `list` of `int`): A list of lists of integers representing class labels.17 canvas_width (`int`, *optional*): Width of the canvas in pixels. Can be provided at initialization or during computation.18 canvas_height (`int`, *optional*): Height of the canvas in pixels. Can be provided at initialization or during computation.19 20Returns:21 float: The ratio of valid elements to all elements (0.0 to 1.0). An element is considered valid if its area within the canvas is greater than 0.1% of the canvas area.22 23Examples:24 >>> import evaluate25 >>> import numpy as np26 >>> metric = evaluate.load("creative-graphic-design/layout-validity")27 >>> # Normalized bounding boxes (left, top, right, bottom)28 >>> predictions = [[[0.1, 0.1, 0.5, 0.5], [0.6, 0.6, 0.9, 0.9]]]29 >>> gold_labels = [[1, 2]] # Non-zero labels indicate valid elements30 >>> result = metric.compute(predictions=predictions, gold_labels=gold_labels, canvas_width=512, canvas_height=512)31 >>> print(result)32 1.033"""34 35_CITATION = """\36@inproceedings{hsu2023posterlayout,37 title={Posterlayout: A new benchmark and approach for content-aware visual-textual presentation layout},38 author={Hsu, Hsiao Yuan and He, Xiangteng and Peng, Yuxin and Kong, Hao and Zhang, Qing},39 booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition},40 pages={6018--6026},41 year={2023}42}43"""44 45 46@add_start_docstrings(_DESCRIPTION, _KWARGS_DESCRIPTION)47class LayoutValidity(evaluate.Metric):48 def __init__(49 self,50 canvas_width: int | None = None,51 canvas_height: int | None = None,52 **kwargs,53 ) -> None:54 super().__init__(**kwargs)55 self.canvas_width = canvas_width56 self.canvas_height = canvas_height57 58 def _info(self) -> evaluate.EvaluationModuleInfo:59 return evaluate.MetricInfo(60 description=_DESCRIPTION,61 citation=_CITATION,62 inputs_description=_KWARGS_DESCRIPTION,63 features=ds.Features(64 {65 "predictions": ds.Sequence(ds.Sequence(ds.Value("float64"))),66 "gold_labels": ds.Sequence(ds.Sequence(ds.Value("int64"))),67 }68 ),69 codebase_urls=[70 "https://github.com/PKU-ICST-MIPL/PosterLayout-CVPR2023/blob/main/eval.py#L105-L127"71 ],72 )73 74 def _compute(75 self,76 *,77 predictions: Union[npt.NDArray[np.float64], List[List[float]]],78 gold_labels: Union[npt.NDArray[np.int64], List[int]],79 canvas_width: int | None = None,80 canvas_height: int | None = None,81 ) -> float:82 # パラメータの優先順位処理83 canvas_width = canvas_width if canvas_width is not None else self.canvas_width84 canvas_height = (85 canvas_height if canvas_height is not None else self.canvas_height86 )87 88 if canvas_width is None or canvas_height is None:89 raise ValueError(90 "canvas_width and canvas_height must be provided either "91 "at initialization or during computation"92 )93 94 predictions = np.array(predictions)95 gold_labels = np.array(gold_labels)96 97 predictions[:, :, ::2] *= canvas_width98 predictions[:, :, 1::2] *= canvas_height99 100 total_elements, empty_elements = 0, 0101 102 w = canvas_width / 100103 h = canvas_height / 100104 105 assert len(predictions) == len(gold_labels)106 107 for gold_label, prediction in zip(gold_labels, predictions):108 mask = (gold_label > 0).reshape(-1)109 mask_prediction = prediction[mask]110 total_elements += len(mask_prediction)111 for mp in mask_prediction:112 xl, yl, xr, yr = mp113 xl = max(0, xl)114 yl = max(0, yl)115 xr = min(canvas_width, xr)116 yr = min(canvas_height, yr)117 118 if abs((xr - xl) * (yr - yl)) < w * h * 10:119 empty_elements += 1120 121 return 1 - empty_elements / total_elements122 