Conversation
/memories/repo/openptv-python-2026-03-07-handoff.md.
…mentation and image processing
There was a problem hiding this comment.
Pull request overview
This PR modernizes the project’s dev/CI/tooling setup, expands documentation and onboarding, and introduces optional delegation to native optv bindings (with parity tests) alongside a new deterministic synthetic “cavity” test case dataset.
Changes:
- Modernize tooling and packaging metadata (Python 3.12+, pre-commit hook updates, CI workflow updates, Makefile python selection).
- Add optional native-interop layer (
optv) with conversion helpers and integrate native delegation for preprocessing + full-frame target recognition. - Add a deterministic synthetic cavity fixture + new/expanded tests (bundle adjustment, preprocessing/segmentation parity, reconstruction parity) and a calibration comparison utility.
Reviewed changes
Copilot reviewed 95 out of 98 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| .cruft.json | Bump tracked cookiecutter template commit. |
| .github/workflows/on-push.yml | Update CI actions and Python matrix; adjust packaging/publish steps. |
| .gitignore | Ignore additional temp directories. |
| .pre-commit-config.yaml | Update hook revisions and tool versions. |
| Dockerfile | Switch base conda Python to 3.12. |
| Makefile | Route QA/tests/mypy through configurable interpreter. |
| README.md | Expand onboarding, installation, backend selection, and capability docs. |
| docs/conf.py | Make AutoAPI optional via OPENPTV_ENABLE_AUTOAPI. |
| docs/index.md | Add quickstart-style overview and adjust docs TOC. |
| mypy.ini | Exclude build/tmp directories from type checking. |
| plans.md | Add plan document links. |
| pyproject.toml | Declare dependencies + Python version range; update classifiers. |
| openptv_python/_native_compat.py | Add optional optv import/probing and native wrappers. |
| openptv_python/_native_convert.py | Add converters between openptv-python objects and optv py_bind types. |
| openptv_python/calibration_compare.py | New utility for camera-by-camera calibration diffing. |
| openptv_python/image_processing.py | Rework preprocessing pipeline; add native delegation hook and new blur/filter implementations. |
| openptv_python/multimed.py | Adjust multilayer radial shift implementation to iterate per-layer. |
| openptv_python/parameters.py | Ensure MultimediaPar.set_layers() keeps nlay consistent. |
| openptv_python/segmentation.py | Add native delegation path for full-frame target recognition + conversions. |
| openptv_python/track.py | Make angle_acc robust to zero-length vectors and clamp acos input. |
| openptv_python/tracking_frame_buf.py | Fail fast when required per-frame files are missing. |
| tests/test_calibration_compare.py | Add tests for the new calibration comparison utility. |
| tests/test_image_processing.py | Update preprocessing expectations; add native-vs-python parity test (skipped when unavailable). |
| tests/test_multimedia_n_lay.py | Add multilayer parity/reference tests and optional native comparisons. |
| tests/test_point_positions.py | Add compiled-vs-reference and optional native reconstruction parity tests. |
| tests/test_read_frame.py | Add regression test for missing linkage file handling. |
| tests/test_segmentation.py | Add optional native-vs-python parity test for full-frame target recognition. |
| tests/test_synthetic_cavity_case.py | New coherence + bundle adjustment recovery tests for synthetic cavity case. |
| tests/test_tracking.py | Extend angle_acc test coverage for degenerate cases. |
| tests/testing_fodder/test_cavity/parameters_Run1.yaml | Add YAML parameter snapshot for cavity test case. |
| tests/testing_fodder/test_cavity_synthetic/README.md | Document synthetic cavity fixture contents. |
| tests/testing_fodder/test_cavity_synthetic/parameters_Run1.yaml | Add YAML parameter snapshot for synthetic cavity case. |
| tests/testing_fodder/test_cavity_synthetic/cal/calblock.txt | Add calibration body point file used in the synthetic case. |
| tests/testing_fodder/test_cavity_synthetic/cal/cam1.tif.addpar | Add synthetic case working calibration addpar. |
| tests/testing_fodder/test_cavity_synthetic/cal/cam1.tif.ori | Add synthetic case working calibration ori. |
| tests/testing_fodder/test_cavity_synthetic/cal/cam2.tif.addpar | Add synthetic case working calibration addpar. |
| tests/testing_fodder/test_cavity_synthetic/cal/cam2.tif.ori | Add synthetic case working calibration ori. |
| tests/testing_fodder/test_cavity_synthetic/cal/cam3.tif.addpar | Add synthetic case working calibration addpar. |
| tests/testing_fodder/test_cavity_synthetic/cal/cam3.tif.ori | Add synthetic case working calibration ori. |
| tests/testing_fodder/test_cavity_synthetic/cal/cam4.tif.addpar | Add synthetic case working calibration addpar. |
| tests/testing_fodder/test_cavity_synthetic/cal/cam4.tif.ori | Add synthetic case working calibration ori. |
| tests/testing_fodder/test_cavity_synthetic/calibration_targets/cam1.00001_targets | Add synthetic calibration targets for cam1. |
| tests/testing_fodder/test_cavity_synthetic/calibration_targets/cam2.00001_targets | Add synthetic calibration targets for cam2. |
| tests/testing_fodder/test_cavity_synthetic/calibration_targets/cam3.00001_targets | Add synthetic calibration targets for cam3. |
| tests/testing_fodder/test_cavity_synthetic/calibration_targets/cam4.00001_targets | Add synthetic calibration targets for cam4. |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/calibration_body_points.txt | Add exact 3D calibration body points. |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/manifest.json | Add fixture generation seed and calibration recovery errors. |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/particles/frame_10001.txt | Add exact ground-truth 3D particles for frame 10001. |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/particles/frame_10002.txt | Add exact ground-truth 3D particles for frame 10002. |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam1.tif.addpar | Add ground-truth camera model addpar (cam1). |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam1.tif.ori | Add ground-truth camera model ori (cam1). |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam2.tif.addpar | Add ground-truth camera model addpar (cam2). |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam2.tif.ori | Add ground-truth camera model ori (cam2). |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam3.tif.addpar | Add ground-truth camera model addpar (cam3). |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam3.tif.ori | Add ground-truth camera model ori (cam3). |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam4.tif.addpar | Add ground-truth camera model addpar (cam4). |
| tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam4.tif.ori | Add ground-truth camera model ori (cam4). |
| tests/testing_fodder/test_cavity_synthetic/img_orig/cam1.10001_targets | Add synthetic particle target observations (cam1/frame 10001). |
| tests/testing_fodder/test_cavity_synthetic/img_orig/cam1.10002_targets | Add synthetic particle target observations (cam1/frame 10002). |
| tests/testing_fodder/test_cavity_synthetic/img_orig/cam2.10001_targets | Add synthetic particle target observations (cam2/frame 10001). |
| tests/testing_fodder/test_cavity_synthetic/img_orig/cam2.10002_targets | Add synthetic particle target observations (cam2/frame 10002). |
| tests/testing_fodder/test_cavity_synthetic/img_orig/cam3.10001_targets | Add synthetic particle target observations (cam3/frame 10001). |
| tests/testing_fodder/test_cavity_synthetic/img_orig/cam3.10002_targets | Add synthetic particle target observations (cam3/frame 10002). |
| tests/testing_fodder/test_cavity_synthetic/img_orig/cam4.10001_targets | Add synthetic particle target observations (cam4/frame 10001). |
| tests/testing_fodder/test_cavity_synthetic/img_orig/cam4.10002_targets | Add synthetic particle target observations (cam4/frame 10002). |
| tests/testing_fodder/test_cavity_synthetic/parameters/cal_ori.par | Add legacy .par calibration-orientation parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/criteria.par | Add legacy .par criteria parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/detect_plate.par | Add legacy .par detect-plate parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/dumbbell.par | Add legacy .par dumbbell parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/examine.par | Add legacy .par examine parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/man_ori.par | Add legacy .par manual orientation parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/multi_planes.par | Add legacy .par multi-plane parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/orient.par | Add legacy .par orientation parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/pft_version | Add legacy pft_version marker file for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/pft_version.par | Add legacy .par pft_version parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/ptv.par | Add legacy .par control parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/sequence.par | Add legacy .par sequence parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/shaking.par | Add legacy .par shaking parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/sortgrid.par | Add legacy .par sortgrid parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/targ_rec.par | Add legacy .par target recognition parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/track.par | Add legacy .par tracking parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/parameters/unsharp_mask.par | Add legacy .par unsharp mask parameters for fixture. |
| tests/testing_fodder/test_cavity_synthetic/res_orig/added.10001 | Add synthetic added linkage/prior file (frame 10001). |
| tests/testing_fodder/test_cavity_synthetic/res_orig/added.10002 | Add synthetic added linkage/prior file (frame 10002). |
| tests/testing_fodder/test_cavity_synthetic/res_orig/ptv_is.10001 | Add synthetic ptv_is linkage file (frame 10001). |
| tests/testing_fodder/test_cavity_synthetic/res_orig/ptv_is.10002 | Add synthetic ptv_is linkage file (frame 10002). |
| tests/testing_fodder/test_cavity_synthetic/res_orig/rt_is.10001 | Add synthetic rt_is correspondence file (frame 10001). |
| tests/testing_fodder/test_cavity_synthetic/res_orig/rt_is.10002 | Add synthetic rt_is correspondence file (frame 10002). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| dependencies = [ | ||
| "mypy>=1.19.1", | ||
| "myst-parser>=5.0.0", | ||
| "numba>=0.64.0", | ||
| "numpy>=2.4.2", | ||
| "optv>=0.3.2", | ||
| "pre-commit>=4.5.1", | ||
| "pydata-sphinx-theme>=0.16.1", | ||
| "pytest>=9.0.2", | ||
| "pytest-cov>=7.0.0", | ||
| "pyyaml>=6.0.3", | ||
| "scipy>=1.17.1", | ||
| "sphinx>=9.1.0", | ||
| "sphinx-autoapi>=3.7.0", | ||
| "types-pyyaml>=6.0.12.20250915" | ||
| ] |
| "Programming Language :: Python", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3.11", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Topic :: Scientific/Engineering" | ||
| ] | ||
| dependencies = [ | ||
| "mypy>=1.19.1", | ||
| "myst-parser>=5.0.0", | ||
| "numba>=0.64.0", | ||
| "numpy>=2.4.2", | ||
| "optv>=0.3.2", | ||
| "pre-commit>=4.5.1", | ||
| "pydata-sphinx-theme>=0.16.1", | ||
| "pytest>=9.0.2", | ||
| "pytest-cov>=7.0.0", | ||
| "pyyaml>=6.0.3", | ||
| "scipy>=1.17.1", | ||
| "sphinx>=9.1.0", | ||
| "sphinx-autoapi>=3.7.0", | ||
| "types-pyyaml>=6.0.12.20250915" | ||
| ] | ||
| description = "Python version of the OpenPTV library" | ||
| dynamic = ["version"] | ||
| license = {file = "LICENSE"} | ||
| name = "openptv-python" | ||
| readme = "README.md" | ||
| requires-python = ">=3.12,<3.14" | ||
|
|
| def fast_box_blur( | ||
| filt_span: int, | ||
| src: np.ndarray, | ||
| cpar: ControlPar | None = None, | ||
| ) -> np.ndarray: | ||
| """Fast box blur matching liboptv border handling.""" | ||
| if src.dtype != np.uint8: | ||
| raise TypeError("Image must be of type uint8") | ||
|
|
||
| if src.ndim != 2: | ||
| raise TypeError("Input array must be two-dimensional") | ||
|
|
||
| if cpar is not None: | ||
| imx = int(cpar.imx) | ||
| imy = int(cpar.imy) | ||
| if src.shape != (imy, imx): | ||
| raise ValueError("Image shape does not match control parameters") | ||
| else: | ||
| imy, imx = src.shape | ||
|
|
||
| image_size = imx * imy | ||
| n = 2 * filt_span + 1 | ||
| row_accum = uniform_filter( | ||
| src.reshape((cpar.imy, cpar.imx)), | ||
| size=n, | ||
| mode="constant", | ||
| cval=0, | ||
| ).reshape(-1) | ||
| return row_accum | ||
| nq = n * n | ||
| src_flat = src.reshape(-1) | ||
| dest_flat = np.zeros(image_size, dtype=np.uint8) | ||
| row_accum = np.zeros(image_size, dtype=np.int64) |
There was a problem hiding this comment.
@copilot apply changes based on this feedback
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR modernizes the project’s tooling/CI and expands the test + documentation surface area while introducing optional delegation to native optv bindings (with Python fallbacks) and adding a deterministic synthetic cavity fixture for validation.
Changes:
- Add optional
optvinterop layer (_native_compat,_native_convert) and delegate preprocessing + full-frame segmentation when available. - Expand tests (native parity checks, bundle adjustment recovery, calibration comparison utilities) and add deterministic synthetic cavity test data.
- Update packaging metadata, docs, pre-commit, Makefile/Dockerfile, and GitHub Actions workflow versions / Python targets.
Reviewed changes
Copilot reviewed 95 out of 98 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
.cruft.json |
Update tracked cookiecutter template commit. |
.github/workflows/on-push.yml |
CI workflow updates (actions versions, Python matrices, packaging/publish steps). |
.gitignore |
Ignore additional temp directories (tmp, .tmp). |
.pre-commit-config.yaml |
Bump pre-commit hook revisions and formatter/linter tool versions. |
Dockerfile |
Update base conda Python version used in the container build. |
Makefile |
Use configurable PYTHON for QA/tests/type-check commands. |
README.md |
Expanded installation, backend behavior, and contributor workflow documentation. |
docs/conf.py |
Gate autoapi extension behind OPENPTV_ENABLE_AUTOAPI. |
docs/index.md |
Refresh docs index/quickstart and table of contents. |
mypy.ini |
Exclude build/tmp directories from mypy scanning. |
openptv_python/_native_compat.py |
New optional import + feature-detection shim for optv bindings. |
openptv_python/_native_convert.py |
New conversion helpers between Python objects and optv py_bind objects. |
openptv_python/calibration_compare.py |
New utilities + CLI to compare calibration folders camera-by-camera. |
openptv_python/image_processing.py |
Refactor preprocessing pipeline; add optional native preprocessing delegation. |
openptv_python/multimed.py |
Fix multi-layer handling in fast_multimed_r_nlay (per-layer beta computation). |
openptv_python/parameters.py |
Ensure MultimediaPar.set_layers() keeps nlay in sync with layer arrays. |
openptv_python/segmentation.py |
Add optional native target recognition delegation for full-frame runs. |
openptv_python/track.py |
Make angle_acc() robust to zero norms and clamp cosine for numerical safety. |
openptv_python/tracking_frame_buf.py |
Fail fast if expected frame/linkage/priority/target files are missing. |
plans.md |
Add pointers to design/plan documents. |
pyproject.toml |
Update Python support + dependency metadata. |
tests/test_calibration_compare.py |
New tests for calibration folder comparison/formatting utilities. |
tests/test_image_processing.py |
Update preprocessing expectations and add optv parity test (skipped if unavailable). |
tests/test_multimedia_n_lay.py |
Add multilayer parity/reference tests; optional native parity checks. |
tests/test_point_positions.py |
Add compiled-vs-reference loop parity tests and optional native parity checks. |
tests/test_read_frame.py |
Add test asserting Frame.read() returns False when linkage file is missing. |
tests/test_segmentation.py |
Add optional native segmentation parity test plus helper for target comparison. |
tests/test_synthetic_cavity_case.py |
New synthetic cavity integration tests (calibration coherence + BA recovery). |
tests/test_tracking.py |
Add coverage for angle_acc() acceleration component on a simple candidate. |
tests/testing_fodder/test_cavity/parameters_Run1.yaml |
Add YAML parameter fixture for the cavity case. |
tests/testing_fodder/test_cavity_synthetic/README.md |
Document the synthetic cavity fixture contents. |
tests/testing_fodder/test_cavity_synthetic/cal/calblock.txt |
Synthetic cavity calibration-block points (working copy). |
tests/testing_fodder/test_cavity_synthetic/cal/cam1.tif.addpar |
Synthetic cavity working calibration added parameters. |
tests/testing_fodder/test_cavity_synthetic/cal/cam1.tif.ori |
Synthetic cavity working calibration orientation. |
tests/testing_fodder/test_cavity_synthetic/cal/cam2.tif.addpar |
Synthetic cavity working calibration added parameters. |
tests/testing_fodder/test_cavity_synthetic/cal/cam2.tif.ori |
Synthetic cavity working calibration orientation. |
tests/testing_fodder/test_cavity_synthetic/cal/cam3.tif.addpar |
Synthetic cavity working calibration added parameters. |
tests/testing_fodder/test_cavity_synthetic/cal/cam3.tif.ori |
Synthetic cavity working calibration orientation. |
tests/testing_fodder/test_cavity_synthetic/cal/cam4.tif.addpar |
Synthetic cavity working calibration added parameters. |
tests/testing_fodder/test_cavity_synthetic/cal/cam4.tif.ori |
Synthetic cavity working calibration orientation. |
tests/testing_fodder/test_cavity_synthetic/calibration_targets/cam1.00001_targets |
Synthetic calibration targets for camera 1. |
tests/testing_fodder/test_cavity_synthetic/calibration_targets/cam2.00001_targets |
Synthetic calibration targets for camera 2. |
tests/testing_fodder/test_cavity_synthetic/calibration_targets/cam3.00001_targets |
Synthetic calibration targets for camera 3. |
tests/testing_fodder/test_cavity_synthetic/calibration_targets/cam4.00001_targets |
Synthetic calibration targets for camera 4. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam1.tif.addpar |
Ground-truth camera 1 added parameters used to generate synthetic data. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam1.tif.ori |
Ground-truth camera 1 orientation used to generate synthetic data. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam2.tif.addpar |
Ground-truth camera 2 added parameters used to generate synthetic data. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam2.tif.ori |
Ground-truth camera 2 orientation used to generate synthetic data. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam3.tif.addpar |
Ground-truth camera 3 added parameters used to generate synthetic data. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam3.tif.ori |
Ground-truth camera 3 orientation used to generate synthetic data. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam4.tif.addpar |
Ground-truth camera 4 added parameters used to generate synthetic data. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/cal/cam4.tif.ori |
Ground-truth camera 4 orientation used to generate synthetic data. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/calibration_body_points.txt |
Ground-truth 3D calibration body points. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/manifest.json |
Synthetic generation seed + calibration recovery error summary. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/particles/frame_10001.txt |
Ground-truth 3D particle coordinates for frame 10001. |
tests/testing_fodder/test_cavity_synthetic/ground_truth/particles/frame_10002.txt |
Ground-truth 3D particle coordinates for frame 10002. |
tests/testing_fodder/test_cavity_synthetic/img_orig/cam1.10001_targets |
Synthetic particle target detections for camera 1, frame 10001. |
tests/testing_fodder/test_cavity_synthetic/img_orig/cam1.10002_targets |
Synthetic particle target detections for camera 1, frame 10002. |
tests/testing_fodder/test_cavity_synthetic/img_orig/cam2.10001_targets |
Synthetic particle target detections for camera 2, frame 10001. |
tests/testing_fodder/test_cavity_synthetic/img_orig/cam2.10002_targets |
Synthetic particle target detections for camera 2, frame 10002. |
tests/testing_fodder/test_cavity_synthetic/img_orig/cam3.10001_targets |
Synthetic particle target detections for camera 3, frame 10001. |
tests/testing_fodder/test_cavity_synthetic/img_orig/cam3.10002_targets |
Synthetic particle target detections for camera 3, frame 10002. |
tests/testing_fodder/test_cavity_synthetic/img_orig/cam4.10001_targets |
Synthetic particle target detections for camera 4, frame 10001. |
tests/testing_fodder/test_cavity_synthetic/img_orig/cam4.10002_targets |
Synthetic particle target detections for camera 4, frame 10002. |
tests/testing_fodder/test_cavity_synthetic/parameters/* |
Add .par fixtures for synthetic case (cal_ori, criteria, detect_plate, etc.). |
tests/testing_fodder/test_cavity_synthetic/parameters_Run1.yaml |
Synthetic case YAML parameters fixture. |
tests/testing_fodder/test_cavity_synthetic/res_orig/added.10001 |
Synthetic linkage/prio data fixture (frame 10001). |
tests/testing_fodder/test_cavity_synthetic/res_orig/added.10002 |
Synthetic linkage/prio data fixture (frame 10002). |
tests/testing_fodder/test_cavity_synthetic/res_orig/ptv_is.10001 |
Synthetic linkage file fixture (frame 10001). |
tests/testing_fodder/test_cavity_synthetic/res_orig/ptv_is.10002 |
Synthetic linkage file fixture (frame 10002). |
tests/testing_fodder/test_cavity_synthetic/res_orig/rt_is.10001 |
Synthetic correspondence file fixture (frame 10001). |
tests/testing_fodder/test_cavity_synthetic/res_orig/rt_is.10002 |
Synthetic correspondence file fixture (frame 10002). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def fast_box_blur( | ||
| filt_span: int, | ||
| src: np.ndarray, | ||
| cpar: ControlPar | None = None, | ||
| ) -> np.ndarray: | ||
| """Fast box blur matching liboptv border handling.""" | ||
| if src.dtype != np.uint8: | ||
| raise TypeError("Image must be of type uint8") | ||
|
|
||
| if src.ndim != 2: | ||
| raise TypeError("Input array must be two-dimensional") | ||
|
|
||
| if cpar is not None: | ||
| imx = int(cpar.imx) | ||
| imy = int(cpar.imy) | ||
| if src.shape != (imy, imx): | ||
| raise ValueError("Image shape does not match control parameters") | ||
| else: | ||
| imy, imx = src.shape | ||
|
|
||
| image_size = imx * imy | ||
| n = 2 * filt_span + 1 | ||
| row_accum = uniform_filter( | ||
| src.reshape((cpar.imy, cpar.imx)), | ||
| size=n, | ||
| mode="constant", | ||
| cval=0, | ||
| ).reshape(-1) | ||
| return row_accum | ||
| nq = n * n | ||
| src_flat = src.reshape(-1) | ||
| dest_flat = np.zeros(image_size, dtype=np.uint8) | ||
| row_accum = np.zeros(image_size, dtype=np.int64) | ||
| col_accum = np.zeros(imx, dtype=np.int64) | ||
|
|
||
| for row in range(imy): | ||
| row_start = row * imx | ||
| accum = int(src_flat[row_start]) | ||
| row_accum[row_start] = accum * n | ||
|
|
||
| for col in range(1, min(filt_span + 1, imx)): | ||
| right = row_start + 2 * col | ||
| left = right - 1 | ||
| if right >= row_start + imx: | ||
| break | ||
| accum += int(src_flat[left]) + int(src_flat[right]) | ||
| row_accum[row_start + col] = accum * n // (2 * col + 1) | ||
|
|
||
| for col in range(filt_span + 1, max(imx - filt_span, filt_span + 1)): | ||
| accum += int(src_flat[row_start + col + filt_span]) | ||
| accum -= int(src_flat[row_start + col - filt_span - 1]) | ||
| row_accum[row_start + col] = accum | ||
|
|
||
| m = n - 2 | ||
| col = imx - filt_span | ||
| left = row_start + imx - n | ||
| right = left + 1 | ||
| while col < row_start + imx - row_start and m > 0 and right < row_start + imx: | ||
| accum -= int(src_flat[left]) + int(src_flat[right]) | ||
| row_accum[row_start + col] = accum * n // m | ||
| left += 2 | ||
| right += 2 | ||
| col += 1 | ||
| m -= 2 | ||
|
|
||
| for col in range(imx): | ||
| col_accum[col] = row_accum[col] | ||
| dest_flat[col] = np.uint8(col_accum[col] // n) | ||
|
|
||
| max_top = min(filt_span, (imy - 1) // 2) | ||
| for row in range(1, max_top + 1): | ||
| base1 = (2 * row - 1) * imx | ||
| base2 = base1 + imx | ||
| out_base = row * imx | ||
| for col in range(imx): | ||
| col_accum[col] += row_accum[base1 + col] + row_accum[base2 + col] | ||
| dest_flat[out_base + col] = np.uint8( | ||
| n * col_accum[col] // nq // (2 * row + 1) | ||
| ) | ||
|
|
||
| for row in range(filt_span + 1, max(imy - filt_span, filt_span + 1)): | ||
| remove_base = (row - filt_span - 1) * imx | ||
| add_base = (row + filt_span) * imx | ||
| out_base = row * imx | ||
| for col in range(imx): | ||
| col_accum[col] += row_accum[add_base + col] - row_accum[remove_base + col] | ||
| dest_flat[out_base + col] = np.uint8(col_accum[col] // nq) | ||
|
|
||
| for remaining in range(min(filt_span, imy - 1), 0, -1): | ||
| remove_base = (imy - 2 * remaining - 1) * imx | ||
| remove_base2 = remove_base + imx | ||
| out_base = (imy - remaining) * imx | ||
| if remove_base < 0: | ||
| continue | ||
| for col in range(imx): | ||
| col_accum[col] -= ( | ||
| row_accum[remove_base + col] + row_accum[remove_base2 + col] | ||
| ) | ||
| dest_flat[out_base + col] = np.uint8( | ||
| n * col_accum[col] // nq // (2 * remaining + 1) | ||
| ) | ||
|
|
||
| return dest_flat.reshape(src.shape) |
| strategy: | ||
| matrix: | ||
| python-version: ['3.11'] | ||
| python-version: ['3.11', '3.12'] |
| @@ -11,13 +11,31 @@ classifiers = [ | |||
| "Programming Language :: Python", | |||
| "Programming Language :: Python :: 3", | |||
| "Programming Language :: Python :: 3.11", | |||
| PYTHON ?= python | ||
|
|
||
| default: qa unit-tests type-check | ||
|
|
||
| qa: | ||
| pre-commit run --all-files | ||
| $(PYTHON) -m pre_commit run --all-files | ||
|
|
||
| unit-tests: | ||
| python -m pytest -vv --cov=. --cov-report=$(COV_REPORT) --doctest-glob="*.md" --doctest-glob="*.rst" | ||
| $(PYTHON) -m pytest -vv --cov=. --cov-report=$(COV_REPORT) --doctest-glob="*.md" --doctest-glob="*.rst" | ||
|
|
||
| type-check: | ||
| python -m mypy . | ||
| $(PYTHON) -m mypy . |
This pull request introduces several important updates to the project, focusing on modernizing the development and CI environment, improving documentation and onboarding, and adding support for native backend delegation. The most significant changes are grouped below.
1. Modernization of Development and CI Environment
Updated all GitHub Actions workflow steps to use the latest major versions, including
actions/checkout,actions/setup-python,actions/upload-artifact, andactions/download-artifact. Also updated the PyPI publish action and added support for Python 3.12 in all jobs, dropping 3.11 from the matrix.Upgraded pre-commit hooks and dependencies to their latest versions, including
pre-commit-hooks,blackdoc,ruff,mdformat,language-formatters-pre-commit-hooks, andgitleaks. [1] [2]Updated Dockerfile and conda environment to use Python 3.12 by default.
Improved
Makefileto use a configurable Python interpreter, defaulting to.venv/bin/python, for all QA and test commands.2. Improved Documentation and Onboarding Experience
README.mdwith detailed information on supported Python versions, installation methods (uvandconda), backend selection, and a backend capability table. Added clear getting-started instructions and clarified developer workflow. [1] [2]autoapiextension only if theOPENPTV_ENABLE_AUTOAPIenvironment variable is set, making documentation builds more flexible.3. Native Backend Support and Compatibility Layer
openptv_python/_native_compat.py, which provides an optional compatibility layer for reusing nativeoptvbindings. This enables automatic delegation to native implementations for image preprocessing and target recognition when available, with feature detection and safe fallbacks.4. Project Template and Tooling Updates
.cruft.jsonto track the latest commit of the project template, ensuring the codebase stays in sync with template improvements. [1] [2]excludepattern tomypy.inito ignore build and temporary directories during type checking.These changes collectively modernize the project infrastructure, streamline onboarding for new contributors, and lay the groundwork for efficient native backend integration.