Miroslav Simko <ms@iolabs.ch> 2026-09-01T10:49:18+02:00
Commit #110 ยท 8 snippets
.../bright_points_filter.py | 23 ++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
| 272 | points_on_road_file: Path to a '*_road_surface.npz' file containing | 272 | points_on_road_file: Path to a '*_road_surface.npz' file containing |
| 273 | arrays: 'points', 'intensity', 'scan_angle', and normally | 273 | arrays: 'points', 'intensity', 'scan_angle', and normally |
| 274 | 'red', 'green', 'blue'. RGB may be omitted only when | 274 | 'red', 'green', 'blue'. RGB may be omitted only when |
| 275 | config['allow_missing_rgb'] is True and the selected filter mode | 275 | config['allow_missing_rgb'] is True and the selected filter mode |
| 276 | does not depend on color. | 276 | does not depend on color. 'number_of_returns' is optional; when |
| 277 | absent it is filled with zeros ("unknown"), never defaulted to 1. | ||
| 277 | output_dir: Optional directory where generated Step 5 artifacts should be | 278 | output_dir: Optional directory where generated Step 5 artifacts should be |
| 278 | written. When omitted, outputs are written beside the input file. | 279 | written. When omitted, outputs are written beside the input file. |
| 279 | 280 | ||
| 280 | Saves: | 281 | Saves: |
| 281 | - '<base>_<filter_mode>.pdf': diagnostic plots (histogram for simple cutoff, | 282 | - '<base>_<filter_mode>.pdf': diagnostic plots (histogram for simple cutoff, |
| 282 | slice fits and cutoff curve for angle-based modes). | 283 | slice fits and cutoff curve for angle-based modes). |
| 283 | - '<base>_bright_filtered.npz': filtered arrays: | 284 | - '<base>_bright_filtered.npz': filtered arrays: |
| 284 | 'points', 'scan_angle', 'intensity', 'red', 'green', 'blue'. | 285 | 'points', 'scan_angle', 'intensity', 'red', 'green', 'blue', |
| 286 | 'number_of_returns'. | ||
| 285 | - '<base>_bright_filtered.ply' (optional): written when | 287 | - '<base>_bright_filtered.ply' (optional): written when |
| 286 | config['save_bright_points_pcd'] is True. Points colored by intensity (greyscale). | 288 | config['save_bright_points_pcd'] is True. Points colored by intensity (greyscale). |
| 287 | - '<stem>_laser_intensity_delta.ply' / '<stem>_laser_intensity_delta_sigma.ply' (optional): | 289 | - '<stem>_laser_intensity_delta.ply' / '<stem>_laser_intensity_delta_sigma.ply' (optional): |
| 288 | written when config['save_all_delta_ply'] is True AND filter_mode is 'laser_intensity'. | 290 | written when config['save_all_delta_ply'] is True AND filter_mode is 'laser_intensity'. |
| 419 | points = data["points"] | 421 | points = data["points"] |
| 420 | intensity = data["intensity"] | 422 | intensity = data["intensity"] |
| 421 | scan_angle = data["scan_angle"] | 423 | scan_angle = data["scan_angle"] |
| 422 | 424 | ||
| 425 | if "number_of_returns" in data_keys: | ||
| 426 | number_of_returns = np.asarray( | ||
| 427 | data["number_of_returns"], dtype=color_intensity_data.NUMBER_OF_RETURNS_DTYPE | ||
| 428 | ) | ||
| 429 | else: | ||
| 430 | # Pre-AI3D-382 inputs lack the key; 0 reads as "unknown" per | ||
| 431 | # ColorIntensityData's contract. Never default to 1. | ||
| 432 | number_of_returns = np.zeros( | ||
| 433 | int(points.shape[0]), dtype=color_intensity_data.NUMBER_OF_RETURNS_DTYPE | ||
| 434 | ) | ||
| 435 | |||
| 423 | missing_rgb = [key for key in rgb_keys if key not in data_keys] | 436 | missing_rgb = [key for key in rgb_keys if key not in data_keys] |
| 424 | if not missing_rgb: | 437 | if not missing_rgb: |
| 425 | red = data["red"] | 438 | red = data["red"] |
| 426 | green = data["green"] | 439 | green = data["green"] |
| 456 | green=green, | 469 | green=green, |
| 457 | blue=blue, | 470 | blue=blue, |
| 458 | intensity=intensity, | 471 | intensity=intensity, |
| 459 | scan_angle_rank=scan_angle, | 472 | scan_angle_rank=scan_angle, |
| 473 | number_of_returns=number_of_returns, | ||
| 460 | ) | 474 | ) |
| 461 | 475 | ||
| 462 | def _process_with_angle_slice_fitting( | 476 | def _process_with_angle_slice_fitting( |
| 463 | self, | 477 | self, |
| 626 | intensity=color_data.intensity, | 640 | intensity=color_data.intensity, |
| 627 | red=color_data.red, | 641 | red=color_data.red, |
| 628 | green=color_data.green, | 642 | green=color_data.green, |
| 629 | blue=color_data.blue, | 643 | blue=color_data.blue, |
| 644 | number_of_returns=color_data.number_of_returns, | ||
| 630 | ) | 645 | ) |
| 631 | return | 646 | return |
| 632 | 647 | ||
| 633 | if self.config.get("save_bright_points_pcd", False): | 648 | if self.config.get("save_bright_points_pcd", False): |
| 676 | intensity=color_data.intensity, | 691 | intensity=color_data.intensity, |
| 677 | red=color_data.red, | 692 | red=color_data.red, |
| 678 | green=color_data.green, | 693 | green=color_data.green, |
| 679 | blue=color_data.blue, | 694 | blue=color_data.blue, |
| 695 | number_of_returns=color_data.number_of_returns, | ||
| 680 | ) | 696 | ) |
| 681 | 697 | ||
| 682 | logger.info( | 698 | logger.info( |
| 683 | f"Saved filtered data from {points.shape[0]} points to {output_npz}" | 699 | f"Saved filtered data from {points.shape[0]} points to {output_npz}" |
| 817 | intensity=color_data.intensity, | 833 | intensity=color_data.intensity, |
| 818 | red=color_data.red, | 834 | red=color_data.red, |
| 819 | green=color_data.green, | 835 | green=color_data.green, |
| 820 | blue=color_data.blue, | 836 | blue=color_data.blue, |
| 837 | number_of_returns=color_data.number_of_returns, | ||
| 821 | ) | 838 | ) |
| 822 | logger.info( | 839 | logger.info( |
| 823 | f"Saved filtered data from {points.shape[0]} points to {output_npz}" | 840 | f"Saved filtered data from {points.shape[0]} points to {output_npz}" |
| 824 | ) | 841 | ) |
| 923 | intensity=filtered_color_data.intensity, | 940 | intensity=filtered_color_data.intensity, |
| 924 | red=filtered_color_data.red, | 941 | red=filtered_color_data.red, |
| 925 | green=filtered_color_data.green, | 942 | green=filtered_color_data.green, |
| 926 | blue=filtered_color_data.blue, | 943 | blue=filtered_color_data.blue, |
| 944 | number_of_returns=filtered_color_data.number_of_returns, | ||
| 927 | ) | 945 | ) |
| 928 | return | 946 | return |
| 929 | 947 | ||
| 930 | # Optionally save PLY file with greyscale intensity coloring | 948 | # Optionally save PLY file with greyscale intensity coloring |
| 958 | intensity=filtered_color_data.intensity, | 976 | intensity=filtered_color_data.intensity, |
| 959 | red=filtered_color_data.red, | 977 | red=filtered_color_data.red, |
| 960 | green=filtered_color_data.green, | 978 | green=filtered_color_data.green, |
| 961 | blue=filtered_color_data.blue, | 979 | blue=filtered_color_data.blue, |
| 980 | number_of_returns=filtered_color_data.number_of_returns, | ||
| 962 | ) | 981 | ) |
| 963 | 982 | ||
| 964 | logger.info( | 983 | logger.info( |
| 965 | f"Saved filtered data from {len(filtered_points):,} points to {output_npz}" | 984 | f"Saved filtered data from {len(filtered_points):,} points to {output_npz}" |