Quadrilateral Fitting

Python Functions

actag.quad_fitting.add_quads_to_axis(ax: Axes, quads: list) Axes

Draw a set of quadrilaterals onto a matplotlib axis for visualization.

Parameters:
  • ax (matplotlib.pyplot.Axes) – The matplotlib axes to draw the quadrilaterals onto.

  • quads (list) – A list of quadrilaterals to draw onto the axis.

Returns:

The matplotlib axes with the quadrilaterals drawn onto it.

Return type:

matplotlib.pyplot.Axes

actag.quad_fitting.distance_between_point_and_line(point: ndarray, line_type: str, slope: float, intercept: float) float

Calculate the smallest distance between a point and a line. The line is represented by an equation form (row or column), a slope, and an intercept.

Parameters:
  • point (np.ndarray) – 2D point, of the form [row, column].

  • line_type (str) – The form of the equation for the line, either row or column.

  • slope (float) – The slope of the line.

  • intercept (float) – The intercept of the line.

Returns:

The smallest distance between the point and any point on the line.

Return type:

float

actag.quad_fitting.distance_between_point_and_line_segment(point: ndarray, line_point_1: ndarray, line_point_2: ndarray) float

Calculates the smallest distance between a point and a line. The line is represented by two points.

Parameters:
  • point (np.ndarray) – 2D point, of the form [row, column].

  • line_point_1 (np.ndarray) – A point on the line segment, of the form [row, column].

  • line_point_2 (np.ndarray) – A different point on the line segment, in the same form as line_point_1.

Returns:

The smallest distance between the point and any point on the line.

Return type:

float

actag.quad_fitting.fit_quadrilaterals_to_contours(contour_list: list[list], img_shape: tuple[int, int], random_seed: None, points_per_line_ratio: float = 0.1, dist_for_inlier: float = 2.5, desired_inlier_ratio: float = 0.85, required_inlier_ratio: float = 0.8, parallel_threshold: float = 0.9, use_same_random_vals: bool = False, starting_roll_val: int = 123456) list[ndarray]

Attempts to fit a quadrilateral to each contour in the list, using a custom RANSAC algorithm.

Parameters:
  • contour_list (list[list]) – A list of contours, with each contour having the form [layer_num, row1, col1, row2, col2, ...].

  • img_shape (tuple[int, int]) – The shape of the image, in the form (num_rows, num_cols).

  • random_seed (None (or int)) – If specified, the discrete uniform random number generator will be seeded with this value. If not specified, the random number generator will have a random seed, leading to new values each time it is run.

  • points_per_line_ratio (float) – The ratio of the number of points within a contour to use for each line fit.

  • dist_for_inlier (float) – The distance threshold for a point to be considered an inlier.

  • desired_inlier_ratio (float) – The desired ratio of inliers within the total number of points.

  • required_inlier_ratio (float) – The required ratio of inliers within the total number of points.

  • parallel_threshold (float) – The value used for determining whether or not two lines are parallel, when checking if the quad is a parallelogram.

  • use_same_random_vals (bool) – Set to true to use repeatable random values, starting with the starting_roll_val. Used to syncronize random values between Python & Rust versions of this function (for testing purposes).

  • starting_roll_val (int) – The starting roll value for when use_same_random_vals is set to true.

Returns:

A list of quadrilaterals. Each quadrilateral is an np.ndarray that contains four corners, each of which is a tuple of the form [row, column].

Return type:

list[np.ndarray]

actag.quad_fitting.get_intersection_of_lines(line_1, line_2) list[int, int]

Calculate the intersection of two lines.

Parameters:
  • line_1 (list[str, float, float]) – The first line. It is stored as a list of the form [solve_for, slope, intercept], where solve_for is the equation form used to represent the line (row or column).

  • line_2 (list[str, float, float]) – The second line, formatted in the same way as line_1.

Returns:

The intersection of the two lines in the form [row, column], rounded to the nearest row and column index.

Return type:

list[int, int]

Raises:

ValueError – Raised if the two lines have the same slope, resulting in either 0 or infinite intersections.

actag.quad_fitting.get_random_point_and_fit_line(shape_points: ndarray, points_per_line: int, use_same_random_vals: bool, rand: Generator, supplied_roll_value: int = 0) list[float, float, float, ndarray]

Randomly sample points_per_line points from shape_points with the provided random number generator, and then fit a line to these points using least squares. If use_same_random_vals is true, roll to the supplied_roll_value instead of randomly.

Parameters:
  • shape_points (np.ndarray) – All of the points in the contour to randomly sample from.

  • points_per_line (int) – The number of points to sample for a line.

  • use_same_random_vals (bool) – If true, sample points starting at the supplied_roll_value instead of randomly.

  • rand (np.random.Generator) – A random number generator used to sample randomly.

  • supplied_roll_value (int) – If use_same_random_vals is true, then sample points starting from this value.

Returns:

A list, containing the form of the line (row or column), the slope, the intercept, and any leftover points from shape_points that were not used to fit this line.

Return type:

list[float, float, float, np.ndarray]

actag.quad_fitting.least_squares_line_fit(line_points: ndarray) tuple[str, float, float]

Fit a line to the points using least squares, trying forms y = m * x + b and x = m * y + b to see which is the better fit. This is necessary because linear regression for vertical lines is very poor with the form y = m * x + b; likewise for horizontal lines we do not want to use the form x = m * y + b.

Parameters:

line_points (np.ndarray) – The points used to fit a line to.

Returns:

The form of the line fit (row or column), the slope, and the intercept.

Return type:

tuple(str, float, float)

Rust Functions

actag.rust_impl.get_intersection_of_lines()

Rust equivalent of actag.quad_fitting.get_intersection_of_lines().

Parameters:
  • line_1 ((f64, f64)) – Slope and intercept of the first line.

  • line_2 ((f64, f64)) – Slope and intercept of the second line.

  • line_1_row (bool) – true if line 1 is in row form, or false for column form.

  • line_2_row (bool) – true if line 2 is in row form, or false for column.

Returns:

The intersection of the two lines in the form (row, column), rounded to the nearest row and column index.

Return type:

PyResult<(i64, i64)>

Raises:

ValueError – Raised if the two lines have the same slope, resulting in either 0 or infinite intersections.

actag.rust_impl.least_squares_line_fit_python_wrap()

Rust equivalent of actag.quad_fitting.least_squares_line_fit().

Parameters:

line_points (Vec<(f64, f64)>) – The points used to fit a line.

Returns:

A vector containing the fitted line in the following format: [equation form, slope, intercept]. The equation form will be 1 for row form or 0 for column form.

Return type:

Vec<f64>

actag.rust_impl.get_random_point_and_fit_line_python_wrap()

Rust equivalent of actag.quad_fitting.get_random_point_and_fit_line(). Randomly sample points_for_line points from shape_points and then fit a line to these points using least squares. If use_same_random_vals is true, roll to the supplied_roll_value instead of randomly.

Parameters:
  • shape_points (&mut Vec<(f64, f64)>) – All of the points in the contour to randomly sample from.

  • points_for_line (u64) – The number of points to sample for a line.

  • use_same_random_vals (bool) – If true, sample points starting at the supplied_roll_value instead of randomly.

  • supplied_roll_value (u32) – If use_same_random_vals is true, then sample points starting from this value.

Returns:

A vector containing the fitted line and the leftover points. The first three values are the equation form of the line (1 for row, 0 for column), the slope, and the intercept. The remaining values are the row and column values of leftover points from shape_points that were not used to fit this line.

Return type:

Vec<f64>

actag.rust_impl.fit_quadrilaterals_to_contours()

Rust equivalent of actag.quad_fitting.fit_quadrilaterals_to_contours().

Parameters:
  • contour_list (Vec<Vec<i64>>) – A list of contours, with each contour having the form [layer_num, row1, col1, row2, col2, ...].

  • img_shape ((i64, i64)) – The shape of the image, in the form (num_rows, num_cols).

  • random_seed (Option<u32>) – If specified, the discrete uniform random number generator will be seeded with this value. If not specified, the random number generator will have a random seed, leading to new values each time it is run.

  • points_per_line_ratio (f64) – The ratio of the number of points within a contour to use for each line fit.

  • dist_for_inlier (f64) – The distance threshold for a point to be considered an inlier.

  • desired_inlier_percentage (f64) – The desired ratio of inliers within the total number of points.

  • required_inlier_percentage (f64) – The required ratio of inliers within the total number of points.

  • parallel_threshold (f64) – The value used for determining whether or not two lines are parallel, when checking if the quad is a parallelogram.

  • use_same_random_vals (bool) – Set to true to use repeatable random values, starting with the starting_roll_val. Used to syncronize random values between Python & Rust versions of this function (for testing purposes).

  • starting_roll_val (u32) – The starting roll value for when use_same_random_vals is set to true.

Returns:

A vector of quadrilaterals. Each quadrilateral contains four corners, each of which is a tuple of the form (row, column).

Return type:

Vec<Vec<(i64, i64)>>