DSH (德胜河) dual-camera safety detection system. A panorama + PTZ camera pair detects people in a construction zone, captures PTZ close-ups, uploads images to S3-compatible OSS, and pushes batch reports to a third-party platform.
Two subdirectories:
dual_camera_system/ — main FastAPI service (production code)testrk3588/ — standalone test scripts for RK3588 NPU inference (not part of the main app)# Local dev (macOS)
cd dual_camera_system
pip install -r requirements.txt
python main.py --port 8000
# On RK3588 device
conda activate rknn
cd /home/admin/dsh/dual_camera_system
python main.py --host 0.0.0.0 --port 8000
# Service management (on device)
./service.sh start|stop|restart|status
Model selection is automatic per platform via config/detection.py:_default_model():
/home/admin/testrk3588/yolo26n_end2end.rknn/Users/wenhongquan/Desktop/阿里云同步/项目/dnn/sb/model/yolo11n.pt/home/wen/dsh/yolo/yolo11n.ptOverride with --model <path> and --model-size n|s|m|l|x CLI flags.
config/device.pyconfig/__init__.py imports from .device import DEVICE_CONFIG, THIRD_PARTY_CONFIG, STORAGE_CONFIG but no device.py exists in the repo. This means import config will fail with ImportError. You must create config/device.py with these three dicts before the service can start. Check devices.md and oss.py for the expected shape.
main.py → app.py (FastAPI factory)
├── StreamManager (RTSP capture threads)
├── DetectorService (YOLO/RKNN inference)
├── CaptureUploader (image save + OSS upload)
├── ThirdPartyPusher (HTTP batch report to platform)
└── FileCleanup workers
Config lives in config/ split by concern: camera.py, detection.py, oss.py, system.py, device.py (missing).
rknn192.168.8.3 (SSH admin/admin)10.126.126.1 (SSH admin/admin)192.168.8.x (test) / 192.168.20.x (prod), port 554http://58.213.48.57:15900, bucket wvpdevices.md has full device inventory, RTSP URLs, SSH commandspanorama_camera.py sets env var before importing cv2:
os.environ['OPENCV_FFMPEG_CAPTURE_OPTIONS'] = 'rtsp_transport;tcp|threads;1'
This must happen before cv2 import to prevent FFmpeg async_lock assertion crashes. All RTSP reads go through video_lock.py:safe_read() with per-camera locks.
.ruff_cache and .mypy_cache are gitignored but no ruff/mypy config exists.testrk3588/ is standalone test code with its own requirements.txt — not a dependency of the main service.config/camera.py and config/oss.py. These match devices.md — update both when changing devices.service.sh hardcodes paths to /home/admin/dsh/dual_camera_system — only works on the RK3588 device.