r-lidar / lasR

Fast and Pipable Airborne LiDAR Data Tools
https://r-lidar.github.io/lasR/
GNU General Public License v3.0
43 stars 0 forks source link

new feature neighborhood_metrics() #49

Open wiesehahn opened 2 weeks ago

wiesehahn commented 2 weeks ago

Original question in https://github.com/r-lidar/lasR/issues/33

I am wondering if there is an efficient way to get attribute values for each local maximum based on points/pixels in the neighborhood? E.g. if I want to get the mean of some attribute for each local maximum, based on all points above min height and within window size diameter. I think about how to get mean intensity for each tree as an indicator for species/vitality.

Response

What you want is a stage like lidR::point_metrics() that takes as input a set of 3d points (e.g. the output of local_maximum()) and that computes some metrics using the points in the neighborhood of the user-defined locations.

lm = local_maximum()
nm = neighborhood_metrics(locations = lm, metrics = "imean")
pipeline = lm + nm

I have not entirely thought through this, but the function could use similar inputs as geometry_features(), namely k and r to define k-nearest neighbours and radius of the neighborhood. For my initial example something like the following would then work to add an attribute imean to ttops.

lm = local_maximum(ws = 5, min_height = 2, filter = "-drop_class 2", use_attribute = "Z")
nm = neighborhood_metrics(locations = lm, metrics = "imean", r = 2.5, filter = "-drop_class 2 -drop_z_below 2", ofile = tempgpkg())
pipeline = lm + nm

I think a filter option here is less problematic than in geometry_features() as we are writing the attribute to 3D points and not the point cloud?!

As stated earlier, this is in idea which I think could be useful, but there is no need to feel pressured to implement it for an individual like me.

Jean-Romain commented 2 weeks ago

As stated earlier, this is in idea which I think could be useful, but there is no need to feel pressured to implement it for an individual like me.

It is also interesting to me to see if I can construct a pipeline of that complexity. But I see no strong limitation, the engine is already designed to handle this kind of use case and most of the code to make this feature already exists. I have no internal structure to add custom attribute to geographic points but it is probably not a big issue. Your example looks good and I can't see any obvious feature to add. locations could handle anything that is made of points including the point cloud itself. Thus such stage could allow to reproduce lidR::point_metrics().

Jean-Romain commented 2 weeks ago

So far I wrote 80% of the code. The remaining 20% are not the funniest and will likely take 80% of the time :smile:

wiesehahn commented 4 days ago

Just out of curiosity I was wondering if the neighborhood metrics feature would allow to reclassify some of the points based on neighbouring classifications. Lets say we have a lasfile with many points classified as overlap points (class 12), but I would like to use these data points in areas of higher density (due to overlapping flight paths). One way would be to reclassify the entire point cloud, but I was wondering if we could simply assign the classification based on neighbouring points (with all the problems this may have)? If I am correct we could provide a classification value and additionally flag points as overlap with LAS 1.4.

I think so far there is nothing like a metric for the mode of classification, so I hyphotetically called it "cmode", which is also redundant in the case of k=1.

overlap <- delete_points(keep_class(12))
nm <- neighborhood_metrics(locations = overlap, metrics = "cmode", k = 1, r = 0.5, filter = "-drop_class 12") 

pipeline <- reader_las() + nm + write_las()
exec(pipeline, on = f)
Jean-Romain commented 4 days ago

This function will compute metrics as its name indicates. The feature you are suggesting is extremely specific and experimental, this not something that can be implemented in lasR. For this kind of fancy experimental ideas there is lidR. Additional metrics however is a reasonable request.