-1

I have a 6 years time series with a thousand of detections of elements in cities (all databases have the same structure).

Year geometry Area-m2
2000 POINT (-122.38705 37.72066) 37.326319
2000 POINT (-122.38791 37.72053) 299.847120
2000 POINT (-122.38757 37.72033) 76.995192

I'm trying to check if an element remains over time and if its area increased. However, these are elements detected by deep learning models, so not all years are detected several elements because the image quality. Also, the coordinate is not exactly at the same point, but visually it is evident that it is the same element. For instance, image below.

enter image description here

I'm trying to do processing with ArcGIS, making a buffer and selecting by location the detections and then consider successful if there are more than three detections in the same element. However, this manual process is very time-consuming and I would like to do it in Python.

Do you have any idea?

1
  • You have to edit your question and add whatever code attempt you have or it is going to get closed. Can you share your data? For example as a text file?
    – BERA
    Mar 16, 2023 at 12:46

1 Answer 1

7

I can show you an example of clustering to find if the observations are in the same location. Then you just need to calculate area change. There are many clustering algorithms I chose DBSCAN because you just need distance and cluster size as input.

import geopandas as gpd
import pandas as pd
from sklearn.cluster import DBSCAN
import matplotlib.pyplot as plt

#Create some test data
coordinates = [[-122.4295, 37.7005], [-122.4283, 37.701], [-122.4268, 37.6995],  [-122.4267, 37.6995], [-122.4268, 37.7003], [-122.4295, 37.6995], [-122.4284, 37.6989], [-122.4268, 37.7009],
               [-122.4258, 37.7004], [-122.4277, 37.7002], [-122.4123, 37.784],  [-122.4107, 37.7833], [-122.4135, 37.7821], [-122.4123, 37.7829], [-122.4142, 37.7835], [-122.4138, 37.7841],
               [-122.4129, 37.7837], [-122.4111, 37.7835], [-122.4122, 37.7848], [-122.4119, 37.7816], [-122.4243, 37.7154], [-122.4228, 37.7146], [-122.4226, 37.7151], [-122.4239, 37.7159],
               [-122.4223, 37.7143], [-122.4238, 37.7138], [-122.425, 37.7143],  [-122.4219, 37.7161], [-122.4248, 37.7151], [-122.4241, 37.7162], [-122.4187, 37.7191], [-122.4173, 37.7195],
               [-122.4188, 37.7178], [-122.4161, 37.7198], [-122.4189, 37.7191], [-122.4182, 37.7186], [-122.4174, 37.7190], [-122.4194, 37.7189], [-122.4196, 37.7185], [-122.4192, 37.7195],
               [-122.4033, 37.7184], [-122.4026, 37.7186], [-122.4016, 37.7172], [-122.402, 37.7159],  [-122.4014, 37.7191], [-122.4015, 37.7189], [-122.4021, 37.7188], [-122.4025, 37.7186],
               [-122.4019, 37.7183], [-122.4035, 37.7171], [-122.402, 37.7532],  [-122.4002, 37.7523], [-122.4001, 37.7535], [-122.4002, 37.754],  [-122.4013, 37.7525], [-122.401, 37.7512],
               [-122.4001, 37.7529], [-122.4023, 37.7535], [-122.4, 37.7516],    [-122.3997, 37.7516], [-122.4957, 37.7597], [-122.4955, 37.7527], [-122.4935, 37.762],  [-122.4993, 37.7592],
               [-122.4878, 37.7646], [-122.4916, 37.7569], [-122.4935, 37.7537], [-122.502, 37.7599],  [-122.4928, 37.7671], [-122.4962, 37.752], [-122.4916, 37.7962],  [-122.4803, 37.7965],
               [-122.4856, 37.7937], [-122.4848, 37.7843], [-122.4906, 37.7866], [-122.4884, 37.7846], [-122.4926, 37.7966], [-122.4807, 37.796], [-122.4891, 37.7991],  [-122.4848, 37.7849]]

df = pd.DataFrame(data=coordinates, columns=["lon","lat"])
df["id"] = range(df.shape[0])
df = gpd.GeoDataFrame(df, geometry = gpd.points_from_xy(x=df["lon"], y=df["lat"], crs=4326))
df = df.to_crs(32610) #You need coordinates in a projected crs
df["x"] = df.apply(lambda f: f.geometry.x, axis=1) #Calculate x and y columns
df["y"] = df.apply(lambda f: f.geometry.y, axis=1)

#Plot
xmin, ymin = 541000,4170500
xmax, ymax = 556000,4185000
fig, ax = plt.subplots(figsize=(3, 3))
ax.set_xlim(xmin, xmax)
ax.set_ylim(ymin, ymax )
df.plot(ax=ax)

There are ~7 point clusters enter image description here

#Cluster using DBSCAN algorithm
X = df[["x","y"]].values #Create a numpy array of the coordinates
clustering = DBSCAN(eps=300, min_samples=10).fit(X) #Cluster them. eps is max distance between points,
#min_samples are the min. number of points to create a cluster

df["clusterid"] = clustering.labels_ #The cluster ids
df["clusterid"].unique()
#array([ 0,  1,  2,  3,  4,  5, -1])

#Plot
c = {-1:"grey", 0:"blue", 1:"lime", 2:"orange", 3:"red", 4:"cyan",5:"magenta"}
df["color"] = df["clusterid"].map(c)
fig2, ax2 = plt.subplots(figsize=(3, 3))
ax2.set_xlim(xmin, xmax)
ax2.set_ylim(ymin, ymax )
df.plot(ax=ax2, color=df["color"])

The points in the two left point concentrations are further apart than 300 m so they get cluster -1:

enter image description here

Not the answer you're looking for? Browse other questions tagged or ask your own question.