Program with graphical user interface for analyzing and evaluating field heights over time captured by LiDAR on a drone.
In main-part1.py program for each las file in data folder:
- Loads 3D
lasfile - Removes 3D points with bigger value than 99.9% quantile and lower than 0.1% quantile
- Subtracts minimal
X,Y,Zvalue and saves that values intoinfo.json - Normalizes
X,Yaxes, then scales them byWH_SCALEfactor - Normalizes
Zaxis, then scales it to 16bit image - Uses dynamic averaging - multiple 3D points at the same position in pixel grid are averaged, then 3D point count is visualized in
1_count.png
- Converts 3D data into 2D pixel grid, saves it into
1_original.png
- Makes median of
1_original.pngthat ignores zeroes when calculating median and then every black pixel replaces with median value => maximizes information from just few 3D points. Then saves it into2_median.png
In main-part2.py then for last image in time series:
- User rotates image using GUI, so that longer sides of blocks of field are vertical, program saves it into
3_rotated.png
- User selects field for analysis from rotated image using GUI, program saves it into
4_cropped.png
- Program automatically rotates and crops all other images
In main-part3.py program:
- Sums all images into one image, saves it into
0_sum.png
- Sums summed image over vertical axis, applies log for better processing, saves it into
blocks_sum.png
- Detects starting and ending edges of blocks using first derivative, saves it into
blocks_derivative.png
- Separates each block into separate image, saves example output in new folder - e.g.
block_1/0_block.png
- Split block into upper and bottom part
For upper and bottom part program:
- Sums block over vertical axis, applies log for better processing, e.g. saves it into
block_1/fit_up_sum.png
- Detects starting and ending edges of sub-blocks using first derivative, e.g. saves it into
block_1/fit_up_derivative.png
Then program puts upper and bottom edge detections together and:
- Detects deformation
- Removes deformation
- Applies local maxima filter (with kernel size 1/10 sub-block width)
Finally, for each sub-block program:
-
Subtracts from it the same sub-block from first las file (the earliest record in time series when nothing has grown yet = terrain)
-
Computes:
- Mean
- Standard deviation
- Median
- Minimum
- Maximum
- Quantiles - 1%, 5%, 25%, 75%, 95%, 99%
- Relative growth rate using formula:
-
Some keys saves into
statistics.csv -
Key enumerating image is saved into
4_cropped_draw.png
Matlab program fits sigmoid for each growth curve with parameters A, B, C:
Visualization of sigmoid of sub-blocks for block 1:
Visualization of sigmoid of sub-blocks for block 2:
Visualization of sigmoid of sub-blocks for block 3:
Visualization with treatment ID of parameter A ("maximum crop height"):
Visualization with treatment ID of parameter B ("growth velocity"):
Visualization with treatment ID of parameter C ("growth onset"):
Reference height validation is important for understanding how much is LiDAR accurate. It is determined by subtracting LiDAR measured height from referenced height measured manually.
| Metric | Value [m] | Value of absolute error [m] |
|---|---|---|
| Mean | 0.0050 | 0.0410 |
| STD | 0.0523 | 0.0325 |
| Median | 0.0062 | 0.0334 |
| Q25 | -0.0252 | 0.0144 |
| Q75 | 0.0359 | 0.0579 |
| Min | -0.1335 | 0.0020 |
| Max | 0.1312 | 0.1335 |
| RMSD | 0.0522 | - |
Lower white values were measured by LiDAR and upper yellow values were measured manually.
Image example:
calibration- calibrationlasortxtfilesdata- input folder forlasfiles210420_065626.las- datetime in filenameYYMMDD_HHMMSS *.las, e.g.:210504_064914.las- ...
results- output folder210420_065626- match with filename from data without extension1_count.png1_original.png2_median.png3_rotated.png- ...
210504_064914- ...
terrain.png- fixed terrain height stability over timeterrain_image.png- visualized fixed cropped terrainheight_diff_histogram.png- difference between reference and measured heights plotted in histogramheight_diff_image.png- difference between reference and measured heights plotted in imagestatistics.csv- all output statistics from Python scripts for visualization and evaluationinfo.json- all computed information used internally to share between scripts
toolscompress.py- Python script to compresses images for documentationvalidate_heights.py- Python script to validate manually measured reference heights with LiDAR heightsvalidate_terrain.py- Python script to validate terrain height stability over timevisualize.py- Python script that visualizes Matlab's sigmoid fit parameters for each sub-block into imagevisualize_sigmoid.py- Python script that visualizes Matlab's sigmoid fits for each sub-block
main.c- optimized C script for converting 3D las data to 2D image and computing medianmain-part1.py- Python wrapper for C scriptmain-part2.py- User GUI for precise field rotation and field selectionmain-part3.py- Python script for analysisinit.py- constants + common block of codes
Code is also optimized for speed. Critical parts of code are written in C and compiled with gcc compiler. On low budget PC it takes lower tens of seconds. The most of the time takes loading big unprocessed las files.
Compared to existing solutions, this program is about 100x faster even when using just single core of CPU.
sudo apt update
sudo apt install python3 python3-pip build-essentialpython3 -m pip install -r requirements.txtgcc -shared -o main.so main.c- Setup working directory as
/project/root/path - Paste/move your las files into data folder (match folder and file structure)
- Run
python3 main-part1.pyto generate images - Run
python3 main-part2.py- Rotate image using arrows, so field blocks lines are vertical
- Press enter or key q
- Select upper left corner using arrows to crop
- Press enter or key q
- Select bottom right corner using arrows to crop
- Press enter or key q
- Run
python3 main-part3.pyto create analysis - Results are in
resultsfolder - Run Matlab code
To run validation, you need to have las or txt file with reference heights. Then you can save them into calibration folder. Then paste this to terminal: python3 tools/validate_heights.py
- MacOS 12 Python 3.8
- Ubuntu 22.04 Python 3.10
- Optimize for multicore processors
- Optimize for low RAM computers
- Object Oriented Programming?
- Python classes for dicts with standardized keys¨
- More robust sub-field search?
- Find missing peaks by fitting periodic function?
- Auto crop black padding at the ends?
























