adaspun 0.1.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.
- adaspun-0.1.0/CHANGELOG.md +7 -0
- adaspun-0.1.0/CITATION.cff +10 -0
- adaspun-0.1.0/LICENSE +5 -0
- adaspun-0.1.0/MANIFEST.in +7 -0
- adaspun-0.1.0/PKG-INFO +47 -0
- adaspun-0.1.0/README.md +13 -0
- adaspun-0.1.0/configs/kaggle_stereo_v9.yaml +58 -0
- adaspun-0.1.0/configs/kaggle_stereo_v9_recall.yaml +58 -0
- adaspun-0.1.0/examples/configs/local_kaggle_stereo_v9.example.yaml +21 -0
- adaspun-0.1.0/pyproject.toml +48 -0
- adaspun-0.1.0/setup.cfg +4 -0
- adaspun-0.1.0/src/adaspun/__init__.py +3 -0
- adaspun-0.1.0/src/adaspun/audit/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/audit/hash_chain.py +27 -0
- adaspun-0.1.0/src/adaspun/cli/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/cli/audit_verify.py +15 -0
- adaspun-0.1.0/src/adaspun/cli/calibrate.py +15 -0
- adaspun-0.1.0/src/adaspun/cli/detect_depth_frame.py +127 -0
- adaspun-0.1.0/src/adaspun/cli/detect_frame.py +75 -0
- adaspun-0.1.0/src/adaspun/cli/make_stereo_video.py +60 -0
- adaspun-0.1.0/src/adaspun/cli/native_video.py +269 -0
- adaspun-0.1.0/src/adaspun/cli/qubo_smoke.py +205 -0
- adaspun-0.1.0/src/adaspun/cli/risk_smoke.py +174 -0
- adaspun-0.1.0/src/adaspun/cli/run_clip.py +15 -0
- adaspun-0.1.0/src/adaspun/cli/run_qubo.py +15 -0
- adaspun-0.1.0/src/adaspun/cli/run_video.py +101 -0
- adaspun-0.1.0/src/adaspun/cli/track_ttc_smoke.py +148 -0
- adaspun-0.1.0/src/adaspun/cli/v9_robust.py +159 -0
- adaspun-0.1.0/src/adaspun/config.py +20 -0
- adaspun-0.1.0/src/adaspun/conformal/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/depth/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/depth/object_depth.py +152 -0
- adaspun-0.1.0/src/adaspun/depth/sgbm.py +37 -0
- adaspun-0.1.0/src/adaspun/perception/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/perception/ensemble.py +143 -0
- adaspun-0.1.0/src/adaspun/qubo/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/qubo/shield.py +104 -0
- adaspun-0.1.0/src/adaspun/risk/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/risk/safety_states.py +108 -0
- adaspun-0.1.0/src/adaspun/risk/ttc.py +58 -0
- adaspun-0.1.0/src/adaspun/riskfield/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/robustness/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/tracking/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/tracking/track_manager.py +104 -0
- adaspun-0.1.0/src/adaspun/types.py +49 -0
- adaspun-0.1.0/src/adaspun/video/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/video/pipeline.py +15 -0
- adaspun-0.1.0/src/adaspun/visualization/__init__.py +0 -0
- adaspun-0.1.0/src/adaspun/visualization/depth_overlays.py +29 -0
- adaspun-0.1.0/src/adaspun/visualization/native_video_overlay.py +84 -0
- adaspun-0.1.0/src/adaspun/visualization/overlays.py +18 -0
- adaspun-0.1.0/src/adaspun/visualization/risk_overlays.py +30 -0
- adaspun-0.1.0/src/adaspun/visualization/track_overlays.py +28 -0
- adaspun-0.1.0/src/adaspun.egg-info/PKG-INFO +47 -0
- adaspun-0.1.0/src/adaspun.egg-info/SOURCES.txt +59 -0
- adaspun-0.1.0/src/adaspun.egg-info/dependency_links.txt +1 -0
- adaspun-0.1.0/src/adaspun.egg-info/entry_points.txt +14 -0
- adaspun-0.1.0/src/adaspun.egg-info/requires.txt +28 -0
- adaspun-0.1.0/src/adaspun.egg-info/top_level.txt +1 -0
- adaspun-0.1.0/tests/test_import.py +3 -0
- adaspun-0.1.0/tests/test_imports.py +9 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
title: "ADASPUN: A Research Package for NeuroSentinel-4D++ ADAS Risk Perception"
|
|
3
|
+
message: "If you use this software, please cite it."
|
|
4
|
+
type: software
|
|
5
|
+
authors:
|
|
6
|
+
- family-names: "T"
|
|
7
|
+
given-names: "Puneeth"
|
|
8
|
+
version: "0.1.0"
|
|
9
|
+
date-released: "2026-06-16"
|
|
10
|
+
license: "TBD"
|
adaspun-0.1.0/LICENSE
ADDED
adaspun-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: adaspun
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Camera-based ADAS perception-to-risk calibration toolkit for monocular and stereo pipelines.
|
|
5
|
+
Author: T, Puneeth
|
|
6
|
+
Keywords: ADAS,computer vision,stereo vision,conformal prediction,risk calibration,QUBO
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: numpy
|
|
11
|
+
Requires-Dist: pandas
|
|
12
|
+
Requires-Dist: opencv-python
|
|
13
|
+
Requires-Dist: pyyaml
|
|
14
|
+
Requires-Dist: tqdm
|
|
15
|
+
Requires-Dist: scipy
|
|
16
|
+
Requires-Dist: scikit-learn
|
|
17
|
+
Requires-Dist: matplotlib
|
|
18
|
+
Requires-Dist: pillow
|
|
19
|
+
Provides-Extra: yolo
|
|
20
|
+
Requires-Dist: ultralytics; extra == "yolo"
|
|
21
|
+
Requires-Dist: torch; extra == "yolo"
|
|
22
|
+
Provides-Extra: clip
|
|
23
|
+
Requires-Dist: open_clip_torch; extra == "clip"
|
|
24
|
+
Provides-Extra: quantum
|
|
25
|
+
Requires-Dist: qiskit; extra == "quantum"
|
|
26
|
+
Requires-Dist: qiskit-aer; extra == "quantum"
|
|
27
|
+
Provides-Extra: crypto
|
|
28
|
+
Requires-Dist: cryptography; extra == "crypto"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest; extra == "dev"
|
|
31
|
+
Requires-Dist: ruff; extra == "dev"
|
|
32
|
+
Requires-Dist: black; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# ADASPUN
|
|
36
|
+
|
|
37
|
+
ADASPUN is a local research package for the NeuroSentinel-4D++ ADAS pipeline.
|
|
38
|
+
|
|
39
|
+
Recommended paper/demo command:
|
|
40
|
+
adaspun-v9-robust --cuda --copy-output D:\Puneeth_Adas\outputs\adaspun_phase7a_v9_robust\adaspun_v9_robust.mp4
|
|
41
|
+
|
|
42
|
+
Development commands:
|
|
43
|
+
adaspun-native-video
|
|
44
|
+
adaspun-risk-smoke
|
|
45
|
+
adaspun-qubo-smoke
|
|
46
|
+
|
|
47
|
+
This package is currently for local research use. Public PyPI release requires removing hardcoded paths and finalizing licensing.
|
adaspun-0.1.0/README.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# ADASPUN
|
|
2
|
+
|
|
3
|
+
ADASPUN is a local research package for the NeuroSentinel-4D++ ADAS pipeline.
|
|
4
|
+
|
|
5
|
+
Recommended paper/demo command:
|
|
6
|
+
adaspun-v9-robust --cuda --copy-output D:\Puneeth_Adas\outputs\adaspun_phase7a_v9_robust\adaspun_v9_robust.mp4
|
|
7
|
+
|
|
8
|
+
Development commands:
|
|
9
|
+
adaspun-native-video
|
|
10
|
+
adaspun-risk-smoke
|
|
11
|
+
adaspun-qubo-smoke
|
|
12
|
+
|
|
13
|
+
This package is currently for local research use. Public PyPI release requires removing hardcoded paths and finalizing licensing.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
mode: stereo
|
|
2
|
+
|
|
3
|
+
video:
|
|
4
|
+
left: "D:/Puneeth_Adas/videos/left.mp4"
|
|
5
|
+
right: "D:/Puneeth_Adas/videos/right.mp4"
|
|
6
|
+
output: "D:/Puneeth_Adas/output_adaspun_v9_package.mp4"
|
|
7
|
+
canvas_width: 1920
|
|
8
|
+
canvas_height: 720
|
|
9
|
+
|
|
10
|
+
detectors:
|
|
11
|
+
primary: "D:/Puneeth_Adas/runs/idd_finetune/yolov8m_idd_stage2_unfreeze/weights/best.pt"
|
|
12
|
+
ensemble:
|
|
13
|
+
- "D:/Puneeth_Adas/runs/idd_finetune/yolov8s_idd_stage2_Ddrive_continue/weights/best.pt"
|
|
14
|
+
- "D:/Puneeth_Adas/runs/idd_finetune/yolov8x_idd_stage1_freeze10_512_batch4/weights/best.pt"
|
|
15
|
+
confidence: 0.25
|
|
16
|
+
iou: 0.50
|
|
17
|
+
fusion: "nms"
|
|
18
|
+
|
|
19
|
+
depth:
|
|
20
|
+
mode: "stereo"
|
|
21
|
+
stereo_method: "sgbm"
|
|
22
|
+
fx: 721.5
|
|
23
|
+
baseline_m: 0.54
|
|
24
|
+
min_depth_m: 1.0
|
|
25
|
+
max_depth_m: 80.0
|
|
26
|
+
fallback: "mono_proxy"
|
|
27
|
+
|
|
28
|
+
risk:
|
|
29
|
+
crc_threshold_file: "D:/Puneeth_Adas/outputs/experiments/neurosentinel_crc_auto_balanced_labels/crc_human_threshold.json"
|
|
30
|
+
lambda_star: 0.61
|
|
31
|
+
epsilon: 0.05
|
|
32
|
+
alert_fraction: 0.60
|
|
33
|
+
conformal_q: 6.8465
|
|
34
|
+
ego_lane_x_min: 0.40
|
|
35
|
+
ego_lane_x_max: 0.60
|
|
36
|
+
|
|
37
|
+
qubo:
|
|
38
|
+
enabled: true
|
|
39
|
+
budget: 5
|
|
40
|
+
overlap_penalty: 0.30
|
|
41
|
+
|
|
42
|
+
riskfield:
|
|
43
|
+
enabled: true
|
|
44
|
+
type: "ddpm"
|
|
45
|
+
model_path: "D:/Puneeth_Adas/outputs/experiments/neurosentinel_diffusion_risk_field_model/diffusion_risk_field_ddpm.pt"
|
|
46
|
+
timesteps: 100
|
|
47
|
+
sample_steps: 20
|
|
48
|
+
|
|
49
|
+
ui:
|
|
50
|
+
style: "v9_clean"
|
|
51
|
+
show_distance_labels: true
|
|
52
|
+
show_bev: true
|
|
53
|
+
show_tpv: true
|
|
54
|
+
show_depth_panel: true
|
|
55
|
+
|
|
56
|
+
audit:
|
|
57
|
+
enabled: false
|
|
58
|
+
output_jsonl: "D:/Puneeth_Adas/outputs/audit/adaspun_hash_chain.jsonl"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
mode: stereo
|
|
2
|
+
|
|
3
|
+
video:
|
|
4
|
+
left: "D:/Puneeth_Adas/videos/left.mp4"
|
|
5
|
+
right: "D:/Puneeth_Adas/videos/right.mp4"
|
|
6
|
+
output: "D:/Puneeth_Adas/output_adaspun_v9_package.mp4"
|
|
7
|
+
canvas_width: 1920
|
|
8
|
+
canvas_height: 720
|
|
9
|
+
|
|
10
|
+
detectors:
|
|
11
|
+
primary: "D:/Puneeth_Adas/runs/idd_finetune/yolov8m_idd_stage2_unfreeze/weights/best.pt"
|
|
12
|
+
ensemble:
|
|
13
|
+
- "D:/Puneeth_Adas/runs/idd_finetune/yolov8s_idd_stage2_Ddrive_continue/weights/best.pt"
|
|
14
|
+
- "D:/Puneeth_Adas/runs/idd_finetune/yolov8x_idd_stage1_freeze10_512_batch4/weights/best.pt"
|
|
15
|
+
confidence: 0.15
|
|
16
|
+
iou: 0.50
|
|
17
|
+
fusion: "nms"
|
|
18
|
+
|
|
19
|
+
depth:
|
|
20
|
+
mode: "stereo"
|
|
21
|
+
stereo_method: "sgbm"
|
|
22
|
+
fx: 721.5
|
|
23
|
+
baseline_m: 0.54
|
|
24
|
+
min_depth_m: 1.0
|
|
25
|
+
max_depth_m: 80.0
|
|
26
|
+
fallback: "mono_proxy"
|
|
27
|
+
|
|
28
|
+
risk:
|
|
29
|
+
crc_threshold_file: "D:/Puneeth_Adas/outputs/experiments/neurosentinel_crc_auto_balanced_labels/crc_human_threshold.json"
|
|
30
|
+
lambda_star: 0.61
|
|
31
|
+
epsilon: 0.05
|
|
32
|
+
alert_fraction: 0.60
|
|
33
|
+
conformal_q: 6.8465
|
|
34
|
+
ego_lane_x_min: 0.40
|
|
35
|
+
ego_lane_x_max: 0.60
|
|
36
|
+
|
|
37
|
+
qubo:
|
|
38
|
+
enabled: true
|
|
39
|
+
budget: 5
|
|
40
|
+
overlap_penalty: 0.30
|
|
41
|
+
|
|
42
|
+
riskfield:
|
|
43
|
+
enabled: true
|
|
44
|
+
type: "ddpm"
|
|
45
|
+
model_path: "D:/Puneeth_Adas/outputs/experiments/neurosentinel_diffusion_risk_field_model/diffusion_risk_field_ddpm.pt"
|
|
46
|
+
timesteps: 100
|
|
47
|
+
sample_steps: 20
|
|
48
|
+
|
|
49
|
+
ui:
|
|
50
|
+
style: "v9_clean"
|
|
51
|
+
show_distance_labels: true
|
|
52
|
+
show_bev: true
|
|
53
|
+
show_tpv: true
|
|
54
|
+
show_depth_panel: true
|
|
55
|
+
|
|
56
|
+
audit:
|
|
57
|
+
enabled: false
|
|
58
|
+
output_jsonl: "D:/Puneeth_Adas/outputs/audit/adaspun_hash_chain.jsonl"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
mode: stereo
|
|
2
|
+
video:
|
|
3
|
+
left: D:/Puneeth_Adas/videos/left.mp4
|
|
4
|
+
right: D:/Puneeth_Adas/videos/right.mp4
|
|
5
|
+
perception:
|
|
6
|
+
backend: yolo
|
|
7
|
+
fusion: nms
|
|
8
|
+
confidence: 0.15
|
|
9
|
+
iou: 0.55
|
|
10
|
+
max_det: 300
|
|
11
|
+
depth:
|
|
12
|
+
fx: 721.5
|
|
13
|
+
baseline_m: 0.54
|
|
14
|
+
min_depth_m: 1.0
|
|
15
|
+
max_depth_m: 80.0
|
|
16
|
+
risk:
|
|
17
|
+
lambda_star: 0.61
|
|
18
|
+
ego_lane_x_min: 0.40
|
|
19
|
+
ego_lane_x_max: 0.60
|
|
20
|
+
qubo:
|
|
21
|
+
budget: 5
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "adaspun"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Camera-based ADAS perception-to-risk calibration toolkit for monocular and stereo pipelines."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
authors = [{ name = "T, Puneeth" }]
|
|
12
|
+
keywords = ["ADAS", "computer vision", "stereo vision", "conformal prediction", "risk calibration", "QUBO"]
|
|
13
|
+
dependencies = [
|
|
14
|
+
"numpy",
|
|
15
|
+
"pandas",
|
|
16
|
+
"opencv-python",
|
|
17
|
+
"pyyaml",
|
|
18
|
+
"tqdm",
|
|
19
|
+
"scipy",
|
|
20
|
+
"scikit-learn",
|
|
21
|
+
"matplotlib",
|
|
22
|
+
"pillow"
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
yolo = ["ultralytics", "torch"]
|
|
27
|
+
clip = ["open_clip_torch"]
|
|
28
|
+
quantum = ["qiskit", "qiskit-aer"]
|
|
29
|
+
crypto = ["cryptography"]
|
|
30
|
+
dev = ["pytest", "ruff", "black"]
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
adaspun-video = "adaspun.cli.run_video:main"
|
|
34
|
+
adaspun-make-stereo-video = "adaspun.cli.make_stereo_video:main"
|
|
35
|
+
adaspun-calibrate = "adaspun.cli.calibrate:main"
|
|
36
|
+
adaspun-qubo = "adaspun.cli.run_qubo:main"
|
|
37
|
+
adaspun-clip-anomaly = "adaspun.cli.run_clip:main"
|
|
38
|
+
adaspun-audit-verify = "adaspun.cli.audit_verify:main"
|
|
39
|
+
adaspun-detect-frame = "adaspun.cli.detect_frame:main"
|
|
40
|
+
adaspun-detect-depth-frame = "adaspun.cli.detect_depth_frame:main"
|
|
41
|
+
adaspun-track-ttc-smoke = "adaspun.cli.track_ttc_smoke:main"
|
|
42
|
+
adaspun-risk-smoke = "adaspun.cli.risk_smoke:main"
|
|
43
|
+
adaspun-qubo-smoke = "adaspun.cli.qubo_smoke:main"
|
|
44
|
+
adaspun-native-video = "adaspun.cli.native_video:main"
|
|
45
|
+
adaspun-v9-robust = "adaspun.cli.v9_robust:main"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["src"]
|
adaspun-0.1.0/setup.cfg
ADDED
|
File without changes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Dict
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class HashChainAuditLogger:
|
|
10
|
+
"""Tamper-evident JSONL hash-chain logger for frame-level ADAS decisions."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, output_jsonl: str | Path):
|
|
13
|
+
self.output_jsonl = Path(output_jsonl)
|
|
14
|
+
self.output_jsonl.parent.mkdir(parents=True, exist_ok=True)
|
|
15
|
+
self.previous_hash = "GENESIS"
|
|
16
|
+
|
|
17
|
+
def append(self, record: Dict[str, Any]) -> str:
|
|
18
|
+
payload = dict(record)
|
|
19
|
+
payload["previous_hash"] = self.previous_hash
|
|
20
|
+
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":"))
|
|
21
|
+
current_hash = hashlib.sha256(canonical.encode("utf-8")).hexdigest()
|
|
22
|
+
payload["current_hash"] = current_hash
|
|
23
|
+
with self.output_jsonl.open("a", encoding="utf-8") as f:
|
|
24
|
+
f.write(json.dumps(payload, sort_keys=True) + "
|
|
25
|
+
")
|
|
26
|
+
self.previous_hash = current_hash
|
|
27
|
+
return current_hash
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import argparse
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main() -> None:
|
|
6
|
+
ap = argparse.ArgumentParser(description="ADASPUN audit verification CLI scaffold.")
|
|
7
|
+
ap.add_argument("--config", required=False, help="Path to YAML config.")
|
|
8
|
+
ap.add_argument("--log", required=False, help="Path to audit log if applicable.")
|
|
9
|
+
args = ap.parse_args()
|
|
10
|
+
print("ADASPUN audit verification scaffold ready. Migrate project logic into this CLI.")
|
|
11
|
+
print(args)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
main()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
import argparse
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def main() -> None:
|
|
6
|
+
ap = argparse.ArgumentParser(description="ADASPUN C3RC calibration CLI scaffold.")
|
|
7
|
+
ap.add_argument("--config", required=False, help="Path to YAML config.")
|
|
8
|
+
ap.add_argument("--log", required=False, help="Path to audit log if applicable.")
|
|
9
|
+
args = ap.parse_args()
|
|
10
|
+
print("ADASPUN C3RC calibration scaffold ready. Migrate project logic into this CLI.")
|
|
11
|
+
print(args)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if __name__ == "__main__":
|
|
15
|
+
main()
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import cv2
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
from adaspun.config import load_config
|
|
11
|
+
from adaspun.perception.ensemble import DetectorEnsemble
|
|
12
|
+
from adaspun.depth.sgbm import SGBMDepthEstimator
|
|
13
|
+
from adaspun.depth.object_depth import extract_depths_for_detections
|
|
14
|
+
from adaspun.visualization.depth_overlays import depth_to_heatmap, draw_detections_with_depth
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _read_frame(video_path: str, frame_index: int):
|
|
18
|
+
cap = cv2.VideoCapture(str(video_path))
|
|
19
|
+
if not cap.isOpened():
|
|
20
|
+
raise RuntimeError(f"Could not open video: {video_path}")
|
|
21
|
+
cap.set(cv2.CAP_PROP_POS_FRAMES, int(frame_index))
|
|
22
|
+
ok, frame = cap.read()
|
|
23
|
+
cap.release()
|
|
24
|
+
if not ok:
|
|
25
|
+
raise RuntimeError(f"Could not read frame {frame_index} from {video_path}")
|
|
26
|
+
return frame
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def main() -> None:
|
|
30
|
+
ap = argparse.ArgumentParser(description="ADASPUN Phase-2 native detector + stereo object-depth smoke test.")
|
|
31
|
+
ap.add_argument("--config", required=True, help="Path to ADASPUN YAML config.")
|
|
32
|
+
ap.add_argument("--frame-index", type=int, default=25)
|
|
33
|
+
ap.add_argument("--output-dir", default="D:/Puneeth_Adas/outputs/adaspun_phase2_depth_smoke")
|
|
34
|
+
args = ap.parse_args()
|
|
35
|
+
|
|
36
|
+
cfg = load_config(args.config)
|
|
37
|
+
mode = cfg.get("mode", "stereo")
|
|
38
|
+
if mode != "stereo":
|
|
39
|
+
raise ValueError("Phase-2 smoke test expects mode: stereo with video.left and video.right.")
|
|
40
|
+
|
|
41
|
+
out_dir = Path(args.output_dir)
|
|
42
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
43
|
+
|
|
44
|
+
video_cfg = cfg.get("video", {})
|
|
45
|
+
left_path = video_cfg.get("left")
|
|
46
|
+
right_path = video_cfg.get("right")
|
|
47
|
+
if not left_path or not right_path:
|
|
48
|
+
raise ValueError("Config must provide video.left and video.right for stereo depth smoke test.")
|
|
49
|
+
|
|
50
|
+
left = _read_frame(left_path, args.frame_index)
|
|
51
|
+
right = _read_frame(right_path, args.frame_index)
|
|
52
|
+
if right.shape[:2] != left.shape[:2]:
|
|
53
|
+
right = cv2.resize(right, (left.shape[1], left.shape[0]))
|
|
54
|
+
|
|
55
|
+
detector = DetectorEnsemble.from_config(cfg)
|
|
56
|
+
detections = detector.predict(left)
|
|
57
|
+
|
|
58
|
+
depth_cfg = cfg.get("depth", {})
|
|
59
|
+
estimator = SGBMDepthEstimator(
|
|
60
|
+
fx=float(depth_cfg.get("fx", 721.5)),
|
|
61
|
+
baseline_m=float(depth_cfg.get("baseline_m", 0.54)),
|
|
62
|
+
min_depth_m=float(depth_cfg.get("min_depth_m", 1.0)),
|
|
63
|
+
max_depth_m=float(depth_cfg.get("max_depth_m", 80.0)),
|
|
64
|
+
)
|
|
65
|
+
depth_map = estimator.compute(left, right)
|
|
66
|
+
depth_items = extract_depths_for_detections(
|
|
67
|
+
depth_map,
|
|
68
|
+
detections,
|
|
69
|
+
left.shape,
|
|
70
|
+
fallback=str(depth_cfg.get("fallback", "mono_proxy")),
|
|
71
|
+
min_depth_m=float(depth_cfg.get("min_depth_m", 1.0)),
|
|
72
|
+
max_depth_m=float(depth_cfg.get("max_depth_m", 80.0)),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
annotated = draw_detections_with_depth(left, depth_items)
|
|
76
|
+
heat = depth_to_heatmap(depth_map, min_depth_m=float(depth_cfg.get("min_depth_m", 1.0)), max_depth_m=float(depth_cfg.get("max_depth_m", 80.0)))
|
|
77
|
+
blended = cv2.addWeighted(left, 0.55, heat, 0.45, 0)
|
|
78
|
+
|
|
79
|
+
out_annotated = out_dir / f"adaspun_depth_frame_{args.frame_index:06d}.jpg"
|
|
80
|
+
out_heat = out_dir / f"adaspun_depth_heatmap_{args.frame_index:06d}.jpg"
|
|
81
|
+
out_blend = out_dir / f"adaspun_depth_blend_{args.frame_index:06d}.jpg"
|
|
82
|
+
out_csv = out_dir / f"adaspun_depth_frame_{args.frame_index:06d}.csv"
|
|
83
|
+
out_json = out_dir / f"adaspun_depth_frame_{args.frame_index:06d}.json"
|
|
84
|
+
|
|
85
|
+
cv2.imwrite(str(out_annotated), annotated)
|
|
86
|
+
cv2.imwrite(str(out_heat), heat)
|
|
87
|
+
cv2.imwrite(str(out_blend), blended)
|
|
88
|
+
|
|
89
|
+
rows = []
|
|
90
|
+
for item in depth_items:
|
|
91
|
+
d = item.detection
|
|
92
|
+
rows.append({
|
|
93
|
+
"frame_index": args.frame_index,
|
|
94
|
+
"left_video": str(left_path),
|
|
95
|
+
"right_video": str(right_path),
|
|
96
|
+
"class_id": d.class_id,
|
|
97
|
+
"class_name": d.class_name,
|
|
98
|
+
"confidence": d.confidence,
|
|
99
|
+
"x1": d.bbox[0], "y1": d.bbox[1], "x2": d.bbox[2], "y2": d.bbox[3],
|
|
100
|
+
"source_model": d.source_model,
|
|
101
|
+
"distance_m": item.distance_m,
|
|
102
|
+
"depth_source": item.depth_source,
|
|
103
|
+
"stereo_valid": item.valid,
|
|
104
|
+
"valid_ratio": item.valid_ratio,
|
|
105
|
+
"depth_p25_m": item.depth_p25_m,
|
|
106
|
+
"depth_p50_m": item.depth_p50_m,
|
|
107
|
+
"depth_p75_m": item.depth_p75_m,
|
|
108
|
+
})
|
|
109
|
+
pd.DataFrame(rows).to_csv(out_csv, index=False)
|
|
110
|
+
out_json.write_text(json.dumps({"frame_index": args.frame_index, "objects": rows}, indent=2), encoding="utf-8")
|
|
111
|
+
|
|
112
|
+
stereo_valid_count = sum(1 for x in depth_items if x.depth_source == "stereo_sgbm")
|
|
113
|
+
fallback_count = sum(1 for x in depth_items if x.depth_source != "stereo_sgbm")
|
|
114
|
+
|
|
115
|
+
print("[ADASPUN] Phase-2 detector+depth smoke test complete")
|
|
116
|
+
print(f"[ADASPUN] Detections: {len(detections)}")
|
|
117
|
+
print(f"[ADASPUN] Stereo-valid object depths: {stereo_valid_count}")
|
|
118
|
+
print(f"[ADASPUN] Fallback object depths: {fallback_count}")
|
|
119
|
+
print(f"[ADASPUN] Annotated frame: {out_annotated}")
|
|
120
|
+
print(f"[ADASPUN] Depth heatmap: {out_heat}")
|
|
121
|
+
print(f"[ADASPUN] Depth blend: {out_blend}")
|
|
122
|
+
print(f"[ADASPUN] CSV: {out_csv}")
|
|
123
|
+
print(f"[ADASPUN] JSON: {out_json}")
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
if __name__ == "__main__":
|
|
127
|
+
main()
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import json
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import cv2
|
|
8
|
+
import pandas as pd
|
|
9
|
+
|
|
10
|
+
from adaspun.config import load_config
|
|
11
|
+
from adaspun.perception.ensemble import DetectorEnsemble
|
|
12
|
+
from adaspun.visualization.overlays import draw_detections
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _open_frame_from_config(cfg: dict, frame_index: int):
|
|
16
|
+
mode = cfg.get("mode", "monocular")
|
|
17
|
+
video_cfg = cfg.get("video", {})
|
|
18
|
+
path = video_cfg.get("left") if mode == "stereo" else video_cfg.get("input")
|
|
19
|
+
if not path:
|
|
20
|
+
raise ValueError("Config must provide video.left for stereo or video.input for monocular.")
|
|
21
|
+
cap = cv2.VideoCapture(str(path))
|
|
22
|
+
if not cap.isOpened():
|
|
23
|
+
raise RuntimeError(f"Could not open video: {path}")
|
|
24
|
+
cap.set(cv2.CAP_PROP_POS_FRAMES, int(frame_index))
|
|
25
|
+
ok, frame = cap.read()
|
|
26
|
+
cap.release()
|
|
27
|
+
if not ok:
|
|
28
|
+
raise RuntimeError(f"Could not read frame {frame_index} from {path}")
|
|
29
|
+
return frame, Path(path)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def main() -> None:
|
|
33
|
+
ap = argparse.ArgumentParser(description="ADASPUN Phase-1 native detector ensemble one-frame smoke test.")
|
|
34
|
+
ap.add_argument("--config", required=True, help="Path to ADASPUN YAML config.")
|
|
35
|
+
ap.add_argument("--frame-index", type=int, default=25)
|
|
36
|
+
ap.add_argument("--output-dir", default="D:/Puneeth_Adas/outputs/adaspun_phase1_detector_smoke")
|
|
37
|
+
args = ap.parse_args()
|
|
38
|
+
|
|
39
|
+
cfg = load_config(args.config)
|
|
40
|
+
out_dir = Path(args.output_dir)
|
|
41
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
42
|
+
|
|
43
|
+
frame, video_path = _open_frame_from_config(cfg, args.frame_index)
|
|
44
|
+
detector = DetectorEnsemble.from_config(cfg)
|
|
45
|
+
detections = detector.predict(frame)
|
|
46
|
+
|
|
47
|
+
annotated = draw_detections(frame, detections)
|
|
48
|
+
out_img = out_dir / f"adaspun_detector_frame_{args.frame_index:06d}.jpg"
|
|
49
|
+
out_json = out_dir / f"adaspun_detector_frame_{args.frame_index:06d}.json"
|
|
50
|
+
out_csv = out_dir / f"adaspun_detector_frame_{args.frame_index:06d}.csv"
|
|
51
|
+
|
|
52
|
+
cv2.imwrite(str(out_img), annotated)
|
|
53
|
+
rows = []
|
|
54
|
+
for d in detections:
|
|
55
|
+
rows.append({
|
|
56
|
+
"frame_index": args.frame_index,
|
|
57
|
+
"video": str(video_path),
|
|
58
|
+
"class_id": d.class_id,
|
|
59
|
+
"class_name": d.class_name,
|
|
60
|
+
"confidence": d.confidence,
|
|
61
|
+
"x1": d.bbox[0], "y1": d.bbox[1], "x2": d.bbox[2], "y2": d.bbox[3],
|
|
62
|
+
"source_model": d.source_model,
|
|
63
|
+
})
|
|
64
|
+
pd.DataFrame(rows).to_csv(out_csv, index=False)
|
|
65
|
+
out_json.write_text(json.dumps({"frame_index": args.frame_index, "video": str(video_path), "detections": rows}, indent=2), encoding="utf-8")
|
|
66
|
+
|
|
67
|
+
print("[ADASPUN] Phase-1 detector smoke test complete")
|
|
68
|
+
print(f"[ADASPUN] Detections: {len(detections)}")
|
|
69
|
+
print(f"[ADASPUN] Annotated frame: {out_img}")
|
|
70
|
+
print(f"[ADASPUN] CSV: {out_csv}")
|
|
71
|
+
print(f"[ADASPUN] JSON: {out_json}")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if __name__ == "__main__":
|
|
75
|
+
main()
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import re
|
|
6
|
+
import cv2
|
|
7
|
+
|
|
8
|
+
IMG_EXTS = {".png", ".jpg", ".jpeg", ".bmp", ".tif", ".tiff"}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def natural_key(p: Path):
|
|
12
|
+
return [int(t) if t.isdigit() else t.lower() for t in re.split(r"(\d+)", p.stem)]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def list_images(d: Path):
|
|
16
|
+
return sorted([p for p in d.iterdir() if p.is_file() and p.suffix.lower() in IMG_EXTS], key=natural_key)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def make_video(files, out_path: Path, fps: float):
|
|
20
|
+
first = cv2.imread(str(files[0]))
|
|
21
|
+
if first is None:
|
|
22
|
+
raise RuntimeError(f"Could not read {files[0]}")
|
|
23
|
+
h, w = first.shape[:2]
|
|
24
|
+
out_path.parent.mkdir(parents=True, exist_ok=True)
|
|
25
|
+
writer = cv2.VideoWriter(str(out_path), cv2.VideoWriter_fourcc(*"mp4v"), fps, (w, h))
|
|
26
|
+
for i, p in enumerate(files):
|
|
27
|
+
img = cv2.imread(str(p))
|
|
28
|
+
if img is None:
|
|
29
|
+
continue
|
|
30
|
+
if img.shape[:2] != (h, w):
|
|
31
|
+
img = cv2.resize(img, (w, h))
|
|
32
|
+
writer.write(img)
|
|
33
|
+
if (i + 1) % 100 == 0:
|
|
34
|
+
print(f"wrote {i+1}/{len(files)} to {out_path.name}")
|
|
35
|
+
writer.release()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def main() -> None:
|
|
39
|
+
ap = argparse.ArgumentParser(description="Create synchronized left/right videos from stereo image folders.")
|
|
40
|
+
ap.add_argument("--left-dir", required=True)
|
|
41
|
+
ap.add_argument("--right-dir", required=True)
|
|
42
|
+
ap.add_argument("--out-left", required=True)
|
|
43
|
+
ap.add_argument("--out-right", required=True)
|
|
44
|
+
ap.add_argument("--fps", type=float, default=10.0)
|
|
45
|
+
args = ap.parse_args()
|
|
46
|
+
|
|
47
|
+
lefts = list_images(Path(args.left_dir))
|
|
48
|
+
rights = list_images(Path(args.right_dir))
|
|
49
|
+
rb = {p.stem: p for p in rights}
|
|
50
|
+
pairs = [(l, rb[l.stem]) for l in lefts if l.stem in rb]
|
|
51
|
+
if not pairs:
|
|
52
|
+
n = min(len(lefts), len(rights))
|
|
53
|
+
pairs = list(zip(lefts[:n], rights[:n]))
|
|
54
|
+
print(f"paired frames: {len(pairs)}")
|
|
55
|
+
make_video([p[0] for p in pairs], Path(args.out_left), args.fps)
|
|
56
|
+
make_video([p[1] for p in pairs], Path(args.out_right), args.fps)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
main()
|