Geometry extraction from trajectories

Viewed 74

I have some trajectories of people moving in a given geometry. For example enter image description here

In this example, the geometry was added manually, a process I would like to automatize: The question is then: How to generate an approximation of the walls, shown as black lines in the picture above?

Code

Here is my Ansatz: count, in a grid, where people go (or not go), and hence identify the empty grid cells. That would tell me where is inside and outside the geometry. Assuming Tx and Ty hold the coordinates of all trajectory points:

from scipy import stats
dx = 0.1
xbins = np.arange(geominX, geomaxX + dx, dx)
ybins = np.arange(geominY, geomaxY + dx, dx)
ret = stats.binned_statistic_2d(
        Tx,
        Ty,
        None,
        "count",
        bins=[xbins, ybins]
    )

Plotting the counts per cell (ret.statistic) yields:

enter image description here

Now, from this, I calculated the points in the geometry with non-empty counts:

X = ret.x_edge + dx/2
Y = ret.y_edge + dx/2
x, y = np.meshgrid(X[:-1], Y[:-1])
xx = x[ret.statistic.T != 0]
yy = y[ret.statistic.T != 0]
plt.plot(xx, yy, ".")

which gives for dx=0.1 the following result:

enter image description here

For the sake of explanation, I'd like to give another example of a bottleneck, where the boundaries of the geometry, the black lines, are added manually.

enter image description here enter image description here

enter image description here

Problem

This is now the point where I'm stuck and need some help. Do you have any idea how I could proceed from here and automatically identify a rough approximation of the geometry's boundaries?

Data

In case of trajectories are needed, here are two links to the above-used trajectories:

EDIT (using OpenCV)

Thanks to @BlackBeans comment, I tried the following:

  1. plot the trajectories with white on black background and save image:
# with a big marker size
ax.plot(d[:, 2], d[:, 3], "o", ms=10, color="white")

enter image description here

  1. In the next step, read the image and find the contours:
img = cv2.imread("trajecotries.png", cv2.IMREAD_GRAYSCALE)
_, binary_img = cv2.threshold(img, 225, 255, cv2.THRESH_BINARY_INV)
contours, _ = cv2.findContours(binary_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[1]
final_image = cv2.drawContours(img, [cnt], 0, (178,34,34), 2)

enter image description here

That brings me closer to my goal. However, the contours are not in original coordinates, but rather some numbers relative to the image.

1 Answers

Your problem is usually called contour approximation. OpenCV has a function that does that for you, documented here (at the Contour Approximation section). It is relatively straightforward to use.

Related