How To: Refine Noisy Detection Boundaries#

After detection, colony masks often have ragged edges, small holes, or spurious fragments. Use refiners to clean up the mask before measuring.

[1]:
from phenotypic.data import load_yeast_plate
from phenotypic.enhance import GaussianBlur, CLAHE
from phenotypic.detect import OtsuDetector
from phenotypic.refine import (
    MaskOpener, MaskFill, SmallObjectRemover, BorderObjectRemover,
)
[2]:
plate = load_yeast_plate()
plate = GaussianBlur(sigma=2.0).apply(plate)
plate = CLAHE(clip_limit=0.01).apply(plate)
plate = OtsuDetector().apply(plate)
print(f"Before refinement: {plate.num_objects} objects")
plate.dash(overlay=True)
Before refinement: 9 objects

Data type cannot be displayed: application/vnd.plotly.v1+json

Remove Border Objects#

Colonies touching the image edge are usually partial. Remove them.

[3]:
plate = BorderObjectRemover(border_size=1).apply(plate)
print(f"After border removal: {plate.num_objects} objects")
After border removal: 9 objects

Remove Small Objects#

Noise fragments smaller than real colonies. Set min_size to the smallest colony area you expect (in pixels).

[4]:
plate = SmallObjectRemover(min_size=50).apply(plate)
print(f"After small object removal: {plate.num_objects} objects")
After small object removal: 7 objects

Morphological Opening#

Smooths jagged mask edges and breaks thin bridges between touching colonies.

[5]:
plate = MaskOpener(width=5).apply(plate)
print(f"After opening: {plate.num_objects} objects")
After opening: 7 objects

Fill Holes#

Some detectors leave holes inside colony masks. MaskFill fills them.

[6]:
plate = MaskFill().apply(plate)
plate.dash(overlay=True)

Data type cannot be displayed: application/vnd.plotly.v1+json

In a Pipeline#

Chain these refiners after detection in your pipeline:

pipeline = pht.ImagePipeline(ops=[
    GaussianBlur(sigma=2.0),
    CLAHE(clip_limit=0.01),
    OtsuDetector(),
    BorderObjectRemover(),
    SmallObjectRemover(min_size=50),
    MaskOpener(width=5),
    MaskFill(),
])