diff --git a/cv_analysis/utils/structures.py b/cv_analysis/utils/structures.py index c799df6..b110862 100644 --- a/cv_analysis/utils/structures.py +++ b/cv_analysis/utils/structures.py @@ -77,14 +77,6 @@ class Rectangle: y2 = y1 + h return cls(x1, y1, x2, y2, discrete=discrete) - @classmethod - def from_dict_xywh(cls, xywh: Dict[str, Coord], discrete=True): - """Creates a rectangle from a point and a width and height.""" - x1, y1, w, h = itemgetter("x", "y", "width", "height")(xywh) - x2 = x1 + w - y2 = y1 + h - return cls(x1, y1, x2, y2, discrete=discrete) - def xyxy(self): return self.x1, self.y1, self.x2, self.y2 diff --git a/cv_analysis/utils/test_metrics.py b/cv_analysis/utils/test_metrics.py index 9e46e97..91d3676 100644 --- a/cv_analysis/utils/test_metrics.py +++ b/cv_analysis/utils/test_metrics.py @@ -1,5 +1,10 @@ +from operator import itemgetter from typing import Iterable + import numpy as np +from funcy import lmap, lpluck + +from cv_analysis.utils import lift from cv_analysis.utils.structures import Rectangle @@ -25,37 +30,28 @@ def compute_page_iou(results_boxes: Iterable[Rectangle], ground_truth_boxes: Ite return score -def compute_document_score(results_dict, annotation_dict): +def compute_document_score(result_dict, ground_truth_dicts): - page_weights = np.array([len(page["cells"]) for page in annotation_dict["pages"]]) - page_weights = page_weights / sum(page_weights) + extract_cells = lambda dicts: lpluck("cells", dicts["pages"]) - scores = [] - for i in range(len(annotation_dict["pages"])): - scores.append( - compute_page_iou( - map(Rectangle.from_dict_xywh, results_dict["pages"][i]["cells"]), - map(Rectangle.from_dict_xywh, annotation_dict["pages"][i]["cells"]), - ) - ) + cells_per_ground_truth_page, cells_per_result_page = map(extract_cells, (ground_truth_dicts, result_dict)) + cells_on_page_to_rectangles = lift(rectangle_from_dict) + cells_on_pages_to_rectangles = lift(cells_on_page_to_rectangles) - doc_score = np.average(np.array(scores), weights=page_weights) + rectangles_per_ground_truth_page, rectangles_per_result_page = map( + cells_on_pages_to_rectangles, (cells_per_ground_truth_page, cells_per_result_page) + ) - return doc_score + scores = lmap(compute_page_iou, rectangles_per_result_page, rectangles_per_ground_truth_page) + + n_cells_per_page = np.array(lmap(len, cells_per_ground_truth_page)) + document_score = np.average(scores, weights=n_cells_per_page / n_cells_per_page.sum()) + + return document_score -""" -from cv_analysis.utils.test_metrics import * - -r1 = Rectangle.from_dict_xywh({'x': 30, 'y': 40, 'width': 50, 'height': 60}) -r2 = Rectangle.from_dict_xywh({'x': 40, 'y': 30, 'width': 55, 'height': 65}) -r3 = Rectangle.from_dict_xywh({'x': 45, 'y': 35, 'width': 45, 'height': 55}) -r4 = Rectangle.from_dict_xywh({'x': 25, 'y': 45, 'width': 45, 'height': 55}) -d1 = {"pages": [{"cells": [r1.json_xywh(), r2.json_xywh()]}]} -d2 = {"pages": [{"cells": [r3.json_xywh(), r4.json_xywh()]}]} - -compute_iou_from_boxes(r1, r2) -find_max_overlap(r1, [r2, r3, r4]) -compute_page_iou([r1, r2], [r3, r4]) -compute_document_score(d1, d2) -""" +def rectangle_from_dict(d): + x1, y1, w, h = itemgetter("x", "y", "width", "height")(d) + x2 = x1 + w + y2 = y1 + h + return Rectangle(x1, y1, x2, y2)