Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding edge from 2d points Python

I have several 2d sets of scattered data that I would like to find the edges of. Some edges may be open lines, others may be polygons.

For example, here is one plot that has an open edge that I would like to be able to keep. I would actually like to create a polygon from the open edges so I can use point_in_poly to check if another point lies inside. The points that would close the polygon are the boundaries of my plot area, btw. enter image description here

enter image description here

Any ideas on where to get started?

EDIT:

Here is what I have already tried:

  1. KernelDensity from sklearn. The edges point density varies significantly enough to not be entirely distinguishable from the bulk of the points.

    kde = KernelDensity()  
    kde.fit(my_data)  
    dens = np.exp(kde.score_samples(ds))  
    dmax = dens.max()  
    dens_mask = (0.4 * dmax < dens) & (dens < 0.8 * dmax)  
    ax.scatter(ds[dens_mask, 0], ds[dens_mask, 1], ds[dens_mask, 2],  
    c=dens[dens_mask], depthshade=False, marker='o', edgecolors='none')  
    

enter image description here

Incidentally, the 'gap' in the left side of the color plot is the same one that is in the black and white plot above. I also am pretty sure that I could be using KDE better. For example, I would like to get the density for a much smaller volume, more like using radius_neighbors from sklearn's NearestNeighbors()

  1. ConvexHull from scipy. I tried removing points from semi-random data (for practice) while still keeping a point of interest (here, 0,0) inside the convex set. This wasn't terribly effective. I had no sophisticated way of exlcuding points from an iteration and only removed the ones that were used in the last convex hull. This code and accompanying image shows the first and last hull made while keeping the point of interest in the set.

    hull = ConvexHull(pts)
    contains = True
    while contains:
    
        temp_pts = np.delete(pts, hull.vertices, 0)
        temp_hull = ConvexHull(temp_pts)
        tp = path.Path(np.hstack((temp_pts[temp_hull.vertices, 0][np.newaxis].T,
        temp_pts[temp_hull.vertices, 1][np.newaxis].T)))
    if not tp.contains_point([0, 0]):
        contains = False
        hull = ConvexHull(pts)
        plt.plot(pts[hull.vertices, 0], pts[hull.vertices, 1])
    else:
        pts = temp_pts
    
    plt.plot(pts[hull.vertices, 0], pts[hull.vertices, 1], 'r-')
    plt.show()
    

enter image description here

Ideally the goal for convex hull would be to maximize the area inside the hull while keeping only the point of interest inside the set but I haven't been able to code this.

  1. KMeans() from sklearn.cluster. Using n=3 clusters I tried just run the class with default settings and got three horizontal groups of points. I haven't learned how to train the data to recognize points that form edges.

Here is a piece of the model where the data points are coming from. The solid areas contain points while the voids do not.

enter image description here

Here, and here are some other questions I have asked that show some more of what I have been looking at.

like image 617
Chris Avatar asked May 13 '26 09:05

Chris


1 Answers

So I was able to do this in a roundabout way.

I used images of slices of the model in the xy plane generated from SolidWorks to distinguish the areas of interest.

Slice of model

If you see them, there are points in the corners of the picture that I placed in the model for reference at known distances. These points allowed me to determine the number of pixels per millimeter. From there, I mapped the points in my analysis set to pixels and checked the color of the pixel. If the pixel is white it is masked.

def mask_z_level(xi, yi, msk_img, x0=-14.3887, y0=5.564):
    im = plt.imread(msk_img)
    msk = np.zeros(xi.shape, dtype='bool')

    pxmm = np.zeros((3, 2))
    p = 0

    for row in range(im.shape[0]):
        for col in range(im.shape[1]):
            if tuple(im[row, col]) == (1., 0., 0.):
                pxmm[p] = (row, col)
                p += 1

    pxx = pxmm[1, 1] / 5.5
    pxy = pxmm[2, 0] / 6.5
    print(pxx, pxy)

    for j in range(xi.shape[1]):
        for i in range(xi.shape[0]):
            x, y = xi[i, j], yi[i, j]
            dx, dy = x - x0, y - y0
            dpx = np.round(dx * pxx).astype('int')
            dpy = -np.round(dy * pxy).astype('int')

            if tuple(im[dpy, dpx]) == (1., 1., 1.):
                msk[i, j] = True

    return msk

Here is a plot showing the effects of the masking: Masked and regular images

I am still fine tuning the borders but I have a very manageable task now that the mask is in largely complete. The reason being is that some mask points are incorrect resulting in banding.

Bands in integrated data

like image 68
Chris Avatar answered May 16 '26 00:05

Chris



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!