Hi OpenCV Community,
I am developing an industrial desktop application (.NET 8 C# with OpenCvSharp4) for analyzing cross-sectional microscope images of multi-filament synthetic fibers (e.g., Spandex/Elastane).
The goal of the project is twofold:
-
Filament Counting & Segmentation: Detect, count, and mark each filament centroid in a fiber pack.
-
Quality & Distortion Metrics (Y-BOT / Laboratory Standard Alignment): Measure individual filament geometry and cross-sectional error across multiple filaments.
I would like to share my current approach, mathematical model, and ask for advice on improving the segmentation accuracy when filaments are tightly packed or partially touching.
1. Mathematical Model & Geometry Pipeline
For each detected filament contour in a cross-section image, we extract two core quality metrics:
A. Distorted ROI (Circularity / Deformation)
Instead of relying solely on standard circularity (4\pi \cdot \text{Area} / \text{Perimeter}^2), we measure width chords along the filament’s principal axis:
-
Long Axis (C): The length of the bounding rotated rectangle (
Cv2.MinAreaRect). -
Short Axis Chords:
-
Short Axis 2 (w\_{50}): Width perpendicular to the Long Axis at the 50\% center point.
-
Short Axis 1 (w\_{25}, w\_{75}): Widths perpendicular to the Long Axis at the 25\% and 75\% length positions.
-
-
Average Diameter: D\_{\text{avg}} = \frac{\frac{w\_{25} + w\_{75}}{2} + w\_{50}}{2}
-
Distortion Ratio Formula:
\text{Distorted ROI (\%)} = \left\vert{} 1 - \frac{D\_{\text{avg}}}{C} \right\vert{} \times 100
B. C-Section ROI (Cross-Section Area Ratio / Multi-Filament Error)
For a group of N filaments in a cross-section:
-
Calculate the pixel area A_i for each filament contour (i = 1 \dots N).
-
Compute the ratio between the smallest and largest filament area:
\text{C-Section ROI (\%)} = \frac{\min(A_1, A_2, \dots, A_n)}{\max(A_1, A_2, \dots, A_n)} \times 100(Higher percentage indicates better size uniformity among filaments, mapped to quality classes like AA, AB, B based on fiber linear density in Denier/dtex).
2. Current OpenCV Pipeline
Our current image processing workflow (OpenCvSharp4) consists of:
-
Preprocessing: Downscale to max 1600px \rightarrow Grayscale \rightarrow CLAHE \rightarrow Small Gaussian Blur.
-
Binarization: Pack-region restricted Adaptive Thresholding (Mean/Gaussian) combined with an Otsu intensity gate.
-
Morphology: Small 3\times 3 opening followed by max 5\times 5 closing to fill internal voids without merging adjacent filaments.
-
Distance Transform & Watershed Segmentation:
-
Calculate Distance Transform (
Cv2.DistanceTransform). -
Extract local maxima/peaks to place initial seeds.
-
Apply Watershed segmentation (
Cv2.Watershed) to separate touching filaments.
-
-
Contour Analysis: Extract contours, fit
MinAreaRect, compute axis chords (25\%, 50\%, 75\%), and validate candidates using aspect ratio, circularity, and solidity thresholds.
3. Challenges & Questions for the Community
-
Over-segmentation / Double-Seed Issue in Watershed:
In dense areas where filaments have non-uniform internal brightness or irregular shapes (peanut-shaped or flat cross-sections),
DistanceTransformoften generates multiple peaks inside a single filament, causing Watershed to over-segment (splitting one filament into two markers).- What are the best practices or alternative peak-clustering strategies in OpenCV to prevent multiple seeds within peanut-shaped/elongated contours?
-
Accurate Axis Chord Measurement (%25, %50, %75):
Currently, we use
MinAreaRectto find the principal angle, rotate the contour points, and sweep vertical lines across 25\%, 50\%, and 75\% of the bounding box width to find intersection points with the contour.- Is there a more robust/native OpenCV approach (e.g., using
cv2.fitEllipseor distance transform ridges) to reliably sample cross-sectional thickness along irregular/non-elliptical contours?
- Is there a more robust/native OpenCV approach (e.g., using
-
Handling Touching Filament Boundaries:
When two filaments are physically fused/coalesced, edge gradients become weak. Has anyone achieved stable boundary recovery using pure OpenCV methods before resorting to deep-learning approaches like Cellpose/UNet?
Any insights, code snippets, or suggested OpenCV functions would be greatly appreciated!
Thanks in advance,
Hasan Baş