AI Slop Code RIsk Monitor

OpenDroneMap/ODM

A command line toolkit to generate maps, point clouds, 3D models and DEMs from drone, balloon or kite images. 📷

18.6 Elevated pattern signal View on GitHub

Maintenance and Governance Review

This report summarizes scanner evidence for OpenDroneMap/ODM, a Python project with 6,518 GitHub stars. SynthScan examined 24,426 lines of code across 181 source files, recording 369 pattern matches distributed across 13 syntactic categories. The legacy adjusted pattern signal is 18.6 (Elevated pattern signal); it is not an authorship estimate.

Use the findings to ask whether maintainers can explain intent, verify dependencies, simplify unnecessary scaffolding, and focus review effort. Risk Payload v1 adds ownership, supply-chain, over-engineering, and review-effort vectors when available. These are prompts for human verification, not probabilities, security findings, or measured maintenance costs.

18.6
Adjusted Signal
18.6
Raw Pattern Score
100%
Time Factor
2026-09-16
Last Push
6.5K
Stars
Python
Language
24.4K
Lines of Code
181
Files
369
Pattern Hits
2026-10-12
Scan Date
0.04
HC Hit Rate

Risk Review · v3

Use each vector to guide manual verification of the underlying findings.

Cognitive Ownership Risk 31.5/100 · MEDIUM

Can maintainers explain intent, assumptions, and trade-offs? 168 finding(s).

Hallucinated Dependency & Supply Chain Risk 20.3/100 · LOW

Are imports declared and package/API names verified? 92 finding(s).

Agent Over-Engineering Ratio 36.3/100 · MEDIUM

Are wrappers, guards, and repeated structures necessary? 166 finding(s).

PR Review Velocity Impact 62.5/100 · HIGH

Which changes need focused human review? 369 finding(s).

What These Metrics Mean

Adjusted Signal
Legacy pattern score normalized per 1,000 scanned lines and multiplied by the repository-level time factor. It is not an estimate of AI authorship.
Raw Pattern Score
Sum of severity- and context-weighted pattern findings before applying the time factor.
Time Factor
A coarse multiplier based on repository last-push metadata. It does not identify when individual code was written.
Pattern Hits
Count of configured pattern findings. Review each location and surrounding code before acting.
HC Hit Rate
High- and critical-severity findings per scanned file. Severity is a configured detector weight, not proof of a vulnerability or authorship.
Lines / Files
Scan coverage denominators used by the legacy normalized score.

Pattern-Signal History

This chart tracks the legacy adjusted pattern score across scan runs. Changes can reflect source changes, scan coverage, or detector/scoring versions; they do not measure AI adoption or prove that a team refactored code. Compare runs only when their scoring versions are compatible. The dashed line tracks the raw pattern-hit count.

Severity Breakdown

Groups findings by configured severity weight. Severity is not a confidence estimate, security rating, or proof that a package is missing. Verify imports against the project's manifests and inspect each finding in its local design context.

CRITICAL 0HIGH 8MEDIUM 35LOW 326

Directory Score Breakdown

This horizontal bar chart shows where configured pattern scores accumulate across directories. Treat the bars as locations to inspect, not as evidence of authorship or code quality. Use the file-level findings to decide whether a directory needs a focused ownership, dependency, complexity, or review check.

Pattern Findings

The scanner identified 369 distinct pattern matches across 13 syntactic categories. Each entry below represents a discrete location in the source code where the engine recorded a detector match to inspect in context. Expand any category row to inspect the individual file paths, line numbers, code snippets, and the lexical context (CODE, COMMENT, or STRING) in which each match was detected.

Reading the findings table: The Severity column indicates the configured finding weight (CRITICAL / HIGH / MEDIUM / LOW). The Context column identifies whether the match occurred inside executable code, an inline comment, or a string literal — legacy comment-context matches receive a ×1.5 score weight. The ⚡ bolt icon marks clustered matches: three or more patterns within a 10-line window, each receiving an additional ×1.5 density multiplier under the legacy scoring model.

Excessive Try-Catch Wrapping96 hits · 114 pts
SeverityFileLineSnippetContext
LOWstages/odm_postprocess.py22 except Exception as e:CODE
LOWstages/odm_georeferencing.py82 except Exception as e:CODE
LOWstages/odm_georeferencing.py146 except Exception as e:CODE
LOWstages/odm_georeferencing.py222 except Exception as e:CODE
LOWstages/odm_georeferencing.py236 except Exception as e:CODE
LOWstages/odm_georeferencing.py250 except Exception as e:CODE
LOWstages/mvstex.py139 except Exception as e:CODE
LOWstages/mvstex.py159 except Exception as e:CODE
LOWstages/dataset.py59 except Exception as e:CODE
LOWstages/dataset.py120 except Exception as e:CODE
LOWstages/dataset.py149 except Exception as e:CODE
LOWstages/dataset.py236 except Exception as e:CODE
LOWstages/dataset.py277 except Exception as e:CODE
MEDIUMstages/dataset.py226def parallel_sky_filter(item):CODE
MEDIUMstages/dataset.py267def parallel_bg_filter(item):CODE
LOWstages/splitmerge.py227 except Exception as e:CODE
LOWstages/odm_app.py116 except Exception as e:CODE
MEDIUMstages/odm_app.py80def execute(self):CODE
LOWtests/test_remote.py88 except Exception as e:CODE
MEDIUMtests/test_remote.py75def monitor():CODE
LOWcontrib/fix_ply/fix_ply.py20 except Exception as e:CODE
LOWcontrib/fix_ply/fix_ply.py46 except Exception as e:CODE
MEDIUMcontrib/resize/resize.py82 print("Error: Cannot resize {}: {}.".format(image_path, str(e)))CODE
MEDIUMcontrib/resize/resize.py110 print("Error: Cannot resize {}: {}.".format(gcp_path, str(e)))CODE
LOWopendm/cropper.py64 except Exception as e:CODE
LOWopendm/arghelpers.py37 except Exception as e:CODE
MEDIUMopendm/arghelpers.py33def save_opts(opts_json, args):CODE
LOWopendm/ogctiles.py34 except Exception as e:CODE
LOWopendm/ogctiles.py55 except Exception as e:CODE
LOWopendm/ogctiles.py69 except Exception as e:CODE
LOWopendm/ogctiles.py101 except Exception as e:CODE
LOWopendm/entwine.py34 except Exception as e:CODE
LOWopendm/entwine.py100 except Exception as e:CODE
LOWopendm/opc.py29 except Exception as e:CODE
LOWopendm/thermal.py68 except Exception as e:CODE
LOWopendm/config.py178 except Exception as e:CODE
LOWopendm/log.py145 except Exception as e:CODE
LOWopendm/remote.py48 except Exception as e:CODE
LOWopendm/remote.py172 except Exception as e:CODE
LOWopendm/remote.py207 except Exception as e:CODE
LOWopendm/remote.py320 except Exception as e:CODE
LOWopendm/remote.py327 except Exception as e:CODE
LOWopendm/remote.py420 except Exception as e:CODE
MEDIUMopendm/remote.py316def _process_local(self, done):CODE
MEDIUMopendm/remote.py323def _process_remote(self, done):CODE
LOWopendm/pseudogeo.py29 except Exception as e:CODE
LOWopendm/ai.py59 except Exception as e:CODE
LOWopendm/net.py108 except Exception as e:CODE
LOWopendm/concurrency.py56 except Exception as e:CODE
LOWopendm/gltf.py307 except Exception as e:CODE
LOWopendm/types.py452 except Exception as e:CODE
MEDIUMopendm/types.py237def georeference_with_gps(self, images_path, output_coords_file, output_model_txCODE
LOWopendm/mesh.py107 except Exception as e:CODE
LOWopendm/mesh.py176 except Exception as e:CODE
LOWopendm/utils.py96 except Exception as e:CODE
LOWopendm/utils.py157 except Exception as e:CODE
MEDIUMopendm/utils.py107def rm_r(path):CODE
LOWopendm/cogeo.py49 except Exception as e:CODE
LOWopendm/exiftool.py44 except Exception as e:CODE
LOWopendm/exiftool.py50 except Exception as e:CODE
36 more matches not shown…
Unused Imports87 hits · 86 pts
SeverityFileLineSnippetContext
LOWstages/odm_meshing.py1CODE
LOWstages/odm_meshing.py6CODE
LOWstages/odm_meshing.py8CODE
LOWstages/run_opensfm.py1CODE
LOWstages/run_opensfm.py9CODE
LOWstages/run_opensfm.py11CODE
LOWstages/odm_filterpoints.py6CODE
LOWstages/odm_postprocess.py3CODE
LOWstages/odm_dem.py1CODE
LOWstages/odm_dem.py2CODE
LOWstages/odm_dem.py7CODE
LOWstages/odm_georeferencing.py3CODE
LOWstages/odm_georeferencing.py4CODE
LOWstages/odm_georeferencing.py17CODE
LOWstages/odm_georeferencing.py23CODE
LOWstages/dataset.py11CODE
LOWstages/dataset.py12CODE
LOWstages/openmvs.py1CODE
LOWstages/openmvs.py7CODE
LOWstages/openmvs.py12CODE
LOWstages/odm_app.py3CODE
LOWstages/odm_app.py4CODE
LOWstages/odm_app.py5CODE
LOWtests/test_camera.py1CODE
LOWtests/test_photo.py2CODE
LOWtests/test_photo.py3CODE
LOWtests/test_gcp.py1CODE
LOWtests/test_remote.py6CODE
LOWcontrib/fix_ply/fix_ply.py4CODE
LOWscripts/smoke.py36CODE
LOWscripts/smoke.py43CODE
LOWscripts/smoke.py43CODE
LOWopendm/cropper.py1CODE
LOWopendm/geo.py1CODE
LOWopendm/shots.py2CODE
LOWopendm/ogctiles.py2CODE
LOWopendm/ogctiles.py6CODE
LOWopendm/entwine.py2CODE
LOWopendm/entwine.py8CODE
LOWopendm/point_cloud.py1CODE
LOWopendm/point_cloud.py1CODE
LOWopendm/point_cloud.py8CODE
LOWopendm/point_cloud.py10CODE
LOWopendm/point_cloud.py11CODE
LOWopendm/concurrency.py2CODE
LOWopendm/bgfilter.py2CODE
LOWopendm/types.py14CODE
LOWopendm/mesh.py1CODE
LOWopendm/mesh.py2CODE
LOWopendm/mesh.py2CODE
LOWopendm/mesh.py2CODE
LOWopendm/mesh.py7CODE
LOWopendm/mesh.py8CODE
LOWopendm/mesh.py9CODE
LOWopendm/mesh.py10CODE
LOWopendm/location.py3CODE
LOWopendm/utils.py11CODE
LOWopendm/exiftool.py8CODE
LOWopendm/osfm.py5CODE
LOWopendm/osfm.py7CODE
27 more matches not shown…
Deep Nesting78 hits · 74 pts
SeverityFileLineSnippetContext
LOWstages/odm_orthophoto.py19CODE
LOWstages/run_opensfm.py23CODE
LOWstages/run_opensfm.py42CODE
LOWstages/odm_report.py40CODE
LOWstages/odm_filterpoints.py13CODE
LOWstages/odm_dem.py19CODE
LOWstages/odm_georeferencing.py28CODE
LOWstages/mvstex.py14CODE
LOWstages/dataset.py48CODE
LOWstages/openmvs.py16CODE
LOWstages/splitmerge.py23CODE
LOWstages/splitmerge.py210CODE
LOWstages/odm_app.py80CODE
LOWcontrib/orthorectify/orthorectify.py200CODE
LOWopendm/geo.py8CODE
LOWopendm/shots.py26CODE
LOWopendm/shots.py130CODE
LOWopendm/ogctiles.py14CODE
LOWopendm/thermal.py24CODE
LOWopendm/point_cloud.py15CODE
LOWopendm/point_cloud.py208CODE
LOWopendm/config.py154CODE
LOWopendm/align.py145CODE
LOWopendm/remote.py60CODE
LOWopendm/remote.py296CODE
LOWopendm/remote.py330CODE
LOWopendm/remote.py96CODE
LOWopendm/net.py14CODE
LOWopendm/net.py55CODE
LOWopendm/net.py71CODE
LOWopendm/io.py71CODE
LOWopendm/gltf.py14CODE
LOWopendm/gltf.py78CODE
LOWopendm/gltf.py128CODE
LOWopendm/types.py27CODE
LOWopendm/types.py130CODE
LOWopendm/types.py237CODE
LOWopendm/location.py116CODE
LOWopendm/camera.py4CODE
LOWopendm/camera.py33CODE
LOWopendm/utils.py82CODE
LOWopendm/utils.py122CODE
LOWopendm/exiftool.py10CODE
LOWopendm/exiftool.py54CODE
LOWopendm/exiftool.py55CODE
LOWopendm/osfm.py648CODE
LOWopendm/osfm.py776CODE
LOWopendm/osfm.py90CODE
LOWopendm/osfm.py134CODE
LOWopendm/osfm.py422CODE
LOWopendm/photo.py69CODE
LOWopendm/photo.py199CODE
LOWopendm/photo.py573CODE
LOWopendm/photo.py631CODE
LOWopendm/orthophoto.py42CODE
LOWopendm/orthophoto.py194CODE
LOWopendm/orthophoto.py266CODE
LOWopendm/gcp.py15CODE
LOWopendm/gcp.py174CODE
LOWopendm/multispectral.py177CODE
18 more matches not shown…
Hyper-Verbose Identifiers53 hits · 58 pts
SeverityFileLineSnippetContext
LOWstages/odm_report.py31def generate_point_cloud_stats(input_point_cloud, pc_info_file, rerun=False):CODE
LOWtests/test_photo.py48 def test_gps_std_missing_vertical(self):CODE
LOWtests/test_photo.py54 def test_gps_std_from_gps_accuracy(self):CODE
LOWtests/test_boundary.py24 def test_load_boundary_without_reprojection(self):CODE
LOWtests/test_boundary.py31 def test_load_boundary_reprojects_to_utm(self):CODE
LOW⚡tests/test_srtparser.py155 def test_coordinates_are_none_before_gps_lock(self):CODE
LOW⚡tests/test_srtparser.py161 def test_no_gps_before_first_lock(self):CODE
LOW⚡tests/test_srtparser.py165 def test_gps_after_lock_is_not_null_island(self):CODE
LOW⚡tests/test_srtparser.py171 def test_interpolates_between_fixes(self):CODE
LOW⚡tests/test_srtparser.py179 def test_unparseable_value_is_skipped(self):CODE
LOWtests/test_osfm.py57 def test_get_submodel_argv_dict(self):CODE
LOW⚡tests/test_cutline.py12 def test_largest_polygon_from_single_polygon(self):CODE
LOW⚡tests/test_cutline.py21 def test_largest_polygon_from_multipolygon_union(self):CODE
LOW⚡tests/test_cutline.py30 def test_polygon_writes_to_gpkg_with_polygon_schema(self):CODE
LOWcontrib/time-sift/Timesift_odm.py59 def clean_reconstruction_dict(subdict, key, images):STRING
LOWopendm/shots.py26def get_geojson_shots_from_opensfm(reconstruction_file, utm_srs=None, utm_offset=None, pseudo_geotiff=None, a_matrix=NonCODE
LOWopendm/boundary.py13def compute_boundary_from_shots(reconstruction_json, buffer=0, reconstruction_offset=(0, 0)):CODE
LOWopendm/dls.py86def __multilayer_transmission(phi, n, polarization=None):CODE
LOWopendm/pseudogeo.py13def add_pseudo_georeferencing(geotiff):CODE
LOWopendm/io.py71def path_or_json_string_to_dict(string):CODE
LOWopendm/rollingshutter.py67def get_rolling_shutter_readout(photo, override_value=0):CODE
LOWopendm/gltf.py78def convert_materials_to_jpeg(materials):CODE
LOWopendm/mesh.py136def screened_poisson_reconstruction(inPointCloud, outMesh, depth = 8, samples = 1, maxVertexCount=100000, pointWeight=4,CODE
LOWopendm/gsd.py102def opensfm_reconstruction_average_gsd(reconstruction_json, use_all_shots=False):CODE
LOWopendm/gsd.py173def calculate_gsd_from_focal_ratio(focal_ratio, flight_height, image_width):CODE
LOWopendm/location.py87def get_utm_zone_and_hemisphere_from(lon, lat):CODE
LOWopendm/camera.py33def get_opensfm_camera_models(cameras):CODE
LOWopendm/utils.py65def get_processing_results_paths():CODE
LOWopendm/exiftool.py10def extract_raw_thermal_image_data(image_path):CODE
LOWopendm/exiftool.py69def extract_temperature_params_from(tags):CODE
LOWopendm/osfm.py90 def check_merge_partial_reconstructions(self):CODE
LOWopendm/osfm.py502 def restore_reconstruction_backup(self):CODE
LOWopendm/osfm.py524 def add_shots_to_reconstruction(self, p2s):CODE
LOWopendm/photo.py680 def get_radiometric_calibration(self):CODE
LOWopendm/photo.py707 def get_vignetting_polynomial(self):CODE
LOWopendm/photo.py728 def get_horizontal_irradiance(self):CODE
LOWopendm/photo.py806 def override_camera_projection(self, camera_projection):CODE
LOWopendm/gpu.py12def has_popsift_and_can_handle_texsize(width, height):CODE
LOWopendm/multispectral.py287def compute_alignment_matrices(multi_camera, primary_band_name, images_path, s2p, p2s, max_concurrency=1, max_samples=30CODE
LOWopendm/multispectral.py297 def parallel_compute_homography(p):CODE
LOW⚡opendm/tiles/tiler.py20def generate_orthophoto_tiles(geotiff, output_dir, max_concurrency, resolution):CODE
LOW⚡opendm/tiles/tiler.py26def generate_colored_hillshade(geotiff):CODE
LOWopendm/tiles/gdal2tiles.py753def add_gdal_warp_options_to_string(vrt_string, warp_options):CODE
LOWopendm/tiles/gdal2tiles.py823def add_alpha_band_to_string_vrt(vrt_string):CODE
LOWopendm/tiles/gdal2tiles.py874def update_alpha_value_for_non_alpha_inputs(warped_vrt_dataset, options=None):CODE
LOWopendm/dem/pdal.py83def json_add_decimation_filter(json, step):CODE
LOWopendm/dem/pdal.py92def json_add_classification_filter(json, classification, equality="equals"):CODE
LOWopendm/dem/ground_rectification/point_cloud.py74 def get_extra_dimension_values(self, name):CODE
LOWopendm/dem/ground_rectification/bounds/types.py20 def percentage_of_points_inside(self, points):CODE
LOWopendm/dem/ground_rectification/bounds/types.py48 def percentage_of_points_inside(self, points):CODE
LOWopendm/dem/ground_rectification/bounds/utils.py5def calculate_convex_hull_bounds(points):CODE
LOW…ound_rectification/partition/surrounding_partitions.py49 def __find_points_for_non_surrounded_cluster(self, bounds, cluster_members, distance, min_area, min_points):CODE
LOWopendm/dem/ground_rectification/grid/builder.py24def __calculate_lonely_points(grid, point_cloud, distance):CODE
Decorative Section Separators10 hits · 30 pts
SeverityFileLineSnippetContext
MEDIUMSuperBuild/CMakeLists.txt118# ---------------------------------------------------------------------------------------------COMMENT
MEDIUMopendm/tiles/hsv_merge.py39# =============================================================================COMMENT
MEDIUMopendm/tiles/hsv_merge.py79# =============================================================================COMMENT
MEDIUMopendm/tiles/hsv_merge.py106# =============================================================================COMMENT
MEDIUMopendm/tiles/hsv_merge.py119# =============================================================================STRING
MEDIUMopendm/tiles/hsv_merge.py121# =============================================================================STRING
MEDIUM⚡opendm/tiles/gdal2tiles.py68# =============================================================================COMMENT
MEDIUM⚡opendm/tiles/gdal2tiles.py69# =============================================================================COMMENT
MEDIUM⚡opendm/tiles/gdal2tiles.py70# =============================================================================COMMENT
MEDIUMopendm/tiles/gdal2tiles.py1442 # -------------------------------------------------------------------------COMMENT
Cross-Language Confusion5 hits · 25 pts
SeverityFileLineSnippetContext
HIGHopendm/tiles/gdal2tiles.py2179 if (document.documentElement && document.documentElement.clientHeight)CODE
HIGHopendm/tiles/gdal2tiles.py2187 if (document.documentElement && document.documentElement.clientWidth)CODE
HIGHopendm/tiles/gdal2tiles.py2286 var url = document.location.toString();CODE
HIGHopendm/tiles/gdal2tiles.py2731 if (document.documentElement && document.documentElement.clientHeight)CODE
HIGHopendm/tiles/gdal2tiles.py2739 if (document.documentElement && document.documentElement.clientWidth)CODE
Self-Referential Comments7 hits · 19 pts
SeverityFileLineSnippetContext
MEDIUMopendm/cropper.py173 # Create a convex hull around the boundaryCOMMENT
MEDIUMopendm/context.py54# Define the number of coresCOMMENT
MEDIUMopendm/multispectral.py474 # Define the motion model, scale the initial warp matrix to smallest levelCOMMENT
MEDIUMopendm/tiles/gdal2tiles.py1016 # Create a KML file for this tile.COMMENT
MEDIUMopendm/tiles/gdal2tiles.py1132 # Create a KML file for this tile.COMMENT
MEDIUMopendm/dem/ground_rectification/rectify.py66 # Create a new point cloudCOMMENT
MEDIUM…m/dem/ground_rectification/partition/partition_plan.py12 """This method is expected to return a list of Partition instances"""STRING
Empty Error Handlers3 hits · 15 pts
SeverityFileLineSnippetContext
HIGHopendm/remote.py124except exceptions.OdmError:CODE
HIGHopendm/photo.py676except ValueError:CODE
HIGHopendm/tiles/gdal2tiles.py58except Exception:CODE
Redundant / Tautological Comments9 hits · 14 pts
SeverityFileLineSnippetContext
LOWstages/odm_report.py52 # Check if alignment has been performed (we need to transform our shots if so)COMMENT
LOWstages/odm_filterpoints.py28 # Check if we need to compute boundaryCOMMENT
LOWstages/dataset.py107 # Check if we need to extract video framesCOMMENT
LOWstages/dataset.py176 # Check if a geo file is availableCOMMENT
LOWopendm/align.py57 # Check if we need to reproject align fileCOMMENT
LOWopendm/ai.py41 # Check if we need to download itCOMMENT
LOWopendm/video/checkers.py127 # Check if ratio of black pixels is above thresholdCOMMENT
LOWopendm/video/video2dataset.py129 # Add element to arrayCOMMENT
LOWopendm/tiles/gdal2tiles.py1289 # Output the resultsCOMMENT
Over-Commented Block13 hits · 12 pts
SeverityFileLineSnippetContext
LOWsettings.yaml1---COMMENT
LOWsettings.yaml21#opensfm_processes: 4 # by default this is set to $(nproc)COMMENT
LOWsettings.yaml41#texturing_skip_visibility_test: FalseCOMMENT
LOWsettings.yaml61#orthophoto_compression: DEFLATE # Options are [JPEG, LZW, PACKBITS, DEFLATE, LZMA, NONE] Don't change unless you know wCOMMENT
LOWopendm/video/parameters.py1COMMENT
LOWopendm/tiles/hsv_merge.py1#!/usr/bin/env pythonCOMMENT
LOWopendm/tiles/hsv_merge.py21#COMMENT
LOWopendm/tiles/gdal2tiles.py1#!/usr/bin/env pythonCOMMENT
LOWopendm/tiles/gdal2tiles.py21# Permission is hereby granted, free of charge, to any person obtaining aCOMMENT
LOWopendm/tiles/gdal2tiles.py781 warped_vrt_dataset.GetDriver().CreateCopy(temp_file, warped_vrt_dataset)COMMENT
LOWopendm/dem/pdal.py1#!/usr/bin/env pythonCOMMENT
LOWopendm/objpacker/imagepacker/imagepacker.py1#! /usr/bin/pythonCOMMENT
LOWopendm/objpacker/imagepacker/utils.py1#! /usr/bin/pythonCOMMENT
AI Structural Patterns4 hits · 4 pts
SeverityFileLineSnippetContext
LOWopendm/mesh.py12CODE
LOWopendm/skyremoval/skyfilter.py71CODE
LOWopendm/dem/commands.py68CODE
LOWopendm/thermal_tools/thermal_utils.py5CODE
Example Usage Blocks2 hits · 3 pts
SeverityFileLineSnippetContext
LOWcontrib/exif-binner/exif_binner.py5# Usage:COMMENT
LOWcontrib/mask-duplicator/mask-duplicator.py16# Usage:COMMENT
AI Slop Vocabulary2 hits · 2 pts
SeverityFileLineSnippetContext
MEDIUMcontrib/time-sift/Timesift_odm.py64 # The list of valid images is prepared by removing any extension (to be robust to the .tif added by ODM)STRING
LOWopendm/multispectral.py130 # Some cameras (Micasense, DJI) store the value (nice! just return)COMMENT