THE CODE READER / PYTHON

cv_masks.py

Your snippet, in context. Explore the file or visualize its recorded example.

Download raw .py ↓
Complete file
PYTHON / LINE NUMBERS
 1"""Deterministic binary segmentation baseline. No learned model or dataset."""
 2from __future__ import annotations
 3
 4from typing import cast
 5
 6import cv2
 7import numpy as np
 8from numpy.typing import NDArray
 9
10ByteImage = NDArray[np.uint8]
11Mask = NDArray[np.bool_]
12
13
14def scene() -> tuple[ByteImage, Mask]:
15    """Return a uint8 (12,12) scene and independently defined rectangle target."""
16    target: Mask = np.zeros((12, 12), dtype=np.bool_)
17    target[3:9, 3:9] = True
18    gray: ByteImage = np.where(target, 180, 30).astype(np.uint8)
19    gray[1, 1] = 220  # distractor: bright, but not part of the target
20    gray[5, 5] = 40   # corruption: dark, but still part of the target
21    return gray, target
22
23# region threshold
24def threshold_mask(gray: ByteImage, threshold: int = 100) -> Mask:
25    """Nonempty uint8 (H,W) -> bool (H,W), using STRICT greater-than."""
26    if gray.dtype != np.uint8 or gray.ndim != 2 or gray.size == 0:
27        raise ValueError("Expected a nonempty uint8 grayscale image")
28    if not 0 <= threshold <= 255:
29        raise ValueError("Threshold must be in [0,255]")
30    mask: Mask = gray > threshold
31    _, encoded = cv2.threshold(gray, threshold, 255, cv2.THRESH_BINARY)
32    np.testing.assert_array_equal(mask, encoded != 0)
33    return mask
34# endregion threshold
35
36# region morphology
37def clean_mask(mask: Mask) -> tuple[Mask, Mask]:
38    """Return closing then opening, 3x3 square, outside-image background=0."""
39    if mask.dtype != np.bool_ or mask.ndim != 2 or mask.size == 0:
40        raise ValueError("Expected a nonempty bool mask")
41    encoded: ByteImage = mask.astype(np.uint8) * np.uint8(255)
42    kernel: ByteImage = np.ones((3, 3), dtype=np.uint8)
43    closed_u8: ByteImage = cast(ByteImage, cv2.morphologyEx(
44        encoded, cv2.MORPH_CLOSE, kernel,
45        borderType=cv2.BORDER_CONSTANT, borderValue=0,
46    ))
47    opened_u8: ByteImage = cast(ByteImage, cv2.morphologyEx(
48        closed_u8, cv2.MORPH_OPEN, kernel,
49        borderType=cv2.BORDER_CONSTANT, borderValue=0,
50    ))
51    closed: Mask = closed_u8 != 0
52    cleaned: Mask = opened_u8 != 0
53    return closed, cleaned
54# endregion morphology