|
1 | 1 | # Code supplement: Towards National-Scale Ecological Applications: Harmonised framework for LiDAR point cloud processing for vegetation metrics calculation |
| 2 | + |
2 | 3 | Code supplement: Towards National-Scale Ecological Applications: Harmonised framework for LiDAR point cloud processing for vegetation metrics calculation |
| 4 | + |
| 5 | +# Preprocessing workflow |
| 6 | + |
| 7 | +## DB Setup |
| 8 | + |
| 9 | +<ol> |
| 10 | + <li> |
| 11 | + Create 3 tables in Postgresql. The sql script can be found under /setup/db. |
| 12 | + |
| 13 | + </li> |
| 14 | +</ol> |
| 15 | + |
| 16 | +## Installation |
| 17 | +<ol> |
| 18 | +<li> create virtual environment |
| 19 | +``` |
| 20 | +micromamba create -n myenv -f ./micromamba_env.yaml |
| 21 | +``` |
| 22 | +</li> |
| 23 | +<li> poetry install |
| 24 | +``` |
| 25 | +micromamba activate myenv |
| 26 | +poetry install |
| 27 | +``` |
| 28 | +</li> |
| 29 | +<li> It will create a executable scripts under the env's bin folder which you can call directly. |
| 30 | + |
| 31 | +<ol> |
| 32 | +- To run the processing in normal mode: |
| 33 | +``` |
| 34 | +lidarprocessing -c <config yaml> -i <identifier> |
| 35 | +``` |
| 36 | + |
| 37 | +- To run the processing in recovery mode: |
| 38 | +``` |
| 39 | +lidarprocessing -c <config yaml> -r <identifier> |
| 40 | +``` |
| 41 | +</ol> |
| 42 | +</li> |
| 43 | + |
| 44 | +</ol> |
| 45 | + |
| 46 | +## How it works? |
| 47 | + |
| 48 | +### Processing with individual laz file |
| 49 | + |
| 50 | +The processing for laz file consist of 2 steps (/model/processing_script) |
| 51 | + |
| 52 | +- fix laz file [fix_laz.py](lidar_processor/model/processing_script/fix_laz_file.py): |
| 53 | + 1. Remove overlapping points |
| 54 | + 2. Assign correct CRS (EPSG:3301) |
| 55 | + 3. Writes out the fixed file in LAZ version 1.4 |
| 56 | + |
| 57 | +- reclassification [reclassify_laz_file.py](lidar_processor/model/processing_script/reclassify_laz_file.py) |
| 58 | + 1. Identification of points within sea polygons (Estonian Topographic Database (ETD) layer `E_201_meri_a`) with the binary attribute `WithinSea` assigned. |
| 59 | + 2. Identification of points within 13 m buffers of high voltage (110, 220 or 330 kV) powerlines (ETD layer `E_601_elektriliin_j`) with the binary attribute `WithinPowerline` assigned. |
| 60 | + 3. Identification of points within inland waterbody polygons (ETD layers `E_202_seisuveekogu_a`, `E_203_vooluveekogu_a`) with the binary attribute `WithinWaterBody` assigned. |
| 61 | + 4. Identification of points located within building polygons (ETD layers `E_401_hoone_ka` and `E_403_muu_rajatis_ka`), with the binary attribute `WithinBuilding` assigned. |
| 62 | + 5. Calculating NDVI for each point by 1) using a seasonal NDVI raster as input for the PDAL function `filters.hag_dem` to calculate a temporary `HeightAboveGround` (HAG) attribute by subtracting NDVI from Z, 2) copying this temporary HAG into a new attribute called `NDVI` and 3) subtracting NDVI from Z to retrieve the original NDVI raster values. We used this workaround because there was no direct way to add NDVI values to the point cloud. |
| 63 | + 6. Calculation of actual `HeightAboveGround` using the corresponding 1 m DTM (including support for VRT input) to overwrite the temporary HAG from the previous step. |
| 64 | + 7. Assignment of new classification values based on defined rules, leveraging attributes added in the previous steps, while preserving original classifications in the attribute `OriginalClassification`. |
| 65 | + |
| 66 | +The above 2 steps can be run individually by : |
| 67 | + |
| 68 | +<ol> |
| 69 | +<li> |
| 70 | + |
| 71 | +```bash |
| 72 | +# fix_laz_file.py input_file output_file |
| 73 | +python lidar_processor.model.processing_script.fix_laz_file 447696_2019_tava.laz 447696_2019_tava_fixed.laz |
| 74 | +``` |
| 75 | +</li> |
| 76 | + |
| 77 | +</l> |
| 78 | + |
| 79 | +```bash |
| 80 | +# reclassify_laz_file.py input_file output_file dem_file etak_file |
| 81 | +python lidar_processor.model.processing_script.reclassify_laz_file 447696_2019_tava_fixed.laz 447696_2019_tava_reclassified.laz 54494_dem_1m_2017-2020.tif ETAK_EESTI_GPKG_2019_01_01/ETAK_EESTI_GPKG.gpkg |
| 82 | +``` |
| 83 | +</li> |
| 84 | +</ol> |
| 85 | + |
| 86 | +### Processing with batch laz files |
| 87 | + |
| 88 | +Since there are over millions of laz files to process, so it is need to keep track on the state for each file. |
| 89 | +The batch processing consist of 4 state : |
| 90 | + |
| 91 | +| state | process | failing state | |
| 92 | +|:-----:|---------------------------|:-------------:| |
| 93 | +| 0 | initial (record creation) | Null | |
| 94 | +| 1 | laz/dem file downloaded | -1 | |
| 95 | +| 2 | laz file fixed | -2 | |
| 96 | +| 3 | laz file reclassified | -3 | |
| 97 | + |
| 98 | +And the state will change according to the following diagram |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | +Config file example: |
| 103 | +```python |
| 104 | + |
| 105 | +db: |
| 106 | + dbname: 'dbname' |
| 107 | + db_schema: 'lidar_processing' |
| 108 | + user: 'user' |
| 109 | + password: 'xxxxxx' |
| 110 | + host: 'localhost' |
| 111 | + port: 5432 |
| 112 | +storage: |
| 113 | + gsjson: 'google_auth_json' |
| 114 | + bucket: 'gs://bucket' |
| 115 | + laz_path: 'test_lidar_processing/LAZ' |
| 116 | + fix_path: 'test_lidar_processing/LAZ_fixed' |
| 117 | + reclassify_path: 'test_lidar_processing/Reclassified' |
| 118 | + dem_path: 'test_lidar_processing/DTM' |
| 119 | + etak_path: './ETAK' |
| 120 | +lidar: |
| 121 | + laz_mapsheets: [ 'laz_map_sheets_#' ] |
| 122 | + laz_to_crs: '' |
| 123 | + laz_year: 2017 |
| 124 | + laz_type: 'tava' |
| 125 | + dem_year: 2017 |
| 126 | + |
| 127 | +``` |
| 128 | + |
| 129 | +If any exception occurs during the batch processing, at the end of the log, it should shows that recovery is needed. |
| 130 | + |
| 131 | +Then, to recover for that particular job, just run lidarprocessing with `-r` option follow by the identifier name. |
0 commit comments