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, EnhanceLocalContrast
from phenotypic.detect import OtsuDetector
from phenotypic.refine import (
    MaskOpening, MaskFill, SmallObjectRemover, RemoveBorderObjects,
)
[2]:
plate = load_yeast_plate()
plate = GaussianBlur(sigma=2.0).apply(plate)
plate = EnhanceLocalContrast(clip_limit=0.01).apply(plate)
plate = OtsuDetector().apply(plate)
print(f"Before refinement: {plate.num_objects} objects")
plate.dash(overlay=True)
Before refinement: 7 objects

Remove Border Objects#

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

[3]:
plate = RemoveBorderObjects(border_size=1).apply(plate)
print(f"After border removal: {plate.num_objects} objects")
After border removal: 7 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 = MaskOpening(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)

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(),
])