Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ jobs:
sudo apt-get -qq install exiftool libgdal-dev libzbar0t64
GDAL_VERSION=$(gdal-config --version)
pip install "gdal==$GDAL_VERSION"
- name: Install package and test dependencies
run: pip install -e ".[test]"
- name: Test with pytest
run: |
pip install -e .[test]
pytest -m "not newgdal"
run: pytest
- name: Build package
run: |
python -m pip install build
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ jobs:
sudo apt-get -qq install exiftool libgdal-dev libzbar0t64
GDAL_VERSION=$(gdal-config --version)
pip install "gdal==$GDAL_VERSION"
- name: Install package and test dependencies
run: pip install -e ".[test]"
- name: Test with pytest
run: |
pip install -e .[test]
pytest -m "not newgdal" --cov=./ --cov-report=xml
run: pytest
- uses: actions/upload-artifact@v6
if: ${{ matrix.python-version == '3.12' }}
with:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Add any directories, files, or patterns you don't want to be tracked by version control
*.pyc
.ipynb_checkpoints
.coverage
coverage.xml
.venv/
__pycache__
/dist/
/*.egg-info
Expand Down
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
rev: v6.0.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- id: check-illegal-windows-names
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.14.6
rev: v0.15.18
hooks:
# Run the linter.
- id: ruff
Expand All @@ -17,7 +17,7 @@ repos:
- id: ruff-format
types_or: [ python, pyi ] # avoid jupyter
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
rev: v2.4.2
hooks:
- id: codespell
additional_dependencies:
Expand Down
30 changes: 6 additions & 24 deletions Alignment v2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@
"metadata": {},
"outputs": [],
"source": [
"from skimage.transform import ProjectiveTransform\n",
"import numpy as np\n",
"from micasense.warp_io import load_warp_matrices\n",
"\n",
"if panchroCam:\n",
" warp_matrices_filename = cam_serial + \"_warp_matrices_SIFT.npy\"\n",
Expand All @@ -177,20 +176,13 @@
"\n",
"if Path(\"./\" + warp_matrices_filename).is_file():\n",
" print(\"Found existing warp matrices for camera\", cam_serial)\n",
" load_warp_matrices = np.load(warp_matrices_filename, allow_pickle=True)\n",
" loaded_warp_matrices = []\n",
" for matrix in load_warp_matrices:\n",
" if panchroCam:\n",
" transform = ProjectiveTransform(matrix=matrix.astype(\"float64\"))\n",
" loaded_warp_matrices.append(transform)\n",
" else:\n",
" loaded_warp_matrices.append(matrix.astype(\"float32\"))\n",
" loaded = load_warp_matrices(warp_matrices_filename, as_projective=panchroCam)\n",
" print(\"Warp matrices successfully loaded.\")\n",
"\n",
" if panchroCam:\n",
" warp_matrices_SIFT = loaded_warp_matrices\n",
" warp_matrices_SIFT = loaded\n",
" else:\n",
" warp_matrices = loaded_warp_matrices\n",
" warp_matrices = loaded\n",
"else:\n",
" print(\"No existing warp matrices found. Create them later in the notebook.\")\n",
" warp_matrices_SIFT = False\n",
Expand Down Expand Up @@ -381,24 +373,14 @@
"metadata": {},
"outputs": [],
"source": [
"import numpy\n",
"import skimage\n",
"from skimage.transform import ProjectiveTransform\n",
"from micasense.warp_io import save_warp_matrices\n",
"\n",
"if panchroCam:\n",
" working_wm = warp_matrices_SIFT\n",
"else:\n",
" working_wm = warp_matrices\n",
"if not Path(\"./\" + warp_matrices_filename).is_file() or regenerate:\n",
" temp_matrices = []\n",
" for x in working_wm:\n",
" if isinstance(x, numpy.ndarray):\n",
" temp_matrices.append(x)\n",
" if isinstance(x, skimage.transform._geometric.ProjectiveTransform):\n",
" temp_matrices.append(x.params)\n",
" np.save(\n",
" warp_matrices_filename, np.array(temp_matrices, dtype=object), allow_pickle=True\n",
" )\n",
" save_warp_matrices(warp_matrices_filename, working_wm)\n",
" print(\"Saved to\", Path(\"./\" + warp_matrices_filename).resolve())\n",
"else:\n",
" print(\"Matrices already exist at\", Path(\"./\" + warp_matrices_filename).resolve())"
Expand Down
22 changes: 8 additions & 14 deletions Batch Processing v2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@
" ) > 0.005 or val == 1: # reduces cpu usage from updating the progressbar by 10x\n",
" f.value = val\n",
"\n",
"\n",
"# time is not recognized and would remove the imageset as unused\n",
"imgset = imageset.ImageSet.from_directory(imagePath, progress_callback=update_f)\n",
"%time imgset = imageset.ImageSet.from_directory(imagePath, progress_callback=update_f)\n",
Expand Down Expand Up @@ -173,8 +174,8 @@
"data, columns = imgset.as_nested_lists()\n",
"df = pd.DataFrame.from_records(data, index=\"timestamp\", columns=columns)\n",
"\n",
"# Insert your mapbox token here\n",
"token = \"pk.eyJ1Ijoic3RlcGhlbm1hbmd1bTIiLCJhIjoiY2xmOXdnYzF1MDFqejNvdGE0YW13aTN5ZyJ9.AG_ckhUqTBjuGC2LuWCfQQ\"\n",
"# Insert your Mapbox access token here (https://account.mapbox.com/access-tokens/)\n",
"token = \"YOUR_MAPBOX_ACCESS_TOKEN\"\n",
"color_property = \"dls-yaw\"\n",
"num_color_classes = 8\n",
"\n",
Expand Down Expand Up @@ -218,7 +219,7 @@
"metadata": {},
"outputs": [],
"source": [
"from skimage.transform import ProjectiveTransform\n",
"from micasense.warp_io import load_warp_matrices\n",
"\n",
"if panchroCam:\n",
" warp_matrices_filename = cam_serial + \"_warp_matrices_SIFT.npy\"\n",
Expand All @@ -227,19 +228,12 @@
"\n",
"if Path(\"./\" + warp_matrices_filename).is_file():\n",
" print(\"Found existing warp matrices for camera\", cam_serial)\n",
" load_warp_matrices = np.load(warp_matrices_filename, allow_pickle=True)\n",
" loaded_warp_matrices = []\n",
" for matrix in load_warp_matrices:\n",
" if panchroCam:\n",
" transform = ProjectiveTransform(matrix=matrix.astype(\"float64\"))\n",
" loaded_warp_matrices.append(transform)\n",
" else:\n",
" loaded_warp_matrices.append(matrix.astype(\"float32\"))\n",
" loaded = load_warp_matrices(warp_matrices_filename, as_projective=panchroCam)\n",
"\n",
" if panchroCam:\n",
" warp_matrices_SIFT = loaded_warp_matrices\n",
" warp_matrices_SIFT = loaded\n",
" else:\n",
" warp_matrices = loaded_warp_matrices\n",
" warp_matrices = loaded\n",
" print(\"Loaded warp matrices from\", Path(\"./\" + warp_matrices_filename).resolve())\n",
"else:\n",
" print(\"No warp matrices found at expected location:\", warp_matrices_filename)"
Expand Down Expand Up @@ -298,7 +292,7 @@
" if panchroCam:\n",
" capture.radiometric_pan_sharpened_aligned_capture(\n",
" warp_matrices=warp_matrices_SIFT,\n",
" irradiance_list=capture.dls_irradiace(),\n",
" irradiance_list=capture.dls_irradiance(),\n",
" img_type=img_type,\n",
" write_exif=write_exif_to_individual_stacks,\n",
" )\n",
Expand Down
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* repr functions to classes so that debugging is easier
* delete old config files
* fixed jupyter notebooks
* `micasense.mp_config.spawn_pool()` using a per-pool spawn context (rawpy/OpenMP safe on Linux)
* `micasense.warp_io` — `save_warp_matrices` / `load_warp_matrices` for `.npy` warp matrix I/O
* Alignment v2, Batch Processing v2 notebooks and `batch_processing_script.py` use `warp_io`
* pytest 9+ native `[tool.pytest]` config with coverage in CI

### Changed

* setup docs and README use venv/pip instead of conda; removed `micasense_conda_env.yml`

### Fixed

* `SIFT_align_capture`: assign reference SIFT image when reference and target bands share shape (fixes `NameError` when `ref` is a multispectral band)
* `SIFT_align_capture`: fall back to calibrated warp matrices when SIFT match count is low (e.g. LWIR) instead of raising
* `ImageSet.save_stacks` and `imageutils` alignment pools use spawn context (not global `set_start_method`)
* declare `rawpy` as a runtime dependency
* remove unused `Capture.__sift_warp_matrices`
* `SIFT_align_capture`: remove redundant raw/undistort work and dead accumulators

## [0.1.1] - 2025-12-28

Expand Down
Loading
Loading