Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IndividualTreeDetection ignores the min_height parameter #349

Closed
williamlidberg opened this issue Jun 3, 2023 · 8 comments
Closed

IndividualTreeDetection ignores the min_height parameter #349

williamlidberg opened this issue Jun 3, 2023 · 8 comments

Comments

@williamlidberg
Copy link

The output shapefile from IndividualTreeDetection contains points with very low values and sometimes even negative values even when the min_height parameter is set.

Here is my code:

# container directories
filtered_las_dir = '/tmp/filtered_las_dir/'
height_dir = '/output_tree_dir/'
min_height = 1

def main(laz_dir, tree_dir, min_height):

    print('create dem for normalization')
    start = time.time() 
    """
    converts all laz tiles in a directory to a digital elevation raster.
    """  
    wbt.set_verbose_mode(True)
    wbt.set_working_dir(laz_dir)
    wbt.lidar_tin_gridding(parameter="elevation", 
    returns="last", # A DEM or DTM is usually obtained from the "last" returns, a DSM uses "first" returns (or better, use the lidar_digital_surface_model tool)
    resolution=1, # This is the spatial resolution of the output raster in meters and should depend on application needs and point density.
    exclude_cls= "0,1,3,4,5,6,7,8,10,11,12,13,14,15,16,17,18", # Example of classified points to be excluded from analysis i.e. class 9 is water.
    minz=None,
    maxz=None,
    max_triangle_edge_length=None
    )
 
    print('Normalize point cloud.')
    for tile in tqdm(os.listdir(laz_dir)):
        if tile.endswith('.laz'):
            intile = laz_dir + tile
            filter_out = filtered_las_dir + tile
            height = height_dir + tile
            indtm = laz_dir + tile.replace('.laz','.tif')

            wbt.normalize_lidar(
                i = intile, 
                output = height, 
                dtm = indtm
            )
            
    print('Detecting individual trees from point cloud.')        
    wbt.set_working_dir(height_dir)
    wbt.individual_tree_detection(
        i=None, 
        output=tree_dir, 
        min_search_radius=1.0, 
        min_height=min_height, 
        max_search_radius=10, 
        max_height=50, 
        only_use_veg=False
    )
@jblindsay
Copy link
Owner

This is odd for sure. Are you able to send me a sample data set for which you encountered this issue so that I can do some testing and hopefully figure out the cause for the problem?

Just as a side note, I'm a little surprised that you're using WBT for Python scripting still given you have WbW. I find myself writing all my Wb-based scripts in WbW these days.

@williamlidberg
Copy link
Author

Here is a link to my data.

The reason why I am not using WbW for this is that I am doing this for someone else. The code will live in a docker image that others can use and I am not comfortable using my WbW license like that.

@jblindsay
Copy link
Owner

Thanks for providing the data. Have you normalized your input point cloud using the NormalizeLidar tool beforehand? Otherwise the point z values are elevations and not height above ground, as you may desire.

That makes perfect sense why you'd be using WbT for this rather than WbW. I was just worried if there was some deficiency that you might have found in WbW as to why this application wouldn't be better suited to it. But I guess that makes a lot of sense. Thanks for sharing.

@williamlidberg
Copy link
Author

This data is the raw version of my data. sorry for not mentioning that. I did use the normalise lidar tool before applying the individual tree detection tool. The code is in the original message above.

First I created a DEM from the laz file and then used that to normalize the data to elevation above ground. Finally I used the normalised data as input to the individual tree detection algorithm.

@jblindsay
Copy link
Owner

Silly me, I should have noticed that.

@jblindsay
Copy link
Owner

Taking your data set and normalizing it, then applying the IndividualTreeDetection tool, I must admit that I'm not seeing any output points that are less than 1 m, which was the value used for min_z. I can't seem to replicate.

Screenshot 2023-06-07 at 9 25 23 AM

@williamlidberg
Copy link
Author

I did some more tests and seems to be related to setting a working directory instead of specifying an input file.
wbt.set_working_dir(normalized_laz_dir)

This works:

min_height = 1
intile = 'C:/william/filtered/18A003_61600_3750_25.laz'
trees = 'C:/william/18A003_61600_3750_25.shp'

wbt.individual_tree_detection(
    i=intile, 
    output=trees, 
    min_search_radius=1.0, 
    min_height=min_height, 
    max_search_radius=10, 
    max_height=50, 
    only_use_veg=False
)

But not this:

filtered_las_dir = 'C:/william/filtered/'
wbt.set_working_dir(filtered_las_dir)
trees = 'C:/william/test_output/'
min_height = 1

wbt.individual_tree_detection(
    i=None, 
    output=trees, 
    min_search_radius=1.0, 
    min_height=min_height, 
    max_search_radius=10, 
    max_height=50, 
    only_use_veg=False
)

I want to use the excellent parallel processing and edge "fixing" that your lidar tools use when working with multiple files.

@jblindsay
Copy link
Owner

That was the missing piece for figuring out the issue. Turns out that I was missing an if statement to filter out points with z < min_height for the batch processing branch. I've fixed it now and pushed to the repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants