├── src └── umetrix │ ├── __init__.py │ ├── render.py │ ├── notebooks.py │ └── core.py ├── .gitignore ├── tests ├── data │ └── unet.tif ├── test_metrics.py └── conftest.py ├── .github └── workflows │ ├── test.yml │ └── linting.yml ├── pyproject.toml ├── .pre-commit-config.yaml ├── LICENSE.md ├── README.md └── notebooks └── unet_segmentation_metrics.ipynb /src/umetrix/__init__.py: -------------------------------------------------------------------------------- 1 | from .core import calculate, batch # NOQA: F401 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.ipynb_checkpoints 2 | *.egg-info/ 3 | .DS_Store 4 | __pycache__ 5 | notebooks/ 6 | _version.py 7 | -------------------------------------------------------------------------------- /tests/data/unet.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lowe-lab-ucl/unet_segmentation_metrics/HEAD/tests/data/unet.tif -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | paths-ignore: 9 | - "**.md" 10 | - "**.rst" 11 | 12 | jobs: 13 | tests: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout source 17 | uses: actions/checkout@v3 18 | 19 | - name: Set up python 20 | uses: actions/setup-python@v4 21 | with: 22 | python-version: "3.10" 23 | cache: "pip" 24 | cache-dependency-path: "pyproject.toml" 25 | 26 | - name: Install dependencies 27 | run: | 28 | python -m pip install --upgrade pip 29 | python -m pip install pytest 30 | 31 | - name: Install umetrics 32 | run: | 33 | pip install -e . 34 | - name: Run tests 35 | run: | 36 | pytest 37 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools", "setuptools-scm"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [project] 6 | name = "umetrix" 7 | authors = [ 8 | {name = "Alan R. Lowe", email = "a.lowe@ucl.ac.uk"} 9 | ] 10 | description = "UNet Segmentation Metrics" 11 | readme = "README.md" 12 | requires-python = ">=3.8" 13 | keywords = ["image analysis"] 14 | license = {text = "BSD-3-Clause"} 15 | classifiers = [ 16 | "Programming Language :: Python :: 3" 17 | ] 18 | dependencies = [ 19 | "matplotlib", 20 | "numpy", 21 | "pandas", 22 | "scikit-learn", 23 | "scikit-image>=0.20.0" # to include the spacing argument in regionprops 24 | ] 25 | dynamic = ["version"] 26 | 27 | [tool.setuptools.packages.find] 28 | where = ["src"] 29 | include = ["umetrix*"] 30 | 31 | [tool.setuptools_scm] 32 | local_scheme = "no-local-version" 33 | write_to = "src/umetrix/_version.py" 34 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/charliermarsh/ruff-pre-commit 3 | rev: v0.0.262 4 | hooks: 5 | - id: ruff 6 | - repo: https://github.com/pre-commit/pre-commit-hooks 7 | rev: v4.4.0 8 | hooks: 9 | - id: check-case-conflict 10 | - id: check-docstring-first 11 | - id: check-executables-have-shebangs 12 | - id: check-merge-conflict 13 | - id: check-toml 14 | - id: end-of-file-fixer 15 | - id: mixed-line-ending 16 | args: [--fix=lf] 17 | - id: trailing-whitespace 18 | args: [--markdown-linebreak-ext=md] 19 | - repo: https://github.com/psf/black 20 | rev: 23.3.0 21 | hooks: 22 | - id: black 23 | - repo: https://github.com/pappasam/toml-sort 24 | rev: v0.23.0 25 | hooks: 26 | - id: toml-sort-fix 27 | -------------------------------------------------------------------------------- /.github/workflows/linting.yml: -------------------------------------------------------------------------------- 1 | name: Linting 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | linting: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout source 14 | uses: actions/checkout@v3 15 | 16 | - name: Cache pre-commit 17 | uses: actions/cache@v3 18 | with: 19 | path: ~/.cache/pre-commit 20 | key: pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} 21 | 22 | - name: Set up python 23 | uses: actions/setup-python@v4 24 | with: 25 | python-version: "3.x" 26 | cache: "pip" 27 | cache-dependency-path: "pyproject.toml" 28 | 29 | - name: Install dependencies 30 | run: |- 31 | python -m pip install pre-commit 32 | pre-commit install 33 | 34 | - name: Run pre-commit 35 | run: pre-commit run --all-files --color always 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Alan R. Lowe (quantumjot) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![PyPI](https://img.shields.io/pypi/v/umetrix)](https://pypi.org/project/umetrix) 2 | [![Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) 3 | [![umetrix](https://github.com/lowe-lab-ucl/unet_segmentation_metrics/actions/workflows/test.yml/badge.svg)]([https://github.com/quantumjot/vne](https://github.com/lowe-lab-ucl/unet_segmentation_metrics)/actions/workflows/test.yml) 4 | [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) 5 | 6 | # UNet segmentation metrics 7 | 8 | *WORK IN PROGRESS* 9 | 10 | Simple Python 3 tools to assess the performance of UNet segmentation networks 11 | (or any other segmentation method) by comparing the prediction to a ground truth 12 | image. 13 | 14 | Use it to calculate: 15 | + Jaccard metric for object detection 16 | + Intersection over Union (IoU) for object segmentation accuracy 17 | + Localization (positional) error for estimating MOTP during tracking 18 | + Pixel identity 19 | 20 | TODO: 21 | + [x] Add strict matching with IoU threshold 22 | + [ ] Add confusion matrix for multi-label/classification type tasks 23 | 24 | 25 | ### Single image usage 26 | 27 | ```python 28 | import umetrix 29 | from skimage.io import imread 30 | 31 | y_true = imread('true.tif') 32 | y_pred = imread('pred.tif') 33 | 34 | 35 | # can now make the calculation strict, by only considering objects that have 36 | # an IoU above a theshold as being true positives 37 | result = umetrix.calculate( 38 | y_true, 39 | y_pred, 40 | strict=True, 41 | iou_threshold=0.5 42 | ) 43 | 44 | print(result.results) 45 | ``` 46 | 47 | returns: 48 | 49 | ``` 50 | ============================ 51 | Segmentation Metrics (n=1) 52 | ============================ 53 | Strict: True (IoU > 0.5) 54 | n_true_labels: 354 55 | n_pred_labels: 362 56 | n_true_positives: 345 57 | n_false_positives: 10 58 | n_false_negatives: 0 59 | IoU: 0.999 60 | Jaccard: 0.972 61 | pixel_identity: 0.998 62 | localization_error: 0.010 63 | ``` 64 | 65 | 66 | ### Batch processing 67 | 68 | ```python 69 | import umetrix 70 | 71 | # provide a list of file pairs ('true', 'prediction') 72 | files = [ 73 | ('true0.tif', 'pred0.tif'), 74 | ('true1.tif', 'pred1.tif'), 75 | ('true2.tif', 'pred2.tif') 76 | ] 77 | 78 | batch_result = umetrix.batch(files) 79 | ``` 80 | 81 | Returns aggregate statistics over the batch. Jaccard index is calculated over 82 | all found objects, while other metrics are the average IoU etc. 83 | 84 | 85 | ### Installation 86 | 87 | 1. First clone the repo: 88 | ```sh 89 | $ git clone https://github.com/quantumjot/unet_segmentation_metrics.git 90 | ``` 91 | 92 | 2. (Optional, but advised) Create a conda environment: 93 | ```sh 94 | $ conda create -n umetrix python=3.9 95 | $ conda activate umetrix 96 | ``` 97 | 98 | 3. Install the package 99 | ```sh 100 | $ cd unet_segmentation_metrics 101 | $ pip install . 102 | ``` 103 | -------------------------------------------------------------------------------- /tests/test_metrics.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | 4 | import umetrix 5 | 6 | 7 | STRICT_PARAMS = [(False, 0.0), (True, 0.1), (True, 0.2), (True, 0.5), (True, 0.7)] 8 | 9 | 10 | @pytest.mark.parametrize("strict,iou_threshold", STRICT_PARAMS) 11 | def test_calculate(image_pair, strict, iou_threshold): 12 | """Run the metrics on a pair of images.""" 13 | y_true, y_pred, stats = image_pair 14 | IoU = stats["IoU"] 15 | 16 | result = umetrix.calculate( 17 | y_true, y_pred, strict=strict, iou_threshold=iou_threshold 18 | ) 19 | 20 | # calculate the real number of true postives based on strict matching 21 | real_tp = int(IoU > result.iou_threshold) if strict else int(IoU > 0) 22 | 23 | assert result.n_true_labels == 1 24 | assert result.n_pred_labels == 1 25 | assert result.n_true_positives == real_tp 26 | assert result.n_false_positives == 1 - real_tp 27 | 28 | 29 | def test_calculate_no_true(image_pair): 30 | """Test a pair of images where there is no object in the GT.""" 31 | y_true, y_pred, _ = image_pair 32 | y_true = np.zeros_like(y_pred) 33 | 34 | result = umetrix.calculate(y_true, y_pred) 35 | assert result.n_true_labels == 0 36 | assert result.n_pred_labels == 1 37 | assert result.n_true_positives == 0 38 | assert result.n_false_negatives == 0 39 | assert result.n_false_positives == 1 40 | 41 | 42 | def test_calculate_no_pred(image_pair): 43 | """Test a pair of images where there is no object in the prediction.""" 44 | y_true, y_pred, _ = image_pair 45 | y_pred = np.zeros_like(y_true) 46 | 47 | result = umetrix.calculate(y_true, y_pred) 48 | assert result.n_true_labels == 1 49 | assert result.n_pred_labels == 0 50 | assert result.n_true_positives == 0 51 | assert result.n_false_negatives == 1 52 | assert result.n_false_positives == 0 53 | 54 | 55 | @pytest.mark.parametrize("strict,iou_threshold", STRICT_PARAMS) 56 | def test_calculate_grid(image_grid, strict, iou_threshold): 57 | """Test a multi-instance segmentation.""" 58 | y_true, y_pred, stats = image_grid 59 | result = umetrix.calculate( 60 | y_true, y_pred, strict=strict, iou_threshold=iou_threshold 61 | ) 62 | 63 | n_iou_over_threshold = sum([iou > iou_threshold for iou in stats["IoU"]]) 64 | n_iou_under_threshold = stats["n_pairs"] - n_iou_over_threshold if strict else 0 65 | n_tp = n_iou_over_threshold 66 | n_fp = stats["n_false_positive"] + n_iou_under_threshold 67 | n_fn = stats["n_false_negative"] + n_iou_under_threshold 68 | 69 | assert result.n_true_labels == stats["n_true"] 70 | assert result.n_pred_labels == stats["n_pred"] 71 | assert result.n_true_positives == n_tp 72 | assert result.n_false_positives == n_fp 73 | assert result.n_false_negatives == n_fn 74 | 75 | 76 | @pytest.mark.parametrize("strict,iou_threshold", STRICT_PARAMS) 77 | def test_real(real_image_pair, strict, iou_threshold): 78 | """Test a real image pair.""" 79 | y_true, y_pred = real_image_pair 80 | result = umetrix.calculate( 81 | y_true, y_pred, strict=strict, iou_threshold=iou_threshold 82 | ) 83 | assert result.n_true_labels == 13 84 | assert result.n_pred_labels == 14 85 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | import numpy.typing as npt 4 | 5 | from pathlib import Path 6 | from skimage.io import imread 7 | from skimage.util import montage 8 | from typing import Tuple 9 | 10 | from umetrix.core import IoU 11 | 12 | SEED = 12343 13 | RNG = np.random.default_rng(seed=SEED) 14 | 15 | 16 | def _synthetic_image(sz: int = 32) -> npt.NDArray: 17 | image = np.zeros((sz, sz), dtype=np.uint8) 18 | boxsz = RNG.integers(low=sz // 4, high=sz - 1) 19 | xlo, ylo = RNG.integers(low=1, high=sz - boxsz, size=(2,)) 20 | image[xlo : xlo + boxsz, ylo : ylo + boxsz] = 1 21 | return image 22 | 23 | 24 | # def _IoU(y_true: npt.NDArray, y_pred: npt.NDArray) -> float: 25 | # union = np.sum(np.logical_or(y_true, y_pred)) 26 | # intersection = np.sum(np.logical_and(y_true, y_pred)) 27 | # return intersection / union 28 | 29 | 30 | @pytest.fixture 31 | def image_grid(N: int = 3, sz: int = 32) -> Tuple[npt.NDArray, npt.NDArray, dict]: 32 | image_types = RNG.choice( 33 | ["pair", "missing_true", "missing_pred"], size=(N * N,) 34 | ).tolist() 35 | true_stack = np.zeros((N * N, sz, sz), dtype=np.uint8) 36 | pred_stack = np.zeros((N * N, sz, sz), dtype=np.uint8) 37 | 38 | ious = [] 39 | 40 | n_true_positive = 0 41 | n_false_positive = 0 42 | n_false_negative = 0 43 | 44 | for idx, img_type in enumerate(image_types): 45 | if img_type == "pair": 46 | true_stack[idx, ...] = _synthetic_image() 47 | pred_stack[idx, ...] = _synthetic_image() 48 | iou = IoU(true_stack[idx, ...], pred_stack[idx, ...]) 49 | ious.append(iou) 50 | if iou > 0: 51 | n_true_positive += 1 52 | else: 53 | n_false_positive += 1 54 | n_false_negative += 1 55 | elif img_type == "missing_true": 56 | pred_stack[idx, ...] = _synthetic_image() 57 | ious.append(0.0) 58 | n_false_positive += 1 59 | else: 60 | true_stack[idx, ...] = _synthetic_image() 61 | ious.append(0.0) 62 | n_false_negative += 1 63 | 64 | # number of pairs where there is some overlap 65 | n_pairs = image_types.count("pair") 66 | n_missing_true = image_types.count("missing_true") 67 | n_missing_pred = image_types.count("missing_pred") 68 | 69 | stats = { 70 | "n_pairs": n_pairs, 71 | "n_true": n_pairs + n_missing_pred, 72 | "n_pred": n_pairs + n_missing_true, 73 | "n_true_positive": n_true_positive, 74 | "n_false_positive": n_false_positive, 75 | "n_false_negative": n_false_negative, 76 | "n_total": len(image_types), 77 | "IoU": ious, 78 | } 79 | 80 | return ( 81 | montage(true_stack, rescale_intensity=False, grid_shape=(N, N)), 82 | montage(pred_stack, rescale_intensity=False, grid_shape=(N, N)), 83 | stats, 84 | ) 85 | 86 | 87 | @pytest.fixture 88 | def image_pair() -> Tuple[npt.NDArray, npt.NDArray, dict]: 89 | y_true = _synthetic_image() 90 | y_pred = _synthetic_image() 91 | stats = {"IoU": IoU(y_true, y_pred)} 92 | return y_true, y_pred, stats 93 | 94 | 95 | @pytest.fixture 96 | def real_image_pair() -> Tuple[npt.NDArray, npt.NDArray]: 97 | filename = Path(__file__).parent.resolve() / "data" / "unet.tif" 98 | img = (imread(filename) > 0).astype(np.uint8) 99 | return img[0, ...], img[1, ...] 100 | -------------------------------------------------------------------------------- /src/umetrix/render.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import matplotlib.patches as patches 4 | 5 | 6 | def plot_metrics(seg_metrics): 7 | pred = seg_metrics._predicted 8 | ref = seg_metrics._reference 9 | 10 | iou = [None] * len(ref.labels) 11 | IoU = seg_metrics.per_object_IoU 12 | for i, tp in enumerate(seg_metrics.true_positives): 13 | iou[tp[0] - 1] = "{:.2f}".format(IoU[i]) 14 | 15 | fig, ax = plt.subplots(1, figsize=(16, 12)) 16 | ax.imshow(seg_metrics.image_overlay) 17 | 18 | for i, (sy, sx) in enumerate(ref.bboxes): 19 | r = patches.Rectangle( 20 | (sx.start, sy.start), 21 | sx.stop - sx.start, 22 | sy.stop - sy.start, 23 | edgecolor="g", 24 | facecolor="None", 25 | ) 26 | ax.add_patch(r) 27 | ax.text( 28 | sx.start, sy.start, "{}, IoU: {}".format(i, iou[i]), fontsize=6, color="w" 29 | ) 30 | for i, (sy, sx) in enumerate(pred.bboxes): 31 | r = patches.Rectangle( 32 | (sx.start, sy.start), 33 | sx.stop - sx.start, 34 | sy.stop - sy.start, 35 | edgecolor="m", 36 | facecolor="None", 37 | ) 38 | ax.add_patch(r) 39 | # ax.text(sx.start, sy.start, '{}'.format(i), fontsize=6, color='w') 40 | 41 | bboxes = pred.bboxes 42 | for fp in seg_metrics.false_positives: 43 | sy, sx = bboxes[fp - 1] 44 | w, h = sx.stop - sx.start, sy.stop - sy.start 45 | r = patches.Rectangle( 46 | (sx.start, sy.start), 47 | w, 48 | h, 49 | edgecolor="r", 50 | facecolor=(1.0, 0.0, 0.0, 0.0), 51 | linewidth=2, 52 | ) 53 | ax.add_patch(r) 54 | 55 | bboxes = ref.bboxes 56 | for fn in seg_metrics.false_negatives: 57 | sy, sx = bboxes[fn - 1] 58 | w, h = sx.stop - sx.start, sy.stop - sy.start 59 | r = patches.Rectangle( 60 | (sx.start, sy.start), 61 | w, 62 | h, 63 | edgecolor="c", 64 | facecolor=(0.0, 1.0, 1.0, 0.0), 65 | linewidth=2, 66 | ) 67 | ax.add_patch(r) 68 | plt.axis("off") 69 | plt.show() 70 | 71 | 72 | def make_bboxes(bbox_slices): 73 | """Calculate bboxes for napari""" 74 | minr = [sxy[0].start for sxy in bbox_slices] 75 | minc = [sxy[1].start for sxy in bbox_slices] 76 | maxr = [sxy[0].stop for sxy in bbox_slices] 77 | maxc = [sxy[1].stop for sxy in bbox_slices] 78 | 79 | bbox_rect = np.array([[minr, minc], [maxr, minc], [maxr, maxc], [minr, maxc]]) 80 | bbox_rect = np.moveaxis(bbox_rect, 2, 0) 81 | return bbox_rect 82 | 83 | 84 | def render_metrics_napari(seg_metrics): 85 | """Render the segmentation metrics for visualization in Napari.""" 86 | 87 | # pred = seg_metrics._predicted 88 | ref = seg_metrics._reference 89 | 90 | properties = {"iou": seg_metrics.per_object_IoU} 91 | 92 | bboxes = make_bboxes(ref.bboxes) 93 | tp_idx = np.asarray(seg_metrics.true_positives)[:, 0] - 1 94 | bboxes = bboxes[tp_idx, ...] 95 | 96 | # specify the display parameters for the text 97 | text_parameters = { 98 | "text": "IoU: {iou:.2f}\n", 99 | "size": 8, 100 | "color": "white", 101 | "anchor": "upper_left", 102 | "translation": [-2, 0], 103 | } 104 | 105 | return bboxes, properties, text_parameters 106 | -------------------------------------------------------------------------------- /src/umetrix/notebooks.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import io 3 | import itertools 4 | import matplotlib.pyplot as plt 5 | import numpy as np 6 | 7 | from matplotlib import colors, colormaps 8 | 9 | from umetrix.core import METRICS 10 | 11 | 12 | DARK_CONTEXT = { 13 | "axes.edgecolor": "gray", 14 | "xtick.color": "gray", 15 | "ytick.color": "gray", 16 | "axes.labelcolor": "gray", 17 | "font.size": 18, 18 | } 19 | 20 | 21 | def _text_color_based_on_value(value: float, cmap: colors.Colormap) -> str: 22 | rgb = cmap(value) 23 | luminance = 0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2] 24 | return "k" if luminance > 0.5 else "w" 25 | 26 | 27 | def _header() -> str: 28 | css = ( 29 | ".row {display: inline-flex; align-items: flex-start;}\n" 30 | ".metrics {float: left;}\n" 31 | ".confusion {width: 200px; float: left;}" 32 | ) 33 | return f"" 34 | 35 | 36 | def _footer() -> str: 37 | return "" 38 | 39 | 40 | def render_metrics_html(metrics) -> str: 41 | """Render the metrics to HTML""" 42 | 43 | html_table = _render_table(metrics) 44 | encoded_cm = _render_confusion(metrics) 45 | html_strict = ( 46 | f"

Strict matching (IoU threshold: {metrics.iou_threshold})

" 47 | if metrics.strict 48 | else "" 49 | ) 50 | 51 | html = ( 52 | _header() 53 | + "

Segmentation Metrics

" 54 | + html_strict 55 | + "
" 56 | + html_table 57 | + "
" 58 | + f"" 59 | + "
" 60 | + _footer() 61 | ) 62 | 63 | return html 64 | 65 | 66 | def _render_table(metrics) -> str: 67 | """Render the table of results""" 68 | 69 | def _get_f_string(m): 70 | val = getattr(metrics, m) 71 | return f"{val:.3f}" if isinstance(val, float) else f"{val:d}" 72 | 73 | return ( 74 | "" 75 | + "".join( 76 | [f"" for m in METRICS] 77 | ) 78 | + "
Metric
{m}" + _get_f_string(m) + "
" 79 | ) 80 | 81 | 82 | def _render_confusion(metrics, *, cmap: str = "Blues") -> str: 83 | """Render a confusion matrix as an image""" 84 | grid = np.zeros((2, 2), dtype=float) 85 | grid[1, 1] = metrics.n_true_positives 86 | grid[0, 1] = metrics.n_false_positives 87 | grid[1, 0] = metrics.n_false_negatives 88 | cmap = colormaps[cmap] 89 | 90 | with plt.rc_context(DARK_CONTEXT): 91 | _, ax = plt.subplots(figsize=(4, 4)) 92 | ax.pcolor(grid, cmap=cmap) 93 | ax.set_xticks([0.5, 1.5], labels=["Negative", "Positive"]) 94 | ax.set_yticks( 95 | [0.5, 1.5], labels=["Negative", "Positive"], rotation=90, va="center" 96 | ) 97 | 98 | for i, j in itertools.product(range(2), range(2)): 99 | ax.text( 100 | i + 0.5, 101 | j + 0.5, 102 | grid[i, j].astype(int), 103 | ha="center", 104 | va="center", 105 | color=_text_color_based_on_value(grid[i, j] / np.max(grid), cmap), 106 | ) 107 | ax.set_ylabel("Predicted") 108 | ax.set_xlabel("Ground truth") 109 | stream = io.BytesIO() 110 | plt.savefig(stream, format="png", bbox_inches="tight", transparent=True) 111 | plt.close() 112 | return base64.b64encode(stream.getvalue()).decode("utf-8") 113 | -------------------------------------------------------------------------------- /src/umetrix/core.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import enum 4 | import numpy as np 5 | import numpy.typing as npt 6 | 7 | from skimage.io import imread 8 | from scipy.ndimage import label 9 | from scipy.ndimage import center_of_mass 10 | from scipy.ndimage import find_objects 11 | from scipy.optimize import linear_sum_assignment 12 | 13 | from typing import Dict, Tuple 14 | 15 | from umetrix import render 16 | 17 | 18 | DEFAULT_MAXIMUM_COST = 1e8 19 | 20 | 21 | class Metrics(str, enum.Enum): 22 | N_TRUE_LABELS = "n_true_labels" 23 | N_PRED_LABELS = "n_pred_labels" 24 | N_TRUE_POSITIVES = "n_true_positives" 25 | N_FALSE_POSITIVES = "n_false_positives" 26 | N_FALSE_NEGATIVES = "n_false_negatives" 27 | IOU = "IoU" 28 | JACCARD = "Jaccard" 29 | PIXEL_IDENTITY = "pixel_identity" 30 | LOCALIZATION_ERROR = "localization_error" 31 | 32 | 33 | METRICS = ( 34 | "n_true_labels", 35 | "n_pred_labels", 36 | "n_true_positives", 37 | "n_false_positives", 38 | "n_false_negatives", 39 | "IoU", 40 | "Jaccard", 41 | "pixel_identity", 42 | "localization_error", 43 | ) 44 | 45 | 46 | def IoU(ref: npt.NDArray, pred: npt.NDArray) -> float: 47 | """Calculate the IoU between two binary masks.""" 48 | intersection = np.sum(np.logical_and(ref, pred)) 49 | union = np.sum(np.logical_or(ref, pred)) 50 | iou = 0.0 if union == 0 else intersection / union 51 | return iou 52 | 53 | 54 | def find_matches( 55 | ref: LabeledSegmentation, 56 | pred: LabeledSegmentation, 57 | *, 58 | strict: bool = False, 59 | iou_threshold: float = 0.5, 60 | ) -> Dict: 61 | """Perform matching between the reference and the predicted image. 62 | 63 | Parameters 64 | ---------- 65 | ref : 66 | The reference (ground truth) segmentation. 67 | pred : 68 | The predicted segmentation. 69 | strict : bool 70 | Whether to use strict matching, i.e. only allowing matches above a 71 | threshold IoU value. 72 | iou_threshold : 73 | A threshold value to use when strict matching. 74 | 75 | Return 76 | ------ 77 | matches : dict 78 | A dictionary of matches between the two images. 79 | """ 80 | 81 | # make an infinite cost matrix, so that we only consider matches where 82 | # there is some overlap in the masks 83 | cost_matrix = np.full((len(ref.labels), len(pred.labels)), DEFAULT_MAXIMUM_COST) 84 | 85 | for r_id, ref_label in enumerate(ref.labels): 86 | mask = ref.labeled == ref_label 87 | _matches = [m for m in np.unique(pred.labeled[mask]) if m > 0] 88 | for pred_label in _matches: 89 | p_id = pred.labels.index(pred_label) 90 | reward = IoU(mask, pred.labeled == pred_label) 91 | if (reward < iou_threshold) and strict: 92 | continue 93 | cost_matrix[r_id, p_id] = 1.0 - reward 94 | 95 | # if it's strict, make sure every element is above the threshold 96 | if strict: 97 | cost_threshold = 1.0 - iou_threshold 98 | cost_mask = cost_matrix == DEFAULT_MAXIMUM_COST 99 | assert np.all(cost_matrix[~cost_mask] <= cost_threshold) 100 | 101 | # solve it using JV 102 | sol_row, sol_col = linear_sum_assignment(cost_matrix) 103 | 104 | # remove infeasible solutions 105 | edges = [ 106 | (ref.labels[r], pred.labels[c], 1.0 - cost_matrix[r, c]) 107 | for r, c in zip(sol_row, sol_col) 108 | if cost_matrix[r, c] <= 1 109 | ] 110 | 111 | # return a default dictionary if there are no matches 112 | if not edges: 113 | matches = { 114 | "true_matches": [], 115 | "true_matches_IoU": [], 116 | "in_ref_only": set(ref.labels), 117 | "in_pred_only": set(pred.labels), 118 | } 119 | return matches 120 | 121 | # find the labels that haven't been used 122 | used_ref, used_pred, IoUs = zip(*edges) 123 | in_ref_only = set(ref.labels).difference(used_ref) 124 | in_pred_only = set(pred.labels).difference(used_pred) 125 | 126 | # return a dictionary of found matches 127 | matches = { 128 | "true_matches": list(set(zip(used_ref, used_pred))), 129 | "true_matches_IoU": IoUs, 130 | "in_ref_only": in_ref_only, 131 | "in_pred_only": in_pred_only, 132 | } 133 | 134 | return matches 135 | 136 | 137 | class MetricResults(object): 138 | def __init__(self, metrics): 139 | assert isinstance(metrics, SegmentationMetrics) 140 | self._images = 1 141 | self._metrics = metrics 142 | 143 | # list of metrics that are aggregated 144 | self._agg = ( 145 | "n_true_labels", 146 | "n_pred_labels", 147 | "n_true_positives", 148 | "n_false_positives", 149 | "n_false_negatives", 150 | "per_object_IoU", 151 | "per_object_localization_error", 152 | "per_image_pixel_identity", 153 | ) 154 | 155 | def __getattr__(self, key): 156 | return getattr(self._metrics, key) 157 | 158 | @property 159 | def n_images(self) -> int: 160 | if any([getattr(self, m) is None for m in self._agg]): 161 | return 0 162 | else: 163 | return self._images 164 | 165 | def __add__(self, result: MetricResults) -> MetricResults: 166 | assert isinstance(result, MetricResults) 167 | for m in self._agg: 168 | setattr(self, m, getattr(result, m) + getattr(self, m)) 169 | self._images += 1 170 | return self 171 | 172 | def __repr__(self) -> str: 173 | title = f" Segmentation Metrics (n={self.n_images})\n" 174 | hbar = "=" * len(title) + "\n" 175 | r = hbar + title + hbar 176 | if self.strict: 177 | r += f"Strict: {self.strict} (IoU > {self.iou_threshold})\n" 178 | for m in METRICS: 179 | mval = getattr(self, m) 180 | if isinstance(mval, float): 181 | r += f"{m}: {mval:.3f}\n" 182 | else: 183 | r += f"{m}: {mval}\n" 184 | return r 185 | 186 | def _repr_html_(self): 187 | from umetrix.notebooks import render_metrics_html 188 | 189 | return render_metrics_html(self) 190 | 191 | @property 192 | def localization_error(self) -> float: 193 | return np.mean(self.per_object_localization_error) 194 | 195 | @property 196 | def IoU(self) -> float: 197 | return np.mean(self.per_object_IoU) 198 | 199 | @property 200 | def Jaccard(self) -> float: 201 | """Jaccard metric""" 202 | tp = self.n_true_positives 203 | fn = self.n_false_negatives 204 | fp = self.n_false_positives 205 | return tp / (tp + fn + fp) 206 | 207 | @property 208 | def pixel_identity(self) -> float: 209 | return np.mean(self.per_image_pixel_identity) 210 | 211 | @staticmethod 212 | def merge(results: list) -> MetricResults: 213 | """Merge n results together and return a single object.""" 214 | merged = results.pop(0) 215 | for result in results: 216 | assert isinstance(result, MetricResults) 217 | assert result.n_images == 1 218 | merged = merged + result 219 | return merged 220 | 221 | 222 | class SegmentationMetrics: 223 | """A class for calculating various segmentation metrics to assess the 224 | accuracy of a trained model. 225 | 226 | Parameters 227 | ---------- 228 | reference : array 229 | An array containing labeled objects from the ground truth. 230 | predicted : array 231 | An array containing labeled objects from the segmentation algorithm. 232 | strict : bool 233 | Whether to disregard matches with a low IoU score. 234 | iou_threshold : float 235 | Threshold IoU for strict matching. 236 | 237 | Properties 238 | ---------- 239 | Jaccard : float 240 | The Jaccard index calculated according to the notes below. 241 | IoU : float 242 | The Intersection over Union metric. 243 | localisation_precision : float 244 | The localisation precision. 245 | true_positives : int 246 | Number of TP predictions. 247 | false_positives : int 248 | Number of FP predictions. 249 | false_negatives : int 250 | Number of FN predicitons. 251 | 252 | 253 | Notes 254 | ----- 255 | The Jaccard metric is calculated accordingly: 256 | 257 | FP = number of objects in predicted but not in reference 258 | TP = number of objects in both 259 | TN = background correctly segmented (not used) 260 | FN = number of objects in true but not in predicted 261 | 262 | J = TP / (TP+FP+FN) 263 | 264 | The IoU is calculated as the intersection of the binary segmentation 265 | divided by the union. 266 | """ 267 | 268 | def __init__( 269 | self, reference: LabeledSegmentation, predicted: LabeledSegmentation, **kwargs 270 | ): 271 | assert isinstance(predicted, LabeledSegmentation) 272 | assert isinstance(reference, LabeledSegmentation) 273 | 274 | self._reference = reference 275 | self._predicted = predicted 276 | self._strict = kwargs.get("strict", False) 277 | self._iou_threshold = kwargs.get("iou_threshold", 0.5) 278 | 279 | if self.iou_threshold < 0.0 or self.iou_threshold > 1.0: 280 | raise ValueError( 281 | f"IoU Threshold shoud be in (0, 1), found: {self.iou_threshold:.2f}" 282 | ) 283 | assert isinstance(self.strict, bool) 284 | 285 | # find the matches 286 | self._matches = find_matches( 287 | self._reference, 288 | self._predicted, 289 | strict=self.strict, 290 | iou_threshold=self.iou_threshold, 291 | ) 292 | 293 | @property 294 | def strict(self) -> bool: 295 | return self._strict 296 | 297 | @property 298 | def iou_threshold(self) -> float: 299 | return self._iou_threshold 300 | 301 | @property 302 | def results(self): 303 | return MetricResults(self) 304 | 305 | @property 306 | def image_overlay(self): 307 | # n_labels = max([self._predicted.n_labels, self._reference.n_labels]) 308 | # scale = int(255 / n_labels) 309 | return ( 310 | np.stack( 311 | [self._predicted.image, self._reference.image, self._predicted.image], 312 | axis=-1, 313 | ) 314 | * 127 315 | ) 316 | 317 | @property 318 | def n_true_labels(self): 319 | return self._reference.n_labels 320 | 321 | @property 322 | def n_pred_labels(self): 323 | return self._predicted.n_labels 324 | 325 | @property 326 | def true_positives(self): 327 | """Only one match between reference and predicted.""" 328 | return self._matches["true_matches"] 329 | 330 | @property 331 | def false_negatives(self): 332 | """No match in predicted for reference object.""" 333 | return self._matches["in_ref_only"] 334 | 335 | @property 336 | def false_positives(self): 337 | """Combination of non unique matches and unmatched objects.""" 338 | return self._matches["in_pred_only"] 339 | 340 | @property 341 | def n_true_positives(self): 342 | return len(self.true_positives) 343 | 344 | @property 345 | def n_false_negatives(self): 346 | return len(self.false_negatives) 347 | 348 | @property 349 | def n_false_positives(self): 350 | return len(self.false_positives) 351 | 352 | @property 353 | def per_object_IoU(self): 354 | """Intersection over Union (IoU) metric""" 355 | return self._matches["true_matches_IoU"] 356 | 357 | @property 358 | def per_image_pixel_identity(self): 359 | """Calculate the per-image pixel identity.""" 360 | n_tot = np.prod(self._reference.image.shape) 361 | return [np.sum(self._reference.image == self._predicted.image) / n_tot] 362 | 363 | @property 364 | def per_object_localization_error(self): 365 | """Calculate the per-object localization error.""" 366 | ref_centroids = self._reference.centroids 367 | tgt_centroids = self._predicted.centroids 368 | positional_error = [] 369 | for m in self.true_positives: 370 | true_centroid = np.array(ref_centroids[m[0] - 1]) 371 | pred_centroid = np.array(tgt_centroids[m[1] - 1]) 372 | err = np.sum((true_centroid - pred_centroid) ** 2) 373 | positional_error.append(err) 374 | return positional_error 375 | 376 | def plot(self): 377 | render.plot_metrics(self) 378 | 379 | def to_napari(self): 380 | return render.render_metrics_napari(self) 381 | 382 | def __repr__(self): 383 | return self.results.__repr__() 384 | 385 | def _repr_html_(self): 386 | return self.results._repr_html_() 387 | 388 | 389 | class LabeledSegmentation: 390 | """A helper class to enable simple calculation of accuracy statistics for 391 | image segmentation output. 392 | """ 393 | 394 | def __init__(self, image: npt.NDArray): 395 | self.image = image 396 | self.labeled, self.n_labels = label(image.astype(bool)) 397 | 398 | @property 399 | def shape(self) -> Tuple[int]: 400 | return self.image.shape 401 | 402 | @property 403 | def bboxes(self): 404 | return [find_objects(self.labeled == label)[0] for label in self.labels] 405 | 406 | @property 407 | def labels(self): 408 | return range(1, self.n_labels + 1) 409 | 410 | @property 411 | def centroids(self): 412 | return [center_of_mass(self.labeled == label) for label in self.labels] 413 | 414 | @property 415 | def areas(self): 416 | return [np.sum(self.labeled == label) for label in self.labels] 417 | 418 | 419 | def calculate(reference, predicted, **kwargs): 420 | """Take a predicted image and compare with the reference image. 421 | 422 | Compute various metrics. 423 | """ 424 | 425 | ref = LabeledSegmentation(reference) 426 | tgt = LabeledSegmentation(predicted) 427 | 428 | # make sure they are the same size 429 | assert ref.shape == tgt.shape 430 | 431 | return SegmentationMetrics(ref, tgt, **kwargs) 432 | 433 | 434 | def batch(files, **kwargs): 435 | """batch process a list of files""" 436 | metrix = [] 437 | for f_ref, f_pred in files: 438 | true = imread(f_ref) 439 | pred = imread(f_pred) 440 | result = calculate(true, pred, **kwargs).results 441 | metrix.append(result) 442 | return MetricResults.merge(metrix) 443 | 444 | 445 | if __name__ == "__main__": 446 | pass 447 | -------------------------------------------------------------------------------- /notebooks/unet_segmentation_metrics.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "## Simple demonstration of calculating segmentation metrics" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "*NOTE(arl)*: the metrics here are calculated as follows in batch mode:\n", 15 | "+ `n_true_labels` is the sum of all true labels, etc\n", 16 | "+ `IoU` is the mean IoU of all found objects\n", 17 | "+ `Jaccard` is the Jaccard index over all found objects\n", 18 | "+ `localization_error` is the mean error for all found objects\n", 19 | "+ `pixel_identity` is the per image pixel identity" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 1, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "import umetrix\n", 29 | "\n", 30 | "import numpy as np\n", 31 | "from skimage.io import imread" 32 | ] 33 | }, 34 | { 35 | "cell_type": "code", 36 | "execution_count": 2, 37 | "metadata": {}, 38 | "outputs": [], 39 | "source": [ 40 | "# load a ground truth - prediction image pair\n", 41 | "p = \"../tests/data/unet.tif\"\n", 42 | "s = imread(p)\n", 43 | "y_true = s[-2, ...]\n", 44 | "y_pred = s[-1, ...]" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": 3, 50 | "metadata": {}, 51 | "outputs": [], 52 | "source": [ 53 | "result = umetrix.calculate(y_true, y_pred)" 54 | ] 55 | }, 56 | { 57 | "cell_type": "code", 58 | "execution_count": 4, 59 | "metadata": {}, 60 | "outputs": [ 61 | { 62 | "data": { 63 | "text/html": [ 64 | "

Segmentation Metrics

Metric
n_true_labels13
n_pred_labels14
n_true_positives12
n_false_positives2
n_false_negatives1
IoU0.807
Jaccard0.800
pixel_identity0.959
localization_error15.524
" 67 | ], 68 | "text/plain": [ 69 | "============================\n", 70 | " Segmentation Metrics (n=1)\n", 71 | "============================\n", 72 | "n_true_labels: 13\n", 73 | "n_pred_labels: 14\n", 74 | "n_true_positives: 12\n", 75 | "n_false_positives: 2\n", 76 | "n_false_negatives: 1\n", 77 | "IoU: 0.807\n", 78 | "Jaccard: 0.800\n", 79 | "pixel_identity: 0.959\n", 80 | "localization_error: 15.524" 81 | ] 82 | }, 83 | "execution_count": 4, 84 | "metadata": {}, 85 | "output_type": "execute_result" 86 | } 87 | ], 88 | "source": [ 89 | "result" 90 | ] 91 | }, 92 | { 93 | "cell_type": "markdown", 94 | "metadata": {}, 95 | "source": [ 96 | "## visualize the metrics" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 5, 102 | "metadata": {}, 103 | "outputs": [ 104 | { 105 | "data": { 106 | "image/png": "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7a688spccsklefDBBzfqo6amJpdccklOOeWUJMnUqVNz8MEHp66u9Pl6jz32yPe///0MHz48s2fPzve///0Nth966KG55JJL0tramptuuikXXnhh9txzz/z26t+malBVHvnZI5l/2fyy7+PyLC+7bV9wek7fpts51wJQJIo4AfQzQ4YMyac//em8973vzZFHHpnf/Ow3PbLf888/PxdffHEOP/zwnH322Rk6dOgG288777yceeaZede73pWjjz461dXVueCCC/K7//hdrj7y6tQcUZOdxu3UI2MFAHonARagn3nXu96V5ubm/PznP8/111+f0buP3uJtBg4cmGuuuSa33357brzxxuy8886bbX/55ZdvFFAnTZqUW2+9NevWrcu9996b/fbbb4PtDz30UKqrqzNo0KCsW7cuq1atyt57753n/vRckqTxz415w+Q3bOW9BQD6EgEWoJ/Zfffd86Y3vSnHHXdc5syZk3O+cM4Wb3PCCSfkqaeeypFHHpkf/vCHOeeczd/m3HPPzapVqza4btCgQWlra0uSNDU1ZZdddtlg+w033JB58+bl4Ycfzu23357Vq1dn4cKFeeO735gBAwek5siaDB21YSgGAPqX3rEGtsRyKWte+5BSD6UlV1Axy5Yty+9+97usWbMmt956ay684MKsyIrN3mbChAlZsGBBkmTBggU55phjsmrVqgwZMqSjzdChQ9Pc3LzJPtasWZOqqqq0trZm1KhRefHFFzc415916Vm5/rDrs2zRsvzjvH/MbvvulpVfWpm3zX5b3vmxd+blp1/O8uc2sa61v71kdOE5tJzXW+tkAegtzMAC9DP/7//9v7z1rW9Nkhx44IF5+vGnkyS7j9t9k7d57LHHMmnSpCTtHwVuaGjIkiVLMn78+Awb1v71O4ceemgeeOCBTfZx7733ZsqUKRk4cGAOOuig/M///M8G29ta27KqaVXSlqx+ZXWGVA/JyqUrc+3J1+YH7/1BqgZX5cnbn9yeuw4AFFzvmIEFoMe8uO7F/OyOn+WOe+5Ia2tr/v0T/57P5XP56n99NUecfkRaWlpeazwsyW7JDb+/ISeedmLuuOeOrFi5Iqf982nJ2ORzl38ut9x5S1paWvLQow/ll3/6ZTI2ubzu8lzwpQs2+BjxxVdenLnfmJsLL74w3/ret7J6l9Wp2q8qex+0d+783p25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FIIACwAAQCEIsAAAABSCAAsAAEAhKOIEANAV6jpfLGjBpm1V6u52Y52lUsdXYSfo+8zAAgAAUAgCLAAAAIUgwAIAAFAI1sACAGytEus9+92a13L08LpYoO/r9TOwAwYMyFVXXZU777wzd9xxR/bee+9Ntr3yyiuz3377ldxWU1OTa6+9tuPy1KlTU1u76TPoHnvskZtvvjl33XVXzjjjjI22H3rooZk/f37uvvvufP7zn0+SfOxjH8ttt92W2267Lc8991yOP/74cu8mAAAAW9DrA+wBBxyQIUOG5PDDD8+///u/55//+Z97ZL/nn39+Lr744hx++OE5++yzM3To0A22n3feeTnzzDPzrne9K0cffXSqq6vz7W9/O1OmTMmUKVPy3HPP5eabb+6RsQIAAPQHvT7A/vWvf+34fdSoUXn++ee3eJuBAwfmmmuuye23354bb7wxO++882bbX3755RsF1EmTJuXWW2/NunXrcu+99240s/vQQw+luro6gwYNyrp167Jq1aqObQcccEAeeeSRNDc3l3MXAQAAKEOvXwO7dOnStLa2ZuHChRkyZEgOOeSQLd7mhBNOyFNPPZXTTjstp59+es4555xcffXVm2x/7rnnbnTdoEGD0tbWliRpamrKLrvsssH2G264IfPmzcvq1aszd+7crF69umPbKaecssHHlQEAANh+vT7ATp06Nc3Nzfmbv/mbHHjggbnsssvyoQ99aLO3mTBhQhYsWJAkWbBgQY455pisWrUqQ4YM6WgzdOjQzc6QrlmzJlVVVWltbc2oUaPy4osvbrD90ksvzWGHHZZFixZl3rx52XffffPwww8nSf7+7/8+F1100bbe5e1SVgGJrqwxsY2FGHzROACF8err5uIk9UlmVHAsfUHn9yHeEgBbodcH2OyYvLTmpWRssmyHZRm1+6hkbDJuj3FZ/NziJMmYdWNS3VqdkUNHpmbnmqxoXJGpR0zNA3c+kOPefVxefObFjFw3Mm9+05vz9vFvz6rmVTnu6OMy/3fzM3H0xJK7fezBx3LGB87I7+/6fQ75u0My++LZG7QdMnBIRg8ancG7Ds6AlgF5W83bsm7puvzN2/4mzz71bPYcvmcyvCcO0IaaU8bHlp/pwh2O3rabTUzp496lViVZvvkmTWlKYxq7fywAAMB2690Btjr59b6/zhmHnJHb7749QwYN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6is7gBnd0GdLkisixAIAsAEBti8YnmSH5B9O+of2WdckE9dMzHvz3lz6kUszc/CGxXp2feOuuePf7kjWvXbd1bm64/dL6y/Npbl0g9s0pCFHfemojXb9+tu9al3WZdrsaRtdP7O+fRx/zV/znq++Z6Ptt6z/j9cpIxzO6JYEuRW6MD/Xp779UwMnpf15LcACAPA6/TLA9tl1dkuTPFviuk7+ado/9cRo2JIirG8tR7nFjMv4s6tLXRZncepTnxmZUfnZZQAAepWqSg8AAAAAyiHAAgAAUAgCLAAAAIUgwAIAAFAIfb+IUx+t10Qv0leKMXW3zoegzKJOnfXZImwAAGyRGVgAAAAKQYAFAACgEARYAAAACkGABQAAoBD6fBEnBV/oSnV1ijEBAEClmIEFAACgEARYAAAACkGABQAAoBD63BrY2lprXtk21rf2sFKH258vAACbYQYWAACAQhBgAQAAKAQBFgAAgEIQYAEAACiEQhdxUrCJcinQBNB/jBgxIrfcckv222+/HHzwwXnwwQczfPjw/OQnP8nQoUOzbt26nHXWWVm0aFHJ25955pkZMWJErrjiipLbFyxYkEmTJiVJhgwZkptuuilTpkwp2XbgwIH5zne+kwkTJuSPf/xjPvnJT26wfc8998zVV1+dQYMG5Wc/+1kuu+yyjm0f/OAH8/Wvfz1jxozZhqMA0DeZgQUA+pTm5ua8733vy3XXXddx3dq1a3PWWWfliCOOyJe+9KWcd955PTKW4447Ln/9619z+OGHZ/jw4Zk8efIG2y+44IL8x3/8R4488sgcccQRGTduXJJkwIABOfnkk/P000/3yDgBikKABQD6lHXr1mXp0qUbXNfS0pLFixcnSdasWZO1a9eW1denP/3p3H333bnrrrvyzne+c7NtzzzzzBx88MEbXDd58uT8+te/TpLcdNNNede73rXB9r333jt/+tOfkiR//vOfOwLuhz/84Vx33XVpbW0ta5wA/YUACwD0G4MGDcrnP//5fP3rX99i29133z3HH398DjnkkHz4wx/Ol7/85c22v/rqqzN//vwNrhs1alRefvnlJElTU1N22WWXDbYvXLgw7373uzNw4MAceeSRGTVqVKqqqnLqqafmv/7rv7by3gH0fYVZA2u9K0lSlzLWslruCsAmzJkzJ7Nnz87jjz++xbZvfOMbc//996et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", 107 | "text/plain": [ 108 | "
" 109 | ] 110 | }, 111 | "metadata": {}, 112 | "output_type": "display_data" 113 | } 114 | ], 115 | "source": [ 116 | "result.plot()" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "### now perform the calculation with strict matching only" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": 6, 129 | "metadata": {}, 130 | "outputs": [ 131 | { 132 | "data": { 133 | "text/html": [ 134 | "

Segmentation Metrics

Strict matching (IoU threshold: 0.5)

Metric
n_true_labels13
n_pred_labels14
n_true_positives11
n_false_positives3
n_false_negatives2
IoU0.841
Jaccard0.688
pixel_identity0.959
localization_error5.305
" 137 | ], 138 | "text/plain": [ 139 | "============================\n", 140 | " Segmentation Metrics (n=1)\n", 141 | "============================\n", 142 | "Strict: True (IoU > 0.5)\n", 143 | "n_true_labels: 13\n", 144 | "n_pred_labels: 14\n", 145 | "n_true_positives: 11\n", 146 | "n_false_positives: 3\n", 147 | "n_false_negatives: 2\n", 148 | "IoU: 0.841\n", 149 | "Jaccard: 0.688\n", 150 | "pixel_identity: 0.959\n", 151 | "localization_error: 5.305" 152 | ] 153 | }, 154 | "execution_count": 6, 155 | "metadata": {}, 156 | "output_type": "execute_result" 157 | } 158 | ], 159 | "source": [ 160 | "result = umetrix.calculate(y_true, y_pred, strict=True, iou_threshold=0.5)\n", 161 | "result" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": 7, 167 | "metadata": {}, 168 | "outputs": [ 169 | { 170 | "data": { 171 | "image/png": "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gc5z+OGH53Of+1z69euXH1z5g+QnycIszIIsWK/dNddck8svvzwPPfTQBuuoqanJ5ZdfnlNOOSVJMmnSpBx44IGpqyt9vt55551z/fXXZ/DgwZkxY0auv/769ZYfcsghufzyy9Pc3Jxbb701F198cXbZZZf85rrfpKpfVR79yaO5/8r7y36My7Ks7LY9weRM3qr7OdcCUCSKOAH0MgMGDMinP/3pvO9978sRRxyRX/3kV12y3QsvvDCXXnppDjvssJxzzjkZOHDgessvuOCCnHnmmXnPe96To48+OtXV1bnooovy2//6ba474rrUHF6T7cdu3yV9BQC6JwEWoJd5z3vek8bGxvz0pz/N3LlzM2qnUZu9T9++fXPDDTfkrrvuyi233JIRI0Zssv1VV121QUCdMGFC7rjjjjQ1NeWBBx7I3nvvvd7yhx9+ONXV1enXr1+ampqycuXK7L777nn+T88nSer/XJ83HfSmLXy0AEBPIsAC9DI77bRT3vzmN+e4447LrFmzcu4Xzt3sfU444YQ89dRTOeKII/L9738/55676fucd955Wbly5Xq39evXLy0tLUmShoaG7LDDDustv/nmmzNnzpw88sgjueuuu7Jq1arMnz8/ux25W/r07ZOaI2oycPj6oRgA6F26xxzYEtOlzHntQUo9laZcQcUsXbo0v/3tb7NmzZrccccdufiii7M8yzd5nz322CPz5s1LksybNy/HHHNMVq5cmQEDBrS1GThwYBobGze6jjVr1qSqqirNzc0ZPnx4XnrppfXO9WddcVbmHjo3Sxcuzb/M+ZeM3mt0VnxpRd4x4x3Z/2P755WnX8my5zcyr7W3vWV04Dm0nPdb82QB6C6MwAL0Mv/v//2/vP3tb0+S7Lfffnn68aeTJDuN3Wmj93nssccyYcKEJK1fBV6wYEEWL16ccePGZdCg1p/fOeSQQ/KXv/xlo+t44IEHMnHixPTt2zcHHHBA/vrXv663vKW5JSsbViYtyapXV2VA9YCsWLIiN558Y773vu+lqn9VnrzryW156ABAwXWPEVgAusxLTS/lJ3f/JHffd3eam5vzn5/4z3wun8tX/ucrOXzy4Vm9evXrjQclGZ3c/Lubc+LpJ+bu++7O8hXLc/q/n56MST531edy+69vz+rVq/Pw3x7Oz//082RMclXdVbnoSxet9zXiS6+5NLO/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/PA8/fTTXdJXAICeToAFCmH33XfPn/70pyTJH/7whxx66KGbvU/fvn1zww035K677sott9zSNjq6MVddddUGAXXChAm544470tTUlAceeGCjI7snn3xybrrppiTJBz7wgQwcODC/+tWv8rWvfS1VVU61AAAdwacqoBDmz5+fI488Mkly1FFHZfjw4Zu9zwknnJCnnnoqRxxxRL7//e/n3HPP3WT78847LytXrlzvtn79+qWlpSVJ0tDQkB122KHkfU888cTMnTs3SbLTTjtl7dq1ee9735sVK1bklFNO2WxfAQDYPEWcepoSNRd6ciEGeo+f/exnmThxYu6444789a9/zfPPP7/Z++yxxx6ZN29ekmTevHk55phjsnLlygwYMKCtzYCBA9LU2LTRdaxZsyZVVVVpbm7O8OHD89JLL23Q5spdrsy4tePyb4v/LUnyjqXvyNP3Pp261OVNd7wpBx18UO7KXVv4iLdAT69HUuFTWKmCL86rlDwEOui16Pjaehsr0DQkVyZpyJAM6doOAR2uGAF21CaWrUmyJKkZXlOUR0NXGJJkUVqPj42oSU1X9YYO0DKsJed/5fwkSe2na3P7b29PxiRjdx6bRc8vWr/xoCSjk8defCwTJk7I3PvmZsLRE7Lg+QVZXLU443Yfl0G7D0pjY2MOOPqALL9leet5pv+G231g/gOZePLE3HXvXTngwAPymSs+k4xZv80uH90l9912XxaNae3Hg/MfzLhDx2XRvEV55+HvzBP1T7Qt6xQtnbfqbmHM5ptsqcErBmd4w/COXzG9wuiszXOlPnRc1vV96UlGL1/bdvncZVv3oa41qJa4ffkrW90voHvp3pFvRZLVSU7aeJOGpQ1pvLox05dO76peUQRLkjy2+WaNaUxDGjq9O2yj6mSnz+6UH3zoB1nbvDa3P3577ll2T7JfMvsjs3PsDcdmddPq19vvmeSU5OYlN+fEw0/M3cfdneWrl+f0uacnU5PP/flzuf2u27O6aXWeffLZvPTvLyVnJ1eddVUu+tVFWbn29a8RX9pwaWZ/aXYu7n9xvvnAN7Nqyqrss9M+OWjcQZnxwIwkyZgpY3LKjadk8dTFSZKqPlWZceSMnHbyaXlh+Qv52NyPZc3UTfxrCps2teNX2X91//z71f8uxLJFmtOcJOmbZOes3bDB8q7tT0/VN8nOy0vs37Js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", 172 | "text/plain": [ 173 | "
" 174 | ] 175 | }, 176 | "metadata": {}, 177 | "output_type": "display_data" 178 | } 179 | ], 180 | "source": [ 181 | "result.plot()" 182 | ] 183 | }, 184 | { 185 | "cell_type": "code", 186 | "execution_count": null, 187 | "metadata": {}, 188 | "outputs": [], 189 | "source": [] 190 | } 191 | ], 192 | "metadata": { 193 | "kernelspec": { 194 | "display_name": "Python [conda env:btrack]", 195 | "language": "python", 196 | "name": "conda-env-btrack-py" 197 | }, 198 | "language_info": { 199 | "codemirror_mode": { 200 | "name": "ipython", 201 | "version": 3 202 | }, 203 | "file_extension": ".py", 204 | "mimetype": "text/x-python", 205 | "name": "python", 206 | "nbconvert_exporter": "python", 207 | "pygments_lexer": "ipython3", 208 | "version": "3.10.9" 209 | } 210 | }, 211 | "nbformat": 4, 212 | "nbformat_minor": 4 213 | } 214 | --------------------------------------------------------------------------------