falcocv 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of falcocv might be problematic. Click here for more details.
- falcocv-1.0.0/.gitattributes +3 -0
- falcocv-1.0.0/.gitignore +44 -0
- falcocv-1.0.0/AGENTS.md +149 -0
- falcocv-1.0.0/ARCHITECTURE.md +597 -0
- falcocv-1.0.0/CREDITS.md +70 -0
- falcocv-1.0.0/LICENSE +674 -0
- falcocv-1.0.0/PKG-INFO +251 -0
- falcocv-1.0.0/README.md +196 -0
- falcocv-1.0.0/TODO.md +28 -0
- falcocv-1.0.0/benchmarks/bench_matcher.py +331 -0
- falcocv-1.0.0/benchmarks/bench_shape_match.py +190 -0
- falcocv-1.0.0/benchmarks/bench_tools.py +256 -0
- falcocv-1.0.0/build_kernel.bat +73 -0
- falcocv-1.0.0/build_kernel.sh +24 -0
- falcocv-1.0.0/cpp/kernel/CMakeLists.txt +39 -0
- falcocv-1.0.0/cpp/kernel/src/kernel.cpp +952 -0
- falcocv-1.0.0/docs/RELEASING.md +128 -0
- falcocv-1.0.0/docs/SMOKE_TEST.md +52 -0
- falcocv-1.0.0/docs/hmi_api.api +47 -0
- falcocv-1.0.0/examples/demo.hmi +51 -0
- falcocv-1.0.0/examples/demo_job1.cvj +0 -0
- falcocv-1.0.0/examples/demo_job2.cvj +0 -0
- falcocv-1.0.0/examples/generate_demo.py +78 -0
- falcocv-1.0.0/plans/falcocv-plan-v2.md +473 -0
- falcocv-1.0.0/plans/opencv5_opportunities.md +411 -0
- falcocv-1.0.0/pyproject.toml +147 -0
- falcocv-1.0.0/requirements.txt +26 -0
- falcocv-1.0.0/scripts/check_wheel.py +95 -0
- falcocv-1.0.0/scripts/download_ocr_models.py +56 -0
- falcocv-1.0.0/scripts/export_effnet_b0.py +48 -0
- falcocv-1.0.0/scripts/export_effnet_multilayer.py +108 -0
- falcocv-1.0.0/scripts/export_resnet_layer3.py +71 -0
- falcocv-1.0.0/scripts/export_resnet_patchcore.py +72 -0
- falcocv-1.0.0/scripts/wheel_smoke.py +131 -0
- falcocv-1.0.0/specifications/falcocv.md +68 -0
- falcocv-1.0.0/specifications/third-party/anomaly_detector_spec.md +1071 -0
- falcocv-1.0.0/specifications/third-party/edge_classifier_opinionated_spec.md +993 -0
- falcocv-1.0.0/specifications/third-party/edge_learning_classifier_spec.md +2286 -0
- falcocv-1.0.0/specifications/third-party/ocr_industrial_spec.md +1583 -0
- falcocv-1.0.0/src/falcocv/__init__.py +5 -0
- falcocv-1.0.0/src/falcocv/__main__.py +4 -0
- falcocv-1.0.0/src/falcocv/accuracy/__init__.py +1 -0
- falcocv-1.0.0/src/falcocv/accuracy/synthetic.py +201 -0
- falcocv-1.0.0/src/falcocv/cli.py +23 -0
- falcocv-1.0.0/src/falcocv/core/__init__.py +27 -0
- falcocv-1.0.0/src/falcocv/core/anomaly/__init__.py +0 -0
- falcocv-1.0.0/src/falcocv/core/anomaly/backbone_effnet.py +92 -0
- falcocv-1.0.0/src/falcocv/core/anomaly/backbone_layer2.py +93 -0
- falcocv-1.0.0/src/falcocv/core/anomaly/detector.py +481 -0
- falcocv-1.0.0/src/falcocv/core/anomaly/memory.py +135 -0
- falcocv-1.0.0/src/falcocv/core/anomaly/patch_backbone.py +89 -0
- falcocv-1.0.0/src/falcocv/core/anomaly/patch_memory.py +178 -0
- falcocv-1.0.0/src/falcocv/core/anomaly/simple_memory.py +108 -0
- falcocv-1.0.0/src/falcocv/core/classifier/__init__.py +0 -0
- falcocv-1.0.0/src/falcocv/core/classifier/classifier_memory.py +119 -0
- falcocv-1.0.0/src/falcocv/core/classifier/inference.py +103 -0
- falcocv-1.0.0/src/falcocv/core/classifier/projection.py +42 -0
- falcocv-1.0.0/src/falcocv/core/classifier/trainer.py +10 -0
- falcocv-1.0.0/src/falcocv/core/classifier/trainer_numpy.py +208 -0
- falcocv-1.0.0/src/falcocv/core/config.py +186 -0
- falcocv-1.0.0/src/falcocv/core/config_paths.py +38 -0
- falcocv-1.0.0/src/falcocv/core/depth_viz.py +148 -0
- falcocv-1.0.0/src/falcocv/core/environment.py +134 -0
- falcocv-1.0.0/src/falcocv/core/hmi.py +675 -0
- falcocv-1.0.0/src/falcocv/core/job_manager.py +72 -0
- falcocv-1.0.0/src/falcocv/core/models.py +174 -0
- falcocv-1.0.0/src/falcocv/core/ocr/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/core/ocr/industrial_ocr_engine.py +394 -0
- falcocv-1.0.0/src/falcocv/core/overlay_layer.py +438 -0
- falcocv-1.0.0/src/falcocv/core/plane_fit.py +290 -0
- falcocv-1.0.0/src/falcocv/core/pointcloud_utils.py +570 -0
- falcocv-1.0.0/src/falcocv/core/results.py +26 -0
- falcocv-1.0.0/src/falcocv/core/roi_3d.py +302 -0
- falcocv-1.0.0/src/falcocv/core/roi_utils.py +205 -0
- falcocv-1.0.0/src/falcocv/core/script_debugger.py +304 -0
- falcocv-1.0.0/src/falcocv/core/tool_base.py +161 -0
- falcocv-1.0.0/src/falcocv/core/tool_registry.py +77 -0
- falcocv-1.0.0/src/falcocv/core/vision_image.py +755 -0
- falcocv-1.0.0/src/falcocv/core/workflow.py +187 -0
- falcocv-1.0.0/src/falcocv/core/workflow_controller.py +75 -0
- falcocv-1.0.0/src/falcocv/hmi_designer.py +110 -0
- falcocv-1.0.0/src/falcocv/main.py +962 -0
- falcocv-1.0.0/src/falcocv/run_job.py +214 -0
- falcocv-1.0.0/src/falcocv/self_test.py +207 -0
- falcocv-1.0.0/src/falcocv/tools/__init__.py +19 -0
- falcocv-1.0.0/src/falcocv/tools/anomaly_detector/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/anomaly_detector/config.py +706 -0
- falcocv-1.0.0/src/falcocv/tools/anomaly_detector/logic.py +251 -0
- falcocv-1.0.0/src/falcocv/tools/barcode_decoder/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/barcode_decoder/config.py +374 -0
- falcocv-1.0.0/src/falcocv/tools/barcode_decoder/logic.py +627 -0
- falcocv-1.0.0/src/falcocv/tools/blob_detector/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/blob_detector/config.py +264 -0
- falcocv-1.0.0/src/falcocv/tools/blob_detector/logic.py +208 -0
- falcocv-1.0.0/src/falcocv/tools/block/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/block/config.py +154 -0
- falcocv-1.0.0/src/falcocv/tools/block/logic.py +45 -0
- falcocv-1.0.0/src/falcocv/tools/classifier/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/classifier/config.py +701 -0
- falcocv-1.0.0/src/falcocv/tools/classifier/logic.py +350 -0
- falcocv-1.0.0/src/falcocv/tools/classifier/train_worker.py +86 -0
- falcocv-1.0.0/src/falcocv/tools/depth_range_loader/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/depth_range_loader/config.py +507 -0
- falcocv-1.0.0/src/falcocv/tools/depth_range_loader/logic.py +237 -0
- falcocv-1.0.0/src/falcocv/tools/edge_detection/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/edge_detection/config.py +321 -0
- falcocv-1.0.0/src/falcocv/tools/edge_detection/logic.py +377 -0
- falcocv-1.0.0/src/falcocv/tools/filters/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/filters/config.py +466 -0
- falcocv-1.0.0/src/falcocv/tools/filters/logic.py +486 -0
- falcocv-1.0.0/src/falcocv/tools/fixture_overlay/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/fixture_overlay/config.py +218 -0
- falcocv-1.0.0/src/falcocv/tools/fixture_overlay/logic.py +133 -0
- falcocv-1.0.0/src/falcocv/tools/gige_camera/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/gige_camera/config.py +504 -0
- falcocv-1.0.0/src/falcocv/tools/gige_camera/logic.py +413 -0
- falcocv-1.0.0/src/falcocv/tools/histogram/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/histogram/config.py +235 -0
- falcocv-1.0.0/src/falcocv/tools/histogram/logic.py +242 -0
- falcocv-1.0.0/src/falcocv/tools/image_calculator/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/image_calculator/config.py +493 -0
- falcocv-1.0.0/src/falcocv/tools/image_calculator/logic.py +321 -0
- falcocv-1.0.0/src/falcocv/tools/image_loader/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/image_loader/config.py +174 -0
- falcocv-1.0.0/src/falcocv/tools/image_loader/logic.py +100 -0
- falcocv-1.0.0/src/falcocv/tools/measurement/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/measurement/config.py +454 -0
- falcocv-1.0.0/src/falcocv/tools/measurement/logic.py +472 -0
- falcocv-1.0.0/src/falcocv/tools/ocr/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/ocr/config.py +217 -0
- falcocv-1.0.0/src/falcocv/tools/ocr/logic.py +164 -0
- falcocv-1.0.0/src/falcocv/tools/pattern_matcher/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/pattern_matcher/config.py +419 -0
- falcocv-1.0.0/src/falcocv/tools/pattern_matcher/logic.py +655 -0
- falcocv-1.0.0/src/falcocv/tools/plane_fitter/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/plane_fitter/config.py +446 -0
- falcocv-1.0.0/src/falcocv/tools/plane_fitter/logic.py +227 -0
- falcocv-1.0.0/src/falcocv/tools/python_script/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/python_script/config.py +696 -0
- falcocv-1.0.0/src/falcocv/tools/python_script/logic.py +174 -0
- falcocv-1.0.0/src/falcocv/tools/shape_match/__init__.py +6 -0
- falcocv-1.0.0/src/falcocv/tools/shape_match/config.py +479 -0
- falcocv-1.0.0/src/falcocv/tools/shape_match/logic.py +1820 -0
- falcocv-1.0.0/src/falcocv/ui/__init__.py +1 -0
- falcocv-1.0.0/src/falcocv/ui/adapters/__init__.py +1 -0
- falcocv-1.0.0/src/falcocv/ui/adapters/controller_adapter.py +50 -0
- falcocv-1.0.0/src/falcocv/ui/assets/brand/FalcoCV_logo_source.jpg +0 -0
- falcocv-1.0.0/src/falcocv/ui/assets/favicon.png +0 -0
- falcocv-1.0.0/src/falcocv/ui/assets/icon.ico +0 -0
- falcocv-1.0.0/src/falcocv/ui/assets/icon_light.ico +0 -0
- falcocv-1.0.0/src/falcocv/ui/assets/logo.svg +4 -0
- falcocv-1.0.0/src/falcocv/ui/assets/logo_light.svg +4 -0
- falcocv-1.0.0/src/falcocv/ui/assets/logo_lockup_dark.png +0 -0
- falcocv-1.0.0/src/falcocv/ui/assets/logo_lockup_light.png +0 -0
- falcocv-1.0.0/src/falcocv/ui/assets/logo_mark_dark.png +0 -0
- falcocv-1.0.0/src/falcocv/ui/assets/logo_mark_light.png +0 -0
- falcocv-1.0.0/src/falcocv/ui/safe_refresh.py +21 -0
- falcocv-1.0.0/src/falcocv/ui/splash.py +85 -0
- falcocv-1.0.0/src/falcocv/ui/style.py +575 -0
- falcocv-1.0.0/src/falcocv/ui/tool_config_helpers.py +130 -0
- falcocv-1.0.0/src/falcocv/ui/tool_help.py +1660 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/__init__.py +1 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/contour_editor.py +254 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/debug_panels.py +282 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/help_dialog.py +408 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/hmi_designer_dialog.py +2447 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/hmi_preview.py +248 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/hmi_scene.py +514 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/job_config_dialog.py +60 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/roi_editor.py +245 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/roi_editor_3d.py +676 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/script_editor.py +339 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/tool_config_dialog.py +108 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/toolbox.py +86 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/viewer.py +804 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/viewer3d.py +1521 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/workflow_editor.py +611 -0
- falcocv-1.0.0/src/falcocv/ui/widgets/workflow_tree.py +757 -0
- falcocv-1.0.0/src/falcocv/ui/window_geometry.py +39 -0
- falcocv-1.0.0/src/falcocv/version.py +20 -0
- falcocv-1.0.0/src/falcocv/web/__init__.py +0 -0
- falcocv-1.0.0/src/falcocv/web/__main__.py +22 -0
- falcocv-1.0.0/src/falcocv/web/controller_adapter.py +57 -0
- falcocv-1.0.0/src/falcocv/web/deploy.py +119 -0
- falcocv-1.0.0/src/falcocv/web/hmi/dashboard.html +44 -0
- falcocv-1.0.0/src/falcocv/web/hmi/dashboard.js +108 -0
- falcocv-1.0.0/src/falcocv/web/hmi/favicon.png +0 -0
- falcocv-1.0.0/src/falcocv/web/hmi/hmi.css +71 -0
- falcocv-1.0.0/src/falcocv/web/hmi/hmi.js +672 -0
- falcocv-1.0.0/src/falcocv/web/hmi/index.html +23 -0
- falcocv-1.0.0/src/falcocv/web/hmi/logo_lockup_dark.png +0 -0
- falcocv-1.0.0/src/falcocv/web/hmi_worker.py +328 -0
- falcocv-1.0.0/src/falcocv/web/image_utils.py +34 -0
- falcocv-1.0.0/src/falcocv/web/server.py +516 -0
- falcocv-1.0.0/src/falcocv/web_runner.py +45 -0
- falcocv-1.0.0/tests/__init__.py +1 -0
- falcocv-1.0.0/tests/accuracy/__init__.py +1 -0
- falcocv-1.0.0/tests/accuracy/test_synthetic.py +53 -0
- falcocv-1.0.0/tests/conftest.py +29 -0
- falcocv-1.0.0/tests/integration/__init__.py +1 -0
- falcocv-1.0.0/tests/integration/helpers.py +37 -0
- falcocv-1.0.0/tests/integration/test_headless_run.py +178 -0
- falcocv-1.0.0/tests/integration/test_job_roundtrip.py +72 -0
- falcocv-1.0.0/tests/integration/test_shape_match.py +435 -0
- falcocv-1.0.0/tests/integration/test_tool_contract.py +36 -0
- falcocv-1.0.0/tests/integration/test_workflow_pipelines.py +155 -0
- falcocv-1.0.0/tests/packaging/__init__.py +1 -0
- falcocv-1.0.0/tests/packaging/test_wheel_contents.py +23 -0
- falcocv-1.0.0/tests/test_barcode_decoder.py +443 -0
- falcocv-1.0.0/tests/test_blob_detector_fixture.py +52 -0
- falcocv-1.0.0/tests/test_cv_api_compat.py +122 -0
- falcocv-1.0.0/tests/test_edge_affine.py +233 -0
- falcocv-1.0.0/tests/test_fixture_roi.py +190 -0
- falcocv-1.0.0/tests/test_help_import.py +41 -0
- falcocv-1.0.0/tests/test_image_viewer_roi_scale.py +95 -0
- falcocv-1.0.0/tests/test_kernel_input_validation.py +126 -0
- falcocv-1.0.0/tests/test_migrated_tools.py +72 -0
- falcocv-1.0.0/tests/test_optional_tools.py +25 -0
- falcocv-1.0.0/tests/test_plane_fitter.py +797 -0
- falcocv-1.0.0/tests/test_ported_regressions.py +190 -0
- falcocv-1.0.0/tests/test_self_test.py +10 -0
- falcocv-1.0.0/tests/test_tool_logic_config_split.py +140 -0
- falcocv-1.0.0/tests/test_trainer_equivalence.py +149 -0
- falcocv-1.0.0/tests/test_viewer3d_handles.py +185 -0
- falcocv-1.0.0/tests/test_web_server.py +72 -0
- falcocv-1.0.0/tests/test_workflow_tree_array_shape.py +13 -0
- falcocv-1.0.0/tests/test_workflow_tree_rename.py +47 -0
- falcocv-1.0.0/tests/test_world_coordinates.py +191 -0
- falcocv-1.0.0/tests/ui/__init__.py +1 -0
- falcocv-1.0.0/tests/ui/conftest.py +48 -0
- falcocv-1.0.0/tests/ui/test_main_window.py +121 -0
- falcocv-1.0.0/tests/ui/test_tool_configs.py +151 -0
- falcocv-1.0.0/tests/web/__init__.py +1 -0
- falcocv-1.0.0/tests/web/test_server_api.py +95 -0
falcocv-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
.venv/
|
|
6
|
+
env/
|
|
7
|
+
venv/
|
|
8
|
+
.env
|
|
9
|
+
.pytest_cache/
|
|
10
|
+
|
|
11
|
+
# IDEs
|
|
12
|
+
.vscode/
|
|
13
|
+
.idea/
|
|
14
|
+
|
|
15
|
+
# OS
|
|
16
|
+
Thumbs.db
|
|
17
|
+
.DS_Store
|
|
18
|
+
|
|
19
|
+
# Local models (downloaded by users; not part of the public repo)
|
|
20
|
+
models/
|
|
21
|
+
|
|
22
|
+
# FalcoCV specific (optional)
|
|
23
|
+
# *.cvj <-- Keep them if you want to include demo jobs
|
|
24
|
+
temp/
|
|
25
|
+
logs/
|
|
26
|
+
|
|
27
|
+
# Local build artifacts
|
|
28
|
+
build/
|
|
29
|
+
dist/
|
|
30
|
+
benchmarks/.legacy/
|
|
31
|
+
benchmarks/__pycache__/
|
|
32
|
+
|
|
33
|
+
# OpenCV 5 source/build (downloaded locally, not part of the repo)
|
|
34
|
+
cpp/opencv5/
|
|
35
|
+
cpp/build/
|
|
36
|
+
cpp/opencv-5.0.0-src.zip
|
|
37
|
+
|
|
38
|
+
# Native kernel build outputs
|
|
39
|
+
*.pyd
|
|
40
|
+
*.dll
|
|
41
|
+
cpp/bin/
|
|
42
|
+
|
|
43
|
+
# Local agent tooling
|
|
44
|
+
.opencode/
|
falcocv-1.0.0/AGENTS.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# FalcoCV — Context Summary
|
|
2
|
+
|
|
3
|
+
Industrial machine vision framework. Python + PyQt6 + OpenCV 5, with a small
|
|
4
|
+
native kernel for the two measured C++ hot paths.
|
|
5
|
+
|
|
6
|
+
## Architecture
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
src/falcocv/
|
|
10
|
+
core/ → workflow engine, VisionImage, overlays, ROI, depth/3D helpers
|
|
11
|
+
tools/ → vision tools: logic.py (processing) + config.py (PyQt6 widget)
|
|
12
|
+
ui/ → PyQt6 widgets, viewers, ROI editors, HMI designer
|
|
13
|
+
web/ → FastAPI + HMI worker subprocesses + dashboard
|
|
14
|
+
main.py → Vision Editor entry point
|
|
15
|
+
cli.py → `falcocv` / `python -m falcocv`
|
|
16
|
+
version.py
|
|
17
|
+
cpp/kernel/ → _falco_kernel (pybind11, NO OpenCV):
|
|
18
|
+
· generate_pointcloud
|
|
19
|
+
· plane_fit (LSQ/RANSAC)
|
|
20
|
+
tests/ → pytest suite
|
|
21
|
+
cpp/bin/ → local kernel build output (gitignored)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Rules
|
|
25
|
+
- Use **Python/OpenCV/NumPy** for tools unless a measured benchmark shows a
|
|
26
|
+
meaningful (>1.5× end-to-end) win.
|
|
27
|
+
- C++ is reserved for **point-cloud generation**, **plane fitting** and
|
|
28
|
+
measured shape-matching hot paths. Any new C++ hot path must ship with a
|
|
29
|
+
benchmark and live in `cpp/kernel`, not in the old `_cv_core` architecture.
|
|
30
|
+
- The kernel exposes **dict→dict / ndarray functions**, never `BaseTool`,
|
|
31
|
+
`VisionImage`, overlays or `data_changed` logic.
|
|
32
|
+
- `_falco_kernel` must not depend on OpenCV. OpenCV comes from
|
|
33
|
+
`opencv-python` for Python code.
|
|
34
|
+
- Models are **not** in the wheel. `core/models.py` resolves/downloads them on
|
|
35
|
+
first run (`%APPDATA%/FalcoCV/models`, `$XDG_DATA_HOME/FalcoCV/models`).
|
|
36
|
+
|
|
37
|
+
## Key pitfalls (do not repeat)
|
|
38
|
+
|
|
39
|
+
- **Point-cloud Z convention** → `z = depth * z_res + z_offset` (not minus).
|
|
40
|
+
X is mirrored: `x = (img_width - 1 - col) * x_res` so image-left maps to
|
|
41
|
+
world +X and the default isometric 3D camera looks natural.
|
|
42
|
+
- **Point-cloud stride** → `step = ceil(sqrt(total_pixels / target_points))`;
|
|
43
|
+
a Python fallback lives in `core.pointcloud_utils.generate_pointcloud`.
|
|
44
|
+
- **PlaneFitter ROIs** → ROIs are stored in fixture coordinates and converted
|
|
45
|
+
to absolute image coordinates before calling the kernel. The kernel converts
|
|
46
|
+
image centers to world coordinates and negates the angle (Qt clockwise
|
|
47
|
+
convention vs world axes).
|
|
48
|
+
- **Plane polygon Z range** → use the depth range of the **whole image**, not
|
|
49
|
+
the ROI, so the overlay spans the image.
|
|
50
|
+
- **Overlay flow** → `inherit_overlays_from` copies layers (no shared lists).
|
|
51
|
+
Correct flow: inherit → claim the layer with
|
|
52
|
+
`get_overlay_layer("default", source_tool=self.name)` → clean elements whose
|
|
53
|
+
`source_tool` is this tool → add new overlays → `_copy_overlays_to_input`.
|
|
54
|
+
Never accumulate. Claiming is mandatory: `add_roi()/add_contour()/add_text()`
|
|
55
|
+
copy `layer.source_tool` into each element, and `_copy_overlays_to_input`
|
|
56
|
+
filters by `element.source_tool`, so an unclaimed inherited layer tags the
|
|
57
|
+
new overlays with the upstream tool's name and they are silently dropped.
|
|
58
|
+
`composite_roi_to_full(..., source_tool=...)` does the same for ROI borders.
|
|
59
|
+
- **Overlay rendering** → render only in visible viewers; never rasterize into
|
|
60
|
+
the image buffer; keep overlays as mathematical primitives.
|
|
61
|
+
- **ROI helpers** accept 4- or 5-element ROIs (`[x,y,w,h]` or `[x,y,w,h,a]`).
|
|
62
|
+
- **ROI crops with rotated fixtures** → `get_roi_data()` and
|
|
63
|
+
`composite_roi_to_full()` must resolve the ROI origin with
|
|
64
|
+
`fixture_to_image()`. An upright ROI drawn on a rotated fixture is stored as
|
|
65
|
+
`ra = -fixture.angle`, so `total_angle == 0` while the fixture still moves
|
|
66
|
+
the ROI; `x + rx` is only valid when the fixture has no rotation. The
|
|
67
|
+
axis-aligned path slices at `int(fixture_to_image(...)[0:2])` (no resampling)
|
|
68
|
+
so crop and composite round-trip losslessly.
|
|
69
|
+
- **Filters on depth** → scrub NaNs, preserve float32 output; Canny/CLAHE/
|
|
70
|
+
equalize normalize float32 to uint8 internally; invert float32 with
|
|
71
|
+
`(max+min)-img`.
|
|
72
|
+
- **Histogram on depth** → support float32/NaN with a finite min/max range;
|
|
73
|
+
never call `np.iinfo` on a float dtype.
|
|
74
|
+
- **Barcode Auto** → try the fast 1D path first (downscaled pyzbar, then
|
|
75
|
+
zxing), then QR/DataMatrix/ArUco only if needed. zxing MicroQR enum names
|
|
76
|
+
differ between versions; look them up dynamically.
|
|
77
|
+
- **DataMatrix** → pylibdmtx uses a bottom-left origin; flip contour Y only.
|
|
78
|
+
- **3D ROIs** → stored in fixture coordinates; convert with
|
|
79
|
+
`image_to_fixture()` before storing and `fixture_to_image()` before drawing.
|
|
80
|
+
- **3D ROI handles** → large, filled, drawn without depth test; add a center
|
|
81
|
+
handle so they remain usable in dense clouds.
|
|
82
|
+
- **3D draw fallback** → if point-picking and plane back-projection both fail,
|
|
83
|
+
show a tooltip and abort; never keep an old ROI silently.
|
|
84
|
+
- **`zero_as_invalid` default True** → depth `0` is invalid for point clouds;
|
|
85
|
+
avoid phantom floor planes. Depth images displayed in 2D are normalized to
|
|
86
|
+
0 after cloud generation.
|
|
87
|
+
- **3D camera** → default isometric camera `azimuth=45°, elevation=30°`.
|
|
88
|
+
|
|
89
|
+
- **ShapeMatch solvers** -> the native kernel is required; there is no Python
|
|
90
|
+
coarse fallback. Alignment >=0.90 uses the ECC solver; lower alignment uses the
|
|
91
|
+
explicit occlusion solver. ECC failure in the 0.90-0.98 band reclassifies to
|
|
92
|
+
occlusion; >=0.98 is rejected with a warning. Results carry `solver`,
|
|
93
|
+
`ncc_score`, `visible_fraction`, `ecc_cc` and `warnings`.
|
|
94
|
+
- **ShapeMatch model** -> `model_b64` stores features, edges, gray and color
|
|
95
|
+
templates. Training ROI is fixture-relative and supports rotation. Do not add
|
|
96
|
+
PatternMatcher-only parameters (`angle_step`, `scale_step`, `use_pyramid`, ...).
|
|
97
|
+
- **ShapeMatch coarse voting** -> vote on a downscaled image (4x for >=2 MP,
|
|
98
|
+
2x for >=0.25 MP, 1x for small ROIs), keep the template >=40 px, cap scene
|
|
99
|
+
edges spatially (at least 4000, 8 per 32 px cell) and use the top 500 model
|
|
100
|
+
features.
|
|
101
|
+
Refine at full resolution; full gradients, Canny and the distance map stay
|
|
102
|
+
lazy and are only computed for the occlusion solver.
|
|
103
|
+
- **ShapeMatch search stage** -> NCC angle/scale scans run on a reduced ROI
|
|
104
|
+
(template >=48 px, max 4x) and reject candidates whose NCC is below
|
|
105
|
+
`_MIN_NCC` before any full-resolution alignment or solver. This is what keeps
|
|
106
|
+
the pipeline at ~4 coarse poses instead of paying for every kernel candidate.
|
|
107
|
+
- **ShapeMatch ECC** -> two levels: affine ECC on a reduced view (factor <=2)
|
|
108
|
+
then a translation-only pass at full resolution. The reduced pass must undo
|
|
109
|
+
its resampling with `template_scale`/`scene_scale`; without that correction
|
|
110
|
+
the reported scale drifts by up to 0.65 %. Small templates (factor 1) keep
|
|
111
|
+
the full-resolution affine + polish path.
|
|
112
|
+
- **ShapeMatch padding** -> the rotated template's padding diagonal must be even,
|
|
113
|
+
otherwise its center lands between pixels and translation is biased by ~0.5 px.
|
|
114
|
+
Render NCC padding with the template's median border color, never zero.
|
|
115
|
+
Crop the padding before `matchTemplate` (`_render_search`); a rotated rectangle
|
|
116
|
+
is centrally symmetric so the crop stays centred.
|
|
117
|
+
|
|
118
|
+
## Build
|
|
119
|
+
|
|
120
|
+
### Native kernel (only C++ build)
|
|
121
|
+
```bash
|
|
122
|
+
build_kernel.bat # Windows: configure + build + deploy cpp/bin
|
|
123
|
+
build_kernel.bat --rebuild
|
|
124
|
+
./build_kernel.sh # Linux/macOS
|
|
125
|
+
```
|
|
126
|
+
No OpenCV world build. Requirements: CMake 3.20+, C++17 compiler, pybind11,
|
|
127
|
+
OpenMP.
|
|
128
|
+
|
|
129
|
+
### Python package
|
|
130
|
+
```bash
|
|
131
|
+
pip install -e ".[dev]" # builds the kernel via scikit-build-core
|
|
132
|
+
pytest -q --ignore=tests/test_trainer_equivalence.py
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Key facts
|
|
136
|
+
- Python 3.10+ (3.13 recommended), branch: `main` / working branch
|
|
137
|
+
`public_refactor`.
|
|
138
|
+
- No PyInstaller/Inno distribution build; distribution is the PyPI wheel/sdist.
|
|
139
|
+
- `config.json` lives in `%APPDATA%/FalcoCV/config.json` (or XDG config).
|
|
140
|
+
- Models live in the user data dir and are downloaded from GitHub Releases.
|
|
141
|
+
- `core/` has no PyQt6/UI imports at module level.
|
|
142
|
+
- License: **GNU GPL v3 or later** (see `LICENSE`).
|
|
143
|
+
- Branding: `src/falcocv/ui/assets/` (`icon.ico`, `icon_light.ico`, `logo.svg`,
|
|
144
|
+
lockups). The splash uses `logo_lockup_dark.png`; the web dashboard serves
|
|
145
|
+
`/hmi/logo_lockup_dark.png`.
|
|
146
|
+
- Do not make commits without explicit permission.
|
|
147
|
+
- Server: `falcocv-server` or `python -m falcocv.web`; dashboard:
|
|
148
|
+
`http://localhost:8000`; HMI: `http://localhost:8000/?id=<project_id>`.
|
|
149
|
+
- Performance harness: `benchmarks/` (`python benchmarks/bench_tools.py`).
|