phenotypic.enhance#
Image enhancers to boost fungal colonies on agar backgrounds.
Preprocessing steps that denoise, normalize, and emphasize colony structure before detection. The module covers local contrast equalization (CLAHE), Gaussian/median/rank denoising, rolling-ball and Gaussian background subtraction, tophat and Laplacian edge accentuation, Sobel gradients, contrast stretching, unsharp masking, bilateral denoising, and BM3D denoising for clean plates. All operate on copies of the grayscale view to keep raw data intact.
- class phenotypic.enhance.BM3DDenoiser(sigma_psd: float = 0.02, *, stage_arg: Literal['all_stages', 'hard_thresholding'] = 'all_stages')[source]#
Bases:
ImageEnhancerBlock-matching and 3D collaborative filtering denoising for plate images.
Applies BM3D, a state-of-the-art denoising algorithm that groups similar image patches and performs collaborative filtering in the transform domain. This is particularly effective for removing structured noise patterns and preserving fine colony details on agar plates (e.g., scanner artifacts, systematic CCD noise, or subtle textures from imaging hardware).
Use cases (agar plates): - Remove structured camera/scanner noise while preserving sharp colony edges
and fine morphological features (e.g., wrinkles, satellite colonies).
Suppress noise from low-light imaging or high ISO settings without the over-smoothing typical of simple Gaussian blur.
Pre-process before edge detection or feature extraction when image quality is poor but colony structures must remain intact.
Tuning and effects: - sigma_psd: Estimated noise standard deviation in [0, 1] scale (matching
normalized image range). Start with automatic estimation (None) or typical values 0.01-0.05 for moderate noise, 0.05-0.15 for very noisy images. For reference: 8-bit noise of σ=10/255 ≈ 0.04; 16-bit noise of σ=300/65535 ≈ 0.005. Too low preserves noise; too high removes real colony texture.
stage_arg: Controls whether to run fast (‘hard_thresholding’) or complete (‘all_stages’) denoising. ‘all_stages’ produces cleaner results but is slower; ‘hard_thresholding’ is faster and often sufficient for plates.
Operates on normalized [0,1] float data directly from enh_gray.
Caveats: - Computationally expensive, especially on high-resolution images. Consider
downsampling or cropping for exploratory analysis.
Requires accurate sigma_psd estimate in [0, 1] scale. If unknown, use None for auto-estimation or test multiple values to avoid under/over- denoising. Noise magnitude differs between 8-bit and 16-bit originals.
Does not correct illumination gradients; combine with background subtraction (e.g., GaussianSubtract, RollingBallRemoveBG) if needed.
May slightly blur very fine colony features if sigma_psd is too high.
- Parameters:
sigma_psd (float)
stage_arg (Literal['all_stages', 'hard_thresholding'])
- sigma_psd#
Noise standard deviation in [0, 1] normalized scale. If None, BM3D auto-estimates from the image. Typical values: 0.01-0.05 for moderate noise (e.g., 8-bit with σ=5-15), 0.05-0.15 for heavy noise. 16-bit images typically have lower relative noise.
- Type:
float | None
- stage_arg#
Processing mode. ‘all_stages’ applies both hard thresholding and Wiener filtering (slower, highest quality); ‘hard_thresholding’ runs only the first stage (faster, good for most plates).
- Type:
Literal[“all_stages”, “hard_thresholding”]
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(sigma_psd: float = 0.02, *, stage_arg: Literal['all_stages', 'hard_thresholding'] = 'all_stages')[source]#
- Parameters:
sigma_psd (float) – Noise level estimate in [0, 1] normalized scale. None for auto-estimation; otherwise specify as standard deviation matching the normalized image range. Start with 0.02-0.05 for typical scanner noise on plates (equivalent to σ=5-12 on 8-bit). Higher value -> more noise.
stage_arg (Literal["all_stages", "hard_thresholding"]) – Denoising stages to run. ‘all_stages’ gives best quality at the cost of speed; ‘hard_thresholding’ is faster and adequate for routine plate analysis.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.BilateralDenoise(sigma_color: float | None = None, sigma_spatial: float = 15, win_size: int | None = None, mode: str = 'constant', cval: float = 0)[source]#
Bases:
ImageEnhancerBilateral filtering for edge-preserving noise reduction on fungal colony plates.
Bilateral filtering is a non-linear denoising technique that averages pixel values based on two criteria: spatial proximity (nearby pixels are weighted higher) and radiometric similarity (pixels with similar intensities are weighted higher). This dual constraint preserves sharp intensity discontinuities (colony edges) while smoothing uniform regions (agar background, colony interiors). On fungal colony plates, bilateral denoising effectively removes scanner noise, agar grain, dust speckles, and condensation artifacts without blurring colony boundaries—ideal preprocessing before segmentation algorithms.
Use cases (agar plates): - Noisy or grainy agar scans (high ISO photography, old scanners) - Uneven agar texture, surface condensation, dust speckles - Background variations that confuse thresholding - Preprocessing before ObjectDetector when colony edges must remain sharp - Handling low-quality captures while preserving colony morphology
Tuning and effects: - sigma_color: Controls how strictly pixel intensities must match to influence
each other. Small values (0.02–0.05) only average pixels with very similar brightness, preserving subtle colony boundaries but leaving more noise. Medium values (0.05–0.15) balance denoising and edge preservation, suitable for most fungal colony plates. Large values (0.2–0.5) aggressively average pixels across a wider brightness range, producing heavy smoothing but risking loss of faint colony features or boundary blurring. If None (default), automatically estimated from image statistics. For float images in [0,1], these are reasonable defaults; for uint8 images, scale values proportionally (e.g., 0.05 float ≈ 13 for uint8).
sigma_spatial: Controls the spatial neighborhood size; larger values smooth over wider areas. Small values (1–5) apply local denoising that preserves fine colony texture but removes only local noise. Medium values (10–20) provide balanced regional smoothing, recommended for general-purpose use. Large values (30–50) smooth over wide regions, helpful for correcting illumination gradients but risky for small colonies or dense plates. Keep below the minimum expected colony diameter to avoid over-smoothing or merging adjacent colonies.
win_size: Window size for filter computations. If None (default), automatically calculated from sigma_spatial; generally safe to leave unset.
mode: Border handling strategy. ‘constant’ (default) pads with cval; ‘reflect’ mirrors edges. ‘constant’ with cval=0 works well for agar plates.
cval: Fill value at image boundaries when mode=’constant’. 0 (black) is typical for agar backgrounds.
Caveats: - Computational cost: Bilateral filtering is slower than simple Gaussian blur,
especially with large sigma_spatial. For large images, keep sigma_spatial ≤ 15 to maintain reasonable speed.
Data type sensitivity: The function internally converts images to float [0,1]. Parameter interpretation (especially sigma_color) assumes this range. Very bright or very dark images may require parameter adjustment.
Over-smoothing: If sigma_color is too high, the filter may blur colony boundaries or merge nearby colonies into connected regions, breaking segmentation.
Not a substitute for proper illumination correction: Bilateral denoising smooths background variations but does not remove large-scale illumination gradients (vignetting, shadows). Use RollingBallRemoveBG or GaussianSubtract for that.
- Parameters:
- sigma_color#
Standard deviation of intensity/color difference for similarity weighting. Controls edge preservation vs smoothing trade-off. None means auto-estimate from image.
- Type:
float | None
- sigma_spatial#
Standard deviation of spatial distance for weighting. Controls neighborhood size.
- Type:
Examples
Denoising a grainy agar plate scan before colony detection
from phenotypic import Image from phenotypic.enhance import BilateralDenoise from phenotypic.detect import OtsuDetector # Load a noisy scan (e.g., high-ISO smartphone image or old scanner) image = Image.from_image_path("noisy_plate.jpg") # Apply bilateral denoising with moderate settings denoiser = BilateralDenoise(sigma_color=0.1, sigma_spatial=15) denoised = denoiser.apply(image) # Detect colonies in cleaned enhanced grayscale detector = OtsuDetector() detected = detector.apply(denoised) colonies = detected.objects print(f"Detected {len(colonies)} colonies in denoised image")
Chaining denoising and sharpening for challenging images
from phenotypic import Image, ImagePipeline from phenotypic.enhance import BilateralDenoise, UnsharpMask from phenotypic.detect import OtsuDetector # Scenario: Noisy image with low-contrast colonies # Solution: Denoise first (remove artifacts), then sharpen (enhance edges) pipeline = ImagePipeline() # Step 1: Remove noise while preserving colony edges # sigma_color=0.08 balances denoising and edge sharpness pipeline.add(BilateralDenoise(sigma_color=0.08, sigma_spatial=15)) # Step 2: Sharpen remaining edges for better segmentation pipeline.add(UnsharpMask(radius=2.0, amount=1.5)) # Step 3: Detect pipeline.add(OtsuDetector()) images = [Image.from_image_path(f) for f in image_paths] results = pipeline.operate(images)
Heavy denoising for very grainy plates with large colonies
from phenotypic import Image from phenotypic.enhance import BilateralDenoise # For large-colony plates (e.g., petri dishes, sparse growth) with heavy # scanner noise or texture, use larger sigma_spatial to smooth broader regions image = Image.from_image_path("sparse_grainy_plate.jpg") # Heavy denoising: large spatial neighborhood, moderate color tolerance heavy_denoiser = BilateralDenoise( sigma_color=0.15, # Blend pixels across wider brightness range sigma_spatial=30, # Smooth over large neighborhoods ) denoised = heavy_denoiser.apply(image) # Result: Agar grain and dust removed, but large colony edges preserved print("Heavy denoising applied.")
Selective denoising for high-resolution dense plates
from phenotypic import Image from phenotypic.enhance import BilateralDenoise # For high-resolution 384-well plates with tiny colonies, small sigma_spatial # preserves fine structure while removing only local speckles image = Image.from_image_path("dense_hires_plate.jpg") # Conservative denoising: small spatial neighborhood, strict color matching conservative_denoiser = BilateralDenoise( sigma_color=0.04, # Only average similar pixels sigma_spatial=8, # Small neighborhood, preserves fine details ) denoised = conservative_denoiser.apply(image) # Result: Local speckles removed, but colony boundaries and microstructure intact print("Light denoising applied; fine morphology preserved.")
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(sigma_color: float | None = None, sigma_spatial: float = 15, win_size: int | None = None, mode: str = 'constant', cval: float = 0)[source]#
- Parameters:
sigma_color (float | None) – Standard deviation for grayvalue/color similarity. Controls how permissive the filter is when averaging nearby pixels. Small values (0.02–0.05 for float images) enforce strict color matching, preserving edges but leaving more noise. Medium values (0.05–0.15) provide balanced denoising and edge preservation—recommended for most fungal colony imaging. Large values (0.2–0.5) aggressively average across brightness ranges, risking boundary blur. If None (default), automatically estimated from the standard deviation of the image. For uint8 images (0–255), scale values proportionally: 0.05 float corresponds roughly to 13 in uint8 scale. Recommended: leave as None for automatic estimation, or set to 0.08–0.12 for typical colony plates.
sigma_spatial (float) – Standard deviation for spatial distance in pixels. Controls the extent of the neighborhood influencing each pixel. Small values (1–5) apply highly local denoising, preserving fine texture. Medium values (10–20) smooth regionally without over-smoothing—suitable for general use. Large values (30–50) smooth broad areas, helpful for correcting illumination variations but risking loss of small colonies or merging of adjacent growth. Recommended: 15 for balanced results; adjust based on colony size (keep smaller than minimum colony diameter).
win_size (int | None) – Window size for bilateral filter computation. If None (default), automatically calculated as max(5, 2 * ceil(3 * sigma_spatial) + 1). Generally safe to leave as None; adjust only if you have specific performance or memory constraints.
mode (str) – How to handle image boundaries. Options: ‘constant’ (default, pad with cval), ‘edge’ (replicate edge), ‘symmetric’, ‘reflect’, ‘wrap’. ‘constant’ with cval=0 works well for agar plate backgrounds (black edges). ‘reflect’ mirrors edges, useful for non-border regions.
cval (float) – Constant fill value for boundaries when mode=’constant’. Default is 0 (black), appropriate for agar backgrounds.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.CLAHE(Contrast Limited Adaptive Histogram Equalization)[source]#
Bases:
ImageEnhancerApplies adaptive histogram equalization while limiting local contrast amplification to control noise. For colony images on solid-media agar plates, this operation is helpful when illumination is uneven (vignetting, shadows from lids) or when colonies are low-contrast/translucent. By boosting local contrast tile-by-tile, faint colonies become easier to separate from agar background in later thresholding or edge-based steps.
Use cases (agar plates): - Improve visibility of small, faint, or translucent colonies that blend
into agar.
Compensate for gradual illumination roll-off across the plate or scanner/lens vignetting.
Preconditioning before global/otsu thresholding to reduce sensitivity to global intensity shifts.
Tuning and effects: - kernel_size (tile size): Smaller tiles emphasize very local contrast and
can reveal tiny colonies, but may also accentuate agar texture and noise. Larger tiles produce smoother results and are safer for noisy images. If left as None, a size proportional to the image dimensions is chosen.
clip_limit: Controls how much local contrast is allowed. Lower values suppress noise amplification and halos but may leave faint colonies under- enhanced. Higher values make colonies pop more strongly but can create ringing around dust, condensation droplets, or plate edges.
Caveats: - Can amplify non-biological artifacts (scratches, dust, glare); consider a
mild blur or artifact suppression before CLAHE if this occurs.
Different tiles adjust differently; ensure consistent parameters across a batch to avoid biasing downstream measurements.
Excessive enhancement may distort intensity-based phenotypes (e.g., pigment quantification). Prefer using it only in the enh_gray pipeline channel.
- kernel_size#
Tile size for local equalization. None selects an automatic size based on image dimensions.
- Type:
int | None
- clip_limit#
Normalized contrast limit per tile; smaller values reduce amplification, larger values increase it. Default 0.01.
- Type:
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(kernel_size: int | None = None, clip_limit: float = 0.01)[source]#
- Parameters:
kernel_size (int | None) – Tile size for adaptive equalization. Smaller tiles enhance very local contrast (revealing tiny colonies) but can amplify agar texture; larger tiles produce smoother, gentler effects. None selects an automatic size based on image dimensions.
clip_limit (float) – Maximum local contrast amplification. Lower values reduce noise/halo amplification; higher values make faint colonies stand out more but can emphasize dust or condensation.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.ContrastStretching(lower_percentile: int = 2, upper_percentile: int = 98)[source]#
Bases:
ImageEnhancerContrast stretching for plate images.
Rescales intensities based on chosen lower/upper percentiles so the bulk of pixel values expands to the full display range. For agar plate colony images, this often improves separability between colonies and agar by compressing extreme outliers (e.g., specular highlights, deep shadows) while expanding the dynamic range where colonies reside.
Use cases (agar plates): - Normalize exposure across scans or camera shots before thresholding. - Recover contrast on low-contrast plates without amplifying noise as much as
aggressive histogram equalization might.
Prepare images for global methods (e.g., Otsu) or for visualization.
Tuning and effects: - lower_percentile: Increasing this value clips more of the darkest pixels
(e.g., shadows/edge artifacts), which brightens the image and can reveal translucent colonies. Too high can erase true dark background structure.
upper_percentile: Decreasing this value clips more highlights (e.g., glare, dust reflections), preventing them from dominating contrast. Too low flattens bright colonies or pigmented regions.
Caveats: - If outliers are biological signals (very bright colonies), heavy clipping can
reduce their apparent intensity and bias measurements.
Contrast stretching is global; it will not fix spatially varying illumination on its own (consider GaussianSubtract or RollingBallRemoveBG).
- Parameters:
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(lower_percentile: int = 2, upper_percentile: int = 98)[source]#
- Parameters:
lower_percentile (int) – Dark clipping point. Increase to suppress deep shadows/edge artifacts; too high may remove meaningful dark background structure. Typical range: 1–5.
upper_percentile (int) – Bright clipping point. Decrease to suppress glare/highlights; too low may flatten bright colonies. Typical range: 95–99.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.GaussianBlur(sigma: int = 2, *, mode: str = 'reflect', cval=0.0, truncate: float = 4.0)[source]#
Bases:
ImageEnhancerGaussian blur smoothing for plate images.
Applies Gaussian smoothing to reduce high-frequency noise and minor texture on agar plates (e.g., scanner noise, agar granularity, condensation speckle). This can make colony boundaries more coherent and reduce false edges before edge detection or thresholding.
Use cases (agar plates): - Suppress “salt-and-pepper” noise and minor agar texture so thresholding is
driven by colony signal rather than noise.
Pre-filter before SobelFilter or Laplacian to avoid amplifying noise.
Slightly smooth within colonies to make segmentation more compact.
Tuning and effects: - sigma: Controls blur strength. Choose below the typical colony radius to
avoid merging close colonies. Too large sigma will wash out small colonies and narrow gaps between neighbors.
mode/cval: Define how edges are handled. For plates, ‘reflect’ usually avoids artificial dark/bright rims. ‘constant’ with a neutral cval may be useful for cropped regions.
truncate: Larger values include more of the Gaussian tail (slightly slower) with subtle effect on smoothness near edges.
Caveats: - Excessive blur merges adjacent colonies and reduces edge sharpness. - Do not rely on blur to fix illumination gradients; prefer background
subtraction (e.g., GaussianSubtract or RollingBallRemoveBG).
- truncate#
Radius of kernel in standard deviations; kernel is truncated beyond this distance.
- Type:
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(sigma: int = 2, *, mode: str = 'reflect', cval=0.0, truncate: float = 4.0)[source]#
- Parameters:
sigma (int) – Blur strength; start near 1–3 for high-resolution scans. Keep below the colony radius to avoid merging colonies.
mode (str) – Boundary handling. ‘reflect’ is a safe default for plates; ‘constant’ may require setting cval close to background.
cval (float) – Constant fill value when mode=’constant’.
truncate (float) – Kernel extent in standard deviations. Rarely needs adjustment; larger values slightly widen the effective kernel.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.GaussianSubtract(sigma: float = 50.0, mode: str = 'reflect', cval: float = 0.0, truncate: float = 4.0, preserve_range: bool = True)[source]#
Bases:
ImageEnhancerBackground correction by Gaussian subtraction.
Estimates a smooth background via Gaussian blur and subtracts it from the image. For agar plate colony analysis, this removes gradual illumination gradients (vignetting, agar thickness, scanner shading) while retaining sharp colony features, improving downstream thresholding and edge detection.
Use cases (agar plates): - Correct uneven lighting across plates or across scan beds. - Enhance visibility of dark colonies on bright agar by flattening the
background.
Normalize batches captured with varying exposure/illumination profiles.
Tuning and effects: - sigma: Sets the spatial scale of the background. Choose a value larger than
the typical colony diameter so colonies are not treated as background. Too small will subtract colony signal and can invert contrast around edges.
mode/cval: Controls border handling; ‘reflect’ often avoids rim artifacts on circular plates. ‘constant’ may require matching cval to background.
truncate: Extent of the Gaussian in standard deviations; rarely needs change.
preserve_range: Keep original intensity range after filtering; useful when subsequent steps assume the same data range/bit depth.
Caveats: - If sigma is too low, colonies can be attenuated or produce halos. - Very large sigma can oversmooth and retain large shadows or plate rim effects. - Background subtraction may re-center intensities around zero; ensure later
steps handle negative values or re-normalize if needed.
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(sigma: float = 50.0, mode: str = 'reflect', cval: float = 0.0, truncate: float = 4.0, preserve_range: bool = True)[source]#
- Parameters:
sigma (float) – Background scale. Set larger than colony diameter so colonies are preserved while slow illumination is removed.
mode (str) – Border handling; ‘reflect’ reduces artificial rims on plates.
cval (float) – Fill value when mode=’constant’.
truncate (float) – Gaussian support in standard deviations (advanced).
preserve_range (bool) – Keep the original intensity range; useful if subsequent steps or measurements assume a specific scaling.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.LaplaceEnhancer(kernel_size: int | None = 3, mask: numpy.ndarray | None = None)[source]#
Bases:
ImageEnhancerLaplacian edge enhancement for colony boundaries.
Applies a Laplacian operator that responds to rapid intensity changes and highlights edges. In agar plate images, this can delineate colony margins and ring-like features, improving contour detection or watershed seeds.
Use cases (agar plates): - Emphasize colony edges prior to edge-based segmentation or as a cue for
separating touching colonies.
Detect ring patterns around colonies (e.g., swarming fronts) for phenotyping.
Tuning and effects: - kernel_size: Larger kernels produce a smoother, more global edge response
and can suppress small noise; smaller kernels capture fine edges but may amplify noise and agar texture.
mask: Restrict processing to the plate region to avoid dish edge glare or labels. A binary mask focusing on the circular plate is often useful.
Caveats: - Laplacian is sensitive to noise; consider a light GaussianBlur first. - May enhance non-biological artifacts (scratches, dust). Combine with masking
or artifact removal if necessary.
- Parameters:
kernel_size (Optional[int]) – Size of the Laplacian kernel controlling edge scale; smaller captures fine edges, larger smooths noise.
mask (Optional[numpy.ndarray]) – Optional boolean/0-1 mask to limit the operation to specific regions (e.g., the plate area).
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(kernel_size: int | None = 3, mask: numpy.ndarray | None = None)[source]#
- Parameters:
kernel_size (Optional[int]) – Controls the edge scale. Smaller values pick up fine edges but increase noise sensitivity; larger values smooth noise and emphasize broader boundaries.
mask (Optional[np.ndarray]) – Boolean/0-1 mask to limit processing to regions of interest (e.g., the circular plate), reducing artifacts from dish rims or labels.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.MedianFilter(mode: Literal['nearest', 'reflect', 'constant', 'mirror', 'wrap'] = 'nearest', shape: Literal['disk', 'square', 'diamond'] | None = None, radius: int = 5, cval: float = 0.0)[source]#
Bases:
ImageEnhancerMedian filtering to reduce impulsive noise while preserving edges.
The median filter replaces each pixel with the median of its local neighborhood and is robust to outliers. For agar plate colony images, this is effective at removing speckle from condensation droplets, dust, or sensor noise without blurring colony edges as much as Gaussian smoothing would.
Use cases (agar plates): - Reduce “salt-and-pepper” artifacts and tiny bright/dark specks prior to
thresholding or edge detection.
Preserve colony boundaries better than linear blur when colonies are small or closely packed.
Tuning and effects: - Footprint: This implementation uses the library default footprint when none
is provided (a small neighborhood). For stronger denoising, prefer RankMedianEnhancer where you can set shape and radius explicitly.
mode/cval: Control how borders are handled. ‘reflect’ or ‘nearest’ avoids artificial artifacts at the plate boundary; ‘constant’ uses cval as fill.
Caveats: - Using a very large neighborhood (when configured via alternative median
functions) can remove small colonies or close thin gaps.
Median filtering can flatten fine texture within pigmented colonies; use a light application or a rank filter with an appropriate footprint.
- Parameters:
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(mode: Literal['nearest', 'reflect', 'constant', 'mirror', 'wrap'] = 'nearest', shape: Literal['disk', 'square', 'diamond'] | None = None, radius: int = 5, cval: float = 0.0)[source]#
This class is designed to facilitate image processing tasks, particularly for analyzing microbe colonies on solid media agar. By adjusting the mode, footprint, radius, and cval attributes, users can modify the processing behavior and results to suit their specific requirements for studying spatial arrangements, colony boundaries, and other morphological features.
- Parameters:
- mode#
Determines how boundaries of the image are handled during processing. For instance, “reflect” can help minimize edge artifacts when analyzing colonies near the edge of the image by mirroring boundary pixels, while “constant” fills with a value (cval), which might highlight isolated colonies. Adjusting this can significantly affect how edge regions are interpreted.
- Type:
Literal[“nearest”, “reflect”, “constant”, “mirror”, “wrap”]
- shape#
Specifies the shape of the structuring element used in morphological operations. For instance, “disk” simulates circular neighborhood which works well for circular colonies, whereas “square” gives a grid-like neighborhood. This can directly impact how structures are identified or segmented.
- Type:
Literal[“disk”, “square”, “diamond”] | None
- radius#
Size of the structuring element. Larger radii result in broader neighborhoods being considered, which may smooth or connect distant colonies, while smaller radii preserve finer details but may miss larger structural relationships. Only if shape is not None.
- Type:
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.RankMedianEnhancer(shape: str = 'square', radius: int | None = None, shift_x=0, shift_y=0)[source]#
Bases:
ImageEnhancerRank-based median filtering with configurable footprint.
Applies a local median using rank filters with a user-defined footprint shape and radius. For agar plate colony images, this enables targeted suppression of impulsive noise while tailoring the spatial scale to colony size and shape, offering more control than a default median.
Use cases (agar plates): - Denoise while preserving colony boundaries by matching the footprint radius
to be smaller than colony diameters.
Use anisotropic or non-circular footprints (e.g., squares) for grid-like artifacts from imaging hardware.
Tuning and effects: - shape: Choose ‘disk’ for circular isotropic smoothing on plates;
‘square’ or ‘cube’ can align with grid artifacts; ‘ball’ for 3D stacks.
radius: Controls neighborhood size. Larger radii remove more noise but can erode small colonies and close tight gaps.
shift_x/shift_y: Offset the footprint center to bias the neighborhood if imaging introduces directional streaks; typically left at 0.
Caveats: - Very large footprints may over-smooth and merge nearby colonies. - Rank filters operate on uint8 here; intensity scaling occurs internally.
Ensure consistency if comparing raw intensities elsewhere.
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(shape: str = 'square', radius: int | None = None, shift_x=0, shift_y=0)[source]#
- Parameters:
shape (str) – Geometry of the neighborhood. Use ‘disk’ for isotropic smoothing on plates; ‘square’ to align with grid noise; ‘sphere’/’cube’ for 3D contexts. Default ‘square’.
radius (int | None) – Neighborhood radius in pixels. Set smaller than the minimum colony radius to preserve colony edges; None chooses a small default based on image size.
shift_x (int) – Horizontal offset of the footprint center to bias the neighborhood if artifacts are directional. Typically 0.
shift_y (int) – Vertical offset of the footprint center. Typically 0.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.RollingBallRemoveBG(radius: int = 100, kernel: numpy.ndarray | None = None, nansafe: bool = False)[source]#
Bases:
ImageEnhancerRolling-ball background removal (ImageJ-style) for agar plates.
Models the background as the surface traced by rolling a ball under the image intensity landscape, then subtracts it. For colony images, this effectively removes slow illumination gradients and agar shading while preserving colony structures.
Use cases (agar plates): - Correct uneven backgrounds from scanner vignetting, lid glare, or agar
thickness variations.
Improve segmentation of dark colonies on bright agar by flattening the background.
Tuning and effects: - radius: Core scale of the rolling ball. Set larger than typical colony
diameter so colonies are not smoothed into the background. Too small a radius will erode colonies and create halos.
kernel: Custom structuring element defining the ball shape. Providing a kernel overrides radius and allows non-spherical shapes if needed.
nansafe: Enable if your images contain masked/NaN regions (e.g., plate outside masked to NaN). When False, NaNs may propagate or cause artifacts.
Caveats: - Overly small radius removes real features and can bias size/area metrics. - May introduce edge effects near the plate boundary; consider masking the
plate region or using nansafe with an appropriate mask.
- radius#
Ball radius (in pixels) controlling the background scale; choose > colony diameter.
- Type:
- kernel#
Optional custom kernel; overrides radius when set.
- Type:
np.ndarray
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(radius: int = 100, kernel: numpy.ndarray | None = None, nansafe: bool = False)[source]#
- Parameters:
radius (int) – Rolling-ball radius (pixels). Use a value larger than colony diameter to avoid removing colony signal. Default 100.
kernel (np.ndarray) – Optional custom ball/footprint; when provided it overrides radius.
nansafe (bool) – If True, treat NaNs as missing data to avoid artifacts when using masked images (e.g., outside the plate).
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.SobelFilter[source]#
Bases:
ImageEnhancerSobel edge filter to highlight colony boundaries.
Computes the gradient magnitude using the Sobel operator to emphasize edges (rapid intensity changes). On agar plate images, this highlights colony perimeters and helps downstream steps that rely on edge strength (e.g., contour finding, watershed seeds, or boundary-based scoring).
Use cases (agar plates): - Emphasize colony outlines before contour detection or watershed. - Separate touching colonies when combined with a distance or marker-based
segmentation strategy.
Guidance: - Consider light smoothing with GaussianBlur beforehand to suppress noise;
Sobel is sensitive to high-frequency artifacts (dust, texture).
Caveats: - Output is an edge map, not a background-corrected image. Use in tandem
with background removal or thresholding for full segmentation.
Strong illumination gradients can still produce spurious edges; correct background first if needed.
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.UnsharpMask(radius: float = 2.0, amount: float = 1.0, preserve_range: bool = False)[source]#
Bases:
ImageEnhancerUnsharp masking for enhanced colony edge definition on agar plates.
Unsharp masking is a classical sharpening technique that enhances edges by subtracting a blurred copy of the image from the original, then scaling the difference to emphasize high-contrast boundaries. On fungal colony plates, this makes soft or indistinct colony edges more pronounced, improving the ability of thresholding and edge-detection algorithms to identify colony boundaries precisely.
Use cases (agar plates): - Low-contrast colonies with soft, gradual edges (translucent growth) - Dense plates where colonies blend into background - Pre-threshold sharpening to improve segmentation accuracy - Enhancing subtle colony morphologies before downstream measurement - Improving edge definition when scanner or lens causes slight blurring
Tuning and effects: - radius: Controls the scale of features enhanced. Small values (0.5–2) sharpen
fine details like small colony boundaries and surface texture; larger values (5–15+) enhance broader features and colony-background contrast. For fungal colonies, keep radius smaller than the minimum colony radius to avoid creating visible halos or merging adjacent colonies. Start at 2.0 for general-purpose enhancement.
amount: Determines the magnitude of edge enhancement (how much darker/brighter the edges become). Low values (0.3–0.7) produce subtle improvements safe for noisy images; standard values (1.0–1.5) give moderate sharpening suitable for most colony plates; high values (2.0+) create aggressive enhancement but risk amplifying noise and creating visible bright/dark halos around colonies. Negative amounts produce blur (opposite effect).
preserve_range: Leave as False for consistency with other enhancers in the framework.
Caveats: - Amplifies noise: In noisy images, unsharp masking sharpens both signal
(colony edges) and noise artifacts. Consider denoising first (e.g., with GaussianBlur, BilateralDenoise, or MedianFilter) on very grainy agar scans.
Halo artifacts: Excessive radius or amount creates bright/dark rims around colonies, which can be mistaken for separate objects or cause thresholding to fail.
Already-sharp images: Applying unsharp mask to crisp, high-contrast colonies may be redundant and introduce artifacts. Reserve for low-contrast scenarios.
- radius#
Standard deviation of Gaussian blur used to compute edges, in pixels. Controls the scale of features enhanced.
- Type:
Examples
Sharpening low-contrast fungal colonies before detection
from phenotypic import Image from phenotypic.enhance import UnsharpMask from phenotypic.detect import OtsuDetector # Load image of low-contrast plate (e.g., translucent yeasts) image = Image.from_image_path("yeast_plate.jpg") # Apply unsharp masking with moderate settings sharpener = UnsharpMask(radius=2.0, amount=1.2) sharpened = sharpener.apply(image) # Detect colonies in sharpened enhanced grayscale detector = OtsuDetector() detected = detector.apply(sharpened) # Original image untouched, detection on enhanced data colonies = detected.objects print(f"Detected {len(colonies)} colonies")
Tuning radius and amount for dense high-throughput plates
from phenotypic import Image, ImagePipeline from phenotypic.enhance import UnsharpMask, GaussianBlur from phenotypic.detect import OtsuDetector # For high-resolution 384-well plate scans with tiny colonies, # use small radius to avoid merging adjacent growth pipeline = ImagePipeline() # Step 1: Light blur to reduce scanner noise pipeline.add(GaussianBlur(sigma=1)) # Step 2: Enhance edges with small radius for dense plates # radius=1.0 emphasizes only fine features (individual colonies) pipeline.add(UnsharpMask(radius=1.0, amount=1.5)) # Step 3: Detect in enhanced grayscale pipeline.add(OtsuDetector()) # Process a batch of images images = [Image.from_image_path(f) for f in image_paths] results = pipeline.operate(images) for i, result in enumerate(results): print(f"Plate {i}: {len(result.objects)} colonies")
Aggressive sharpening for very translucent colonies
from phenotypic import Image from phenotypic.enhance import UnsharpMask # For extremely low-contrast colonies (e.g., slow-growing mutants, # low-turbidity liquid culture plates), use higher amount image = Image.from_image_path("faint_colonies.jpg") # Aggressive parameters: larger radius for broader features, # higher amount for stronger enhancement aggressive_sharpener = UnsharpMask(radius=5.0, amount=2.5) enhanced = aggressive_sharpener.apply(image) # Inspect result for artifacts (halos); adjust if needed # If halos appear, reduce amount to 1.5–2.0 print("Sharpening applied. Check for halo artifacts around large colonies.")
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(radius: float = 2.0, amount: float = 1.0, preserve_range: bool = False)[source]#
- Parameters:
radius (float) – Standard deviation (sigma) of the Gaussian blur in pixels. Defines the scale of features to enhance. Small values (0.5–2) sharpen fine details (thin colony edges, small morphologies); larger values (5–15) enhance broad features (large colonies, colony-background separation). Must be > 0. For fungal colonies, keep below the typical colony radius to avoid merging adjacent colonies. Recommended: 2.0–3.0 for general-purpose use, 1.0 for high-density plates, 5.0+ for emphasizing large-scale features on low-resolution images.
amount (float) – Amplification factor for the sharpening effect. Controls how much the edge enhancement contributes to the output. Typical range: 0.3–2.5. Low values (0.3–0.7) produce subtle enhancement suitable for noisy images; standard values (1.0–1.5) give balanced sharpening; high values (2.0+) create aggressive enhancement for very low-contrast colonies. Can be negative to produce blurring instead. Excessive amounts risk visible artifacts and noise amplification.
preserve_range (bool) – If False (default), output may be rescaled if necessary. If True, the original range of input values is preserved. Keep as False for consistency with other enhancers.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.
- class phenotypic.enhance.WhiteTophatEnhancer(shape: str = 'diamond', radius: int | None = None)[source]#
Bases:
ImageEnhancerWhite top-hat transform to suppress small bright structures.
Computes the white top-hat (original minus opening) using a structuring element, then subtracts it from the image here (i.e., remove small bright blobs). In agar plate colony images, this helps reduce bright specks from dust, glare, or condensation, making colonies stand out against a smoother background.
Use cases (agar plates): - Remove small bright artifacts that can be mistaken for tiny colonies. - Reduce glare highlights on shiny plates before thresholding.
Tuning and effects: - shape: The morphology footprint geometry. ‘diamond’ or ‘disk’ are good
isotropic choices on plates; ‘square’ can align with pixel grids.
radius: Sets the maximum size of bright features to remove. Choose slightly smaller than the minimum colony radius so real colonies are preserved.
Caveats: - If radius is too large, real small colonies will be attenuated. - Operates on bright features; for dark colonies on bright agar, it primarily
removes bright noise rather than enhancing the colonies themselves.
- radius#
Footprint radius in pixels; if None, a small default is derived from the image size.
- Type:
int | None
- __del__()#
Automatically stop tracemalloc when the object is deleted.
- __getstate__()#
Prepare the object for pickling by disposing of any widgets.
This ensures that UI components (which may contain unpickleable objects like input functions or thread locks) are cleaned up before serialization.
Note
This method modifies the object state by calling dispose_widgets(). Any active widgets will be detached from the object.
- __init__(shape: str = 'diamond', radius: int | None = None)[source]#
- Parameters:
shape (str) – Footprint geometry controlling which bright features are removed. ‘diamond’ or ‘disk’ provide isotropic behavior on plates; ‘square’ can align with sensor grid artifacts. Advanced: ‘sphere’ or ‘cube’ for volumetric data.
radius (int | None) – Maximum bright-object size (in pixels) targeted for removal. Set slightly smaller than the smallest colonies to avoid suppressing real colonies. None picks a small default based on image dimensions.
- apply(image, inplace=False)#
Applies the operation to an image, either in-place or on a copy.
- widget(image: Image | None = None, show: bool = False) Widget#
Return (and optionally display) the root widget.
- Parameters:
- Returns:
The root widget.
- Return type:
ipywidgets.Widget
- Raises:
ImportError – If ipywidgets or IPython are not installed.