---
name: v.lidar.edgedetection
description: "Detects the object's edges from a LIDAR data set."
keywords: [ vector, LIDAR, edges ]
---

# v.lidar.edgedetection

Detects the object's edges from a LIDAR data set.

=== "Command line"

    **v.lidar.edgedetection**
    [**-e**]
    **input**=*name*
    **output**=*name*
    [**ew_step**=*float*]
    [**ns_step**=*float*]
    [**lambda_g**=*float*]
    [**tgh**=*float*]
    [**tgl**=*float*]
    [**theta_g**=*float*]
    [**lambda_r**=*float*]
    [**--overwrite**]
    [**--verbose**]
    [**--quiet**]
    [**--qq**]
    [**--ui**]

    Example:

    ```sh
    v.lidar.edgedetection input=name output=name
    ```

=== "Python (grass.tools)"

    *grass.tools.Tools.v_lidar_edgedetection*(**input**,
        **output**,
        **ew_step**=*None*,
        **ns_step**=*None*,
        **lambda_g**=*0.01*,
        **tgh**=*6*,
        **tgl**=*3*,
        **theta_g**=*0.26*,
        **lambda_r**=*2*,
        **flags**=*None*,
        **overwrite**=*None*,
        **verbose**=*None*,
        **quiet**=*None*,
        **superquiet**=*None*)

    Example:

    ```python
    tools = Tools()
    tools.v_lidar_edgedetection(input="name", output="name")
    ```

    This grass.tools API is experimental in version 8.5 and expected to be stable in version 8.6.

=== "Python (grass.script)"

    *grass.script.run_command*("***v.lidar.edgedetection***",
        **input**,
        **output**,
        **ew_step**=*None*,
        **ns_step**=*None*,
        **lambda_g**=*0.01*,
        **tgh**=*6*,
        **tgl**=*3*,
        **theta_g**=*0.26*,
        **lambda_r**=*2*,
        **flags**=*None*,
        **overwrite**=*None*,
        **verbose**=*None*,
        **quiet**=*None*,
        **superquiet**=*None*)

    Example:

    ```python
    gs.run_command("v.lidar.edgedetection", input="name", output="name")
    ```

## Parameters

=== "Command line"

    **input**=*name* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Or data source for direct OGR access  
    **output**=*name* **[required]**  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map  
    **ew_step**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;Length of each spline step in the east-west direction  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: 4 \* east-west resolution  
    **ns_step**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;Length of each spline step in the north-south direction  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: 4 \* north-south resolution  
    **lambda_g**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;Regularization weight in gradient evaluation  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0.01*  
    **tgh**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;High gradient threshold for edge classification  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *6*  
    **tgl**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;Low gradient threshold for edge classification  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *3*  
    **theta_g**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;Angle range for same direction detection  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0.26*  
    **lambda_r**=*float*  
    &nbsp;&nbsp;&nbsp;&nbsp;Regularization weight in residual evaluation  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *2*  
    **-e**  
    &nbsp;&nbsp;&nbsp;&nbsp;Estimate point density and distance and quit  
    &nbsp;&nbsp;&nbsp;&nbsp;Estimate point density and distance in map units for the input vector points within the current region extents and quit  
    **--overwrite**  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    **--help**  
    &nbsp;&nbsp;&nbsp;&nbsp;Print usage summary  
    **--verbose**  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    **--quiet**  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    **--qq**  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    **--ui**  
    &nbsp;&nbsp;&nbsp;&nbsp;Force launching GUI dialog

=== "Python (grass.tools)"

    **input** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Or data source for direct OGR access  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, vector, *name*  
    **output** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, vector, *name*  
    **ew_step** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Length of each spline step in the east-west direction  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: 4 \* east-west resolution  
    **ns_step** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Length of each spline step in the north-south direction  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: 4 \* north-south resolution  
    **lambda_g** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Regularization weight in gradient evaluation  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0.01*  
    **tgh** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;High gradient threshold for edge classification  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *6*  
    **tgl** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Low gradient threshold for edge classification  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *3*  
    **theta_g** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Angle range for same direction detection  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0.26*  
    **lambda_r** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Regularization weight in residual evaluation  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *2*  
    **flags** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *e*  
    &nbsp;&nbsp;&nbsp;&nbsp;**e**  
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Estimate point density and distance and quit  
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Estimate point density and distance in map units for the input vector points within the current region extents and quit  
    **overwrite** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **verbose** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **quiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **superquiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  

    Returns:

    **result** : grass.tools.support.ToolResult | None  
    If the tool produces text as standard output, a *ToolResult* object will be returned. Otherwise, `None` will be returned.

    Raises:

    *grass.tools.ToolError*: When the tool ended with an error.

=== "Python (grass.script)"

    **input** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name of input vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Or data source for direct OGR access  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: input, vector, *name*  
    **output** : str, *required*  
    &nbsp;&nbsp;&nbsp;&nbsp;Name for output vector map  
    &nbsp;&nbsp;&nbsp;&nbsp;Used as: output, vector, *name*  
    **ew_step** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Length of each spline step in the east-west direction  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: 4 \* east-west resolution  
    **ns_step** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Length of each spline step in the north-south direction  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: 4 \* north-south resolution  
    **lambda_g** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Regularization weight in gradient evaluation  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0.01*  
    **tgh** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;High gradient threshold for edge classification  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *6*  
    **tgl** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Low gradient threshold for edge classification  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *3*  
    **theta_g** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Angle range for same direction detection  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *0.26*  
    **lambda_r** : float, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Regularization weight in residual evaluation  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *2*  
    **flags** : str, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allowed values: *e*  
    &nbsp;&nbsp;&nbsp;&nbsp;**e**  
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Estimate point density and distance and quit  
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Estimate point density and distance in map units for the input vector points within the current region extents and quit  
    **overwrite** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Allow output files to overwrite existing files  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **verbose** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Verbose module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **quiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*  
    **superquiet** : bool, *optional*  
    &nbsp;&nbsp;&nbsp;&nbsp;Very quiet module output  
    &nbsp;&nbsp;&nbsp;&nbsp;Default: *None*

## DESCRIPTION

*v.lidar.edgedetection* is the first of three steps to filter LiDAR
data. The filter aims to recognize and extract attached and detached
object (such as buildings, bridges, power lines, trees, etc.) in order
to create a Digital Terrain Model.

In particular, this module detects the edge of each single feature over
the terrain surface of a LIDAR point surface. First of all, a bilinear
spline interpolation with a Tychonov regularization parameter is
performed. The gradient is minimized and the low Tychonov regularization
parameter brings the interpolated functions as close as possible to the
observations. Bicubic spline interpolation with Tychonov regularization
is then performed. However, now the curvature is minimized and the
regularization parameter is set to a high value. For each point, an
interpolated value is computed from the bicubic surface and an
interpolated gradient is computed from the bilinear surface. At each
point the gradient magnitude and the direction of the edge vector are
calculated, and the residual between interpolated and observed values is
computed. Two thresholds are defined on the gradient, a high threshold
**tgh** and a low one **tgl**. For each point, if the gradient magnitude
is greater than or equal to the high threshold and its residual is
greater than or equal to zero, it is labeled as an EDGE point. Similarly
a point is labeled as being an EDGE point if the gradient magnitude is
greater than or equal to the low threshold, its residual is greater than
or equal to zero, and the gradient to two of eight neighboring points is
greater than the high threshold. Other points are classified as TERRAIN.

The length (in mapping units) of each spline step is defined by
**ew_step** for the east-west direction and **ns_step** for the
north-south direction.

The output will be a vector map in which points has been classified as
TERRAIN, EDGE or UNKNOWN. This vector map should be the input of
*[v.lidar.growing](v.lidar.growing.md)* module.

## NOTES

In this module, an external table will be created which will be useful
for the next module of the procedure of LiDAR data filtering. In this
table the interpolated height values of each point will be recorded.
Also points in the output vector map will be classified as:

```sh
TERRAIN (cat = 1, layer = 1)
EDGE (cat = 2, layer = 1)
UNKNOWN (cat = 3, layer = 1)
```

The final result of the whole procedure (*v.lidar.edgedetection*,
*[v.lidar.growing](v.lidar.growing.md)*,
*[v.lidar.correction](v.lidar.correction.md)*) will be a point
classification in four categories:

```sh
TERRAIN SINGLE PULSE (cat = 1, layer = 2)
TERRAIN DOUBLE PULSE (cat = 2, layer = 2)
OBJECT SINGLE PULSE (cat = 3, layer = 2)
OBJECT DOUBLE PULSE (cat = 4, layer = 2)
```

## EXAMPLES

### Basic edge detection

```sh
# last return points
v.lidar.edgedetection input=vector_last output=edge ew_step=8 ns_step=8 lambda_g=0.5
```

### Complete workflow

```sh
# region settings (using an existing raster)
g.region raster=elev_lid792_1m

# import
v.in.pdal -r input=points.las output=points
v.in.pdal -r input=points.las output=points_first return_filter=first

# detection
v.lidar.edgedetection input=points output=edge ew_step=8 ns_step=8 lambda_g=0.5
v.lidar.growing input=edge output=growing first=points_first
v.lidar.correction input=growing output=correction terrain=only_terrain

# visualization of selected points
# zoom somewhere first, to make it faster
d.rast map=orthophoto
d.vect map=correction layer=2 cats=2,3,4 color=red size=0.25
d.vect map=correction layer=2 cats=1 color=0:128:0 size=0.5

# interpolation (this may take some time)
v.surf.rst input=only_terrain elevation=terrain

# get object points for 3D visualization
v.extract input=correction layer=2 cats=2,3,4 output=objects
```

![Example output from complete workflow](v_lidar_edgedetection.png)  
*Figure 1: Example output from complete workflow (red: objects, green:
terrain)*

![3D visualization of filtered object points](v_lidar_edgedetection_objects.png)  
*Figure 2: 3D visualization of filtered object points (red) and terrain
created from terrain points (gray)*

## REFERENCES

- Antolin, R. et al., 2006. Digital terrain models determination by
  LiDAR technology: Po basin experimentation. Bolletino di Geodesia e
  Scienze Affini, anno LXV, n. 2, pp. 69-89.
- Brovelli M. A., Cannata M., Longoni U.M., 2004. LIDAR Data Filtering
  and DTM Interpolation Within GRASS, Transactions in GIS, April 2004,
  vol. 8, iss. 2, pp. 155-174(20), Blackwell Publishing Ltd.
- Brovelli M. A., Cannata M., 2004. Digital Terrain model reconstruction
  in urban areas from airborne laser scanning data: the method and an
  example for Pavia (Northern Italy). Computers and Geosciences
  30 (2004) pp.325-331
- Brovelli M. A. and Longoni U.M., 2003. Software per il filtraggio di
  dati LIDAR, Rivista dell'Agenzia del Territorio, n. 3-2003, pp. 11-22
  (ISSN 1593-2192).
- Brovelli M. A., Cannata M. and Longoni U.M., 2002. DTM LIDAR in area
  urbana, Bollettino SIFET N.2, pp. 7-26.
- Performances of the filter can be seen in the [ISPRS WG III/3
  Comparison of Filters](https://www.itc.nl/isprs/wgIII-3/filtertest/)
  report by Sithole, G. and Vosselman, G., 2003.

## SEE ALSO

*[v.lidar.growing](v.lidar.growing.md),
[v.lidar.correction](v.lidar.correction.md),
[v.surf.bspline](v.surf.bspline.md), [v.surf.rst](v.surf.rst.md),
[v.in.pdal](v.in.pdal.md), [v.in.ascii](v.in.ascii.md)*

## AUTHORS

Original version of program in GRASS 5.4:  
Maria Antonia Brovelli, Massimiliano Cannata, Ulisse Longoni and Mirko
Reguzzoni  
  
Update for GRASS 6.X:  
Roberto Antolin and Gonzalo Moreno

## SOURCE CODE

Available at: [v.lidar.edgedetection source code](https://github.com/OSGeo/grass/tree/main/vector/v.lidar.edgedetection)
([history](https://github.com/OSGeo/grass/commits/main/vector/v.lidar.edgedetection))  
Latest change: Friday May 09 14:33:40 2025 in commit [b356c7e](https://github.com/OSGeo/grass/commit/b356c7e108fcbeca77474c8e83ebec8f1e7b3e4a)
