P2DingoCV.PanelSegmentation.PanelSegmentor

Classes

PanelSegmentor(height, width, outputPath[, ...])

class P2DingoCV.PanelSegmentation.PanelSegmentor.PanelSegmentor(height, width, outputPath, config=None)[source]

Bases: object

Parameters:
  • height (int)

  • width (int)

  • outputPath (str)

  • config (str | None)

KmeansCluster(angles, k=2, maxIter=300, randomState=None)[source]

Cluster line orientations (in degrees) using circular k-means on the unit circle.

This function takes angles in degrees in the range [0, 180], maps them onto the unit circle to handle circularity (so 0° and 180° are close), performs k-means clustering, and converts the resulting cluster centers back to angles.

Parameters

anglesnp.ndarray

Array of angles in degrees, expected in the range [0, 180].

kint, optional

Number of clusters. Default is 2.

maxIterint, optional

Maximum number of k-means iterations. Default is 300.

randomStateOptional[int], optional

Random seed for reproducibility. Default is None.

Returns

ptsNDArray[np.float64]

Points on the unit circle corresponding to the input angles, shape (N, 2).

labelsNDArray[np.integer]

Cluster labels for each input angle, shape (N,).

centersXYNDArray[np.float64]

Cluster centers in unit-circle (x, y) coordinates, shape (k, 2).

centersDegNDArray[np.float64]

Cluster centers converted back to angles in degrees in the range [0, 180).

Raises

ValueError

If any input angle is outside the range [0, 180].

Parameters:
  • angles (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.float64]])

  • k (int)

Return type:

Tuple[numpy.ndarray[tuple[int, …], numpy.dtype[numpy.float64]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.float64]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.float64]]]

__init__(height, width, outputPath, config=None)[source]

PanelSegmentor class for detecting and segmenting panel-like regions in an image.

This segmentor uses a combination of denoising, edge detection, and Hough line transform techniques to identify candidate panels based on expected line counts, aspect ratios, and image characteristics.

Parameters

lineCountint

Expected number of lines in the image for line detection. This is an approximate value and does not need to be precise.

lineBufferint

Pixel buffer added around detected lines to extend candidate regions.

denoiseLambdaWeightfloat

Weight factor for the denoising algorithm. Higher values prioritize smoothness over detail preservation.

denoiseMeanKernelSizeint

Kernel size for the mean/average filter applied during denoising.

denoiseGaussianSigmafloat

Standard deviation for Gaussian smoothing during denoising.

denoiseDownsampleFactorfloat

Factor to downsample input frames before applying denoising, reducing computation.

edgeSlideFactorfloat

Initial sliding window size for edge detection. The algorithm adjusts this dynamically.

clipLimitfloat

Clip limit for CLAHE (Contrast Limited Adaptive Histogram Equalization) to enhance local contrast.

rhofloat

Distance resolution in pixels for the Hough line transform.

thetafloat

Angle resolution in radians for the Hough line transform.

aspectRatiofloat

Expected width-to-height ratio for candidate panel regions.

sigmaMultiplerfloat

Multiplier for Gaussian sigma used in edge detection or smoothing, relative to image diagonal.

edgeThresholdMultiplierfloat

Multiplier applied to edge detection thresholds, scaled by image diagonal.

minLineLengthMultiplerfloat

Multiplier to determine the minimum line length for line detection, relative to image diagonal.

maxLineGapMultiplerfloat

Multiplier to determine the maximum allowed gap between line segments, relative to image diagonal.

Notes

The parameters involving “multipliers” (sigmaMultipler, edgeThresholdMultiplier, minLineLengthMultipler, maxLineGapMultipler) are scaled relative to the image diagonal to make the algorithm more robust across different image resolutions.

Example

segmentor = PanelSegmentor(

lineCount=5, lineBuffer=10, denoiseLambdaWeight=0.8, denoiseMeanKernelSize=5, denoiseGaussianSigma=1.5, denoiseDownsampleFactor=2.0, edgeSlideFactor=5.0, clipLimit=2.0, rho=1, theta=0.0174533, aspectRatio=1.5, sigmaMultipler=0.02, edgeThresholdMultiplier=0.05, minLineLengthMultipler=0.1, maxLineGapMultipler=0.02

)

Parameters:
  • height (int)

  • width (int)

  • outputPath (str)

  • config (str | None)

Return type:

None

angleClusters(lines, k=2)[source]

Cluster line segments by orientation using circular k-means.

This function takes 2D line segments, computes their orientation angles (in degrees), maps them into a circular-safe representation, and clusters them into k groups using k-means. It is robust to wrap-around effects (e.g., near 0°/180°) by using absolute deltas and modulo arithmetic.

Parameters

linesNDArray[np.integer] | None

Array of line segments with shape (N, 4), where each row is [x1, y1, x2, y2]. Typically from HoughLinesP. If None or empty, the function returns None.

kint, optional

Number of orientation clusters to form. Default is 2.

Returns

Tuple[NDArray[np.float64], NDArray[np.integer], NDArray[np.float64], NDArray[np.float64]] | None

If input is valid, returns a 4-tuple: - pts : (N, 2) array of unit-circle coordinates used for clustering - labels : (N,) array of cluster indices for each line - centersXY : (k, 2) array of cluster centers in unit-circle space - centersDeg : (k,) array of cluster center angles in degrees [0, 180)

Returns None if lines is None or empty.

Notes

  • Line angles are computed using atan2() and wrapped to [0, 180)

    to treat lines as undirected.

  • Clustering is performed by self.KmeansCluster, which handles the

    circular nature of angular data.

Parameters:
  • lines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]] | None)

  • k (int)

Return type:

Tuple[numpy.ndarray[tuple[int, …], numpy.dtype[numpy.float64]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.float64]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.float64]]] | None

calculateCornerPoints(horizontalLines, verticalLines, topline, bottomline, leftline, rightline)[source]

Calculate the four corner intersection points of a grid or rectangle.

Parameters:
  • horizontalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]]) – List or array of horizontal lines, each as (x1, y1, x2, y2) integers.

  • verticalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]]) – List or array of vertical lines, each as (x1, y1, x2, y2) integers.

  • topline (int) – Index of the top horizontal line.

  • bottomline (int) – Index of the bottom horizontal line.

  • leftline (int) – Index of the left vertical line.

  • rightline (int) – Index of the right vertical line.

Returns:

A dictionary with keys ‘top_left’, ‘top_right’, ‘bottom_left’, ‘bottom_right’. Each value is an np.ndarray of shape (2,) with [x, y] as floats, or None if lines are parallel.

Return type:

Dict[str, numpy.ndarray[tuple[int, …], numpy.dtype[numpy.float64]] | None]

calculateGridSpacings(horizontalLines, verticalLines, isHorizontal, tolerancePercent=5.0)[source]

Estimate the spacing between grid lines in an image based on detected intersections.

This method analyzes intersections between horizontal and vertical lines to determine the most likely number of evenly spaced columns or rows along a specified axis (horizontal or vertical). It iteratively adjusts a guess for the spacing, considering a tolerance, and returns whether a regular spacing pattern was detected along with the estimated count.

Parameters

horizontalLinesNDArray[np.integer]

Array of horizontal lines in the format (x1, y1, x2, y2).

verticalLinesNDArray[np.integer]

Array of vertical lines in the format (x1, y1, x2, y2).

isHorizontalbool

If True, compute spacings along the horizontal axis (columns), otherwise along the vertical axis (rows).

tolerancePercentfloat, optional

Percentage of the axis length allowed as deviation from the expected spacing to still be considered a valid interval. Default is 5.0.

Returns

np.ndarray | None

An array of shape (N, 2), where N is the number of grid lines analyzed. Each row contains: [spacingDetected: bool, estimatedCount: int] - spacingDetected indicates whether a regular spacing pattern was found. - estimatedCount is the estimated number of evenly spaced segments along the axis. Returns None if no intersections are found.

Raises

ValueError

If no intersections between horizontal and vertical lines are found.

Notes

  • The method sorts intersections along the axis to ensure proper spacing calculation.

  • It iteratively guesses the number of columns/rows (colsGeuss) and checks distances between intersections against the guessed spacing with a specified tolerance.

  • The detection algorithm attempts to handle multiple panels by doubling and halving the guessed count when necessary.

Parameters:
  • horizontalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]])

  • verticalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]])

  • isHorizontal (bool)

  • tolerancePercent (float)

Return type:

numpy.ndarray[tuple[int, …], numpy.dtype[numpy._typing._array_like._ScalarType_co]] | None

calculateIntersections(horizontalLines, verticalLines)[source]

Compute all intersection points between sets of horizontal and vertical lines.

Each horizontal line is intersected with each vertical line using the standard line–line intersection formula. The result is grouped by horizontal line: each row in the output corresponds to one horizontal input line and contains the (x, y) intersection points with all vertical lines.

Parameters:
  • horizontalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]]) – Array of shape (H, 4) containing horizontal line segments as (x1, y1, x2, y2).

  • verticalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]]) – Array of shape (V, 4) containing vertical line segments as (x1, y1, x2, y2).

Returns:

An array of shape (H, V, 2) with integer (x, y) intersection points, grouped per horizontal line, or None if no valid intersections are found or if either input is None.

Return type:

numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]] | None

Notes

  • Parallel line pairs are skipped.

  • The output is structured so each sub-array corresponds to one

    horizontal line’s intersections.

  • Coordinates are cast to int before returning.

determineGridLines(horizontalLines, verticalLines)[source]

Determine the most likely regular grid spacings for horizontal and vertical lines.

This method analyzes detected horizontal and vertical lines to estimate the number of evenly spaced rows and columns in a grid. It uses calculateGridSpacings to detect candidate spacings along each axis, filters out invalid detections, and returns the median spacing for each axis, ensuring consistency with the mode.

Parameters

horizontalLinesNDArray[np.integer]

Array of detected horizontal lines, shape (N, 4), where each row is (x1, y1, x2, y2).

verticalLinesNDArray[np.integer]

Array of detected vertical lines, shape (M, 4), where each row is (x1, y1, x2, y2).

Returns

tuple[int, int]

A tuple (horizontalSpacing, verticalSpacing) representing the estimated number of evenly spaced segments along the horizontal and vertical axes.

Raises

ValueError
  • If no grid spacings are detected on either axis.

  • If no valid spacings remain after filtering.

  • If the median and mode of the detected spacings do not match, indicating inconsistent or unreliable detections.

Notes

  • Filtering ensures only grid lines with a detected regular spacing pattern are considered.

  • The median of the filtered spacings is used as the primary estimate, with the mode used as a consistency check.

  • This method assumes that calculateGridSpacings returns an array where each row contains [spacingDetected: bool, estimatedCount: int].

Parameters:
  • horizontalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]])

  • verticalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]])

Return type:

tuple[int, int]

discardShortLines(lines, lengthThreshold)[source]
Parameters:
  • lines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]] | None)

  • lengthThreshold (int)

Return type:

numpy.ndarray | None

edgeDetection(frame)[source]

Perform adaptive Canny edge detection based on the median intensity of the input frame.

The lower and upper Canny thresholds are computed through a loop that converges on a number of detected lines close to the expected line count.

Thresholds are computed as:

v = edgeSlideFactor * median(frame) lower = max(0, (1 - σ) * v) upper = min(255, (1 + σ) * v)

Parameters:

frame (Frame) – Input image frame, expected to be a single-channel (grayscale) or 3-channel image in uint8 format.

Returns:

A single-channel binary edge map produced by the Canny detector.

Return type:

Frame

Notes

  • Uses OpenCV’s Canny edge detector.

endLines(lines)[source]

Determine the first and last non-outlier line indices based on line angles.

This method computes the orientation angle of each line segment using atan2(dy, dx), normalizes angles to the range [0, 180), and identifies angular outliers via the interquartile range (IQR) method using self.iqrOutliers. The earliest and latest indices whose angles are not classified as outliers are returned.

Parameters:

lines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]]) – Array of line segments with shape (N, 4), where each row is (x1, y1, x2, y2).

Returns:

  • startline is the index of the first non-outlier line.

  • endline is the index of the last non-outlier line.

Return type:

A tuple (startline, endline) where

Notes

  • Angles are computed in degrees and wrapped into [0, 180).

  • If all angles are considered outliers, the defaults are:

    startline = 0 and endline = len(lines) - 1.

  • Relies on self.iqrOutliers to return indices of outliers.

execute(image, frameCount, logPath='', visuals=True, visualPath='', diagonstics=True)[source]

Execute the full visual segmentation and rectification pipeline on a frame.

This method performs grid line detection, homography rectification, spacing estimation, and cell extraction on the input image. Each detected cell is then resized to a target aspect ratio and optionally saved along with diagnostic and visualization outputs.

Parameters

imageFrame

Input image/frame to process.

frameCountint

Index of the frame being processed (used for logging and output naming).

logPathstr, optional

Directory where log files should be written.

visualsbool, optional

If True, saves intermediate and final visualization images to disk.

visualPathstr, optional

Base directory for saving visualization outputs.

diagonsticsbool, optional

If True, enables per-frame diagnostic logging.

Returns

List[Frame]

List of rectified and aspect-ratio-adjusted cell images extracted from the input frame.

Raises

ValueError

If no cells are extracted from the image.

Notes

Pipeline steps:
  1. Detect grid lines in the original image.

  2. Apply homography to rectify the grid.

  3. Re-run line detection on the rectified image.

  4. Estimate horizontal and vertical spacing.

  5. Split the rectified image into grid cells.

  6. Stretch each cell to the target aspect ratio.

  7. Optionally save visualizations and diagnostics.

Parameters:
  • frameCount (int)

  • logPath (str)

  • visuals (bool)

  • visualPath (str)

  • diagonstics (bool)

Return type:

List[numpy.ndarray]

gridPipeline(image, expectedLines, logPath='')[source]

Run the full grid line detection pipeline on an image.

This method preprocesses the input image, detects line segments, and groups and filters them into horizontal and vertical line sets suitable for grid estimation and rectification.

Parameters

imageFrame

Input image/frame to process.

expectedLinesint

Approximate number of line segments expected in the image, used to tune the line detection stage.

logPathstr, optional

Directory path used for resetting parameters and logging context.

Returns

linesNDArray[np.integer]

Array of all detected line segments in (x1, y1, x2, y2) format.

horizontalLinesNDArray[np.integer]

Subset of lines corresponding to horizontal grid lines.

verticalLinesNDArray[np.integer]

Subset of lines corresponding to vertical grid lines.

kMeansVisualslist[Frame] or None

Optional list of diagnostic visualization frames from the clustering and filtering stages.

Raises

ValueError

If no lines are detected at any stage of the grid pipeline.

Notes

Pipeline steps:
  1. Reset internal parameters based on image shape.

  2. Preprocess the image (denoising, blurring, downsampling).

  3. Detect line segments.

  4. Group and filter lines into horizontal and vertical sets.

Parameters:
  • image (numpy.ndarray)

  • expectedLines (int)

  • logPath (str)

Return type:

tuple[numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], list[numpy.ndarray] | None]

groupAndFilter(frame, lines, discardPercentageofMedian=0.8)[source]

Remove noisy/short Hough lines and separate them into horizontal and vertical sets.

This function performs a full cleanup pipeline on detected line segments: 1. Discards obvious outliers using k-means clustering. 2. Iteratively merges nearly parallel and spatially close lines. 3. Clusters lines by angle into two groups (horizontal vs vertical). 4. Estimates representative line lengths in each group. 5. Removes lines shorter than a fraction of the median length. 6. Returns the filtered horizontal, vertical, and combined line sets.

Parameters

frameAny

Input image/frame associated with the detected lines (used by the k-means noise discard step).

linesNDArray[np.integer] | None

Array of line segments of shape (N, 4) in the form [x1, y1, x2, y2]. Must contain at least 3 lines.

discardPercentageofMedianfloat, default=0.8

Fraction of the median line length used as a cutoff. Lines shorter than (median_length * discardPercentageofMedian) are discarded within each orientation group.

Returns

combinedLinesNDArray[np.integer]

Array of filtered lines containing both horizontal and vertical segments, shape (M, 4).

npHorizontalNDArray[np.integer]

Filtered horizontal lines, shape (H, 4).

npVerticalNDArray[np.integer]

Filtered vertical lines, shape (V, 4).

kmeansVisualsList[Frame]

Visualizations of the k-means clustering step, showing lines colored by cluster.

Raises

ValueError

If there are not enough input lines, if k-means discarding fails, if angle clustering fails, or if no horizontal/vertical lines remain after filtering.

Notes

  • Line orientation is determined via angle clustering into exactly two bins (horizontal-like and vertical-like).

  • Length thresholds are computed separately for horizontal and vertical groups using the median of the top longest lines in each group.

Parameters:
  • lines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]] | None)

  • discardPercentageofMedian (float)

Return type:

tuple[numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], List[numpy.ndarray] | None]

homographyTransform(image, horizontalLines, verticalLines)[source]

Apply a homography-based perspective correction to an image using detected grid lines.

This method selects the outermost horizontal and vertical lines from the detected grid, computes the four corner points of the grid via line intersections, and then rectifies the image so that the grid appears fronto-parallel.

Steps:
  1. Sort horizontal lines by their average y-coordinate and vertical lines by their average x-coordinate.

  2. Identify the topmost, bottommost, leftmost, and rightmost lines using endLines.

  3. Compute the corner points where these lines intersect using calculateCornerPoints.

  4. Rectify the image using the computed corners via rectifyGrid.

Parameters:
  • image (Frame) – The input image to be transformed.

  • horizontalLines (NDArray[np.integer]) – Array of shape (N, 4) containing detected horizontal lines in the format (x1, y1, x2, y2).

  • verticalLines (NDArray[np.integer]) – Array of shape (M, 4) containing detected vertical lines in the format (x1, y1, x2, y2).

Returns:

The rectified image after perspective correction.

Return type:

Frame

Raises:

ValueError – If horizontalLines or verticalLines is None.

kMeansNoiseDiscard(frame, lines, k=3)[source]

Cluster Hough lines by orientation using k-means and discard the smallest cluster as angular noise if it is sufficiently distinct.

This function groups detected lines into k angle-based clusters (via self.angleClusters). The cluster with the fewest members is treated as noise and removed, unless: • Its center angle is too close to another cluster center, or • Its size exceeds a fixed threshold (i.e., it is not truly noise).

Optionally, visual debug frames are produced showing each cluster drawn in a different color.

Parameters:
  • frame (numpy.ndarray) – Input image frame used only for generating visualization images.

  • lines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]] | None) – Array of line segments of shape (N, 4), where each row is (x1, y1, x2, y2). Must not be None.

  • k (int) – Number of angle clusters to compute (default is 3).

Returns:

  • combined_lines: NDArray[np.integer]

    Array of lines with the noise cluster removed. If no valid noise cluster is detected, all input lines are returned.

  • visuals: list[Frame] | None

    List of frames visualizing each cluster in a different color, or None if clustering could not be performed.

Return type:

A tuple of

Raises:

ValueError – If lines is None.

Notes

  • The smallest cluster is considered “noise” only if its center angle

    differs from all other cluster centers by more than degreeThreshold.

  • Clusters larger than a hardcoded size threshold are never discarded.

  • Uses self.angle_diff, self.angleClusters, and VisualUtils.drawLines.

lineDetection(frame, expectedLines=100)[source]

Detect line segments in an image using adaptive Canny + Hough Transform.

This method iteratively adjusts the edge detection sensitivity (edgeSlideFactor) to converge on an expected number of detected line segments. It is designed to be robust across varying contrast and noise conditions.

The process is:
  1. Apply adaptive Canny edge detection.

  2. Detect line segments using probabilistic Hough transform.

  3. Adjust edge sensitivity until the number of detected lines falls within the acceptable buffer range.

Parameters:
  • frame (Frame) – Input image frame (typically grayscale) used for line detection.

  • expectedLines (int, optional) – Target number of line segments to detect. The algorithm adapts thresholds to approach this value. Defaults to 100.

Returns:

A tuple containing:
  • lines: NumPy array of shape (N, 4), where each row is (x1, y1, x2, y2) for a detected line segment.

  • edges: The binary edge image used for Hough detection.

Returns None only if no valid detection occurs (normally a ValueError is raised instead).

Return type:

tuple[np.ndarray, Frame] | None

Raises:

ValueError – If no lines are detected after exhausting all threshold adjustments, or if the detection logic enters an invalid state.

Notes

  • Uses OpenCV’s cv.HoughLinesP for line detection.

  • The parameter edgeSlideFactor is automatically tuned per frame.

  • lineBuffer defines the acceptable deviation from expectedLines.

lineIntersection(line1, line2)[source]

Compute the intersection point of two 2D lines.

Each line is defined by four integer coordinates: (x1, y1, x2, y2).

Parameters:
  • line1 (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]] | None) – Line in the form (x1, y1, x2, y2) as integers.

  • line2 (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]] | None) – Line in the form (x3, y3, x4, y4) as integers.

Returns:

A NumPy array of shape (2,) with the intersection point [x, y] as floats, or None if the lines are parallel.

Return type:

numpy.ndarray[tuple[int, …], numpy.dtype[numpy.float64]] | None

mergeLines(lines, angle_thresh=np.float64(0.08726646259971647), dist_thresh=50)[source]

Merge approximately collinear and nearby line segments into longer “superlines”.

This function groups 2D line segments that have similar orientation (within angle_thresh) and are spatially close (within dist_thresh measured along the normal direction). For each group, it fits a single representative line using PCA and returns the endpoints of the merged segment.

Parameters

linesNDArray[np.integer]

Array of line segments with shape (N, 4), where each row is [x1, y1, x2, y2].

angle_threshfloat, optional

Maximum angular difference (in radians) between two lines for them to be considered collinear. Default is 5 degrees in radians.

dist_threshint, optional

Maximum perpendicular distance (in pixels) between two lines for them to be considered part of the same group. Default is 50.

Returns

NDArray[np.integer]

Array of merged line segments with shape (M, 4), where each row is [x1, y1, x2, y2] representing the endpoints of a fitted “superline”.

Notes

  • The algorithm:

  1. Iterates over all input lines.

  2. Groups lines with similar angle and nearby perpendicular offset.

  3. Collects all endpoints from each group.

  4. Fits a line using PCA to find the dominant direction.

  5. Projects points onto that direction and uses min/max projections

    as the merged segment endpoints.

  • Output endpoints are rounded to integer pixel coordinates.

Parameters:
  • lines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]])

  • angle_thresh (float)

  • dist_thresh (int)

Return type:

numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]]

normalize_params(height, width)[source]
Parameters:

height (int)

Return type:

dict

preProcess(frame, lambdaWeight, meanKernelSizeL, gaussianSigma, downsampleFactor)[source]

Preprocess an input image frame using guided filtering and edge enhancement, followed by grayscale conversion and Gaussian denoising.

This pipeline enhances structural edges while suppressing noise, making the output suitable for downstream tasks such as line detection, grid extraction, or feature analysis.

The processing steps are:
  1. Normalize the input frame to float32 in the range [0, 1].

  2. Split into color channels.

  3. Downsample each channel.

  4. Generate a guidance image using mean filtering.

  5. Upsample the guidance image and apply guided filtering.

  6. Perform edge enhancement using: Ai = Qi + λ (Ii − Qi).

  7. Merge enhanced channels.

  8. Convert to grayscale.

  9. Apply Gaussian blur for final denoising.

Parameters:
  • frame (Frame) – Input image frame in BGR format. Expected as a NumPy array of dtype uint8 or float32 with shape (H, W, 3).

  • lambdaWeight (float) – Edge enhancement strength λ. Higher values increase edge contrast.

  • meanKernelSizeL (int) – Kernel size for the mean filter used to generate the guidance image.

  • gaussianSigma (float) – Standard deviation for the final Gaussian denoising filter.

  • downsampleFactor (int) – Downsampling factor applied before guidance image computation.

Returns:

A single-channel (grayscale) denoised image frame suitable for further processing.

Return type:

Frame

Raises:

ValueError – If the input frame has an unexpected shape or dtype.

Notes

  • Requires OpenCV’s ximgproc module for guided filtering.

  • Kernel sizes should be positive odd integers for best results.

rectifiedPipeline(image, expectedLines, logPath)[source]

Run the full rectified-image grid detection pipeline.

This method preprocesses a rectified image, detects line segments, augments them with image-border lines, and then groups and filters the lines into horizontal and vertical sets suitable for grid reconstruction.

Parameters

imageFrame

Rectified input image to process.

expectedLinesint

Approximate number of line segments expected in the image, used to tune the line detection stage.

logPathstr

Directory path used for resetting parameters and logging context.

Returns

linesNDArray[np.integer]

Array of all detected and augmented line segments in (x1, y1, x2, y2) format.

horizontalLinesNDArray[np.integer]

Subset of lines corresponding to horizontal grid lines.

verticalLinesNDArray[np.integer]

Subset of lines corresponding to vertical grid lines.

kMeansVisualslist[Frame] or None

Optional list of diagnostic visualization frames from the clustering and filtering stages.

Raises

ValueError

If no lines are detected at any stage of the rectified pipeline.

Notes

Pipeline steps:
  1. Reset internal parameters based on image shape.

  2. Preprocess the image (denoising, blurring, downsampling).

  3. Detect line segments.

  4. Add border lines corresponding to the image edges.

  5. Group and filter lines into horizontal and vertical sets.

Parameters:
  • image (numpy.ndarray)

  • expectedLines (int)

  • logPath (str)

Return type:

tuple[numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], numpy.ndarray[tuple[int, …], numpy.dtype[numpy.integer]], list[numpy.ndarray] | None]

rectifyGrid(image, corners)[source]

Rectify a quadrilateral region of an image to a top-down rectangular view.

This function takes the four corner points of a grid (or any quadrilateral) in an image and computes a perspective transform (homography) to produce a rectified, axis-aligned rectangle containing the region.

Parameters:
  • image (np.ndarray) – Input image as a NumPy array (H x W x C or H x W).

  • corners (dict[str, np.ndarray]) – Dictionary of corner points with keys: - “top_left” - “top_right” - “bottom_right” - “bottom_left” Each value should be a NumPy array of shape (2,) representing [x, y] coordinates.

Returns:

Rectified image cropped and warped to a rectangle defined by the maximum width and height of the quadrilateral.

Return type:

np.ndarray

Raises:

ValueError – If any corner is None or if the homography cannot be computed.

Notes

  • The output rectangle will have its top-left corner at (0, 0).

  • Width is determined by the maximum of the top and bottom edge lengths.

  • Height is determined by the maximum of the left and right edge lengths.

  • The method logs corner information for debugging purposes.

resetParameters(height, width, logPath)[source]
Parameters:
  • height (int)

  • width (int)

  • logPath (str)

Return type:

None

spacingPipeline(image, horizontalLines, verticalLines)[source]

Estimate grid spacing from detected line sets and render a grid overlay.

This method determines the horizontal and vertical grid spacings from previously detected horizontal and vertical line segments, logs the results, and draws the inferred grid onto the rectified image.

Parameters

imageFrame

Rectified image on which the grid spacing is estimated and visualized.

horizontalLinesNDArray[np.integer]

Array of horizontal line segments in (x1, y1, x2, y2) format.

verticalLinesNDArray[np.integer]

Array of vertical line segments in (x1, y1, x2, y2) format.

Returns

horizontalSpacingint

Estimated spacing between horizontal grid lines (in pixels).

verticalSpacingint

Estimated spacing between vertical grid lines (in pixels).

gridOnRectifiedFrame

Copy of the input image with the estimated grid spacing overlaid.

Notes

This step assumes the input image has already been rectified such that grid lines are approximately axis-aligned.

Parameters:
  • image (numpy.ndarray)

  • horizontalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]])

  • verticalLines (numpy.ndarray[tuple[int, ...], numpy.dtype[numpy.integer]])

Return type:

tuple[int, int, numpy.ndarray]