import numpy as np
[docs]def get_array_edges(array: np.ndarray) -> list[list[tuple[int, int]]]:
"""
Get edges of region in binary array.
Parameters
----------
array
Binary array.
Returns
-------
:
List of unconnected region edges.
"""
edges = []
x, y = np.nonzero(array)
for i, j in zip(x.tolist(), y.tolist()):
if j == array.shape[1] - 1 or not array[i, j + 1]:
edges.append([(i, j + 1), (i + 1, j + 1)])
if i == array.shape[0] - 1 or not array[i + 1, j]:
edges.append([(i + 1, j), (i + 1, j + 1)])
if j == 0 or not array[i, j - 1]:
edges.append([(i, j), (i + 1, j)])
if i == 0 or not array[i - 1, j]:
edges.append([(i, j), (i, j + 1)])
return edges
[docs]def connect_array_edges(edges: list[list[tuple[int, int]]]) -> list[list[tuple[int, int]]]:
"""
Group unconnected region edges into connected contour edges.
Parameters
----------
edges
List of unconnected region edges.
Returns
-------
:
List of connected contour edges.
"""
contours: list[list[tuple[int, int]]] = []
while edges:
contour = edges[0]
contour_length = 0
edges.remove(contour)
while contour_length != len(contour):
contour_length = len(contour)
forward = list(filter(lambda edge: contour[-1] == edge[0], edges))
if len(forward) > 0:
edges.remove(forward[0])
contour.extend(forward[0][1:])
backward = list(filter(lambda edge: contour[-1] == edge[-1], edges))
if len(backward) > 0:
edges.remove(backward[0])
contour.extend(list(reversed(backward[0]))[1:])
if contour_length == len(contour):
contours.append(list(contour))
return sorted(contours, key=len)
[docs]def merge_contour_edges(contour: list[tuple[int, int]]) -> list[tuple[int, int]]:
"""
Merge connected contour edges.
Parameters
----------
contour
List of connected contour edges.
Returns
-------
:
List of connected contours.
"""
merged = contour.copy()
for (x0, y0), (x1, y1), (x2, y2) in zip(contour, contour[1:], contour[2:]):
area = x0 * (y1 - y2) + x1 * (y2 - y0) + x2 * (y0 - y1)
if area == 0:
merged.remove((x1, y1))
return merged