diff --git a/.dockerignore b/.dockerignore index 8172ca39a..abf0713fe 100644 --- a/.dockerignore +++ b/.dockerignore @@ -13,3 +13,4 @@ /tags /compile_commands.json /build_output +/output diff --git a/.gitattributes b/.gitattributes index 0c2a1bd07..385fdd20e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -22,6 +22,9 @@ *.css text eol=lf *.scss text eol=lf *.html text eol=lf +*.txt text eol=lf +*.log text eol=lf +*.svg text eol=lf CMakeLists.txt text eol=lf Makefile text eol=lf @@ -31,8 +34,11 @@ Makefile text eol=lf # 二进制文件不做转换 *.bmodel binary +*.nn binary *.onnx binary +*.rknn binary *.so binary +*.so.* binary *.a binary *.png binary *.jpg binary diff --git a/.github/workflows/ci-build-rk3576.yml b/.github/workflows/ci-build-rk3576.yml new file mode 100644 index 000000000..e0726a0bd --- /dev/null +++ b/.github/workflows/ci-build-rk3576.yml @@ -0,0 +1,76 @@ +name: Nightly RK3576 Cross Build + +on: + # Run daily at 02:12 Beijing Time (18:12 UTC on the previous day). + schedule: + - cron: '12 18 * * *' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + build-rk3576: + runs-on: ubuntu-latest + timeout-minutes: 90 + + steps: + - name: Checkout code + uses: actions/checkout@v7 + with: + submodules: recursive + + - name: Validate RK3576 Compose entry + run: docker compose -f docker-compose.rk3576.yml config --quiet + + - name: Pull pinned RK3576 builder with RKLLM + run: docker compose -f docker-compose.rk3576.yml pull cosmo-rk3576-package + + - name: Build RK3576 package and tests + run: docker compose -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package + + - name: Verify RK3576 artifacts + run: | + set -euo pipefail + shopt -s nullglob + packages=(build_output/rk3576/cosmo-*.tar.gz) + if (( ${#packages[@]} != 1 )) || [[ ! -f "${packages[0]:-}" || -L "${packages[0]:-}" ]]; then + echo "Expected exactly one regular RK3576 package artifact." >&2 + exit 1 + fi + package="${packages[0]}" + package_name="${package##*/}" + digest="$(sha256sum -- "$package")" + digest="${digest%% *}" + printf '%s %s\n' "$digest" "$package" | tee rk3576-package.sha256 + package_listing="$(tar -tzf "$package")" + grep -Eq '/lib/librkllmrt[.]so$' <<< "$package_listing" + grep -Eq '/share/licenses/rkllm/LICENSE$' <<< "$package_listing" + for binary in build_rknn/cosmo-tests build_rknn/cosmo-rknn-backend-smoke build_rknn/cosmo-rknn-fastpath-qualify; do + binary_info="$(file "$binary")" + printf '%s\n' "$binary_info" + grep -Fq 'ARM aarch64' <<< "$binary_info" + done + docker compose -f docker-compose.rk3576.yml run --rm --entrypoint /usr/bin/python3 \ + cosmo-rk3576-package -I -B scripts/verify_package_contents.py \ + --archive "/build_output/rk3576/$package_name" --build-profile public-runtime + printf '## RK3576 candidate\n\n- Package: `%s`\n- SHA-256: `%s`\n' \ + "$package_name" "$digest" >> "$GITHUB_STEP_SUMMARY" + + - name: Upload RK3576 candidate + uses: actions/upload-artifact@v7 + with: + name: rk3576-candidate-${{ github.sha }} + path: | + build_output/rk3576/*.tar.gz + rk3576-package.sha256 + build_rknn/cosmo-tests + build_rknn/cosmo-rknn-backend-smoke + build_rknn/cosmo-rknn-fastpath-qualify + if-no-files-found: error + overwrite: true + retention-days: 7 diff --git a/.github/workflows/nightly-build-test-sophon.yml b/.github/workflows/nightly-build-test-sophon.yml index 58249e53e..a09949cfd 100644 --- a/.github/workflows/nightly-build-test-sophon.yml +++ b/.github/workflows/nightly-build-test-sophon.yml @@ -14,6 +14,11 @@ jobs: build-sophon: runs-on: ubuntu-latest timeout-minutes: 60 + outputs: + candidate_guard_sha256: ${{ steps.candidate_guard_runtime.outputs.sha256 }} + candidate_tests_sha256: ${{ steps.candidate_test_binary.outputs.sha256 }} + env: + COSMO_MODEL_GUARD_BUILD_PROFILE: public-runtime # Specify the public container image for the build environment container: @@ -26,13 +31,13 @@ jobs: submodules: recursive # Recommended if the repository uses git submodules # Enforce project standards: use the unified build script instead of cmake directly. - # A single configure builds the clean production package and cosmo-tests + # A single configure builds the clean public-runtime package and cosmo-tests # together, sharing one set of compiled OBJECT libraries; coverage is off # by default (COSMO_ENABLE_COVERAGE), so the package binary stays clean. - name: Build package and tests run: | chmod +x scripts/build.sh - ./scripts/build.sh -T + ./scripts/build.sh -T -c bm1688 # Upload the build artifacts for deployment or download - name: Upload Artifacts @@ -41,13 +46,62 @@ jobs: name: sophon-build-package # Path where the built binaries/packages are generated by scripts/build.sh path: build/install/ + overwrite: true retention-days: 3 + - name: Record Candidate Test Binary + id: candidate_test_binary + run: | + set -euo pipefail + binary="build/cosmo-tests" + if [ ! -f "$binary" ] || [ -L "$binary" ]; then + echo "Candidate test binary is not a regular file: $binary" >&2 + exit 1 + fi + digest="$(sha256sum "$binary" | awk '{print $1}')" + if [ "${#digest}" -ne 64 ] || [[ "$digest" == *[!0-9a-f]* ]]; then + echo "Invalid Candidate test binary SHA-256: $digest" >&2 + exit 1 + fi + echo "sha256=$digest" >> "$GITHUB_OUTPUT" + echo "Candidate test binary SHA-256: $digest" + - name: Upload Test Binary uses: actions/upload-artifact@v7 with: name: sophon-tests-binary path: build/cosmo-tests + if-no-files-found: error + overwrite: true + retention-days: 1 + + - name: Record Candidate Guard Runtime + id: candidate_guard_runtime + run: | + set -euo pipefail + runtime="build/install/lib/libcosmo_model_guard.so.2.0.0" + if [ ! -f "$runtime" ] || [ -L "$runtime" ]; then + echo "Candidate Guard runtime is not a regular file: $runtime" >&2 + exit 1 + fi + digest="$(sha256sum "$runtime" | awk '{print $1}')" + if [ "${#digest}" -ne 64 ] || [[ "$digest" == *[!0-9a-f]* ]]; then + echo "Invalid Candidate Guard SHA-256: $digest" >&2 + exit 1 + fi + echo "sha256=$digest" >> "$GITHUB_OUTPUT" + echo "Candidate Guard SHA-256: $digest" + + # Keep the candidate Guard runtime independent from the large package and + # test-binary cache. overwrite=true makes a full job re-run replace the + # artifact, while a failed-job re-run still downloads the build's artifact. + - name: Upload Candidate Guard Runtime + uses: actions/upload-artifact@v7 + with: + name: sophon-model-guard-runtime + path: build/install/lib/libcosmo_model_guard.so.2.0.0 + if-no-files-found: error + overwrite: true retention-days: 1 test-sophon: @@ -61,34 +115,100 @@ jobs: COSMO_CATCH2_RESULTS_DIR: test-results/catch2 COSMO_CATCH2_REPORTER: compact COSMO_SOPHON_LD_LIBRARY_PATH: /appfs/cosmo_wander/cwai_data/lib:/data:/usr/lib + COSMO_CANDIDATE_RUNTIME_DIR: ${{ github.workspace }}/candidate-runtime + COSMO_CANDIDATE_GUARD_SHA256: ${{ needs.build-sophon.outputs.candidate_guard_sha256 }} + COSMO_CANDIDATE_TESTS_SHA256: ${{ needs.build-sophon.outputs.candidate_tests_sha256 }} steps: + # The test binary may be restored from the persistent device cache, but + # the Guard library must always come from this build's current artifact. + - name: Prepare Candidate Guard Runtime Directory + run: | + set -euo pipefail + expected_dir="$GITHUB_WORKSPACE/candidate-runtime" + if [ "$COSMO_CANDIDATE_RUNTIME_DIR" != "$expected_dir" ]; then + echo "Refusing unexpected candidate runtime directory: $COSMO_CANDIDATE_RUNTIME_DIR" >&2 + exit 1 + fi + rm -rf -- "$COSMO_CANDIDATE_RUNTIME_DIR" + mkdir -p -- "$COSMO_CANDIDATE_RUNTIME_DIR" + + - name: Download Candidate Guard Runtime + uses: actions/download-artifact@v8 + with: + name: sophon-model-guard-runtime + path: candidate-runtime + + - name: Verify Candidate Guard Runtime + run: | + set -euo pipefail + runtime="$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so.2.0.0" + if [ ! -f "$runtime" ] || [ -L "$runtime" ]; then + echo "Downloaded Candidate Guard runtime is not a regular file: $runtime" >&2 + exit 1 + fi + if [ "${#COSMO_CANDIDATE_GUARD_SHA256}" -ne 64 ] \ + || [[ "$COSMO_CANDIDATE_GUARD_SHA256" == *[!0-9a-f]* ]]; then + echo "Missing or invalid expected Candidate Guard SHA-256." >&2 + exit 1 + fi + actual_sha256="$(sha256sum "$runtime" | awk '{print $1}')" + if [ "$actual_sha256" != "$COSMO_CANDIDATE_GUARD_SHA256" ]; then + echo "Candidate Guard SHA-256 mismatch." >&2 + echo "Expected: $COSMO_CANDIDATE_GUARD_SHA256" >&2 + echo "Actual: $actual_sha256" >&2 + exit 1 + fi + ln -s -- "libcosmo_model_guard.so.2.0.0" \ + "$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so.2" + ln -s -- "libcosmo_model_guard.so.2" \ + "$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so" + test "$(readlink "$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so.2")" \ + = "libcosmo_model_guard.so.2.0.0" + test "$(readlink "$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so")" \ + = "libcosmo_model_guard.so.2" + echo "Candidate Guard runtime verified: $actual_sha256" + # The Download step below is the dominant wall-clock cost on this # self-hosted device (fetching the artifact from GitHub over a slow link # routinely takes 7-13 min, vs seconds-to-minutes for the tests). On # "Re-run failed jobs" the whole job re-runs, so we cache the binary on - # the device's persistent filesystem keyed by GITHUB_RUN_ID (stable across - # re-run attempts) and skip re-downloading on a cache hit. - # CAVEAT: "Re-run all jobs" rebuilds the binary under the same artifact - # name; this cache would then serve a stale binary. Before a full re-run, - # clear the cache dir on the device (rm -rf $HOME/cosmo-ci-cache). + # the device's persistent filesystem keyed by both GITHUB_RUN_ID and the + # build-produced SHA-256. A full job re-run therefore cannot reuse a stale + # binary, while a failed-job re-run can still skip the large download. - name: Restore Test Binary From Device Cache id: binary-cache run: | set -euo pipefail + if [ "${#COSMO_CANDIDATE_TESTS_SHA256}" -ne 64 ] \ + || [[ "$COSMO_CANDIDATE_TESTS_SHA256" == *[!0-9a-f]* ]]; then + echo "Missing or invalid expected Candidate test binary SHA-256." >&2 + exit 1 + fi # $HOME persists across runs and is outside the per-job workspace # GitHub cleans, so a file saved here survives across attempts. # Override the dir by setting COSMO_TEST_BINARY_CACHE_DIR in env. cache_dir="${COSMO_TEST_BINARY_CACHE_DIR:-$HOME/cosmo-ci-cache}" mkdir -p "$cache_dir" - cached="$cache_dir/cosmo-tests-${GITHUB_RUN_ID}" - if [ -f "$cached" ]; then - cp "$cached" ./cosmo-tests - echo "cache-hit=true" >> "$GITHUB_OUTPUT" - echo "Restored cosmo-tests from $cached (skipping artifact download)." + cached="$cache_dir/cosmo-tests-${GITHUB_RUN_ID}-${COSMO_CANDIDATE_TESTS_SHA256}" + if [ -f "$cached" ] && [ ! -L "$cached" ]; then + cached_sha256="$(sha256sum "$cached" | awk '{print $1}')" + if [ "$cached_sha256" = "$COSMO_CANDIDATE_TESTS_SHA256" ]; then + cp -- "$cached" ./cosmo-tests + restored_sha256="$(sha256sum ./cosmo-tests | awk '{print $1}')" + if [ "$restored_sha256" != "$COSMO_CANDIDATE_TESTS_SHA256" ]; then + echo "Restored Candidate test binary SHA-256 mismatch." >&2 + exit 1 + fi + echo "cache-hit=true" >> "$GITHUB_OUTPUT" + echo "Restored verified cosmo-tests from $cached (skipping artifact download)." + else + echo "cache-hit=false" >> "$GITHUB_OUTPUT" + echo "Ignoring corrupt test-binary cache entry: $cached" + fi else echo "cache-hit=false" >> "$GITHUB_OUTPUT" - echo "No cached binary for run ${GITHUB_RUN_ID}; will download." + echo "No verified cache entry for run ${GITHUB_RUN_ID} and SHA ${COSMO_CANDIDATE_TESTS_SHA256}; will download." fi - name: Download Test Binary @@ -98,19 +218,42 @@ jobs: name: sophon-tests-binary path: . + - name: Verify Candidate Test Binary + run: | + set -euo pipefail + if [ ! -f ./cosmo-tests ] || [ -L ./cosmo-tests ]; then + echo "Candidate test binary is not a regular file." >&2 + exit 1 + fi + actual_sha256="$(sha256sum ./cosmo-tests | awk '{print $1}')" + if [ "$actual_sha256" != "$COSMO_CANDIDATE_TESTS_SHA256" ]; then + echo "Candidate test binary SHA-256 mismatch." >&2 + echo "Expected: $COSMO_CANDIDATE_TESTS_SHA256" >&2 + echo "Actual: $actual_sha256" >&2 + exit 1 + fi + echo "Candidate test binary verified: $actual_sha256" + - name: Save Test Binary To Device Cache if: steps.binary-cache.outputs.cache-hit != 'true' && success() run: | set -euo pipefail cache_dir="${COSMO_TEST_BINARY_CACHE_DIR:-$HOME/cosmo-ci-cache}" - cached="$cache_dir/cosmo-tests-${GITHUB_RUN_ID}" - cp ./cosmo-tests "$cached" + cached="$cache_dir/cosmo-tests-${GITHUB_RUN_ID}-${COSMO_CANDIDATE_TESTS_SHA256}" + pending="${cached}.pending-${GITHUB_RUN_ATTEMPT}" + cp --remove-destination -- ./cosmo-tests "$pending" + pending_sha256="$(sha256sum "$pending" | awk '{print $1}')" + if [ "$pending_sha256" != "$COSMO_CANDIDATE_TESTS_SHA256" ]; then + echo "Refusing to cache test binary with mismatched SHA-256." >&2 + exit 1 + fi + mv -f -- "$pending" "$cached" # Prune to the 5 most-recent entries; never touch the current run. # `|| true`: grep exits 1 when only the current run's file exists # (nothing left after filtering), which under `set -o pipefail` would # otherwise fail this step. Pruning is best-effort cleanup. ls -t "$cache_dir"/cosmo-tests-* 2>/dev/null \ - | grep -v -F -- "cosmo-tests-${GITHUB_RUN_ID}" \ + | grep -v -F -- "$cached" \ | tail -n +6 \ | xargs -r rm -f || true echo "Saved cosmo-tests to $cached; cache pruned." @@ -118,12 +261,35 @@ jobs: - name: Add Execution Permission run: chmod +x ./cosmo-tests + - name: Verify Candidate Guard Resolution + run: | + set -euo pipefail + export LD_LIBRARY_PATH="$COSMO_CANDIDATE_RUNTIME_DIR:$COSMO_SOPHON_LD_LIBRARY_PATH:${LD_LIBRARY_PATH:-}" + if ! command -v ldd >/dev/null 2>&1; then + echo "Required command is missing: ldd" >&2 + exit 1 + fi + resolved="$(ldd ./cosmo-tests \ + | awk '$1 == "libcosmo_model_guard.so.2" && $2 == "=>" {print $3; exit}')" + if [ -z "$resolved" ]; then + echo "cosmo-tests did not resolve libcosmo_model_guard.so.2." >&2 + exit 1 + fi + expected_real="$(readlink -f \ + "$COSMO_CANDIDATE_RUNTIME_DIR/libcosmo_model_guard.so.2.0.0")" + resolved_real="$(readlink -f "$resolved")" + if [ "$resolved_real" != "$expected_real" ]; then + echo "cosmo-tests resolved a non-candidate Guard runtime: $resolved" >&2 + exit 1 + fi + echo "cosmo-tests resolves Candidate Guard runtime: $resolved_real" + - name: Run Catch2 Tests run: | set +e set -uo pipefail - export LD_LIBRARY_PATH="$COSMO_SOPHON_LD_LIBRARY_PATH:${LD_LIBRARY_PATH:-}" + export LD_LIBRARY_PATH="$COSMO_CANDIDATE_RUNTIME_DIR:$COSMO_SOPHON_LD_LIBRARY_PATH:${LD_LIBRARY_PATH:-}" shard_count="$COSMO_CATCH2_SHARDS" shard_timeout_seconds="$COSMO_CATCH2_SHARD_TIMEOUT_SECONDS" diff --git a/.gitignore b/.gitignore index 1921802b6..ad653212c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,8 @@ /artifacts/ /output/ /tmp/ +/docs/evidence/rk3576/ +/tools/scenario-bench/reports/ CLAUDE.md build @@ -19,6 +21,7 @@ build_linux build32 build64 build_cpu +build_rknn build_cpu_windows release tags @@ -541,3 +544,6 @@ test/video/demo.mp4 *.webm *.flv *.m4v + +# Sanitized logs are part of the versioned v1.1 public benchmark evidence pack. +!docs/benchmarks/scenario-bench/v1.1/**/*.log diff --git a/3rd/libsophon-0.4.11/lib/tpu_module/libbm1688_kernel_module.so b/3rd/libsophon-0.4.11/lib/tpu_module/libbm1688_kernel_module.so new file mode 100644 index 000000000..d400eb530 Binary files /dev/null and b/3rd/libsophon-0.4.11/lib/tpu_module/libbm1688_kernel_module.so differ diff --git a/3rd/srs-6.0-r0/trunk/auto/depends.sh b/3rd/srs-6.0-r0/trunk/auto/depends.sh index c9c24df0f..8bd6a19f4 100755 --- a/3rd/srs-6.0-r0/trunk/auto/depends.sh +++ b/3rd/srs-6.0-r0/trunk/auto/depends.sh @@ -61,7 +61,7 @@ perl --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then fi exit $ret; fi -gcc --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then +"${SRS_TOOL_CC}" --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then if [[ $OS_IS_CENTOS == YES ]]; then echo "Please install gcc by:" echo " yum install -y gcc" @@ -73,7 +73,7 @@ gcc --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then fi exit $ret; fi -aarch64-linux-gnu-g++ --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then +"${SRS_TOOL_CXX}" --version >/dev/null 2>/dev/null; ret=$?; if [[ 0 -ne $ret ]]; then if [[ $OS_IS_CENTOS == YES ]]; then echo "Please install g++ by:" echo " yum install -y gcc-c++" diff --git a/AGENTS.md b/AGENTS.md index ff3c1ffd7..e34f4bfc0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -16,8 +16,9 @@ workflow. implemented task-specific executors. - `tools/` — Python and Node validation utilities. - `test/` — Catch2 tests and the HTTP/MQTT push test service. -- `data/resource/aiboxresource/` and `data/resource/aiboxresource_x86/` — - Sophon and x86 model resources and templates. +- `data/resource/aiboxresource_bm1688/`, `data/resource/aiboxresource_cv186x/`, + and `data/resource/aiboxresource_x86/` — platform-scoped Sophon and x86 model + resources and templates. - `3rd/` and `prebuild/` — third-party and prebuilt dependencies; do not edit. ## Mandatory agent-assistance trigger diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a028d000..139bdf92d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,105 @@ This project follows a release-note style inspired by Keep a Changelog. ## [Unreleased] +### 1.1.0 release candidate + +Multi-platform release for BM1688, CV186X, RK3576, and x86. Capacity claims remain bound to the +models, packages, environments, thresholds, and durations recorded in their linked evidence. + +### Added + +- CV186X benchmark bindings for the open Sophon YOLOV8n detector and helmet classifier, including + byte-identical device/repository hashes, runtime contracts, and a dedicated CV186X Open-package + resource set. +- Rockchip RK3576 integration with an RKNN inference backend, native MPP/RGA media pipeline, + cross-compilation toolchain, accelerator telemetry, integration assets, and + qualification fixtures. +- Platform-neutral host/backend and media-factory contracts, derived model-artifact identities, + accelerator and preview-pipeline metrics, and ScenarioBench preview validation for additional + accelerator families. +- Chip-agnostic Sophon model-directory discovery and explicit `chip_type` validation, preparing a + shared model metadata and import path for BM1688 and CV186X while keeping compiled artifacts + target-specific. +- Model Guard 2.3 support for loading CEMC-protected commercial preset models through the CMG + runtime, device authorization, Open/Protected Sophon package profiles, protected-resource + checks, and SOURCE deployment. Open packages continue to support plaintext user models without + device authorization. +- Persistent, resumable staged uploads with idempotent client requests, restart recovery, + cancellation, and real-time disk/memory admission. Large models, images, videos, and files now + stream instead of depending on fixed total-size limits; exports support single HTTP Range + requests (`206`/`416`) and deterministic temporary-file cleanup. +- Detection target details in HTTP event payloads, including persistence/retry propagation and + target rendering in the HTTP push-test service. +- Platform-neutral offline accuracy validation and CI gates for ScenarioBench and accuracy tools. +- Agent-assisted secondary-development tooling for environment admission, chip compatibility, + measured model-conversion evidence, and evidence lifecycle governance. +- AVI, DAV, and MKV local-video inputs, plus the restored license-plate OCR workflow. + +### Changed + +- Improved cross-platform CV detector capacity and runtime efficiency through per-task FPS-aware + `AiDetector` placement, platform-neutral performance telemetry, more efficient media and buffer + lifecycles, and backend-specific Sophon and RKNN data-path optimizations. +- Optimized the RK3576 detector path with RGA/MPP-backed preprocessing, native quantized tensor + handling, persistent RKNN input memory, direct YOLOv8 output decoding, decoder reuse, and + qualified NPU core scheduling. +- Improved Sophon high-rate and long-running workloads through lower detector reuse defaults, + glibc allocator tuning, bounded repeated-stream decoder warm-up handling, and explicit BMRuntime + ownership. +- Reduced preview startup and overlay-switch latency, strengthened publisher recovery and preview + lifecycle handling, serialized concurrent OSD sessions, and exposed preview pipeline metrics. +- Batched arbitrary numbers of accepted same-frame alarm targets into one event while retaining + per-target filtering and metadata; reset tracking and suppression state when tasks restart. +- Expanded area-alarm rule interaction, region-rule localization, runtime translations, and task + category refresh behavior in the web console. +- Unified Sophon package upgrades on the legacy-compatible permanent-MD5 lifecycle, including + legacy installer invocation, safe internal symlinks, upgrade recovery, and Open/Protected model + lifecycle checks. Application archives themselves remain unsigned. +- Simplified linkage runtime task handling and made task saves atomic under resource pressure. +- Hardened change validation, sharded Sophon tests, and aligned ScenarioBench capacity, VLM + throughput, preview-load, report, and cleanup behavior with the current staging protocol. + +### Fixed + +- RTSP URLs whose passwords contain `@`, and algorithm-file names with leading-zero prefixes. +- HTTP, WebSocket, multicast-discovery, periodic-timer, shared-database, camera-task, task-binding, + memory-pool, and thread-pool lifetime/concurrency defects. +- Live-preview playback, padded Annex-B packets, publisher recovery, unbound algorithm previews, + small startup keyframes, and multi-second overlay-preview black screens. +- Sophon crop validation and odd-dimension image decoding, including even-dimension frame + alignment for face import. +- Upload and extraction reserve edge cases, image-analysis JSON capacity, media MIME handling, + upgrade recovery, and propagation of HTTP client transfer failures. +- Area-alarm interval handling for same-frame tracked and untracked targets, including zero track + IDs and restart-safe suppression state. +- DINO model/task contract validation, HandFrame exception log storms, RKNN classifier and FP16 + input compatibility, and shared-detector throughput accounting. +- Windows Docker checkout/web-port handling, generated mp4v2 timestamps, and cross-backend CPU + allocator linkage. + +### Security + +- Blocked `pictureUrl` path traversal in image-library APIs and retained bounded request parsing + while routing product-sized content through resource-aware streaming paths. +- Externalized manager signing credentials and tightened protected-resource/package admission and + device-authorization handling. +- Prevented encrypted preset-model export and deletion, with an explicit factory-restore path. +- Hardened upgrade-package verification while permitting safe package-internal symlinks. + +### Docs + +- Reworked the English and Simplified Chinese README files around the v1.1 platform matrix, + Open/Protected boundary, published validation baselines, and task-oriented quick starts. +- Added official website links, certified-device purchase links, x86 first-run verification, an + Ultralytics YOLO deployment guide, and reusable community-case documentation. +- Expanded and restored the bilingual system guide, region-alarm tutorials, runtime localization, + and model/resource references. +- Added the bilingual CosmoEdge 1.1 multi-platform ScenarioBench report, sanitized single-detector, + dual-detector, and Experimental VLM attachments, environment/model identities, reproduction + descriptors, release manifest, and file checksums. +- Added the agent-assisted development entry, environment and model-conversion guidance, and a + contributor pre-commit hook guide. + ## [1.0.0] - 2026-07-03 First stable public release: a security and CI hardening pass plus feature, refactor, and documentation work over the `v0.1.0` baseline. @@ -83,12 +182,13 @@ Initial public open-source baseline. - Sample camera credentials and device serial values scrubbed from examples. - Sophon build environment Dockerfile made self-contained. -[Unreleased]: https://github.com/cosmo-wander-ai/cosmo-edge/compare/v1.0.0...HEAD +[Unreleased]: https://github.com/cosmo-wander-ai/cosmo-edge/compare/v1.1.0...HEAD +[1.1.0]: https://github.com/cosmo-wander-ai/cosmo-edge/releases/tag/v1.1.0 [1.0.0]: https://github.com/cosmo-wander-ai/cosmo-edge/releases/tag/v1.0.0 [0.1.0]: https://github.com/cosmo-wander-ai/cosmo-edge/releases -[Unreleased (Gitee)]: https://gitee.com/cosmo-wander-ai/cosmo-edge/compare/v1.0.0...master +[Unreleased (Gitee)]: https://gitee.com/cosmo-wander-ai/cosmo-edge/compare/v1.1.0...master +[1.1.0 (Gitee)]: https://gitee.com/cosmo-wander-ai/cosmo-edge/releases [1.0.0 (Gitee)]: https://gitee.com/cosmo-wander-ai/cosmo-edge/releases [0.1.0 (Gitee)]: https://gitee.com/cosmo-wander-ai/cosmo-edge/releases - diff --git a/CMakeLists.txt b/CMakeLists.txt index f300d44cf..d58fc9f0a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,24 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +# Keep the existing numeric version formats while deriving a unique patch +# number from the nearest vX.Y.Z tag and the number of commits after it. +# Source archives without Git metadata retain the historical fallback version. +include("${CMAKE_SOURCE_DIR}/cmake/CosmoVersion.cmake") +cosmo_resolve_version("${CMAKE_SOURCE_DIR}" 1 1 0 0) +set(VER_MAJOR "${COSMO_VERSION_MAJOR}") +set(VER_MINOR "${COSMO_VERSION_MINOR}") +set(VER_PATCH "${COSMO_VERSION_PATCH}") +add_compile_definitions( + COSMO_VERSION_MAJOR=${COSMO_VERSION_MAJOR} + COSMO_VERSION_MINOR=${COSMO_VERSION_MINOR} + COSMO_VERSION_PATCH=${COSMO_VERSION_PATCH} + COSMO_VERSION_BUILD=${COSMO_VERSION_BUILD} +) +message(STATUS + "Cosmo version: V${COSMO_VERSION_MAJOR}.${COSMO_VERSION_MINOR}." + "${COSMO_VERSION_PATCH}.${COSMO_VERSION_BUILD} (${COSMO_VERSION_SOURCE})") + #Generate compile_commands.json for static analysis tools(clang - tidy, IDE) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) @@ -84,12 +102,19 @@ endif() #-- Backend selection(mutually exclusive) -- option(COSMO_NN_USE_SOPHON_BACKEND "Enable Sophon TPU backend" ON) option(COSMO_NN_USE_CPU_BACKEND "Enable CPU inference backend (ONNX Runtime)" OFF) +option(COSMO_NN_USE_RKNN_BACKEND "Enable Rockchip RKNN backend" OFF) -if(COSMO_NN_USE_SOPHON_BACKEND AND COSMO_NN_USE_CPU_BACKEND) - message(FATAL_ERROR "COSMO_NN_USE_SOPHON_BACKEND and COSMO_NN_USE_CPU_BACKEND are mutually exclusive") -endif() -if(NOT COSMO_NN_USE_SOPHON_BACKEND AND NOT COSMO_NN_USE_CPU_BACKEND) - message(FATAL_ERROR "At least one NN backend must be enabled") +set(_cosmo_nn_backend_count 0) +foreach(_nn_backend_option + COSMO_NN_USE_SOPHON_BACKEND + COSMO_NN_USE_CPU_BACKEND + COSMO_NN_USE_RKNN_BACKEND) + if(${_nn_backend_option}) + math(EXPR _cosmo_nn_backend_count "${_cosmo_nn_backend_count} + 1") + endif() +endforeach() +if(NOT _cosmo_nn_backend_count EQUAL 1) + message(FATAL_ERROR "Exactly one NN backend must be enabled: Sophon, CPU, or RKNN") endif() # Media acceleration is selected independently from inference. Defaults keep @@ -97,8 +122,12 @@ endif() # paired with another inference backend. set(_cosmo_media_sophon_default OFF) set(_cosmo_media_cpu_default OFF) +set(_cosmo_media_rockchip_default OFF) if(COSMO_NN_USE_SOPHON_BACKEND) set(_cosmo_media_sophon_default ON) +elseif(COSMO_NN_USE_RKNN_BACKEND AND + (COSMO_ROCKCHIP_MEDIA_ROOT OR DEFINED ENV{ROCKCHIP_MEDIA_ROOT})) + set(_cosmo_media_rockchip_default ON) else() set(_cosmo_media_cpu_default ON) endif() @@ -107,35 +136,42 @@ option(COSMO_MEDIA_USE_SOPHON_BACKEND "Enable Sophon hardware media backend" ${_cosmo_media_sophon_default}) option(COSMO_MEDIA_USE_CPU_BACKEND "Enable FFmpeg software media backend" ${_cosmo_media_cpu_default}) +option(COSMO_MEDIA_USE_ROCKCHIP_BACKEND "Enable Rockchip MPP/RGA Copy-first media backend" + ${_cosmo_media_rockchip_default}) set(_cosmo_media_backend_count 0) foreach(_media_backend_option COSMO_MEDIA_USE_SOPHON_BACKEND - COSMO_MEDIA_USE_CPU_BACKEND) + COSMO_MEDIA_USE_CPU_BACKEND + COSMO_MEDIA_USE_ROCKCHIP_BACKEND) if(${_media_backend_option}) math(EXPR _cosmo_media_backend_count "${_cosmo_media_backend_count} + 1") endif() endforeach() if(NOT _cosmo_media_backend_count EQUAL 1) - message(FATAL_ERROR "Exactly one media backend must be enabled: Sophon or CPU") + message(FATAL_ERROR "Exactly one media backend must be enabled: Sophon, CPU, or Rockchip") endif() if(COSMO_MEDIA_USE_SOPHON_BACKEND AND NOT COSMO_NN_USE_SOPHON_BACKEND) message(FATAL_ERROR "Sophon media requires the Sophon device runtime") endif() +if(COSMO_MEDIA_USE_ROCKCHIP_BACKEND AND NOT COSMO_TARGET_ARCH STREQUAL "aarch64") + message(FATAL_ERROR "Rockchip media requires an aarch64 target") +endif() if(COSMO_MEDIA_USE_SOPHON_BACKEND) add_compile_definitions(COSMO_MEDIA_USE_SOPHON_BACKEND) +elseif(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + add_compile_definitions(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) else() add_compile_definitions(COSMO_MEDIA_USE_CPU_BACKEND) endif() -if(COSMO_MEDIA_USE_CPU_BACKEND) - set(COSMO_ENABLE_OPENH264 ON) - set(COSMO_OPENH264_USE_ASM OFF) -else() - set(COSMO_ENABLE_OPENH264 OFF) - set(COSMO_OPENH264_USE_ASM OFF) +set(_cosmo_openh264_default OFF) +if(COSMO_MEDIA_USE_CPU_BACKEND AND COSMO_TARGET_ARCH STREQUAL "x86_64") + set(_cosmo_openh264_default ON) endif() +option(COSMO_ENABLE_OPENH264 "Require the bundled OpenH264 encoder" ${_cosmo_openh264_default}) +set(COSMO_OPENH264_USE_ASM OFF) if(COSMO_NN_USE_SOPHON_BACKEND) set(COSMO_MODEL_GUARD ON) @@ -143,16 +179,127 @@ else() set(COSMO_MODEL_GUARD OFF) endif() +set(COSMO_MODEL_GUARD_BUILD_PROFILE "public-runtime" CACHE STRING + "Model Guard build profile: public-runtime or production-release") +set_property(CACHE COSMO_MODEL_GUARD_BUILD_PROFILE PROPERTY STRINGS + public-runtime production-release) +set(COSMO_PACKAGE_MODELS "include" CACHE STRING + "Package preset models: include or preserve the installed model directory") +set_property(CACHE COSMO_PACKAGE_MODELS PROPERTY STRINGS include preserve) +if(NOT COSMO_PACKAGE_MODELS STREQUAL "include" AND + NOT COSMO_PACKAGE_MODELS STREQUAL "preserve") + message(FATAL_ERROR "COSMO_PACKAGE_MODELS must be include or preserve") +endif() +set(COSMO_MODEL_GUARD_BUILD_PROFILES public-runtime production-release) +if(NOT COSMO_MODEL_GUARD_BUILD_PROFILE IN_LIST + COSMO_MODEL_GUARD_BUILD_PROFILES) + message(FATAL_ERROR + "Unsupported COSMO_MODEL_GUARD_BUILD_PROFILE=" + "${COSMO_MODEL_GUARD_BUILD_PROFILE}. Expected public-runtime or " + "production-release.") +endif() + if(COSMO_MODEL_GUARD) - # .so is pre-installed in system image at /usr/lib/ or provided in prebuild/ - find_library(MODEL_GUARD_LIB cosmo_model_guard - PATHS /usr/lib ${CMAKE_SOURCE_DIR}/prebuild - NO_DEFAULT_PATH) - if(MODEL_GUARD_LIB) - message(STATUS "Model guard enabled: ${MODEL_GUARD_LIB}") - else() - message(WARNING "COSMO_MODEL_GUARD=ON but libcosmo_model_guard.so not found — " - "encrypted models will fail at runtime") + set(COSMO_MODEL_GUARD_SDK_ROOT + "${CMAKE_SOURCE_DIR}/prebuild/model-guard-v2" + CACHE PATH "Verified Cosmo Model Guard v2 SDK root") + get_filename_component(COSMO_MODEL_GUARD_SDK_ROOT + "${COSMO_MODEL_GUARD_SDK_ROOT}" ABSOLUTE) + set(MODEL_GUARD_V2_HEADER + "${COSMO_MODEL_GUARD_SDK_ROOT}/include/cosmo_model_guard_v2.h") + set(MODEL_GUARD_V2_LIBRARY + "${COSMO_MODEL_GUARD_SDK_ROOT}/lib/libcosmo_model_guard.so.2.0.0") + if(COSMO_MODEL_GUARD_BUILD_PROFILE STREQUAL "production-release") + set(MODEL_GUARD_V2_PROVISION_TOOL + "${COSMO_MODEL_GUARD_SDK_ROOT}/bin/cosmo-model-provision") + endif() + set(MODEL_GUARD_V2_TEST_FIXTURE_MARKER + "${COSMO_MODEL_GUARD_SDK_ROOT}/share/cosmo-model-guard/TEST_FIXTURE_DO_NOT_DEPLOY") + + set(COSMO_PYTHON3_EXECUTABLE "/usr/bin/python3") + if(NOT EXISTS "${COSMO_PYTHON3_EXECUTABLE}" OR + IS_DIRECTORY "${COSMO_PYTHON3_EXECUTABLE}" OR + NOT CMAKE_READELF OR NOT EXISTS "${CMAKE_READELF}" OR + NOT CMAKE_NM OR NOT EXISTS "${CMAKE_NM}") + message(FATAL_ERROR + "The protected Sophon build requires Python 3 and the target " + "readelf/nm tools to verify the Model Guard v2 SDK") + endif() + + set(MODEL_GUARD_V2_VERIFY_ARGUMENTS + --admission-profile "${COSMO_MODEL_GUARD_BUILD_PROFILE}" + --sdk-root "${COSMO_MODEL_GUARD_SDK_ROOT}" + --readelf "${CMAKE_READELF}" + --nm "${CMAKE_NM}") + if(EXISTS "${MODEL_GUARD_V2_TEST_FIXTURE_MARKER}") + message(FATAL_ERROR + "A marked Model Guard test fixture cannot satisfy either public-runtime " + "or production-release SDK admission") + endif() + + set(MODEL_GUARD_V2_ADMISSION_INPUTS + "${MODEL_GUARD_V2_HEADER}" + "${MODEL_GUARD_V2_LIBRARY}" + "${CMAKE_SOURCE_DIR}/scripts/verify_model_guard_v2_sdk.py") + if(COSMO_MODEL_GUARD_BUILD_PROFILE STREQUAL "production-release") + list(APPEND MODEL_GUARD_V2_ADMISSION_INPUTS + "${MODEL_GUARD_V2_PROVISION_TOOL}") + endif() + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS + ${MODEL_GUARD_V2_ADMISSION_INPUTS}) + + execute_process( + COMMAND "${COSMO_PYTHON3_EXECUTABLE}" -I -B + "${CMAKE_SOURCE_DIR}/scripts/verify_model_guard_v2_sdk.py" + ${MODEL_GUARD_V2_VERIFY_ARGUMENTS} + RESULT_VARIABLE MODEL_GUARD_V2_VERIFY_RESULT + OUTPUT_VARIABLE MODEL_GUARD_V2_VERIFY_OUTPUT + ERROR_VARIABLE MODEL_GUARD_V2_VERIFY_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE + ) + if(NOT MODEL_GUARD_V2_VERIFY_RESULT EQUAL 0) + message(FATAL_ERROR + "COSMO_MODEL_GUARD requires a usable v2 SDK.\n" + "${MODEL_GUARD_V2_VERIFY_ERROR}") + endif() + + string(REGEX MATCH "(^|\n)verified_sdk_root=([^\n]+)" + MODEL_GUARD_V2_VERIFIED_ROOT_LINE "${MODEL_GUARD_V2_VERIFY_OUTPUT}") + set(MODEL_GUARD_V2_VERIFIED_SDK_ROOT "${CMAKE_MATCH_2}") + if(NOT IS_ABSOLUTE "${MODEL_GUARD_V2_VERIFIED_SDK_ROOT}" OR + NOT EXISTS "${MODEL_GUARD_V2_VERIFIED_SDK_ROOT}") + message(FATAL_ERROR "Model Guard verifier did not return a valid SDK root") + endif() + set(MODEL_GUARD_V2_HEADER + "${MODEL_GUARD_V2_VERIFIED_SDK_ROOT}/include/cosmo_model_guard_v2.h") + set(MODEL_GUARD_V2_LIBRARY + "${MODEL_GUARD_V2_VERIFIED_SDK_ROOT}/lib/libcosmo_model_guard.so.2.0.0") + if(COSMO_MODEL_GUARD_BUILD_PROFILE STREQUAL "production-release") + set(MODEL_GUARD_V2_PROVISION_TOOL + "${MODEL_GUARD_V2_VERIFIED_SDK_ROOT}/bin/cosmo-model-provision") + endif() + add_library(cosmo_model_guard_v2 SHARED IMPORTED GLOBAL) + set_target_properties(cosmo_model_guard_v2 PROPERTIES + IMPORTED_LOCATION "${MODEL_GUARD_V2_LIBRARY}" + IMPORTED_SONAME "libcosmo_model_guard.so.2" + INTERFACE_INCLUDE_DIRECTORIES "${MODEL_GUARD_V2_VERIFIED_SDK_ROOT}/include" + ) + message(STATUS "Verified Model Guard v2 SDK:\n${MODEL_GUARD_V2_VERIFY_OUTPUT}") + message(STATUS + "Model Guard build profile: ${COSMO_MODEL_GUARD_BUILD_PROFILE}") +endif() + +if(COSMO_MODEL_GUARD_BUILD_PROFILE STREQUAL "production-release") + if(NOT COSMO_MODEL_GUARD) + message(FATAL_ERROR + "COSMO_MODEL_GUARD_BUILD_PROFILE=production-release requires the " + "protected Sophon build") + endif() + if(NOT COSMO_TARGET_ARCH STREQUAL "aarch64" OR + NOT COSMO_NN_USE_SOPHON_BACKEND) + message(FATAL_ERROR + "The protected build is valid only for Sophon/AArch64") endif() endif() @@ -170,6 +317,13 @@ message(STATUS "\tTarget: ${COSMO_TARGET_ARCH}") set(THIRDPARTY_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/thirdparty_install CACHE PATH "thirdparty install dir") add_custom_target(third_build) +# Third-party projects must not inherit wall-clock or ephemeral container +# identity in release artifacts. +set(COSMO_REPRODUCIBLE_BUILD_EPOCH 1784776233) +set(COSMO_REPRODUCIBLE_BUILD_UTC "2026-07-23 03:10:33") +set(COSMO_REPRODUCIBLE_BUILD_UNAME + "Linux cosmo-build 0.0.0 #1 SMP ${COSMO_TARGET_ARCH} GNU/Linux") + # Pre-create include directories for all ExternalProject-managed libraries. # CMake validates INTERFACE_INCLUDE_DIRECTORIES paths at configure time, but # ExternalProject only installs headers at build time. Without this, a clean @@ -190,11 +344,11 @@ include(cmake/uuid.cmake) include(cmake/uSockets.cmake) include(cmake/mp4v2.cmake) include(cmake/openssl.cmake) +include(cmake/cryptopp.cmake) include(cmake/curl.cmake) include(cmake/mqtt.cmake) include(cmake/event.cmake) include(cmake/ffmpeg.cmake) -include(cmake/cryptopp.cmake) include(cmake/uWebSockets.cmake) include(cmake/tokenizers.cmake) if(COSMO_NN_USE_SOPHON_BACKEND) @@ -203,9 +357,15 @@ endif() if(COSMO_NN_USE_CPU_BACKEND) include(cmake/onnxruntime.cmake) endif() +if(COSMO_NN_USE_RKNN_BACKEND) + include(cmake/rknn.cmake) + include(cmake/rkllm.cmake) +endif() +if(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + include(cmake/rockchip_media.cmake) +endif() include(cmake/pcap.cmake) include(cmake/srs.cmake) - #Header - only third - party libraries add_library(nlohmann INTERFACE) target_include_directories(nlohmann SYSTEM INTERFACE ${CMAKE_SOURCE_DIR}/3rd/include) @@ -315,6 +475,15 @@ endif() if(COSMO_NN_USE_CPU_BACKEND) list(APPEND COMMON_LIBS onnxruntime) endif() +if(COSMO_NN_USE_RKNN_BACKEND) + list(APPEND COMMON_LIBS rknnrt) +endif() +if(COSMO_NN_USE_RKLLM_BACKEND) + list(APPEND COMMON_LIBS rkllmrt) +endif() +if(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + list(APPEND COMMON_LIBS rockchip_mpp rockchip_rga) +endif() ########################################################## #Main Executable @@ -332,9 +501,7 @@ if(COSMO_NN_USE_SOPHON_BACKEND) endif() if(COSMO_MODEL_GUARD) target_compile_definitions(${EXECUTABLE_NAME} PRIVATE COSMO_HAS_MODEL_GUARD=1) - if(MODEL_GUARD_LIB) - target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${MODEL_GUARD_LIB}) - endif() + target_link_libraries(${EXECUTABLE_NAME} PRIVATE cosmo_model_guard_v2) endif() if(COSMO_NN_USE_CPU_BACKEND) target_compile_definitions(${EXECUTABLE_NAME} PRIVATE @@ -342,14 +509,63 @@ if(COSMO_NN_USE_CPU_BACKEND) COSMO_NN_USE_HOST_BACKEND COSMO_NN_USE_ONNX_BACKEND) endif() +if(COSMO_NN_USE_RKNN_BACKEND) + target_compile_definitions(${EXECUTABLE_NAME} PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) + set_target_properties(${EXECUTABLE_NAME} PROPERTIES + BUILD_RPATH "${COSMO_RKNN_ROOT}/lib" + INSTALL_RPATH "$ORIGIN/../lib") +endif() +if(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + set_property(TARGET ${EXECUTABLE_NAME} APPEND PROPERTY + BUILD_RPATH "${COSMO_ROCKCHIP_MEDIA_ROOT}/lib") + set_target_properties(${EXECUTABLE_NAME} PROPERTIES + INSTALL_RPATH "$ORIGIN/../lib") +endif() #Build order: OBJECT libs → third_build (explicit, see foreach above) target_link_libraries(${EXECUTABLE_NAME} PRIVATE ${COMMON_LIBS}) +if(COSMO_NN_USE_RKNN_BACKEND) + add_executable(cosmo-rknn-backend-smoke + tools/rknn/cosmo_rknn_backend_smoke.cc + ${ALL_OBJECTS}) + target_include_directories(cosmo-rknn-backend-smoke PRIVATE ${CMAKE_SOURCE_DIR}/src) + target_compile_definitions(cosmo-rknn-backend-smoke PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) + target_link_libraries(cosmo-rknn-backend-smoke PRIVATE + nlohmann stb uWebSockets ${COMMON_LIBS}) + set_target_properties(cosmo-rknn-backend-smoke PROPERTIES + BUILD_RPATH "${COSMO_RKNN_ROOT}/lib") + if(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + set_property(TARGET cosmo-rknn-backend-smoke APPEND PROPERTY + BUILD_RPATH "${COSMO_ROCKCHIP_MEDIA_ROOT}/lib") + + add_executable(cosmo-rknn-fastpath-qualify + tools/rknn/cosmo_rknn_fastpath_qualify.cc + ${ALL_OBJECTS}) + target_include_directories(cosmo-rknn-fastpath-qualify PRIVATE ${CMAKE_SOURCE_DIR}/src) + target_compile_definitions(cosmo-rknn-fastpath-qualify PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) + target_link_libraries(cosmo-rknn-fastpath-qualify PRIVATE + nlohmann stb uWebSockets ${COMMON_LIBS}) + set_target_properties(cosmo-rknn-fastpath-qualify PROPERTIES + BUILD_RPATH "${COSMO_RKNN_ROOT}/lib;${COSMO_ROCKCHIP_MEDIA_ROOT}/lib") + endif() +endif() + ########################################################## #Unit Tests(optional, cmake - DBUILD_TESTS = ON) ########################################################## if(BUILD_TESTS) file(GLOB TEST_SRC "test/*.cc" "test/*.cpp" "test/mock/*.cc") + list(FILTER TEST_SRC EXCLUDE REGEX + ".*ReleaseBootstrapVerifierStandaloneTest\\.cc$") #App sources without main.cc set(APP_SRC_NO_MAIN ${APP_SRC}) @@ -370,9 +586,7 @@ if(BUILD_TESTS) endif() if(COSMO_MODEL_GUARD) target_compile_definitions(cosmo-tests PRIVATE COSMO_HAS_MODEL_GUARD=1) - if(MODEL_GUARD_LIB) - target_link_libraries(cosmo-tests PRIVATE ${MODEL_GUARD_LIB}) - endif() + target_link_libraries(cosmo-tests PRIVATE cosmo_model_guard_v2) endif() if(COSMO_NN_USE_CPU_BACKEND) target_compile_definitions(cosmo-tests PRIVATE @@ -380,6 +594,18 @@ if(BUILD_TESTS) COSMO_NN_USE_HOST_BACKEND COSMO_NN_USE_ONNX_BACKEND) endif() + if(COSMO_NN_USE_RKNN_BACKEND) + target_compile_definitions(cosmo-tests PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) + set_target_properties(cosmo-tests PROPERTIES + BUILD_RPATH "${COSMO_RKNN_ROOT}/lib") + endif() + if(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + set_property(TARGET cosmo-tests APPEND PROPERTY + BUILD_RPATH "${COSMO_ROCKCHIP_MEDIA_ROOT}/lib") + endif() target_link_libraries(cosmo-tests PRIVATE ${COMMON_LIBS}) if(COSMO_ENABLE_COVERAGE) # gcov runtime is only needed when the test binary was instrumented. @@ -434,6 +660,9 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/ PATTERN "netplan" EXCLUDE PATTERN "resource" EXCLUDE PATTERN "test-video" EXCLUDE + PATTERN "__pycache__" EXCLUDE + PATTERN "*.pyc" EXCLUDE + PATTERN "*.pyo" EXCLUDE ) # Font install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/data/SOURCEHANSANSCN-REGULAR.OTF @@ -448,11 +677,60 @@ if(DEFINED RESOURCE_DIR AND IS_DIRECTORY "${RESOURCE_DIR}") DESTINATION resource FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ PATTERN ".git" EXCLUDE + PATTERN "models" EXCLUDE + PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE PATTERN "*.pyo" EXCLUDE ) + if(DEFINED RESOURCE_OVERLAY_DIR AND IS_DIRECTORY "${RESOURCE_OVERLAY_DIR}") + message(STATUS "Resource overlay directory: ${RESOURCE_OVERLAY_DIR}") + install(DIRECTORY ${RESOURCE_OVERLAY_DIR}/ + DESTINATION resource + FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ + PATTERN ".git" EXCLUDE + PATTERN "models" EXCLUDE + PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE PATTERN "*.pyo" EXCLUDE + ) + endif() + if(COSMO_PACKAGE_MODELS STREQUAL "include" AND + DEFINED RESOURCE_MODELS_DIR AND IS_DIRECTORY "${RESOURCE_MODELS_DIR}") + message(STATUS "Resource model directory: ${RESOURCE_MODELS_DIR}") + install(DIRECTORY ${RESOURCE_MODELS_DIR}/ + DESTINATION resource/models + FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ + PATTERN ".git" EXCLUDE + PATTERN "model.nn" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ + PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE PATTERN "*.pyo" EXCLUDE + ) + elseif(COSMO_PACKAGE_MODELS STREQUAL "include" AND IS_DIRECTORY "${RESOURCE_DIR}/models") + install(DIRECTORY ${RESOURCE_DIR}/models/ + DESTINATION resource/models + FILE_PERMISSIONS OWNER_WRITE OWNER_READ GROUP_WRITE GROUP_READ + PATTERN ".git" EXCLUDE + PATTERN "model.nn" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ + PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE PATTERN "*.pyo" EXCLUDE + ) + endif() else() message(STATUS "No resource directory specified — package will not contain models") endif() +if(COSMO_NN_USE_RKNN_BACKEND) + install(FILES "${RKNN_RUNTIME_LIBRARY}" + DESTINATION lib + PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE + ) + if(COSMO_NN_USE_RKLLM_BACKEND) + install(FILES "${RKLLM_RUNTIME_LIBRARY}" + DESTINATION lib + PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE + ) + install(FILES "${RKLLM_RUNTIME_LICENSE}" + DESTINATION share/licenses/rkllm + RENAME LICENSE + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ + ) + endif() +endif() + # Scripts (exclude dev-only tools from device deployment) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts/ DESTINATION scripts @@ -462,10 +740,33 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/scripts/ PATTERN "static_analysis*" EXCLUDE PATTERN "install-hooks*" EXCLUDE PATTERN "pre-commit" EXCLUDE + PATTERN "__pycache__" EXCLUDE + PATTERN "*.pyc" EXCLUDE + PATTERN "*.pyo" EXCLUDE + PATTERN "package_md5_rename.sh" EXCLUDE + PATTERN "restore-symlinks.sh" EXCLUDE + PATTERN "sync-source-volume.sh" EXCLUDE + PATTERN "legacy_migration_install.sh" EXCLUDE + PATTERN "install.sh" EXCLUDE + PATTERN "start.sh" EXCLUDE + PATTERN "inte_run_start.sh" EXCLUDE PATTERN "*.sh" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE ) +# Open and Protected editions deliberately share one permanent MD5 upgrade +# lifecycle. The Protected edition differs only in its guarded model runtime +# and provisioning tool; application archives are not signed. +install(PROGRAMS + ${CMAKE_CURRENT_SOURCE_DIR}/scripts/legacy_migration_install.sh + DESTINATION scripts RENAME install.sh + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE) +install(PROGRAMS + ${CMAKE_CURRENT_SOURCE_DIR}/scripts/start.sh + ${CMAKE_CURRENT_SOURCE_DIR}/scripts/inte_run_start.sh + DESTINATION scripts + PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_READ GROUP_EXECUTE) + # Netplan failsafe config (deployed to scripts/ to keep device-side path unchanged) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/netplan/ DESTINATION scripts @@ -477,17 +778,28 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data/netplan/ ########################################################## # Packaging ########################################################## -file(STRINGS "${CMAKE_SOURCE_DIR}/src/util/Version.h" _ver_major REGEX "kVersionMajor") -file(STRINGS "${CMAKE_SOURCE_DIR}/src/util/Version.h" _ver_minor REGEX "kVersionMinor") -file(STRINGS "${CMAKE_SOURCE_DIR}/src/util/Version.h" _ver_patch REGEX "kVersionPatch") -string(REGEX REPLACE ".*kVersionMajor = ([0-9]+).*" "\\1" VER_MAJOR "${_ver_major}") -string(REGEX REPLACE ".*kVersionMinor = ([0-9]+).*" "\\1" VER_MINOR "${_ver_minor}") -string(REGEX REPLACE ".*kVersionPatch = ([0-9]+).*" "\\1" VER_PATCH "${_ver_patch}") - set(PACKAGE_PREFIX "cosmo") set(PACKAGE_VERSION "V${VER_MAJOR}.${VER_MINOR}.${VER_PATCH}") set(PACKAGE_NAME "${PACKAGE_PREFIX}-${PACKAGE_VERSION}") +# Record the intended accelerator inside the archive. The exported sidecar is +# convenient for automation, but it can be separated from the package during a +# manual copy. This marker keeps such mistakes observable and prevents packages +# for different chips from being byte-identical. +set(COSMO_TARGET_CHIP "" CACHE STRING "Target accelerator chip recorded in release packages") +if(COSMO_TARGET_CHIP) + string(TOLOWER "${COSMO_TARGET_CHIP}" COSMO_TARGET_CHIP_NORMALIZED) + if(NOT COSMO_TARGET_CHIP_NORMALIZED MATCHES "^(bm1688|cv186x|rk3576|unspecified)$") + message(FATAL_ERROR "Unsupported COSMO_TARGET_CHIP: ${COSMO_TARGET_CHIP}") + endif() + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/target-chip.txt" + "${COSMO_TARGET_CHIP_NORMALIZED}\n") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/target-chip.txt" + DESTINATION share/cosmo + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) + message(STATUS "Package target chip: ${COSMO_TARGET_CHIP_NORMALIZED}") +endif() + # Generate and install version.txt file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version.txt" "${PACKAGE_VERSION}\n") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/version.txt" @@ -495,14 +807,45 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/version.txt" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ ) -# Install model guard shared library to lib/ (used at runtime via dlopen or direct link) -if(COSMO_MODEL_GUARD AND MODEL_GUARD_LIB) - install(FILES ${MODEL_GUARD_LIB} +# Install the exact verified compatibility member. The linker aliases are +# recreated inside the package; no unversioned host/system library is copied. +if(COSMO_MODEL_GUARD) + install(FILES "${MODEL_GUARD_V2_LIBRARY}" DESTINATION lib PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE ) + if(COSMO_MODEL_GUARD_BUILD_PROFILE STREQUAL "production-release") + install(PROGRAMS "${MODEL_GUARD_V2_PROVISION_TOOL}" + DESTINATION bin + RENAME cosmo-model-provision + PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + ) + endif() + install(FILES "${MODEL_GUARD_V2_HEADER}" + DESTINATION share/cosmo-model-guard + PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ + ) + install(CODE [[ + set(model_guard_lib_dir "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/lib") + file(CREATE_LINK libcosmo_model_guard.so.2.0.0 + "${model_guard_lib_dir}/libcosmo_model_guard.so.2" + SYMBOLIC RESULT model_guard_soname_link_result) + if(NOT model_guard_soname_link_result STREQUAL "0") + message(FATAL_ERROR + "Cannot create Model Guard SONAME link: ${model_guard_soname_link_result}") + endif() + file(CREATE_LINK libcosmo_model_guard.so.2 + "${model_guard_lib_dir}/libcosmo_model_guard.so" + SYMBOLIC RESULT model_guard_link_link_result) + if(NOT model_guard_link_link_result STREQUAL "0") + message(FATAL_ERROR + "Cannot create Model Guard linker alias: ${model_guard_link_link_result}") + endif() + ]]) else() - # Create empty lib directory to satisfy legacy upgrade checks on target device + # CPU-only development packages retain the historical empty directory. file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" DESTINATION . @@ -524,10 +867,19 @@ set(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_BINARY_DIR}/packages") include(CPack) +set(COSMO_PACKAGE_TARGETS ${EXECUTABLE_NAME} web_frontend) add_custom_target(package_all + # CPack names are content-addressed only after generation. Clear artifacts + # from an earlier profile before creating and exporting this build's output. + COMMAND "${CMAKE_COMMAND}" -E remove_directory + "${CMAKE_BINARY_DIR}/packages" + COMMAND "${CMAKE_COMMAND}" -E make_directory + "${CMAKE_BINARY_DIR}/packages" COMMAND cpack - COMMAND bash ${CMAKE_SOURCE_DIR}/scripts/package_md5_rename.sh - ${CMAKE_BINARY_DIR}/packages ${PACKAGE_NAME} - DEPENDS ${EXECUTABLE_NAME} web_frontend - COMMENT "Creating package with MD5 in filename" + COMMAND bash "${CMAKE_SOURCE_DIR}/scripts/package_md5_rename.sh" + "${CMAKE_BINARY_DIR}/packages" "${PACKAGE_NAME}" + "${COSMO_MODEL_GUARD_BUILD_PROFILE}" + "${COSMO_REPRODUCIBLE_BUILD_EPOCH}" + DEPENDS ${COSMO_PACKAGE_TARGETS} + COMMENT "Creating MD5-compatible upgrade package" ) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c8d901084..2f0758976 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,7 +22,7 @@ If you are new to the project, start with the smallest path that matches your ch | Frontend web console | `cd src/web`, `npm ci`, `npm run build` | | C++ backend or tests | `bash scripts/format_check.sh --staged --check`, `bash scripts/build_cpu_test.sh`, `./build_cpu/cosmo-tests` | | Runtime smoke test | `docker compose -f docker-compose.x86.yml up -d --build` on Linux, or `docker compose -f docker-compose.x86.windows.yml up -d --build` on Windows | -| Sophon release package | `docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package`, or `.\scripts\build_sophon_package.ps1` on Windows | +| Sophon release package | `./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package [--chip ]`, or `.\scripts\build_sophon_package.ps1 [-Chip ]` on Windows; models are `bm1688` / `cv186x`, defaulting to `bm1688` | For a fuller contributor-oriented walkthrough, see: diff --git a/Dockerfile.rk3576 b/Dockerfile.rk3576 new file mode 100644 index 000000000..6689b0bc1 --- /dev/null +++ b/Dockerfile.rk3576 @@ -0,0 +1,14 @@ +FROM ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_rk3576@sha256:0dbb35f5a4336777c311b5f881886cd9b284371d61ceffff55a8216c01d2b076 + +LABEL org.opencontainers.image.title="CosmoEdge RK3576 build environment" +LABEL org.opencontainers.image.description="Pinned RKNN/MPP/RGA builder extended with Rockchip RKLLM Runtime v1.3.0" +LABEL org.opencontainers.image.source="https://github.com/cosmo-wander-ai/cosmo-edge" +LABEL org.opencontainers.image.rkllm.version="1.3.0" +LABEL org.opencontainers.image.rkllm.revision="878f9361fd3afa7e167b7079918918f78d2c1c2a" + +COPY scripts/install_rkllm_sdk.py /tmp/install_rkllm_sdk.py +RUN python3 -I -B /tmp/install_rkllm_sdk.py --root /opt/rkllm \ + && rm -f /tmp/install_rkllm_sdk.py \ + && test -f /opt/rkllm/include/rkllm.h \ + && test -f /opt/rkllm/lib/librkllmrt.so \ + && test -f /opt/rkllm/LICENSE diff --git a/Dockerfile.x86 b/Dockerfile.x86 index bda6e93e7..b01534da1 100644 --- a/Dockerfile.x86 +++ b/Dockerfile.x86 @@ -1,4 +1,7 @@ -FROM ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_x86:v1 AS builder +ARG BUILD_ENV_IMAGE=ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_x86:v1 +ARG RUNTIME_BASE_IMAGE=debian:12-slim + +FROM ${BUILD_ENV_IMAGE} AS builder WORKDIR /src COPY . . @@ -19,13 +22,14 @@ RUN find prebuild 3rd -path '*/lib/*.so*' -type f -size -256c -print | while IFS done ARG RESOURCE_DIR=data/resource/aiboxresource_x86 +ARG COSMO_BUILD_JOBS RUN if [ -n "${RESOURCE_DIR}" ]; then \ bash ./scripts/build_cpu.sh -t -m "${RESOURCE_DIR}"; \ else \ bash ./scripts/build_cpu.sh -t; \ fi -FROM debian:12-slim AS runtime +FROM ${RUNTIME_BASE_IMAGE} AS runtime ENV DEBIAN_FRONTEND=noninteractive ENV INSTALLPATH=/appfs/cosmo_wander/cwai_data @@ -85,8 +89,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY --from=builder /src/build_cpu/install/ /appfs/cosmo_wander/cwai_data/ COPY --from=builder /src/build_cpu/packages/ /cosmo-packages/ COPY scripts/docker-entrypoint.x86.sh /usr/local/bin/cosmo-x86-entrypoint +COPY scripts/docker-healthcheck.x86.sh /usr/local/bin/cosmo-x86-healthcheck -RUN chmod +x /usr/local/bin/cosmo-x86-entrypoint \ +RUN chmod +x /usr/local/bin/cosmo-x86-entrypoint /usr/local/bin/cosmo-x86-healthcheck \ && mkdir -p /data/cwaiuserdata/log/logs /data/cwaiuserdata/upgrade \ && mkdir -p /appfs/cosmo_wander/cwai_data/bin/nginx_conf/logs \ && mkdir -p /appfs/cosmo_wander/cwai_data/web/staticfile \ diff --git a/README.md b/README.md index 9a9b258a6..8605d2666 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,20 @@ CosmoEdge -**C++ edge AI engine for production video analytics, visual pipeline orchestration, and on-device VLM workflows** +**Turn video AI models into deployable edge applications — a C++ edge AI engine for Sophon, Rockchip, and x86.** -[![Nightly Sophon Build and Test](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/nightly-build-test-sophon.yml/badge.svg?branch=main)](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/nightly-build-test-sophon.yml) +Build and operate video analytics, VLM, and event workflows through a consistent orchestration experience. Each platform uses its own runtime, build, and model artifacts. +[![Nightly Sophon Build and Test](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/nightly-build-test-sophon.yml/badge.svg?branch=main)](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/nightly-build-test-sophon.yml) +[![Nightly RK3576 Cross Build](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/ci-build-rk3576.yml/badge.svg?branch=main)](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/ci-build-rk3576.yml) [![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](LICENSE) -[![Runtime](https://img.shields.io/badge/runtime-C%2B%2B17-orange?style=flat-square)](#c-native-runtime) -[![Platform](https://img.shields.io/badge/platform-Sophon%20BM1688%20%2F%20x86%20Linux%20%2F%20Windows-purple?style=flat-square)](#supported-platforms) -[![Release](https://img.shields.io/badge/release-v1.0.0-green?style=flat-square)](https://github.com/cosmo-wander-ai/cosmo-edge/releases) -[![Stress Test](https://img.shields.io/badge/stress%20test-200%20video%20samples-brightgreen?style=flat-square)](#validation) -[![Pipelines](https://img.shields.io/badge/pipelines-26%20validated-brightgreen?style=flat-square)](#validation) +[![Runtime](https://img.shields.io/badge/runtime-C%2B%2B17-orange?style=flat-square)](#core-capabilities) +[![Release](https://img.shields.io/badge/release-v1.1.0-green?style=flat-square)](https://github.com/cosmo-wander-ai/cosmo-edge/releases) [![Website](https://img.shields.io/badge/website-cosmowander.ai-3B82F6?style=flat-square)](https://www.cosmowander.ai/) [![Docs](https://img.shields.io/badge/docs-online-2563EB?style=flat-square)](https://www.cosmowander.ai/docs/) -[![GitHub](https://img.shields.io/badge/GitHub-cosmo--edge-181717?style=flat-square&logo=github)](https://github.com/cosmo-wander-ai/cosmo-edge) [![Gitee](https://img.shields.io/badge/Gitee-cosmo--edge-C71D23?style=flat-square&logo=gitee)](https://gitee.com/cosmo-wander-ai/cosmo-edge) -[Official Website](https://www.cosmowander.ai/) | [Online Docs](https://www.cosmowander.ai/docs/) | [Quick Start](#quick-start) | [Features](#key-features) | [Validation](#validation) | [Benchmarks](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/) | [Hardware](#cosmoedge-ready-devices) - -[English](README.md) | [简体中文](README.zh-CN.md) +[Quick Start](#quick-start) · [Platforms](#choose-a-platform) · [Validation](#validation) · [Documentation](#documentation-devices-and-community) · [简体中文](README.zh-CN.md) @@ -31,414 +27,252 @@ -*Run multiple AI pipelines with real-time OSD overlays and live event output on a single edge device.* - -CosmoEdge is a C++ edge AI engine for production video analytics. It takes teams from model files to running applications: import models, compose pipelines, connect video sources, view AI overlays in the browser, and send structured events over MQTT or HTTP. - -The C++17 runtime handles multi-channel video processing, hardware decoding, OSD rendering, and low-overhead edge deployment — the runtime, web console, and integration path needed to deploy, monitor, debug, and maintain edge AI applications in the field. - -## What You Can Build +CosmoEdge goes beyond model serving with a complete application layer for model import, visual orchestration, alarms, and event delivery. The core engine and console in this repository are released under Apache-2.0; certified hardware, commercial preset models, and Model Guard distribution protection have separate boundaries. -- Multi-camera safety monitoring with real-time OSD and event snapshots. -- Counting, line-crossing, and zone-intrusion analytics for people, vehicles, and objects. -- On-device visual inspection driven by VLM prompts for quality and compliance checks. -- Long-tail detection of rare or unlisted objects from a text prompt, with no task-specific training (GroundingDINO). +## CosmoEdge 1.1 -Each runs as a managed edge deployment with model management, scenario tasks, alarm rules, and MQTT/HTTP data export. +> This branch is the CosmoEdge 1.1 source line. Platform capacity varies by model and workload; use the linked evidence rather than treating a short-run maximum as a deployment recommendation. -## Key Features +- **Multi-platform release:** BM1688, CV186X, and RK3576 use the same video-ingest, orchestration, event, and observability workflow with target-specific model artifacts. +- **Public benchmark pack:** the [CosmoEdge 1.1 multi-platform report](docs/benchmarks/scenario-bench/v1.1/README.md) covers single-detector, dual-detector, and Experimental VLM workloads with sanitized reproducibility attachments. +- **Rockchip RK3576:** cross-build, board operation, RKNN inference, and MPP/RGA media paths are integrated. A 4-channel single-detector profile has 12-hour evidence; higher short-run points remain measured boundaries rather than recommended profiles. +- **Sophon model handling:** chip-aware validation supports target-specific `.nn` artifacts for BM1688 and CV186X. The benchmark records an exact Open-package and running-engine binding for both reference devices. +- **RKNN data path:** targeted DMA-BUF-to-RGA input, persistent bound-input, native quantized output, and direct YOLOv8 tensor decoding paths with explicit fallbacks. +- **Agent-assisted development:** a repository-guided path for handing model porting, integration, and UI tasks to the coding agent you already use and receiving verifiable deliverables. +- **Model Guard 2.3:** protects commercial preset-model distribution in Sophon Protected packages. Open and Protected expose the same application features, with no SKU-gated software functionality; they differ in model encryption and device-provisioning tooling. +- **macOS Docker Preview:** an isolated `linux/amd64` candidate for one local-video workflow on Apple Silicon. Two consecutive end-to-end acceptance runs are still required before publication; it does not enable Model Guard or represent native/NPU performance. -### C++ Native Runtime - -CosmoEdge uses a C++17 runtime at its core. For edge video systems, decoding, inference scheduling, OSD rendering, event generation, and stream output must run continuously on resource-constrained devices. - -- Lower overhead for long-running multi-channel video workloads. -- Direct integration with hardware decoding, NPU runtimes, memory pools, and streaming components. -- Predictable CPU, memory, and thread behavior for appliance-style edge deployments. -- One engine core across x86 developer mode and Sophon production deployments. - -### Visual Pipeline Orchestration - -Build video AI workflows in a browser. Connect video sources, AI models, post-processing nodes, OSD rendering, alarm rules, and output channels with a visual pipeline editor. - -
+## Choose a Platform - - -
- -### Application Workflow - -CosmoEdge connects the runtime, web console, and integration layer into one deployment workflow: - -```text -Model Repository -> Scenario Task -> Real-time Analysis -> Alarm Management -> Data Push - | | | | | - Upload/manage Configure Multi-channel Rule engine MQTT / HTTP - ONNX/bmodel pipelines AI + OSD overlay snapshots webhook - model versions per scene WebRTC streaming event log integration -``` - -
-Full capability list - -| Module | Capabilities | -| ------------------ | ------------------------------------------------------------------------ | -| Model Repository | Model upload, metadata management, version management, hot-swap workflow | -| Scenario Tasks | Pipeline binding, camera binding, scheduling, scene-level configuration | -| Real-time Analysis | RTSP, video files, USB cameras, WebRTC live view, HTTP-FLV fallback | -| Image Analysis | Batch image upload, VLM analysis, structured results | -| Alarm Management | Rule-based alarms, severity levels, snapshots, filtering, event history | -| Data Integration | MQTT push, HTTP webhook, structured JSON event format | -| System Management | Dashboard, device status, user auth, i18n, configuration management | - -
+CosmoEdge provides one engine architecture and orchestration experience, but each build selects one inference backend and uses models generated for that target platform. -### Real-time Visual Debugging - -CosmoEdge includes an OSD system for both operators and developers: - -- Business labels instead of raw model class names. -- Semantic colors for normal, warning, violation, and uncertain states. -- Zone overlays, line-crossing indicators, counters, and event panels. -- Debug view for raw detections, confidence scores, track IDs, and model output. - -### Prompt-driven AI: GroundingDINO + VLM - -Run prompt-driven vision models on edge devices as asynchronous pipeline nodes alongside traditional CV pipelines: - -| Capability | How it works | Typical use | -| ------------------ | ----------------------------------------------- | ----------------------------------------------------- | -| GroundingDINO | Text prompt -> open-vocabulary object detection | Find long-tail objects without task-specific training | -| Edge VLM | Closed question -> YES/NO state judgment | "Is the cabinet door open?" -> alarm on YES | -| VLM Image Analysis | Image upload -> structured visual check | Quality inspection, compliance review | - -
- - - -
- -Edge VLM nodes support compatible Qwen3 VLM series and Qwen3.5 multimodal models. Certified device packages can provide `CosmoEdge-VL-Judge-0.8B`, optimized for YES/NO visual state judgment. - -Newly added: the VLM node runs in two interchangeable backends — an embedded on-device runtime (data stays on the device) or any OpenAI-compatible endpoint (self-hosted or SaaS) for larger models. The async, event-driven VLM path absorbs the extra network latency; the on-device runtime remains the validated default. - -### Model Sources - -**Available in CosmoEdge:** - -| Category | Supported Models / Architectures | Pipeline Support | -| :------------------------ | :------------------------------------------------------------------ | :------------------ | -| Object Detection | YOLOv5, YOLOv8, YOLOv10, YOLOv11, YOLOv12, YOLO26 | Full pipeline | -| Object Tracking | ByteTrack | Full pipeline | -| Attribute Classification | Safety helmet, vest, uniform classifiers | Full pipeline | -| Counting & Statistics | Line crossing, zone counting, directional flow | Full pipeline | -| Open-vocabulary Detection | GroundingDINO | Async pipeline node | -| Visual State Judgment | Qwen3 VLM models, Qwen3.5 multimodal models (text prompt -> YES/NO) | Async pipeline node (on-device or OpenAI-compatible API) | -| Image Analysis | VLM batch analysis | Standalone task | - -**Model ecosystem compatibility:** - -CosmoEdge uses ONNX as the model interchange format. Models from major CV training frameworks can be imported through a documented conversion path: - -- **Ultralytics (YOLO)**: Export with `yolo export format=onnx`, then import via Model Repository or convert to bmodel for NPU deployment. -- **Roboflow**: Train on Roboflow, export ONNX, import into CosmoEdge. -- **Custom models**: Any ONNX-compatible detection or classification model can be integrated through the model porting guide. - -**Broader Sophon model ecosystem:** - -CosmoEdge runs on the Sophon BM1688 inference stack. Models from SOPHGO's official model zoo can be integrated through the model porting guide, which covers post-processing adaptation and pipeline node registration. - -→ [SOPHGO Model Zoo (sophon-demo)](https://github.com/sophgo/sophon-demo) -→ [CosmoEdge Model Porting Guide](docs/en/tutorials/05-model-porting/model-porting.md) +| Platform | Status | Runtime / model artifact | Current scope and evidence | +| --- | --- | --- | --- | +| Sophon BM1688 | v1.1 supported / primary | BMRT / `.nn` | Production deployment path with [v1.1 workload evidence](docs/benchmarks/scenario-bench/v1.1/README.md) and published [v1.0 baselines](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/) | +| Rockchip RK3576 | v1.1 supported | RKNN / `.rknn` | Cross-build and board paths validated; see the [integration guide](docs/en/guide/rk3576-rknn-development.md) and [v1.1 workload evidence](docs/benchmarks/scenario-bench/v1.1/README.md) | +| Sophon CV186X | v1.1 supported | BMRT / target-specific `.nn` | Model import and device workload evidence included in the [v1.1 benchmark](docs/benchmarks/scenario-bench/v1.1/README.md) | +| x86 Linux / Windows; Apple Silicon macOS | Linux / Windows supported; macOS Preview | ONNX Runtime / `.onnx` | Mac uses amd64 emulation for one local-video developer workflow, not native performance evidence | +| Sophon BM1684X | Planned | — | Not part of the current release scope | ## Quick Start -### Option A: x86 Developer Mode +### Try locally on x86 -You can try CosmoEdge without edge hardware. The x86 developer mode uses the same UI and workflow as edge deployment, with lower throughput than Sophon NPU mode. +No edge hardware is required. The x86 mode uses the same UI and workflow with lower throughput than an NPU deployment. ```bash # 1. Clone git clone https://github.com/cosmo-wander-ai/cosmo-edge.git -# Or use Gitee mirror (China): -# git clone https://gitee.com/cosmo-wander-ai/cosmo-edge.git cd cosmo-edge -``` - -> **💡 Docker Compose Version Note** -> This documentation uses the latest Docker Compose V2 command format (`docker compose`). If you are using an older Docker environment, please replace `docker compose` with the hyphenated `docker-compose` in all commands. -```bash -# 2. Start in x86 mode -# Linux: +# 2. Start on Linux sudo docker compose -f docker-compose.x86.yml up -d --build +# Windows: docker compose -f docker-compose.x86.windows.yml up -d --build -# Windows (PowerShell/CMD): -docker compose -f docker-compose.x86.windows.yml up -d --build - -# 3. Open the web console -# http://localhost:8080 +# 3. Open http://localhost:8080 ``` -> **USB cameras**: If you have USB cameras attached, uncomment the `devices` block in `docker-compose.x86.yml` before starting. +Apple Silicon macOS uses a separate amd64-emulation Preview path: -After startup, follow the [Scenario Configuration tutorial](docs/en/tutorials/02-scenario-config/scenario-config.md) to set up your first AI detection scenario. +```bash +./scripts/macos-docker-preview.sh doctor +./scripts/macos-docker-preview.sh up +./scripts/macos-docker-preview.sh status +# Open http://127.0.0.1:8080 +``` -### Option B: Sophon Edge Device +The Mac Preview is for local, single-video evaluation. It is not a native macOS +binary, an NPU deployment, or production performance evidence. Read the full +[macOS Docker Preview](docs/en/guide/macos-docker-preview.md) boundaries first. -Use this path for NPU-accelerated deployment. +After startup, use the [Scenario Configuration tutorial](https://www.cosmowander.ai/docs/tutorials/02-scenario-config/scenario-config) to create your first AI detection task. Docker Compose V1 users can replace `docker compose` with `docker-compose`. + +### Build for Sophon ```bash -# 1. Clone git clone https://github.com/cosmo-wander-ai/cosmo-edge.git -# Or use Gitee mirror (China): -# git clone https://gitee.com/cosmo-wander-ai/cosmo-edge.git cd cosmo-edge +# BM1688 (default when the chip model is omitted) +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip bm1688 -# 2. Build the Sophon/aarch64 package -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package - -# 3. View exported release packages -ls -lh build_output/ -# The output package will be named like: cosmo-V-.tar.gz - -# 4. Copy the package to the Sophon edge device (replace with actual IP, default is 192.168.100.1) -scp build_output/cosmo-V*.tar.gz root@:/tmp/ - -# 5. SSH to the device, extract the package, and run the installation script -ssh root@ -cd /tmp -tar -zxvf cosmo-V*.tar.gz -sudo bash scripts/install.sh - -# 6. Reboot the device to start the services -sudo reboot -``` - -On Windows PowerShell to build the package: - -```powershell -.\scripts\build_sophon_package.ps1 +# CV186X +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x ``` -After installing the package and rebooting the device: +The wrapper selects the available Compose implementation and requests elevated +Docker access only when required. The build selects the matching model resources +without a model-path argument and exports each target independently under +`build_output/public-runtime//`, together with `TARGET_CHIP` and +`SHA256SUMS`. -- **Default IP**: `192.168.100.1` (ensure your computer is configured with a static IP in the `192.168.100.x` subnet to connect directly) -- **Web Console URL**: `http://192.168.100.1` -- **Default Username**: `admin` -- **Default Password**: `admin` (it is highly recommended to change this password after your first login) +The default Open package contains plaintext models and requires no device +authorization. Verify the chip marker and checksum before deployment. The +[Build Guide](https://www.cosmowander.ai/docs/guide/build) is the authoritative +build reference; follow the [Deployment Guide](https://www.cosmowander.ai/docs/guide/deployment) +for SSH installation, web upgrade, recovery, and post-reboot acceptance. -This path builds a release package and installs it on a Sophon device. For teams that need production hardware, certified CosmoEdge devices include preconfigured Sophon acceleration, production model packages, and deployment support. See [CosmoEdge-ready devices](#cosmoedge-ready-devices). +### Build for RK3576 -Initial Onboarding Guide -
- - +```bash +./scripts/docker-compose.sh -f docker-compose.rk3576.yml pull cosmo-rk3576-package +./scripts/docker-compose.sh -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package +ls -lh build_output/rk3576/ +``` -Test video path: cosmo-edge\data\test-video +The public digest-pinned builder contains the checksum-pinned official RKLLM +v1.3.0 runtime and the RKNN, MPP, and RGA build dependencies. See +the [RK3576 integration guide](docs/en/guide/rk3576-rknn-development.md) +for the target runtime and device-validation boundary. -
+For CV186X, follow the [CV186X Quick Start](docs/en/guide/cv186x-quick-start.md) for package installation, model import, first-event verification, upgrade, and recovery boundaries. -## Validation +## What You Can Build -CosmoEdge comes from a commercial codebase and has completed internal system validation before open-source release. +- **Real-time video analytics:** detection, classification, tracking, zones, counters, OSD, and alarm snapshots. +- **Prompt-driven vision:** VLM state judgment and GroundingDINO open-vocabulary detection alongside conventional CV pipelines. +- **Visual application workflows:** connect models, rules, events, and output actions in the browser. +- **Edge integrations:** operate managed tasks and deliver structured events through REST, WebSocket, MQTT, or HTTP webhooks. -A scenario task (pipeline) bundles model, scheduling, and rule logic; at deployment it binds to specific inputs, zones, and rules. The 26 figure counts validated pipelines — the same set covers far more real deployments as inputs and rules change, with no new code. +## Core Capabilities -| Area | Current validation status | -| ---------------------- | ------------------------------------------------------------------------------------------------------------ | -| Video stress test | Continuous playback test with 200 video samples; no memory leaks or crashes observed | -| Pipeline validation | 26 pipelines validated against internal scenario baselines (CV, VLM, and GroundingDINO) | -| Concurrent CV workload | ScenarioBench v1.0 verifies up to 16 NPU video channels for CV workloads; detailed reports are linked below | -| Regression testing | Multi-round system regression completed with dedicated QA, including the final v1.0 release regression pass | -| Pilot deployments | Authorized customer pilots covering several hundred video-analysis channels, 2+ months continuous, across a range of industry scenarios | +| Capability | What it covers | Go deeper | +| --- | --- | --- | +| Native runtime | C++17 engine for multi-channel media, inference scheduling, OSD, tasks, and events | [Architecture](https://www.cosmowander.ai/docs/guide/architecture) | +| Visual orchestration | Browser-based pipeline composition, task binding, parameter validation, and live feedback | [Pipeline tutorial](https://www.cosmowander.ai/docs/tutorials/04-pipeline-orchestration/pipeline-orchestration) | +| Inference and media | Platform backends for Sophon, RKNN, and x86; platform-specific builds and model artifacts | [Build Guide](https://www.cosmowander.ai/docs/guide/build) | +| VLM and DINO | Prompt-based judgment, open-vocabulary detection, and optional VLM review before a detection alarm is reported | [VLM Guide](https://www.cosmowander.ai/docs/tutorials/03-vlm-guide/vlm-guide) | +| Operations and integration | Model management, alarms, event history, REST, WebSocket, MQTT, and webhooks | [API Overview](https://www.cosmowander.ai/docs/reference/api) | +| Model onboarding and protection | Model conversion, import, validation, and the Open/Protected distribution boundary | [Model Porting Guide](https://www.cosmowander.ai/docs/tutorials/05-model-porting/model-porting) | -### Performance Benchmarks +
+▶ Watch: compose a complete visual pipeline -The results below are reproducible ScenarioBench benchmarks. CV and x86 reports are kept under the [v1.0 benchmark set](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/); the VLM row points to the current refreshed VLM methodology report. Full raw `metrics.json` traces are distributed separately from the repository. + -A video channel means one decoded input stream. A scenario task is one algorithm pipeline bound to a channel, so mixed scenarios can run more tasks than video channels. The table reports the maximum verified stable channel count within the published benchmark range. +
-| ScenarioBench workload | Hardware profile | Max verified video channels | Concurrent scenario tasks | Target FPS | Result | Evidence | -| --- | --- | ---: | ---: | ---: | --- | --- | -| No Safety Helmet | YY-16T01-Preview / NPU | 16 | 16 | 3/channel | PASS | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/helmet-7463-npu/report.html) | -| Pedestrian Detection | YY-16T01-Preview / NPU | 16 | 16 | 5/channel | PASS | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/pedestrian-45626-npu/report.html) | -| Pedestrian + No Safety Helmet | YY-16T01-Preview / NPU | 16 | 32 | 3/channel/task | PASS | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/pedestrian-helmet-mixed-npu/report.html) | -| VLM Review | YY-16T01-Preview / NPU | 8 | 8 | 0.1/channel | PASS | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/current/vlm-77175-npu/report.html) | -| No Safety Helmet x86 baseline | X86 CPU baseline | 7 | 7 | 3/channel | LIMITED; 8 channels exceeded latency thresholds | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/helmet-7463-x86/report.html) | +
+▶ Watch: GroundingDINO and VLM visual workflows -See the bilingual [v1.0 benchmark manifest](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/manifest.json), [environment notes](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/environment), and [current benchmark refresh notes](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/current/) for hardware profiles, model inputs, and publication policy. The x86 row is a CPU-only comparison baseline, not the v1.0 NPU device capacity target. + -## Architecture +
-```text -+---------------------------------------------------------------+ -| Web Frontend | -| Pipeline Editor | Management Console | Real-time View | -+-------------------------------+-------------------------------+ - | REST / WebSocket / MQTT - v -+---------------------------------------------------------------+ -| C++ Engine Core | -| Flow Engine | Media Pipeline | Inference | Services | -| Task/Action | Decode/Encode | CV/VLM/DINO | Alarm/Event/Model | -+-------------------------------+-------------------------------+ - | - v -+---------------------------------------------------------------+ -| Hardware Abstraction | -| Sophon BM1688 NPU/VPU/VPP | x86 CPU | -+---------------------------------------------------------------+ -``` +## Agent-Assisted Development -### Tech Stack +Already have a model-porting, integration, or UI task? Give your usual coding agent the business goal, available materials, target device or test environment, and acceptance criteria. The repository provides task entry points, examples, checks, and evidence boundaries so the result can include importable artifacts, scoped code changes, and a verifiable conclusion. -| Layer | Technology | -| ----------- | ------------------------------------------- | -| Engine | C++17, CMake, FFmpeg, SQLiteCpp | -| Inference | Sophon BMRT, ONNX Runtime for x86 mode | -| Frontend | Vue.js, Vue Flow, Element Plus | -| Streaming | SRS 6.0, WebRTC, HTTP-FLV | -| Integration | REST API, WebSocket, MQTT, HTTP webhook | +Start with [Agent-Assisted Development](docs/en/development/agent-assisted-development.md), then use the [Model Porting Guide](https://www.cosmowander.ai/docs/tutorials/05-model-porting/model-porting) or [Contributor Guide](docs/en/development/contributing.md) for the task at hand. -## Supported Platforms +## Validation -| Platform | Status | Intended use | -| -------------- | :-------: | -------------------------------------------- | -| Sophon BM1688 | Primary | NPU-accelerated production deployment | -| x86 Linux | Supported | Development, evaluation, integration testing | -| x86 Windows | Supported | Development and evaluation | -| Sophon BM1684X | Planned | NPU-accelerated deployment | +### CosmoEdge 1.1 multi-platform performance report -## CosmoEdge-ready Devices +The publication-ready v1.1 material covers BM1688, CV186X, and RK3576 with a concise public report plus linked single-detector, dual-detector, and Experimental VLM attachments. Results are short-run workload evidence unless a longer duration is explicitly stated; they are not theoretical chip limits or automatic deployment recommendations. -CosmoEdge is open source. The repository provides the same engine, web UI, and workflow used by certified device packages. You can bring your own models, run on x86 for development, and deploy on compatible edge hardware. +- [English benchmark index](docs/benchmarks/scenario-bench/v1.1/README.md) +- [中文基准报告索引](docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md) +- [English primary report (rendered documentation site)](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/report.html) +- [Methodology and reproduction](docs/benchmarks/scenario-bench/v1.1/methodology.md) -Certified devices help teams avoid hardware bring-up and model packaging work. They include preconfigured NPU acceleration, production model packages, and dedicated support. +The release-branch preparation baseline is `feat/model-guard-v2.3` commit `209bc2b52849864a15bdad91beb61f5bc982c17f`, tree `f64a98bce05b9ee8dc64dda8e56ad50f9d15687f`. BM1688 and CV186X are byte-bound to the recorded Open package and running engine; that package does not embed a source commit and therefore is not claimed as a reproducible build of the preparation baseline. The RK3576 package digest and Protected-package provenance are not distributed in this public benchmark, so the report does not make package-qualified claims for them. See the [release manifest](docs/benchmarks/scenario-bench/v1.1/release-manifest.json) for the exact evidence boundary. -| Capability | Open-source repository | Certified device package | -| ---------------------------- | :------------------------------------------------: | :-----------------------------: | -| C++ engine | Included | Included | -| Visual pipeline orchestrator | Included | Included | -| Web management console | Included | Included | -| x86 developer mode | Included | Included | -| Sophon NPU runtime support | Source support, hardware required | Preconfigured | -| CV model package | Bring your own models | Pre-installed (~25 production CV models) | -| `CosmoEdge-VL-Judge-0.8B` | Bring your own/custom package; validation required | Pre-installed validated package | -| GroundingDINO package | Bring your own or custom package | Pre-installed | -| Deployment support | Community | Dedicated | +The following table preserves the previously published **v1.0 baseline** for historical comparison: -Certified devices improve deployment readiness; they do not lock software features behind a hardware SKU. +| ScenarioBench workload | Hardware | Max verified channels | Target FPS | Result | Evidence | +| --- | --- | ---: | ---: | --- | --- | +| No Safety Helmet | YY-16T01-Preview / NPU | 16 | 3/channel | PASS | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/helmet-7463-npu/report.html) | +| Pedestrian Detection | YY-16T01-Preview / NPU | 16 | 5/channel | PASS | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/pedestrian-45626-npu/report.html) | +| Pedestrian + No Safety Helmet | YY-16T01-Preview / NPU | 16 | 3/channel/task | PASS | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/pedestrian-helmet-mixed-npu/report.html) | +| VLM Review | YY-16T01-Preview / NPU | 8 | 0.1/channel | PASS | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/vlm-55009-npu/report.html) | +| No Safety Helmet x86 baseline | x86 CPU | 7 | 3/channel | LIMITED; 8 channels exceeded latency limits | [report](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/helmet-7463-x86/report.html) | -The open-source engine and all software features are available worldwide today, no purchase required. CosmoEdge-ready certified devices are now available in mainland China through the [Taobao store](https://item.taobao.com/item.htm?id=1066672051450). For availability outside mainland China or project deployment support, contact . +See the [v1.0 benchmark manifest](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/manifest.json), [environment notes](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/environment), and [current refresh notes](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/current/) for the legacy methodology and publication boundaries. -## Documentation +### RK3576 long-duration validation context -| Start here | For | Description | -| -------------------------------------------------------------------------------------------- | -------------- | ----------------------------------------- | -| [Documentation Home](docs/en/index.md) | Everyone | Full documentation index and reading path | -| [Quick Start Guide](docs/en/tutorials/01-quickstart/quickstart.md) | Everyone | First setup and scenario run | -| [Scenario Configuration](docs/en/tutorials/02-scenario-config/scenario-config.md) | Integrators | Build scene-level AI workflows | -| [VLM Guide](docs/en/tutorials/03-vlm-guide/vlm-guide.md) | Developers | Use visual state judgment with prompts | -| [Pipeline Orchestration](docs/en/tutorials/04-pipeline-orchestration/pipeline-orchestration.md) | Advanced users | Compose custom pipelines visually | -| [Model Porting Guide](docs/en/tutorials/05-model-porting/model-porting.md) | ML engineers | Import ONNX or target-runtime models | -| [Agent-Assisted Development](docs/en/development/agent-assisted-development.md) | Integrators | Hand tasks like model conversion to the coding agent you already use, with verifiable results | -| [Build Guide](docs/en/guide/build.md) | Developers | Build x86 Docker and Sophon packages | -| [API Overview](docs/en/reference/api.md) | Developers | REST, WebSocket, and MQTT API categories | +This earlier long-duration evidence remains bound to source [`8f8b4b8e`](https://github.com/cosmo-wander-ai/cosmo-edge/commit/8f8b4b8e793172963ef92da7fc9942a1c860534b) (tree `fd1b646f`), engine SHA-256 `bc829d9513334c4520fad1b58439bb3e6e31338c664e93eb15babdaaa564d886`, RKNN Runtime `2.3.2-429f97ae6b`, driver `0.9.8`, RGA `1.10.1_[4]`, and MPP `1.5.0-1`. -## Release Status and Roadmap +| ScenarioBench workload | Hardware | Max verified channels | Target FPS | Result | +| --- | --- | ---: | ---: | --- | +| No Safety Helmet | Rockchip RK3576 EVB1 V10 / RKNN | 8 | 5/channel | PASS | -CosmoEdge `v1.0.0` is the first stable public release. The engine is production-ready for evaluation, integration, and community model expansion. +The 1 / 2 / 4 / 8-channel steps all passed with zero discarded frames or inference, RGA, or MPP failures. Single-channel Detect average decreased from 142.3 ms to 58.2 ms (-59.1%). A separate 12-hour run at 4 channels and 5 FPS, with four algorithm previews, recorded 720 continuous hold samples, CPU avg/P95/max of 33.92% / 39% / 43%, and zero discarded frames or runtime/preview failures. -### Shipped in v1.0.0 +The four-channel, 5 FPS profile completed the 12-hour run. The 8-channel step records engineering headroom and is not a release capacity guarantee. This historical evidence is retained as long-duration context and is not silently rebound to the newer v1.1 source baseline. -- [X] C++17 edge inference engine -- [X] Visual pipeline orchestrator -- [X] Web management console -- [X] x86 developer mode for Linux and Windows -- [X] Sophon BM1688 release packaging -- [X] VLM and GroundingDINO integration -- [X] 26 pipeline scenarios internally validated -- [X] Final v1.0 regression pass and hardening (shell-injection guards, null-safety and lifecycle fixes, default-password enforcement) +## Architecture -### Roadmap +```text ++------------------------------------------------------------------+ +| Web Console | Visual Orchestration | REST / WebSocket / MQTT | ++--------------------------------+---------------------------------+ + | ++--------------------------------v---------------------------------+ +| C++ Engine Core | +| Media | Inference | Tasks | Rules | Alarms | Events | Models | ++--------------------------------+---------------------------------+ + | ++--------------------------------v---------------------------------+ +| Inference and Media Backend Interfaces | ++--------------------+----------------------+----------------------+ +| Sophon BMRT/VPU | RKNN + MPP/RGA | ONNX Runtime/FFmpeg | +| BM1688; CV186X | RK3576 | x86 Linux / Windows | ++--------------------+----------------------+----------------------+ +``` -- [ ] Expand the validated pipeline scenario library -- [ ] Community model and scenario examples -- [ ] Additional model adapters and post-processing templates +One build selects one inference backend. Model artifacts are generated for the target platform, and feature/model coverage and capacity remain platform-specific. Model Guard Protected distribution currently belongs to the Sophon packaging path. -## Contributing +## Documentation, Devices, and Community -CosmoEdge is at v1.0.0. We welcome focused contributions in these areas: +| Start here | Best for | +| --- | --- | +| [Documentation Home](https://www.cosmowander.ai/docs/) | Full documentation index and learning path | +| [Quick Start Guide](https://www.cosmowander.ai/docs/tutorials/01-quickstart/quickstart) | First setup and scenario run | +| [Scenario Configuration](https://www.cosmowander.ai/docs/tutorials/02-scenario-config/scenario-config) | Building scene-level workflows | +| [VLM Guide](https://www.cosmowander.ai/docs/tutorials/03-vlm-guide/vlm-guide) | Prompt-based visual judgment and events | +| [Model Porting Guide](https://www.cosmowander.ai/docs/tutorials/05-model-porting/model-porting) | Importing your own model | +| [Agent-Assisted Development](docs/en/development/agent-assisted-development.md) | Delegating an extension task with verifiable results | +| [Build Guide](https://www.cosmowander.ai/docs/guide/build) | x86, Sophon, and RK3576 build/package paths | +| [API Overview](https://www.cosmowander.ai/docs/reference/api) | REST, WebSocket, MQTT, and webhook integration | -- Bug reports with logs and reproduction steps. -- Documentation fixes and tutorial improvements. -- Scenario examples and integration notes. -- Small, scoped pull requests after an issue discussion. +Certified devices add preconfigured acceleration, validated commercial model packages, and dedicated deployment support; they do not unlock separate software features. Devices are available in mainland China from the [Taobao store](https://item.taobao.com/item.htm?id=1066672051450); contact for other regions or project support. -Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. First-time contributors can also start with the [Contributor Guide](docs/en/development/contributing.md). +Contributions are welcome through scoped bug reports, documentation improvements, scenarios, and integration notes. Read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request. Community support is available through [GitHub Discussions](https://github.com/cosmo-wander-ai/cosmo-edge/discussions) and [Gitee Issues](https://gitee.com/cosmo-wander-ai/cosmo-edge/issues); report vulnerabilities through [SECURITY.md](SECURITY.md). ## FAQ
-Do I need a Sophon device to try CosmoEdge? - -No. Use x86 developer mode on Linux or Windows to try the UI, pipeline workflow, model management, and integration path. Sophon hardware is needed for production-level NPU throughput. - -
- -
-How many scenarios or algorithms does CosmoEdge support? +Can I try CosmoEdge without Sophon or Rockchip hardware? -CosmoEdge has two core concepts: models (AI weights) and scenario tasks — also called pipelines — each an orchestrated graph of model, scheduling, and rule logic that binds to specific inputs, zones, and rules at deployment. The 26 validated pipelines each cover many real deployments as their inputs and rules change. Capability scales with composition, not with a fixed algorithm catalog. +Yes. Use x86 developer mode on Linux or Windows. Apple Silicon Macs can use the Docker Preview for the console, pipeline, model-management, and integration workflow with one local video. The Mac path uses amd64 emulation and does not enable Model Guard. Edge NPU hardware is still required for target-platform acceleration and capacity validation.
-Does the open-source repository include model weights? +What is the boundary between the Open and Protected packages? -The open-source repository does not include production model weights by default. You can bring your own models, including compatible Qwen3 VLM series models and Qwen3.5 multimodal models. Certified device packages can provide a library of ~25 pre-installed production CV models, plus `CosmoEdge-VL-Judge-0.8B` and GroundingDINO. Community or custom models should be validated for the target scenario. +They expose the same application features and use the same MD5 upgrade lifecycle. Open uses plaintext models without device authorization; Sophon Protected packages can carry encrypted commercial preset models and provisioning tooling that require a device-bound certificate. Application archives themselves are not signed.
Can I use my own trained models? -Yes. CosmoEdge is designed around model import and model lifecycle management. The model porting guide documents the recommended path from ONNX or target runtime formats into the model repository. - -
- -
-How is CosmoEdge different from inference servers or NVR projects? - -CosmoEdge is an application runtime for complete edge AI workflows, not just a model-serving layer or video recorder. +Yes. Use the model-porting path to validate the tensor, preprocessing, post-processing, target runtime, and business accuracy contract. A model artifact must be generated for the platform where it will run.
-Is CosmoEdge production-ready? +How production-ready is CosmoEdge? -The codebase comes from commercial development for production deployments and has passed internal stress, pipeline, and regression validation, including the final v1.0 release regression pass. CosmoEdge `v1.0.0` is the first stable public release: the engine, core workflows, and release packaging are built for field deployment, and public APIs and contributor workflows are stable. +`v1.1.0` is the multi-platform release line for BM1688, CV186X, RK3576, and x86. The linked report records measured workload boundaries and explicit evidence gaps; production sizing still requires validation with your own models, streams, accuracy requirements, and deployment conditions.
-## Contact +### License -- Community: [GitHub Discussions](https://github.com/cosmo-wander-ai/cosmo-edge/discussions) -- 国内社区: [Gitee Issues](https://gitee.com/cosmo-wander-ai/cosmo-edge/issues) -- Partnership & Enterprise: -- Security: see [SECURITY.md](SECURITY.md) for private vulnerability reporting - -## License - -CosmoEdge is licensed under the [Apache License 2.0](LICENSE). - -```text -Copyright 2026 CosmoEdge Contributors - -Licensed under the Apache License, Version 2.0 -``` +CosmoEdge is licensed under the [Apache License 2.0](LICENSE). Copyright 2026 CosmoEdge Contributors. --- @@ -448,6 +282,6 @@ An open-source project by Cosmo Wander AI and the CosmoEdge contributors. Turn video AI models into deployable edge applications. -📦 This repo is mirrored to [Gitee](https://gitee.com/cosmo-wander-ai/cosmo-edge) for mainland China access. See [MIRRORING.md](MIRRORING.md). +📦 This repository is mirrored read-only to [Gitee](https://gitee.com/cosmo-wander-ai/cosmo-edge) for mainland China access. See [MIRRORING.md](MIRRORING.md). diff --git a/README.zh-CN.md b/README.zh-CN.md index c322dad3c..aa61bd0ed 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -2,444 +2,258 @@ CosmoEdge -**面向视频智能分析的生产级 C++ 边缘 AI 引擎,支持可视化流水线编排与端侧 VLM 工作流** +**把视频 AI 模型变成可部署的边缘应用——面向 Sophon、Rockchip 与 x86 的 C++ 边缘 AI 引擎。** -[![Nightly Sophon Build and Test](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/nightly-build-test-sophon.yml/badge.svg?branch=main)](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/nightly-build-test-sophon.yml) +使用一致的可视化编排和设备管理体验构建视频分析、VLM 与事件工作流;不同平台使用各自的运行时、构建产物和模型包。 +[![Nightly Sophon Build and Test](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/nightly-build-test-sophon.yml/badge.svg?branch=main)](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/nightly-build-test-sophon.yml) +[![Nightly RK3576 Cross Build](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/ci-build-rk3576.yml/badge.svg?branch=main)](https://github.com/cosmo-wander-ai/cosmo-edge/actions/workflows/ci-build-rk3576.yml) [![License](https://img.shields.io/badge/license-Apache%202.0-blue?style=flat-square)](LICENSE) -[![Runtime](https://img.shields.io/badge/runtime-C%2B%2B17-orange?style=flat-square)](#c-原生运行时) -[![Platform](https://img.shields.io/badge/platform-Sophon%20BM1688%20%2F%20x86%20Linux%20%2F%20Windows-purple?style=flat-square)](#支持平台) -[![Release](https://img.shields.io/badge/release-v1.0.0-green?style=flat-square)](https://github.com/cosmo-wander-ai/cosmo-edge/releases) -[![Stress Test](https://img.shields.io/badge/stress%20test-200%20video%20samples-brightgreen?style=flat-square)](#验证与性能) -[![Pipelines](https://img.shields.io/badge/pipelines-26%20validated-brightgreen?style=flat-square)](#验证与性能) -[![Website](https://img.shields.io/badge/website-cosmowander.ai-3B82F6?style=flat-square)](https://www.cosmowander.ai/zh/) -[![Docs](https://img.shields.io/badge/docs-online-2563EB?style=flat-square)](https://www.cosmowander.ai/docs/) -[![GitHub](https://img.shields.io/badge/GitHub-cosmo--edge-181717?style=flat-square&logo=github)](https://github.com/cosmo-wander-ai/cosmo-edge) +[![Runtime](https://img.shields.io/badge/runtime-C%2B%2B17-orange?style=flat-square)](#核心能力) +[![Release](https://img.shields.io/badge/release-v1.1.0-green?style=flat-square)](https://github.com/cosmo-wander-ai/cosmo-edge/releases) +[![Website](https://img.shields.io/badge/website-cosmowander.ai-3B82F6?style=flat-square)](https://www.cosmowander.ai/) +[![Docs](https://img.shields.io/badge/docs-online-2563EB?style=flat-square)](https://www.cosmowander.ai/zh/docs/) [![Gitee](https://img.shields.io/badge/Gitee-cosmo--edge-C71D23?style=flat-square&logo=gitee)](https://gitee.com/cosmo-wander-ai/cosmo-edge) -[官网](https://www.cosmowander.ai/zh/) | [在线文档](https://www.cosmowander.ai/docs/) | [快速开始](#快速开始) | [核心特性](#核心特性) | [验证与性能](#验证与性能) | [Benchmark](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.0/) | [硬件](#cosmoedge-ready-设备) - -[English](README.md) | 简体中文 +[快速开始](#快速开始) · [平台选择](#选择平台) · [验证](#验证与性能) · [文档](#文档设备与社区) · [English](README.md) --- -> 本文档与英文 README 保持同步更新。如内容存在差异,请以英文版和最新发布说明为准。 - -
- -https://github.com/user-attachments/assets/96eeba7e-5b00-4c54-97b3-3ee4571cd5a0 - -
- -*在单台边缘设备上运行多路 AI 流水线、实时 OSD 叠加和事件输出。* - -CosmoEdge 是一款面向生产级视频智能分析的 C++ 边缘 AI 引擎。它帮助团队从模型文件走向可运行应用:导入模型、编排流水线、接入视频源、在浏览器中查看 AI 叠加画面,并通过 MQTT 或 HTTP 推送结构化事件。 - -其 C++17 运行时负责多路视频处理、硬件解码、OSD 渲染和低开销边缘部署,提供在现场部署、监控、调试和维护边缘 AI 应用所需的运行时、Web 控制台和集成路径。 - -## 你可以构建什么 - -- 多摄像头安全监测,支持实时 OSD 和告警截图。 -- 面向人、车、物的计数、越线和区域入侵分析。 -- 端侧 VLM 提示词驱动的视觉巡检,用于质量与合规检查。 -- 从文本提示词检测罕见或未列举目标,无需针对性训练(GroundingDINO)。 - -以上每个应用都以受管边缘部署的形式交付:模型管理、场景任务、告警规则,以及 MQTT/HTTP 数据推送。 - -## 核心特性 - -### C++ 原生运行时 - -CosmoEdge 以 C++17 运行时为核心。对边缘视频系统来说,解码、推理调度、OSD 渲染、事件生成和流输出都需要在资源受限的设备上持续运行。 - -- 长期运行的多路视频负载开销更低。 -- 直接集成硬件解码、NPU 运行时、内存池和流媒体组件。 -- 面向设备化边缘部署,CPU、内存和线程行为更可预测。 -- x86 开发模式和 Sophon 生产部署使用同一套引擎核心。 - -### 可视化流水线编排 - -在浏览器中构建视频 AI 工作流。通过可视化流水线编辑器连接视频源、AI 模型、后处理节点、OSD 渲染、告警规则和输出通道。 - -
- -https://github.com/user-attachments/assets/c9673081-ad73-4455-9486-1a3021358cdd - -
- -### 应用工作流 - -CosmoEdge 将运行时、Web 控制台和集成层连接成一条部署工作流: - -```text -模型仓库 -> 场景任务 -> 实时分析 -> 告警管理 -> 数据推送 - | | | | | -上传/管理 配置流水线 多路 AI + 规则引擎 MQTT / HTTP -ONNX/bmodel 按场景绑定 OSD 叠加 告警截图 webhook -模型版本 摄像头 WebRTC 流 事件日志 集成 -``` - -
-完整能力列表 - -| 模块 | 能力 | -| --- | --- | -| 模型仓库 | 模型上传、元数据管理、版本管理、热替换流程 | -| 场景任务 | 流水线绑定、摄像头绑定、任务调度、场景级配置 | -| 实时分析 | RTSP、视频文件、USB 摄像头、WebRTC 实时预览、HTTP-FLV 兜底 | -| 图片分析 | 批量图片上传、VLM 分析、结构化结果 | -| 告警管理 | 基于规则的告警、严重等级、告警截图、筛选、事件历史 | -| 数据集成 | MQTT 推送、HTTP webhook、结构化 JSON 事件格式 | -| 系统管理 | 仪表盘、设备状态、用户认证、国际化、配置管理 | - -
- -### 实时可视化调试 - -CosmoEdge 内置 OSD 系统,面向操作人员和开发者: - -- 使用业务标签,避免直接展示原始模型类别名。 -- 使用语义化颜色区分正常、预警、违规和不确定状态。 -- 支持区域叠加、越线指示、计数器和事件面板。 -- 调试视图可展示原始检测框、置信度、跟踪 ID 和模型输出。 - -### 提示词驱动 AI:GroundingDINO + VLM - -在边缘设备上运行提示词驱动的视觉模型,作为异步流水线节点与传统 CV 流水线一起使用: - -| 能力 | 工作方式 | 典型用途 | -| --- | --- | --- | -| GroundingDINO | 文本提示词 -> 开放词表目标检测 | 无需针对特定类别训练即可查找长尾目标 | -| 端侧 VLM | 封闭式问题 -> YES/NO 状态判断 | “柜门是否打开?” -> YES 时触发告警 | -| VLM 图片分析 | 图片上传 -> 结构化视觉检查 | 质量检测、合规检查 | -
-https://github.com/user-attachments/assets/f47b541e-0d01-437d-86e1-4183f6e610fd +
-端侧 VLM 节点支持兼容的 Qwen3 VLM 系列和 Qwen3.5 多模态模型。认证设备包可提供 `CosmoEdge-VL-Judge-0.8B`,面向 YES/NO 视觉状态判断优化。 - -新增:VLM 节点支持两种可互换后端——嵌入式本地运行时(数据不出设备),或任意 OpenAI 兼容端点(自建或 SaaS)以调用更大的模型。VLM 走的是异步、事件驱动路径,可吸收额外的网络往返延迟;本地运行时仍是已验证的默认方案。 - -### 模型来源 +CosmoEdge 不只是模型推理服务:它提供从模型导入、可视化编排到告警与事件推送的完整应用层。仓库中的核心引擎与控制台以 Apache-2.0 开源;认证硬件、商业预置模型与 Model Guard 分发保护具有独立边界。 -**CosmoEdge 已支持:** +## CosmoEdge 1.1 -| 类别 | 支持模型/架构 | 流水线支持 | -| :--- | :--- | :--- | -| 目标检测 | YOLOv5、YOLOv8、YOLOv10、YOLOv11、YOLOv12、YOLO26 | 完整流水线 | -| 目标跟踪 | ByteTrack | 完整流水线 | -| 属性分类 | 安全帽、反光背心、工服等分类器 | 完整流水线 | -| 计数与统计 | 越线统计、区域计数、方向流量 | 完整流水线 | -| 开放词表检测 | GroundingDINO | 异步流水线节点 | -| 视觉状态判断 | Qwen3 VLM 系列、Qwen3.5 多模态模型(文本提示词 -> YES/NO) | 异步流水线节点(本地或 OpenAI 兼容 API) | -| 图片分析 | VLM 批量分析 | 独立任务 | +> 当前分支是 CosmoEdge 1.1 源码线。不同模型和负载的容量不同,请以关联证据为准,不把短时最高点直接当作部署推荐值。 -**模型生态兼容性:** +- **多平台发布:**BM1688、CV186X 与 RK3576 共享同一套视频接入、任务编排、事件和可观测流程,并分别使用目标平台模型产物。 +- **公开 benchmark 包:**[CosmoEdge 1.1 多平台报告](docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md)覆盖单算法、双算法与 Experimental VLM,提供脱敏后的可复现附件。 +- **Rockchip RK3576:**已集成交叉构建、板端运行、RKNN 推理和 MPP/RGA 媒体路径;4 路单算法已有 12 小时证据,更高短时结果只作为实测边界,不直接作为推荐配置。 +- **Sophon 模型处理:**芯片感知校验支持 BM1688 与 CV186X 的目标 `.nn` 产物;benchmark 已记录两台参考设备的 Open 安装包和运行引擎精确绑定。 +- **RKNN 数据路径:**包含 DMA-BUF 到 RGA 输入、持久绑定输入、原生量化输出和 YOLOv8 张量直接解码路径,并保留明确 fallback。 +- **智能体辅助二开:**提供仓库级入口,把模型适配、系统集成和界面改造任务交给常用编码智能体,并获得可核验交付物。 +- **Model Guard 2.3:**为 Sophon Protected 包中的商业预置模型提供分发保护;Open 与 Protected 的应用软件能力一致,不以 SKU 解锁软件功能,区别在于模型是否加密以及是否包含设备授权工具。 +- **macOS Docker Preview:**为 Apple Silicon 提供隔离的 `linux/amd64` 单路本地视频体验候选;发布前仍需完成连续两轮端到端验收。它不启用 Model Guard,也不代表 NPU 或原生性能。 -CosmoEdge 使用 ONNX 作为模型交换格式。来自主流 CV 训练框架的模型可以按文档中的转换路径导入: +## 选择平台 -- **Ultralytics (YOLO)**:使用 `yolo export format=onnx` 导出,然后通过模型仓库导入,或转换为 bmodel 用于 NPU 部署。 -- **Roboflow**:在 Roboflow 上训练,导出 ONNX,再导入 CosmoEdge。 -- **自定义模型**:任何兼容 ONNX 的检测或分类模型,都可以通过模型适配指南接入。 +CosmoEdge 提供统一的引擎架构与编排体验,但每次构建只选择一个推理后端,并使用面向目标平台生成的模型产物。 -**Sophon 模型生态:** - -CosmoEdge 运行在 Sophon BM1688 推理栈上。SOPHGO 官方模型仓库中的模型可以通过模型适配指南接入,指南覆盖后处理适配和流水线节点注册。 - -→ [SOPHGO Model Zoo (sophon-demo)](https://github.com/sophgo/sophon-demo) -→ [CosmoEdge Model Porting Guide](docs/tutorials/05-model-porting/model-porting.md) +| 平台 | 状态 | 运行时 / 模型产物 | 当前范围与证据 | +| --- | --- | --- | --- | +| Sophon BM1688 | v1.1 已支持 / 主力平台 | BMRT / `.nn` | 生产部署路径,包含 [v1.1 工作负载证据](docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md)和已发布 [v1.0 基线](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/) | +| Rockchip RK3576 | v1.1 已支持 | RKNN / `.rknn` | 交叉构建和板端路径已验证;参见 [RK3576 集成指南](docs/guide/rk3576-rknn-development.md)与 [v1.1 工作负载证据](docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md) | +| Sophon CV186X | v1.1 已支持 | BMRT / 目标芯片专用 `.nn` | 模型导入与设备工作负载证据见 [v1.1 benchmark](docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md) | +| x86 Linux / Windows;Apple Silicon macOS | Linux / Windows 已支持;macOS Preview | ONNX Runtime / `.onnx` | Mac 通过 amd64 仿真覆盖单路本地视频开发体验,不代表原生性能 | +| Sophon BM1684X | 规划中 | — | 不属于当前发布范围 | ## 快速开始 -### 方案 A:x86 开发模式 +### 在 x86 本地试用 -无需边缘硬件即可试用 CosmoEdge。x86 开发模式使用与边缘部署相同的 UI 和工作流,但吞吐低于 Sophon NPU 模式。 +无需边缘硬件即可体验。x86 模式使用与边缘部署一致的 UI 和工作流,但吞吐低于 NPU 部署。 ```bash -# 1. Clone +# 1. 克隆 git clone https://github.com/cosmo-wander-ai/cosmo-edge.git -# 或使用 Gitee 镜像(国内推荐): -# git clone https://gitee.com/cosmo-wander-ai/cosmo-edge.git cd cosmo-edge -``` -> **💡 Docker Compose 版本提示** -> 本文档统一使用最新的 Docker Compose V2 命令格式 (`docker compose`)。如果你使用的是旧版 Docker 环境,请将文中的 `docker compose` 替换为带横杠的 `docker-compose`。 - -```bash -# 2. 启动 x86 模式 -# Linux: +# 2. 在 Linux 启动 sudo docker compose -f docker-compose.x86.yml up -d --build +# Windows:docker compose -f docker-compose.x86.windows.yml up -d --build +# Apple Silicon macOS(Preview):./scripts/macos-docker-preview.sh up -# Windows (PowerShell/CMD): -docker compose -f docker-compose.x86.windows.yml up -d --build - -# 3. 打开 Web 控制台 -# http://localhost:8080 +# 3. 打开 http://localhost:8080 ``` -> **USB 摄像头**:如有 USB 摄像头设备,请在启动前取消 `docker-compose.x86.yml` 中 `devices` 段的注释。 - -启动后,参照 [场景配置教程](docs/tutorials/02-scenario-config/scenario-config.md) 设置你的第一个 AI 检测场景。 +启动后,按照[场景配置教程](https://www.cosmowander.ai/zh/docs/tutorials/02-scenario-config/scenario-config)创建第一个 AI 检测任务。Mac 用户先阅读 [macOS Docker Preview](docs/guide/macos-docker-preview.md) 的许可、环境和能力边界。使用 Docker Compose V1 时,可将 `docker compose` 替换为 `docker-compose`。 -### 方案 B:Sophon 边缘设备 - -该路径用于 Sophon NPU 加速部署。 +### 为 Sophon 构建 ```bash -# 1. Clone git clone https://github.com/cosmo-wander-ai/cosmo-edge.git -# 或使用 Gitee 镜像(国内推荐): -# git clone https://gitee.com/cosmo-wander-ai/cosmo-edge.git cd cosmo-edge +# BM1688(省略芯片型号时的默认值) +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip bm1688 -# 2. 构建 Sophon/aarch64 发布包 -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package - -# 3. 查看导出的发布包 -ls -lh build_output/ -# 输出的包名格式如:cosmo-V-.tar.gz - -# 4. 将安装包拷贝到 Sophon 边缘设备上(将 替换为设备的实际 IP,默认是 192.168.100.1) -scp build_output/cosmo-V*.tar.gz root@:/tmp/ - -# 5. SSH 登录设备,解压并执行 install.sh 安装脚本 -ssh root@ -cd /tmp -tar -zxvf cosmo-V*.tar.gz -sudo bash scripts/install.sh - -# 6. 重启设备以启动服务 -sudo reboot -``` - -在 Windows PowerShell 下构建发布包: - -```powershell -.\scripts\build_sophon_package.ps1 +# CV186X +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x ``` -安装完成并重启设备后: -- **默认 IP**:`192.168.100.1`(请确保你的电脑与设备处于同一网段,例如配置静态 IP 为 `192.168.100.x`) -- **登录地址**:`http://192.168.100.1` -- **默认用户名**:`admin` -- **默认密码**:`admin`(首次登录后建议修改) +包装脚本会自动选择当前环境可用的 Compose 实现,并仅在 Docker 权限不足时请求提权。 +构建脚本会根据芯片型号选择对应模型资源,无需填写模型路径;不同目标分别导出到 +`build_output/public-runtime//`,目录内同时包含 `TARGET_CHIP` 和 `SHA256SUMS`。 -该路径会构建发布包并安装到 Sophon 设备。需要生产硬件时,认证 CosmoEdge 设备可提供预配置 Sophon 加速、生产模型包和部署支持。参见 [CosmoEdge-ready 设备](#cosmoedge-ready-设备)。 +默认 Open 包包含明文模型,不需要设备授权。部署前必须核对芯片标记和校验和。 +[构建指南](https://www.cosmowander.ai/zh/docs/guide/build)是构建事实的权威入口;SSH 安装、 +页面升级、恢复与重启后验收统一参阅[部署指南](https://www.cosmowander.ai/zh/docs/guide/deployment)。 -初始引导指南 -
+### 为 RK3576 构建 -https://github.com/user-attachments/assets/395e5b89-c6af-4276-a89b-577b3400efc1 +```bash +docker compose -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package +ls -lh build_output/rk3576/ +``` -测试视频路径:cosmo-edge\data\test-video +公开构建镜像已固定 digest,并包含 RKNN、MPP 和 RGA 构建依赖。目标运行时与 +设备验证边界请参阅 [RK3576 集成指南](docs/guide/rk3576-rknn-development.md)。 -
+CV186X 请按照 [CV186X 快速开始](docs/guide/cv186x-quick-start.md)完成安装、模型导入、首个事件验证,以及升级和恢复检查。 -## 验证与性能 +## 你可以构建什么 -CosmoEdge 源自商业化代码库,开源发布前已完成内部系统验证。 +- **实时视频分析:**检测、分类、跟踪、区域规则、计数、OSD 和告警截图。 +- **提示词驱动视觉:**让 VLM 状态判断和 GroundingDINO 开放词汇检测与传统 CV 流水线协同工作。 +- **可视化应用工作流:**在浏览器中连接模型、规则、事件和输出动作。 +- **边缘系统集成:**管理场景任务,并通过 REST、WebSocket、MQTT 或 HTTP webhook 输出结构化事件。 -一条场景任务(流水线)封装了模型、调度和规则逻辑;部署时再绑定具体输入、区域和规则。这里的 26 计的是已验证流水线——同一套任务随输入和规则变化即可覆盖大量实际部署,无需写代码。 +## 核心能力 -| 范围 | 当前验证状态 | -| --- | --- | -| 视频压力测试 | 使用 200 个视频样本进行连续播放测试,未观察到内存泄漏或崩溃 | -| 流水线验证 | 26 条流水线已按内部场景基线完成验证(涵盖 CV、VLM 与 GroundingDINO) | -| 并发 CV 负载 | ScenarioBench v1.0 已验证 NPU 设备最高 16 路 CV 视频负载,详细报告见下方 | -| 回归测试 | 专职 QA 已完成多轮系统回归,含 v1.0 最终发布回归 | -| 试点部署 | 已授权客户试点覆盖数百路视频分析,连续运行两个月以上,覆盖多个行业场景 | +| 能力 | 能力范围 | 深入了解 | +| --- | --- | --- | +| 原生运行时 | 面向多路媒体、推理调度、OSD、任务和事件的 C++17 引擎 | [架构](https://www.cosmowander.ai/zh/docs/guide/architecture) | +| 可视化编排 | 浏览器端流水线组合、任务绑定、参数校验和实时反馈 | [流水线教程](https://www.cosmowander.ai/zh/docs/tutorials/04-pipeline-orchestration/pipeline-orchestration) | +| 推理与媒体 | Sophon、RKNN 和 x86 平台后端;平台专用构建与模型产物 | [构建指南](https://www.cosmowander.ai/zh/docs/guide/build) | +| VLM 与 DINO | 提示词视觉判断、开放词汇检测,以及检测告警上报前可选的 VLM 复核 | [VLM 指南](https://www.cosmowander.ai/zh/docs/tutorials/03-vlm-guide/vlm-guide) | +| 运维与集成 | 模型管理、告警、事件历史、REST、WebSocket、MQTT 和 webhook | [API 概览](https://www.cosmowander.ai/zh/docs/reference/api) | +| 模型接入与保护 | 模型转换、导入、验证,以及 Open/Protected 分发边界 | [模型适配指南](https://www.cosmowander.ai/zh/docs/tutorials/05-model-porting/model-porting) | -### 性能基准 +
+▶ 观看演示:可视化编排一条完整 pipeline -下列结果来自可复现的 ScenarioBench 基准测试。CV 与 x86 报告保留在 [ScenarioBench v1.0 基准测试](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/);VLM 行指向当前刷新后的 VLM 方法报告。完整原始 `metrics.json` 采样数据不随仓库提交。 + -一个视频通道表示一路已解码输入流。一个场景任务表示绑定到通道上的一条算法流水线,因此混合场景的任务数可以高于视频通道数。表中的路数是本次公开基准测试范围内验证通过的最大稳定视频通道数。 +
-| ScenarioBench 负载 | 硬件档位 | 最大验证视频通道数 | 并发场景任务数 | 目标 FPS | 结果 | 证据 | -| --- | --- | ---: | ---: | ---: | --- | --- | -| 安全帽检测 | YY-16T01-Preview / NPU | 16 | 16 | 3/channel | 通过 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/helmet-7463-npu/report.zh-CN.html) | -| 行人检测 | YY-16T01-Preview / NPU | 16 | 16 | 5/channel | 通过 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/pedestrian-45626-npu/report.zh-CN.html) | -| 行人 + 安全帽双算法 | YY-16T01-Preview / NPU | 16 | 32 | 3/channel/task | 通过 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/pedestrian-helmet-mixed-npu/report.zh-CN.html) | -| VLM 审核 | YY-16T01-Preview / NPU | 8 | 8 | 0.1/channel | 通过 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/current/vlm-77175-npu/report.zh-CN.html) | -| 安全帽检测 x86 基线 | X86 CPU baseline | 7 | 7 | 3/channel | 受限;8 路开始超过延迟阈值 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/helmet-7463-x86/report.zh-CN.html) | +
+▶ 观看演示:GroundingDINO 与 VLM 视觉工作流 -硬件档位、模型输入和发布策略见双语 [benchmark manifest](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/manifest.json)、[测试环境说明](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/environment) 与 [当前 benchmark 刷新说明](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/current/)。x86 行是 CPU-only 对照基线,不代表 v1.0 NPU 设备容量目标。 + -## 架构 +
-```text -+---------------------------------------------------------------+ -| Web Frontend | -| Pipeline Editor | Management Console | Real-time View | -+-------------------------------+-------------------------------+ - | REST / WebSocket / MQTT - v -+---------------------------------------------------------------+ -| C++ Engine Core | -| Flow Engine | Media Pipeline | Inference | Services | -| Task/Action | Decode/Encode | CV/VLM/DINO | Alarm/Event/Model | -+-------------------------------+-------------------------------+ - | - v -+---------------------------------------------------------------+ -| Hardware Abstraction | -| Sophon BM1688 NPU/VPU/VPP | x86 CPU | -+---------------------------------------------------------------+ -``` +## 智能体辅助二次开发 -### 技术栈 +已经有模型适配、系统集成或界面改造任务?把业务目标、已有物料、目标设备或测试环境和验收要求交给常用编码智能体。仓库提供任务入口、示例、检查和证据边界,使结果可以包含可导入产物、范围明确的代码改动和可核验结论。 -| 层级 | 技术 | -| --- | --- | -| 引擎 | C++17、CMake、FFmpeg、SQLiteCpp | -| 推理 | Sophon BMRT、x86 模式使用 ONNX Runtime | -| 前端 | Vue.js、Vue Flow、Element Plus | -| 流媒体 | SRS 6.0、WebRTC、HTTP-FLV | -| 集成 | REST API、WebSocket、MQTT、HTTP webhook | +从[智能体辅助二次开发](docs/development/agent-assisted-development.md)开始,再根据具体任务进入[模型适配指南](https://www.cosmowander.ai/zh/docs/tutorials/05-model-porting/model-porting)或[贡献者指南](docs/development/contributing.md)。 -## 支持平台 +## 验证与性能 -| 平台 | 状态 | 目标用途 | -| --- | :---: | --- | -| Sophon BM1688 | 主力平台 | NPU 加速生产部署 | -| x86 Linux | 已支持 | 开发、评估、集成测试 | -| x86 Windows | 已支持 | 开发和评估 | -| Sophon BM1684X | 规划中 | NPU 加速部署 | +### CosmoEdge 1.1 多平台性能报告 -## CosmoEdge-ready 设备 +已收口的 v1.1 公开材料覆盖 BM1688、CV186X 与 RK3576,包括精简主报告及关联的单算法、双算法、Experimental VLM 附件。除非明确标注更长时长,当前结果属于短时工作负载证据,不代表芯片理论上限,也不会自动成为部署推荐配置。 -CosmoEdge 是开源项目。仓库提供认证设备包所使用的同一套引擎、Web UI 和工作流。你可以使用自带模型,在 x86 上开发,并部署到兼容的边缘硬件。 +- [中文 benchmark 索引](docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md) +- [English benchmark index](docs/benchmarks/scenario-bench/v1.1/README.md) +- [中文主报告(官网渲染版)](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/report.zh-CN.html) +- [方法与复现](docs/benchmarks/scenario-bench/v1.1/methodology.md) -认证设备帮助团队减少硬件适配和模型打包工作,提供预配置 NPU 加速、生产模型包和专属部署支持。 +发布分支准备基线为 `feat/model-guard-v2.3` commit `209bc2b52849864a15bdad91beb61f5bc982c17f`、tree `f64a98bce05b9ee8dc64dda8e56ad50f9d15687f`。BM1688 与 CV186X 已绑定到记录的 Open 安装包和运行引擎;该安装包不嵌入 source commit,因此不宣称它可从这一准备基线复现构建。RK3576 包哈希与 Protected 包构建来源不在公开 benchmark 中,因此报告不对它们作 package-qualified 声明。精确证据边界见 [release manifest](docs/benchmarks/scenario-bench/v1.1/release-manifest.json)。 -| 能力 | 开源仓库 | 认证设备包 | -| --- | :---: | :---: | -| C++ 引擎 | 包含 | 包含 | -| 可视化流水线编排器 | 包含 | 包含 | -| Web 管理控制台 | 包含 | 包含 | -| x86 开发模式 | 包含 | 包含 | -| Sophon NPU 运行时支持 | 源码支持,需自备硬件 | 预配置 | -| CV 模型包 | 自带模型 | 预安装(约 25 个生产 CV 模型) | -| `CosmoEdge-VL-Judge-0.8B` | 自带或定制模型包,需自行验证 | 预安装认证模型包 | -| GroundingDINO 包 | 自带或定制模型包 | 预安装 | -| 部署支持 | 社区支持 | 专属支持 | +下表保留此前已经公开的 **v1.0 历史基线**: -认证设备提升部署就绪度,不把软件能力锁定在特定硬件上。 +| ScenarioBench 负载 | 硬件 | 最大验证路数 | 目标 FPS | 结果 | 证据 | +| --- | --- | ---: | ---: | --- | --- | +| 安全帽检测 | YY-16T01-Preview / NPU | 16 | 3/channel | 通过 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/helmet-7463-npu/report.zh-CN.html) | +| 行人检测 | YY-16T01-Preview / NPU | 16 | 5/channel | 通过 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/pedestrian-45626-npu/report.zh-CN.html) | +| 行人 + 安全帽双算法 | YY-16T01-Preview / NPU | 16 | 3/channel/task | 通过 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/pedestrian-helmet-mixed-npu/report.zh-CN.html) | +| VLM 复核 | YY-16T01-Preview / NPU | 8 | 0.1/channel | 通过 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/vlm-55009-npu/report.zh-CN.html) | +| 安全帽检测 x86 基线 | x86 CPU | 7 | 3/channel | 受限;8 路超过延迟阈值 | [报告](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/helmet-7463-x86/report.zh-CN.html) | -开源引擎和全部软件功能现已面向全球开放,无需购买。CosmoEdge-ready 认证设备已在中国大陆上架,可通过[淘宝购买认证设备](https://item.taobao.com/item.htm?id=1066672051450)。如需咨询中国大陆以外地区的可用性或项目部署支持,请联系 hello@cosmowander.ai。 +v1.0 的测试方法和发布边界见 [benchmark manifest](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/manifest.json)、[环境说明](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/v1.0/environment)和[当前刷新说明](https://www.cosmowander.ai/zh/docs/benchmarks/scenario-bench/current/)。 -## 文档 +### RK3576 长稳验证背景 -| 入口 | 读者 | 说明 | -| --- | --- | --- | -| [文档首页](docs/index.md) | 所有用户 | 完整文档索引和阅读路径 | -| [快速开始](docs/tutorials/01-quickstart/quickstart.md) | 所有用户 | 完成首次启动和场景体验 | -| [场景配置](docs/tutorials/02-scenario-config/scenario-config.md) | 集成商 | 构建场景级 AI 工作流 | -| [VLM 指南](docs/tutorials/03-vlm-guide/vlm-guide.md) | 开发者 | 使用提示词完成视觉状态判断 | -| [流水线编排](docs/tutorials/04-pipeline-orchestration/pipeline-orchestration.md) | 高级用户 | 可视化编排自定义流水线 | -| [模型适配指南](docs/tutorials/05-model-porting/model-porting.md) | 算法工程师 | 导入 ONNX 或目标运行时模型 | -| [使用智能体完成二次开发](docs/development/agent-assisted-development.md) | 二次开发者 | 用你熟悉的编码智能体完成模型转换等二开任务,交付可验证 | -| [构建指南](docs/guide/build.md) | 开发者 | 构建 x86 Docker 和 Sophon 发布包 | -| [API 概览](docs/reference/api.md) | 开发者 | REST、WebSocket 和 MQTT API 类别 | +这组较早的长稳证据仍绑定源码 [`8f8b4b8e`](https://github.com/cosmo-wander-ai/cosmo-edge/commit/8f8b4b8e793172963ef92da7fc9942a1c860534b)(tree `fd1b646f`)、engine SHA-256 `bc829d9513334c4520fad1b58439bb3e6e31338c664e93eb15babdaaa564d886`、RKNN Runtime `2.3.2-429f97ae6b`、driver `0.9.8`、RGA `1.10.1_[4]` 和 MPP `1.5.0-1`。 -## 发布状态与路线图 +| ScenarioBench 负载 | 硬件 | 最大验证路数 | 目标 FPS | 结果 | +| --- | --- | ---: | ---: | --- | +| 安全帽检测 | Rockchip RK3576 EVB1 V10 / RKNN | 8 | 5/路 | 通过 | -CosmoEdge `v1.0.0` 是首个稳定公开发布版本。引擎已可用于评估、集成和社区模型拓展。 +1/2/4/8 路阶梯全部通过,丢帧及推理、RGA、MPP 失败均为 0;单路 Detect 平均耗时由 142.3 ms 降至 58.2 ms(下降 59.1%)。另一次 4 路 × 5 FPS、4 路算法预览的 12 小时长稳获得 720 个连续 hold 采样,CPU 平均/P95/最大值为 33.92% / 39% / 43%,丢帧及运行期/预览失败均为 0。 -### v1.0.0 已交付 +4 路 × 5 FPS 配置已完成 12 小时运行;8 路阶梯只记录工程余量,不作为发布容量承诺。这份历史证据作为长稳背景保留,不静默重绑定到更新的 v1.1 源码基线。 -- [X] C++17 边缘推理引擎 -- [X] 可视化流水线编排器 -- [X] Web 管理控制台 -- [X] x86 Linux 和 Windows 开发模式 -- [X] Sophon BM1688 发布打包 -- [X] VLM 与 GroundingDINO 集成 -- [X] 26 条流水线场景完成内部验证 -- [X] v1.0 最终回归测试与加固(shell 注入防护、空指针与生命周期修复、默认密码强制修改) +## 架构 -### 路线图 +```text ++------------------------------------------------------------------+ +| Web 控制台 | 可视化编排 | REST / WebSocket / MQTT | ++--------------------------------+---------------------------------+ + | ++--------------------------------v---------------------------------+ +| C++ 引擎核心 | +| 媒体 | 推理 | 任务 | 规则 | 告警 | 事件 | 模型 | ++--------------------------------+---------------------------------+ + | ++--------------------------------v---------------------------------+ +| 推理与媒体后端接口 | ++--------------------+----------------------+----------------------+ +| Sophon BMRT/VPU | RKNN + MPP/RGA | ONNX Runtime/FFmpeg | +| BM1688;CV186X | RK3576 | x86 Linux / Windows | ++--------------------+----------------------+----------------------+ +``` -- [ ] 扩充已验证流水线场景库 -- [ ] 社区模型和场景示例 -- [ ] 更多模型适配器与后处理模板 +每次构建只选择一个推理后端,模型产物面向目标平台生成;功能、模型覆盖和容量仍具有平台差异。Model Guard Protected 分发目前属于 Sophon 打包路径。 -## 贡献 +## 文档、设备与社区 -CosmoEdge 已发布 v1.0.0,欢迎围绕以下方向进行聚焦贡献: +| 入口 | 适合场景 | +| --- | --- | +| [文档首页](https://www.cosmowander.ai/zh/docs/) | 完整文档索引和学习路径 | +| [快速开始](https://www.cosmowander.ai/zh/docs/tutorials/01-quickstart/quickstart) | 首次启动和场景体验 | +| [场景配置](https://www.cosmowander.ai/zh/docs/tutorials/02-scenario-config/scenario-config) | 构建场景级工作流 | +| [VLM 指南](https://www.cosmowander.ai/zh/docs/tutorials/03-vlm-guide/vlm-guide) | 提示词视觉判断与事件 | +| [模型适配指南](https://www.cosmowander.ai/zh/docs/tutorials/05-model-porting/model-porting) | 导入自有模型 | +| [智能体辅助二次开发](docs/development/agent-assisted-development.md) | 委托二开任务并获得可核验结果 | +| [构建指南](https://www.cosmowander.ai/zh/docs/guide/build) | x86、Sophon 与 RK3576 构建、打包路径 | +| [API 概览](https://www.cosmowander.ai/zh/docs/reference/api) | REST、WebSocket、MQTT 与 webhook 集成 | -- 带日志和复现步骤的 bug 报告。 -- 文档修正和教程改进。 -- 场景示例和集成说明。 -- 先通过 issue 讨论,再提交范围清晰的小型 PR。 +认证设备提供预配置加速、经过验证的商业模型包和专属部署支持,但不解锁另一套软件功能。中国大陆可通过[淘宝购买认证设备](https://item.taobao.com/item.htm?id=1066672051450);其他地区或项目部署支持请联系 。 -提交 pull request 前,请先阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。首次贡献者也可以从[贡献者上手路径](docs/development/contributing.md)开始。 +欢迎提交范围明确的 bug 报告、文档改进、场景示例和集成说明。提交 pull request 前请阅读 [CONTRIBUTING.md](CONTRIBUTING.md)。社区支持入口为 [GitHub Discussions](https://github.com/cosmo-wander-ai/cosmo-edge/discussions)和 [Gitee Issues](https://gitee.com/cosmo-wander-ai/cosmo-edge/issues);安全问题请按 [SECURITY.md](SECURITY.md) 私密报告。 ## FAQ
-我需要 Sophon 设备才能体验 CosmoEdge 吗? +没有 Sophon 或 Rockchip 设备可以试用吗? -不需要。你可以在 Linux 或 Windows 上使用 x86 开发模式体验 UI、流水线工作流、模型管理和集成路径。Sophon 硬件主要用于生产级 NPU 吞吐。 +可以。在 Linux 或 Windows 上使用 x86 开发模式;Apple Silicon Mac 可以使用 Docker Preview 体验单路本地视频下的控制台、流水线、模型管理和集成路径。Mac 路径运行 amd64 仿真且不启用 Model Guard。目标平台的 NPU 加速和容量验证仍需要对应边缘硬件。
-CosmoEdge 支持多少种场景或算法? +Open 与 Protected 包的边界是什么? -CosmoEdge 有两个核心概念:模型(AI 权重)和场景任务(又称流水线,是模型、调度与规则逻辑编排成的图,部署时绑定具体输入、区域和规则)。26 条已验证流水线,每条都能随输入和规则变化覆盖大量实际部署。能力随编排组合扩展,而非取决于固定的算法目录。 - -
- -
-开源仓库包含模型权重吗? - -开源仓库不默认包含生产模型权重。你可以自带模型,包括兼容的 Qwen3 VLM 系列和 Qwen3.5 多模态模型;认证设备包可提供约 25 个预安装的生产 CV 模型,外加 `CosmoEdge-VL-Judge-0.8B` 和 GroundingDINO。社区或自定义模型建议按目标场景验证效果。 +两者提供相同的应用软件能力,并使用同一种 MD5 升级生命周期。Open 使用明文模型且不需要设备授权;Sophon Protected 包可携带加密商业预置模型和授权工具,需要设备绑定证书。应用升级包本身不签名。
可以使用自己训练的模型吗? -可以。CosmoEdge 围绕模型导入和模型生命周期管理设计。模型适配指南会说明从 ONNX 或目标运行时格式进入模型仓库的推荐路径。 - -
- -
-CosmoEdge 和推理服务器或 NVR 项目有什么区别? - -CosmoEdge 是面向完整边缘 AI 工作流的应用运行时,不是单纯的模型服务层或视频录像系统。 +可以。模型适配流程会验证张量、预处理、后处理、目标运行时和业务精度约束;模型产物必须面向实际运行的平台生成。
-CosmoEdge 是否已经生产可用? +CosmoEdge 的生产就绪程度如何? -代码库源自面向生产部署的商业化开发,并通过了内部压力、流水线和回归验证,含 v1.0 最终发布回归。CosmoEdge `v1.0.0` 是首个稳定公开发布版本:引擎、核心工作流和发布打包按现场交付需求设计,公共 API 和贡献者流程已稳定。 +`v1.1.0` 是 BM1688、CV186X、RK3576 与 x86 的多平台发布线。关联报告记录了实测工作负载边界和明确的证据缺口;生产容量仍需结合自有模型、视频流、精度要求和部署条件完成验证。
-## 联系方式 +### License -- Community: [GitHub Discussions](https://github.com/cosmo-wander-ai/cosmo-edge/discussions) -- 国内社区: [Gitee Issues](https://gitee.com/cosmo-wander-ai/cosmo-edge/issues) -- Partnership & Enterprise: hello@cosmowander.ai -- 安全报告:请参见 [SECURITY.md](SECURITY.md),按私密披露流程上报安全漏洞 - -## License - -CosmoEdge 使用 [Apache License 2.0](LICENSE) 开源许可。 - -```text -Copyright 2026 CosmoEdge Contributors - -Licensed under the Apache License, Version 2.0 -``` +CosmoEdge 使用 [Apache License 2.0](LICENSE) 开源许可。Copyright 2026 CosmoEdge Contributors。 --- @@ -449,6 +263,6 @@ An open-source project by Cosmo Wander AI and the CosmoEdge contributors. Turn video AI models into deployable edge applications. -📦 本项目在 [Gitee](https://gitee.com/cosmo-wander-ai/cosmo-edge) 维护只读镜像,代码自动从 GitHub 同步。详见 [MIRRORING.md](MIRRORING.md)。 +📦 本仓库在 [Gitee](https://gitee.com/cosmo-wander-ai/cosmo-edge) 维护只读镜像,代码自动从 GitHub 同步。详见 [MIRRORING.md](MIRRORING.md)。 diff --git a/SECURITY.md b/SECURITY.md index bc621a147..0a2d8db40 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,6 +1,6 @@ # Security Policy -CosmoEdge `v1.0.0` has been publicly released. Please avoid disclosing security-sensitive details publicly before maintainers have had time to review them. This policy describes how to report vulnerabilities privately and what to expect. +CosmoEdge `v1.1.0` is the next release line and is still prepared but unpublished. Until its tag and release artifacts are published, `v1.0.x` remains the current public stable line. Please avoid disclosing security-sensitive details publicly before maintainers have had time to review them. This policy describes how to report vulnerabilities privately and what to expect. ## Reporting a Vulnerability @@ -49,8 +49,9 @@ The table below shows the versions that receive security fixes. Builds made dire | Version | Supported | Notes | | ------- | ------------------ | ------------------------------------------------------ | -| 1.0.x | :white_check_mark: | Current stable public release (`v1.0.0`) | -| 0.1.x | :x: | Superseded by v1.0.0; only critical fixes on request | +| 1.1.x | :warning: | Release candidate; supported after `v1.1.0` publication | +| 1.0.x | :white_check_mark: | Current public stable line until `v1.1.0` is published | +| 0.1.x | :x: | Superseded by v1.0.0; only critical fixes on request | | < 0.1 | :x: | Not publicly released | ## Deployment Hardening Notes diff --git a/cmake/CosmoVersion.cmake b/cmake/CosmoVersion.cmake new file mode 100644 index 000000000..1b4603688 --- /dev/null +++ b/cmake/CosmoVersion.cmake @@ -0,0 +1,49 @@ +function(cosmo_resolve_version source_dir fallback_major fallback_minor fallback_patch fallback_build) + set(_major "${fallback_major}") + set(_minor "${fallback_minor}") + set(_patch "${fallback_patch}") + set(_build "${fallback_build}") + set(_source "fallback") + + find_package(Git QUIET) + if(GIT_FOUND AND EXISTS "${source_dir}/.git") + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --tags + --match "v[0-9]*.[0-9]*.[0-9]*" + --long --abbrev=8 HEAD + WORKING_DIRECTORY "${source_dir}" + RESULT_VARIABLE _git_result + OUTPUT_VARIABLE _git_describe + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(_git_result EQUAL 0 AND + _git_describe MATCHES "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)-([0-9]+)-g[0-9A-Fa-f]+$") + set(_tag_major "${CMAKE_MATCH_1}") + set(_tag_minor "${CMAKE_MATCH_2}") + set(_tag_patch "${CMAKE_MATCH_3}") + set(_tag_distance "${CMAKE_MATCH_4}") + set(_tag_version "${_tag_major}.${_tag_minor}.${_tag_patch}") + set(_fallback_version + "${fallback_major}.${fallback_minor}.${fallback_patch}") + + # An older repository tag must not pull a prepared release back + # below the source fallback. Once that release is tagged, later + # commits advance its patch component automatically. + if(NOT _tag_version VERSION_LESS _fallback_version) + set(_major "${_tag_major}") + set(_minor "${_tag_minor}") + math(EXPR _patch "${_tag_patch} + ${_tag_distance}") + set(_build 0) + set(_source "git:${_git_describe}") + endif() + endif() + endif() + + set(COSMO_VERSION_MAJOR "${_major}" PARENT_SCOPE) + set(COSMO_VERSION_MINOR "${_minor}" PARENT_SCOPE) + set(COSMO_VERSION_PATCH "${_patch}" PARENT_SCOPE) + set(COSMO_VERSION_BUILD "${_build}" PARENT_SCOPE) + set(COSMO_VERSION_SOURCE "${_source}" PARENT_SCOPE) +endfunction() diff --git a/cmake/cryptopp.cmake b/cmake/cryptopp.cmake index 6e956f0ae..f0ed413f8 100644 --- a/cmake/cryptopp.cmake +++ b/cmake/cryptopp.cmake @@ -1,5 +1,6 @@ set(CRYPTOPP_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/cryptopp-cmake-CRYPTOPP_8_9_0) -set(CRYPTOPP_INSTALL_DIR ${THIRDPARTY_INSTALL_PREFIX}/cryptopp) +set(CRYPTOPP_BUILD_INSTALL_DIR ${THIRDPARTY_INSTALL_PREFIX}/cryptopp) +set(CRYPTOPP_INSTALL_DIR ${CRYPTOPP_BUILD_INSTALL_DIR}) set(CRYPTOPP_HEADERS ${CRYPTOPP_INSTALL_DIR}/include) set(CRYPTOPP_LIB ${CRYPTOPP_INSTALL_DIR}/lib/libcryptopp.a) @@ -11,7 +12,7 @@ ExternalProject_Add( CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_INSTALL_PREFIX=${CRYPTOPP_INSTALL_DIR} + -DCMAKE_INSTALL_PREFIX=${CRYPTOPP_BUILD_INSTALL_DIR} -DCRYPTOPP_SOURCES=${CMAKE_CURRENT_SOURCE_DIR}/3rd/cryptopp-CRYPTOPP_8_9_0 -DCRYPTOPP_BUILD_TESTING=OFF -DCRYPTOPP_BUILD_DOCUMENTATION=OFF diff --git a/cmake/curl.cmake b/cmake/curl.cmake index 0f12b63e7..ee90fb23a 100644 --- a/cmake/curl.cmake +++ b/cmake/curl.cmake @@ -2,6 +2,7 @@ set(CURL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/curl-8.17.0) set(CURL_INSTALL_DIR ${THIRDPARTY_INSTALL_PREFIX}/curl) set(CURL_HEADERS ${CURL_INSTALL_DIR}/include) set(CURL_LIB ${CURL_INSTALL_DIR}/lib/libcurl.so) +set(CURL_EXTERNAL_DEPENDS openssl_external) ExternalProject_Add( curl_external @@ -12,7 +13,10 @@ ExternalProject_Add( -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CURL_INSTALL_DIR} - -DOPENSSL_ROOT_DIR=${THIRDPARTY_INSTALL_PREFIX}/openssl + -DOPENSSL_ROOT_DIR=${OPENSSL_INSTALL_DIR} + -DOPENSSL_INCLUDE_DIR=${OPENSSL_HEADERS} + -DOPENSSL_SSL_LIBRARY=${OPENSSL_SSL_LIB} + -DOPENSSL_CRYPTO_LIBRARY=${OPENSSL_CRYPTO_LIB} -DBUILD_SHARED_LIBS=ON -DCURL_USE_LIBPSL=OFF # Cross-compilation skips curl's host CA auto-detection. This path is @@ -28,7 +32,7 @@ ExternalProject_Add( INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install - DEPENDS openssl_external + DEPENDS ${CURL_EXTERNAL_DEPENDS} UPDATE_COMMAND "" BUILD_ALWAYS OFF diff --git a/cmake/device.cmake b/cmake/device.cmake index 234c7a65a..ef9cdb10d 100644 --- a/cmake/device.cmake +++ b/cmake/device.cmake @@ -1,4 +1,3 @@ -# set(DEVICE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(DEVICE_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/libsophon-0.4.11) set(DEVICE_HEADERS ${DEVICE_ROOT_DIR}/include) set(DEVICE_LIB_DIR ${DEVICE_ROOT_DIR}/lib) @@ -46,7 +45,7 @@ set_target_properties(bmvenc PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${DEVICE_HEADERS}" ) -install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/3rd/libsophon-0.4.11/lib/ +install(DIRECTORY ${DEVICE_ROOT_DIR}/lib/ DESTINATION lib FILES_MATCHING PATTERN "*so*" diff --git a/cmake/event.cmake b/cmake/event.cmake index 8d79e3693..61120a2c0 100644 --- a/cmake/event.cmake +++ b/cmake/event.cmake @@ -1,4 +1,5 @@ -set(EVENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/libevent-2.1.12-stable) +set(EVENT_ORIGINAL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/libevent-2.1.12-stable) +set(EVENT_SOURCE_DIR ${CMAKE_BINARY_DIR}/event_source) set(EVENT_INSTALL_DIR ${THIRDPARTY_INSTALL_PREFIX}/event) set(EVENT_HEADERS ${EVENT_INSTALL_DIR}/include) set(EVENT_LIB ${EVENT_INSTALL_DIR}/lib/libevent.so) @@ -6,17 +7,31 @@ set(EVENT_CORE_LIB ${EVENT_INSTALL_DIR}/lib/libevent_core.so) set(EVENT_EXTRA_LIB ${EVENT_INSTALL_DIR}/lib/libevent_extra.so) set(EVENT_OPENSSL_LIB ${EVENT_INSTALL_DIR}/lib/libevent_openssl.so) set(EVENT_PTHREADS_LIB ${EVENT_INSTALL_DIR}/lib/libevent_pthreads.so) +set(EVENT_EXTERNAL_DEPENDS openssl_external) ExternalProject_Add( event_external SOURCE_DIR ${EVENT_SOURCE_DIR} + BINARY_DIR ${CMAKE_BINARY_DIR}/event_build + + DOWNLOAD_COMMAND + ${CMAKE_COMMAND} -E rm -rf + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${EVENT_ORIGINAL_SOURCE_DIR} + + PATCH_COMMAND + patch --batch --forward -p1 + -i ${CMAKE_CURRENT_SOURCE_DIR}/cmake/libevent-relative-rpath.patch CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${EVENT_INSTALL_DIR} - -DOPENSSL_ROOT_DIR=${THIRDPARTY_INSTALL_PREFIX}/openssl + -DOPENSSL_ROOT_DIR=${OPENSSL_INSTALL_DIR} + -DOPENSSL_INCLUDE_DIR=${OPENSSL_HEADERS} + -DOPENSSL_SSL_LIBRARY=${OPENSSL_SSL_LIB} + -DOPENSSL_CRYPTO_LIBRARY=${OPENSSL_CRYPTO_LIB} -DEVENT__LIBRARY_TYPE=SHARED -DEVENT__DISABLE_DEBUG_MODE=ON -DEVENT__ENABLE_VERBOSE_DEBUG=OFF @@ -27,7 +42,7 @@ ExternalProject_Add( INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install - DEPENDS openssl_external + DEPENDS ${EVENT_EXTERNAL_DEPENDS} UPDATE_COMMAND "" BUILD_ALWAYS OFF @@ -80,4 +95,4 @@ install(DIRECTORY ${EVENT_INSTALL_DIR}/lib/ FILES_MATCHING PATTERN "*event*" PATTERN "*so*" -) \ No newline at end of file +) diff --git a/cmake/libevent-relative-rpath.patch b/cmake/libevent-relative-rpath.patch new file mode 100644 index 000000000..3a1b6172d --- /dev/null +++ b/cmake/libevent-relative-rpath.patch @@ -0,0 +1,5 @@ +--- a/cmake/AddEventLibrary.cmake ++++ b/cmake/AddEventLibrary.cmake +@@ -162 +162 @@ +- INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") ++ INSTALL_RPATH "$ORIGIN") diff --git a/cmake/mqtt.cmake b/cmake/mqtt.cmake index 6b4a8d2f8..56d4f7dbb 100644 --- a/cmake/mqtt.cmake +++ b/cmake/mqtt.cmake @@ -3,31 +3,41 @@ set(MQTT_INSTALL_DIR ${THIRDPARTY_INSTALL_PREFIX}/mqtt) set(MQTT_HEADERS ${MQTT_INSTALL_DIR}/include) set(MQTT_C_LIB ${MQTT_INSTALL_DIR}/lib/libpaho-mqtt3c.so) set(MQTT_CS_LIB ${MQTT_INSTALL_DIR}/lib/libpaho-mqtt3cs.so) +set(MQTT_EXTERNAL_DEPENDS openssl_external) + +set(MQTT_CONFIGURE_ARGS + -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DCMAKE_INSTALL_PREFIX=${MQTT_INSTALL_DIR} + -DCMAKE_INSTALL_LIBDIR=lib + -DOPENSSL_ROOT_DIR=${OPENSSL_INSTALL_DIR} + -DOPENSSL_INCLUDE_DIR=${OPENSSL_HEADERS} + -DOPENSSL_SSL_LIBRARY=${OPENSSL_SSL_LIB} + -DOPENSSL_CRYPTO_LIBRARY=${OPENSSL_CRYPTO_LIB} + -DPAHO_WITH_SSL=ON + -DPAHO_WITH_LIBUUID=OFF + -DPAHO_ENABLE_TESTING=OFF + -DPAHO_BUILD_SAMPLES=OFF + -DPAHO_BUILD_DEB_PACKAGE=OFF + -DPAHO_BUILD_DOCUMENTATION=OFF + "-G${CMAKE_GENERATOR}" + +) ExternalProject_Add( mqtt_external SOURCE_DIR ${MQTT_SOURCE_DIR} - CMAKE_ARGS - -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DCMAKE_INSTALL_PREFIX=${MQTT_INSTALL_DIR} - -DCMAKE_INSTALL_LIBDIR=lib - -DOPENSSL_ROOT_DIR=${THIRDPARTY_INSTALL_PREFIX}/openssl - -DOPENSSL_INCLUDE_DIR=${THIRDPARTY_INSTALL_PREFIX}/openssl/include - -DOPENSSL_SSL_LIBRARY=${THIRDPARTY_INSTALL_PREFIX}/openssl/lib/libssl.so - -DOPENSSL_CRYPTO_LIBRARY=${THIRDPARTY_INSTALL_PREFIX}/openssl/lib/libcrypto.so - -DPAHO_WITH_SSL=ON - -DPAHO_WITH_LIBUUID=OFF - -DPAHO_ENABLE_TESTING=OFF - -DPAHO_BUILD_SAMPLES=OFF - -DPAHO_BUILD_DEB_PACKAGE=OFF - -DPAHO_BUILD_DOCUMENTATION=OFF + # Paho's configure step embeds string(TIMESTAMP) in both shared + # libraries. CMake honors SOURCE_DATE_EPOCH for that operation. + CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env + SOURCE_DATE_EPOCH=${COSMO_REPRODUCIBLE_BUILD_EPOCH} + ${CMAKE_COMMAND} ${MQTT_CONFIGURE_ARGS} INSTALL_COMMAND ${CMAKE_COMMAND} --build . --target install - DEPENDS openssl_external + DEPENDS ${MQTT_EXTERNAL_DEPENDS} UPDATE_COMMAND "" BUILD_ALWAYS OFF diff --git a/cmake/normalize_srs_build_metadata.cmake b/cmake/normalize_srs_build_metadata.cmake new file mode 100644 index 000000000..fdab10d5c --- /dev/null +++ b/cmake/normalize_srs_build_metadata.cmake @@ -0,0 +1,41 @@ +foreach(required_variable IN ITEMS + SRS_AUTO_HEADERS + SRS_BUILD_EPOCH + SRS_BUILD_DATE + SRS_BUILD_UNAME) + if(NOT DEFINED ${required_variable} OR "${${required_variable}}" STREQUAL "") + message(FATAL_ERROR "${required_variable} is required") + endif() +endforeach() + +if(NOT EXISTS "${SRS_AUTO_HEADERS}" OR IS_DIRECTORY "${SRS_AUTO_HEADERS}") + message(FATAL_ERROR "SRS generated header is missing: ${SRS_AUTO_HEADERS}") +endif() + +file(READ "${SRS_AUTO_HEADERS}" srs_auto_headers) + +function(replace_srs_build_define define_name define_value) + string(REGEX MATCHALL + "#define ${define_name} \"[^\"]*\"" + matching_defines + "${srs_auto_headers}") + list(LENGTH matching_defines matching_define_count) + if(NOT matching_define_count EQUAL 1) + message(FATAL_ERROR + "Expected exactly one ${define_name} in ${SRS_AUTO_HEADERS}") + endif() + + list(GET matching_defines 0 matching_define) + string(REPLACE + "${matching_define}" + "#define ${define_name} \"${define_value}\"" + srs_auto_headers + "${srs_auto_headers}") + set(srs_auto_headers "${srs_auto_headers}" PARENT_SCOPE) +endfunction() + +replace_srs_build_define(SRS_BUILD_TS "${SRS_BUILD_EPOCH}") +replace_srs_build_define(SRS_BUILD_DATE "${SRS_BUILD_DATE}") +replace_srs_build_define(SRS_UNAME "${SRS_BUILD_UNAME}") + +file(WRITE "${SRS_AUTO_HEADERS}" "${srs_auto_headers}") diff --git a/cmake/openssl.cmake b/cmake/openssl.cmake index bef6ddee1..65b18546d 100644 --- a/cmake/openssl.cmake +++ b/cmake/openssl.cmake @@ -1,12 +1,26 @@ set(OPENSSL_ORIGINAL_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rd/openssl-3.5.3) set(OPENSSL_SOURCE_DIR ${OPENSSL_ORIGINAL_SOURCE_DIR}) -set(OPENSSL_INSTALL_DIR ${THIRDPARTY_INSTALL_PREFIX}/openssl) +set(OPENSSL_BUILD_INSTALL_DIR ${THIRDPARTY_INSTALL_PREFIX}/openssl) +set(OPENSSL_INSTALL_DIR ${OPENSSL_BUILD_INSTALL_DIR}) set(OPENSSL_HEADERS ${OPENSSL_INSTALL_DIR}/include) -set(OPENSSL_SSL_LIB ${OPENSSL_INSTALL_DIR}/lib/libssl.so) -set(OPENSSL_CRYPTO_LIB ${OPENSSL_INSTALL_DIR}/lib/libcrypto.so) +if(COSMO_MODEL_GUARD) + set(OPENSSL_SSL_LIB ${OPENSSL_INSTALL_DIR}/lib/libssl.so.3) + set(OPENSSL_CRYPTO_LIB ${OPENSSL_INSTALL_DIR}/lib/libcrypto.so.3) +else() + set(OPENSSL_SSL_LIB ${OPENSSL_INSTALL_DIR}/lib/libssl.so) + set(OPENSSL_CRYPTO_LIB ${OPENSSL_INSTALL_DIR}/lib/libcrypto.so) +endif() set(OPENSSL_DOWNLOAD_COMMAND "") set(OPENSSL_PATCH_COMMAND ${CMAKE_COMMAND} -E true) +# OpenSSL embeds its build time in libcrypto. Keep the dependency byte-for-byte +# compatible with the formally admitted Guard SDK instead of inheriting the +# wall clock of each clean build. +set(OPENSSL_REPRODUCIBLE_ENV + ${CMAKE_COMMAND} -E env + SOURCE_DATE_EPOCH=${COSMO_REPRODUCIBLE_BUILD_EPOCH} +) + if(COSMO_TARGET_ARCH STREQUAL "x86_64") set(OPENSSL_SOURCE_DIR ${CMAKE_BINARY_DIR}/openssl_source) set(OPENSSL_DOWNLOAD_COMMAND @@ -17,7 +31,7 @@ if(COSMO_TARGET_ARCH STREQUAL "x86_64") endif() set(OPENSSL_COMMON_CONFIGURE_ARGS - --prefix=${OPENSSL_INSTALL_DIR} + --prefix=${OPENSSL_BUILD_INSTALL_DIR} --openssldir=/usr/local/ssl --libdir=lib --release @@ -49,10 +63,12 @@ ExternalProject_Add( DOWNLOAD_COMMAND ${OPENSSL_DOWNLOAD_COMMAND} PATCH_COMMAND ${OPENSSL_PATCH_COMMAND} - CONFIGURE_COMMAND ${OPENSSL_CONFIGURE_COMMAND} + CONFIGURE_COMMAND ${OPENSSL_REPRODUCIBLE_ENV} + ${OPENSSL_CONFIGURE_COMMAND} - BUILD_COMMAND $(MAKE) - INSTALL_COMMAND $(MAKE) install_sw + BUILD_COMMAND ${OPENSSL_REPRODUCIBLE_ENV} ${CMAKE_MAKE_PROGRAM} + INSTALL_COMMAND ${OPENSSL_REPRODUCIBLE_ENV} + ${CMAKE_MAKE_PROGRAM} install_sw UPDATE_COMMAND "" BUILD_ALWAYS OFF @@ -78,8 +94,15 @@ set_target_properties(openssl_crypto PROPERTIES ) add_dependencies(openssl_crypto openssl_external) -install(DIRECTORY ${OPENSSL_INSTALL_DIR}/lib/ - DESTINATION lib - FILES_MATCHING - PATTERN "*so*" -) +if(COSMO_MODEL_GUARD) + install(FILES + ${OPENSSL_INSTALL_DIR}/lib/libcrypto.so.3 + ${OPENSSL_INSTALL_DIR}/lib/libssl.so.3 + DESTINATION lib) +else() + install(DIRECTORY ${OPENSSL_INSTALL_DIR}/lib/ + DESTINATION lib + FILES_MATCHING + PATTERN "*so*" + ) +endif() diff --git a/cmake/rkllm.cmake b/cmake/rkllm.cmake new file mode 100644 index 000000000..5ffa1a8c5 --- /dev/null +++ b/cmake/rkllm.cmake @@ -0,0 +1,34 @@ +# RKLLM is packaged with the RKNN target so the deployed service does not depend +# on a host mount or a board-wide manual installation. +set(COSMO_RKLLM_ROOT "${COSMO_RKNN_ROOT}" CACHE PATH + "RKLLM Runtime root containing include/rkllm.h and lib/librkllmrt.so") +if(DEFINED ENV{RKLLM_ROOT} AND NOT EXISTS "${COSMO_RKLLM_ROOT}/include/rkllm.h") + set(COSMO_RKLLM_ROOT "$ENV{RKLLM_ROOT}" CACHE PATH "RKLLM Runtime root" FORCE) +endif() + +set(RKLLM_RUNTIME_HEADER "${COSMO_RKLLM_ROOT}/include/rkllm.h") +set(RKLLM_RUNTIME_LIBRARY "${COSMO_RKLLM_ROOT}/lib/librkllmrt.so") +set(RKLLM_RUNTIME_LICENSE "${COSMO_RKLLM_ROOT}/LICENSE") + +option(COSMO_RKLLM_REQUIRED "Fail configuration when the RKLLM SDK is unavailable" OFF) +set(COSMO_NN_USE_RKLLM_BACKEND OFF) + +if(EXISTS "${RKLLM_RUNTIME_HEADER}" AND EXISTS "${RKLLM_RUNTIME_LIBRARY}" AND + EXISTS "${RKLLM_RUNTIME_LICENSE}") + add_library(rkllmrt SHARED IMPORTED GLOBAL) + set_target_properties(rkllmrt PROPERTIES + IMPORTED_LOCATION "${RKLLM_RUNTIME_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${COSMO_RKLLM_ROOT}/include" + ) + set(COSMO_NN_USE_RKLLM_BACKEND ON) + add_compile_definitions(COSMO_NN_USE_RKLLM_BACKEND) + message(STATUS "RKLLM multimodal backend enabled: ${COSMO_RKLLM_ROOT}") +elseif(COSMO_RKLLM_REQUIRED) + message(FATAL_ERROR + "RKLLM SDK is required but incomplete under ${COSMO_RKLLM_ROOT} " + "(expected include/rkllm.h, lib/librkllmrt.so, and LICENSE)") +else() + message(STATUS + "complete RKLLM SDK not found under ${COSMO_RKLLM_ROOT}; " + "building the RKNN runtime without Qwen3.5 VLM support") +endif() diff --git a/cmake/rknn.cmake b/cmake/rknn.cmake new file mode 100644 index 000000000..4e43250e2 --- /dev/null +++ b/cmake/rknn.cmake @@ -0,0 +1,26 @@ +# RKNN Runtime is supplied by the pinned offline SDK bundle. Keep it external +# to the repository while copying the validated runtime into deployment +# packages so the target never falls back to an incompatible system library. +set(COSMO_RKNN_ROOT "" CACHE PATH "RKNN Runtime root containing include/ and lib/") +if(NOT COSMO_RKNN_ROOT AND DEFINED ENV{RKNN_ROOT}) + set(COSMO_RKNN_ROOT "$ENV{RKNN_ROOT}" CACHE PATH "RKNN Runtime root" FORCE) +endif() + +if(NOT COSMO_RKNN_ROOT) + message(FATAL_ERROR "COSMO_RKNN_ROOT is required for the RKNN backend") +endif() + +set(RKNN_RUNTIME_HEADER "${COSMO_RKNN_ROOT}/include/rknn_api.h") +set(RKNN_RUNTIME_LIBRARY "${COSMO_RKNN_ROOT}/lib/librknnrt.so") +if(NOT EXISTS "${RKNN_RUNTIME_HEADER}") + message(FATAL_ERROR "RKNN header not found: ${RKNN_RUNTIME_HEADER}") +endif() +if(NOT EXISTS "${RKNN_RUNTIME_LIBRARY}") + message(FATAL_ERROR "RKNN runtime not found: ${RKNN_RUNTIME_LIBRARY}") +endif() + +add_library(rknnrt SHARED IMPORTED GLOBAL) +set_target_properties(rknnrt PROPERTIES + IMPORTED_LOCATION "${RKNN_RUNTIME_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${COSMO_RKNN_ROOT}/include" +) diff --git a/cmake/rockchip_media.cmake b/cmake/rockchip_media.cmake new file mode 100644 index 000000000..fc01ebb1b --- /dev/null +++ b/cmake/rockchip_media.cmake @@ -0,0 +1,49 @@ +# Rockchip MPP and RGA are supplied by a candidate-bound external sysroot. +# The validated shared libraries are packaged beside CosmoEdge so qualification +# never depends on a silently different target image library. +set(COSMO_ROCKCHIP_MEDIA_ROOT "" CACHE PATH + "Rockchip media root containing include/rockchip, include/rga, and lib/") +if(NOT COSMO_ROCKCHIP_MEDIA_ROOT AND DEFINED ENV{ROCKCHIP_MEDIA_ROOT}) + set(COSMO_ROCKCHIP_MEDIA_ROOT "$ENV{ROCKCHIP_MEDIA_ROOT}" + CACHE PATH "Rockchip media root" FORCE) +endif() + +if(NOT COSMO_ROCKCHIP_MEDIA_ROOT) + message(FATAL_ERROR + "COSMO_ROCKCHIP_MEDIA_ROOT is required for the Rockchip media backend") +endif() + +set(ROCKCHIP_MPP_HEADER + "${COSMO_ROCKCHIP_MEDIA_ROOT}/include/rockchip/rk_mpi.h") +set(ROCKCHIP_RGA_HEADER + "${COSMO_ROCKCHIP_MEDIA_ROOT}/include/rga/im2d.h") +set(ROCKCHIP_MPP_LIBRARY + "${COSMO_ROCKCHIP_MEDIA_ROOT}/lib/librockchip_mpp.so") +set(ROCKCHIP_RGA_LIBRARY + "${COSMO_ROCKCHIP_MEDIA_ROOT}/lib/librga.so") + +foreach(_required + "${ROCKCHIP_MPP_HEADER}" + "${ROCKCHIP_RGA_HEADER}" + "${ROCKCHIP_MPP_LIBRARY}" + "${ROCKCHIP_RGA_LIBRARY}") + if(NOT EXISTS "${_required}") + message(FATAL_ERROR "Rockchip media artifact not found: ${_required}") + endif() +endforeach() + +add_library(rockchip_mpp SHARED IMPORTED GLOBAL) +set_target_properties(rockchip_mpp PROPERTIES + IMPORTED_LOCATION "${ROCKCHIP_MPP_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${COSMO_ROCKCHIP_MEDIA_ROOT}/include") + +add_library(rockchip_rga SHARED IMPORTED GLOBAL) +set_target_properties(rockchip_rga PROPERTIES + IMPORTED_LOCATION "${ROCKCHIP_RGA_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${COSMO_ROCKCHIP_MEDIA_ROOT}/include") + +install(DIRECTORY "${COSMO_ROCKCHIP_MEDIA_ROOT}/lib/" + DESTINATION lib + FILES_MATCHING + PATTERN "librockchip_mpp.so*" + PATTERN "librga.so*") diff --git a/cmake/srs.cmake b/cmake/srs.cmake index 03126df9f..dd6633198 100644 --- a/cmake/srs.cmake +++ b/cmake/srs.cmake @@ -58,6 +58,12 @@ ExternalProject_Add( --srtp-nasm=off --utest=off --jobs=4 + COMMAND ${CMAKE_COMMAND} + "-DSRS_AUTO_HEADERS=/objs/srs_auto_headers.hpp" + "-DSRS_BUILD_EPOCH=${COSMO_REPRODUCIBLE_BUILD_EPOCH}" + "-DSRS_BUILD_DATE=${COSMO_REPRODUCIBLE_BUILD_UTC}" + "-DSRS_BUILD_UNAME=${COSMO_REPRODUCIBLE_BUILD_UNAME}" + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/normalize_srs_build_metadata.cmake BUILD_COMMAND $(MAKE) BUILD_IN_SOURCE ON diff --git a/cmake/web_frontend.cmake b/cmake/web_frontend.cmake index 1a223df02..cce9c7ec2 100644 --- a/cmake/web_frontend.cmake +++ b/cmake/web_frontend.cmake @@ -2,36 +2,63 @@ # Web Frontend Build (Vue 3 + Vite) ########################################################## find_program(NPM_EXECUTABLE npm REQUIRED) +find_program(BASH_EXECUTABLE bash REQUIRED) set(WEB_BUILD_DIR ${CMAKE_BINARY_DIR}/web) set(WEB_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/web) +set(WEB_STAGE_DIR ${WEB_BUILD_DIR}/web_unified) set(WEB_STAMP ${WEB_BUILD_DIR}/web_unified.stamp) +if(DEFINED RESOURCE_DIR AND NOT "${RESOURCE_DIR}" STREQUAL "") + set(WEB_RESOURCE_DIR ${RESOURCE_DIR}) +else() + set(WEB_RESOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/data/resource/aiboxresource_bm1688) +endif() -file(GLOB_RECURSE WEB_SRC_FILES +file(GLOB_RECURSE WEB_SRC_FILES CONFIGURE_DEPENDS ${WEB_SRC_DIR}/src/* - ${WEB_SRC_DIR}/index.html + ${WEB_SRC_DIR}/public/* + ${WEB_SRC_DIR}/scripts/* ) list(APPEND WEB_SRC_FILES + ${CMAKE_CURRENT_LIST_FILE} + ${CMAKE_CURRENT_SOURCE_DIR}/docs/i18n/GLOSSARY.md + ${CMAKE_CURRENT_SOURCE_DIR}/docs/i18n/SHORT-SCOPES.md + ${WEB_RESOURCE_DIR}/i18n/resource.en-US.json + ${WEB_RESOURCE_DIR}/i18n/resource.zh-CN.json + ${WEB_SRC_DIR}/.npmrc + ${WEB_SRC_DIR}/index.html + ${WEB_SRC_DIR}/package-lock.json ${WEB_SRC_DIR}/package.json ${WEB_SRC_DIR}/vite.config.js + ${CMAKE_CURRENT_SOURCE_DIR}/scripts/build_npm_dependencies.sh ) -file(MAKE_DIRECTORY ${WEB_BUILD_DIR}/web_unified) +file(MAKE_DIRECTORY ${WEB_BUILD_DIR}) add_custom_command( OUTPUT ${WEB_STAMP} DEPENDS ${WEB_SRC_FILES} - COMMAND ${CMAKE_COMMAND} -E copy_directory ${WEB_SRC_DIR} ${WEB_BUILD_DIR}/web_unified - COMMAND ${CMAKE_COMMAND} -E rm -f ${WEB_BUILD_DIR}/web_unified/package-lock.json - # copy_directory dereferences node_modules/.bin symlinks. Restore them when a cached - # dependency tree is present so npm can execute ESM command-line tools offline. - COMMAND ${CMAKE_COMMAND} -DWEB_SRC_DIR=${WEB_SRC_DIR} -DWEB_STAGING_DIR=${WEB_BUILD_DIR}/web_unified - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/repair_web_node_bins.cmake - COMMAND ${NPM_EXECUTABLE} install --loglevel=error - COMMAND chmod -R +x node_modules/.bin - COMMAND ${NPM_EXECUTABLE} run build - COMMAND ${CMAKE_COMMAND} -E touch ${WEB_STAMP} - WORKING_DIRECTORY ${WEB_BUILD_DIR}/web_unified + COMMAND ${CMAKE_COMMAND} -E remove_directory "${WEB_STAGE_DIR}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${WEB_STAGE_DIR}" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEB_SRC_DIR}/src" "${WEB_STAGE_DIR}/src" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEB_SRC_DIR}/public" "${WEB_STAGE_DIR}/public" + COMMAND ${CMAKE_COMMAND} -E copy_directory "${WEB_SRC_DIR}/scripts" "${WEB_STAGE_DIR}/scripts" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${WEB_SRC_DIR}/.npmrc" "${WEB_STAGE_DIR}/.npmrc" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${WEB_SRC_DIR}/index.html" "${WEB_STAGE_DIR}/index.html" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${WEB_SRC_DIR}/package-lock.json" "${WEB_STAGE_DIR}/package-lock.json" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${WEB_SRC_DIR}/package.json" "${WEB_STAGE_DIR}/package.json" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${WEB_SRC_DIR}/vite.config.js" "${WEB_STAGE_DIR}/vite.config.js" + COMMAND ${BASH_EXECUTABLE} + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/build_npm_dependencies.sh" + "${WEB_STAGE_DIR}" + COMMAND ${CMAKE_COMMAND} -E chdir "${WEB_STAGE_DIR}" + ${CMAKE_COMMAND} -E env "AIBOX_RESOURCE_DIR=${WEB_RESOURCE_DIR}" + ${NPM_EXECUTABLE} run resource-i18n:check + COMMAND ${CMAKE_COMMAND} -E chdir "${WEB_STAGE_DIR}" + ${CMAKE_COMMAND} -E env "COSMO_REPO_ROOT=${CMAKE_CURRENT_SOURCE_DIR}" + ${NPM_EXECUTABLE} run build + COMMAND ${CMAKE_COMMAND} -E touch "${WEB_STAMP}" COMMENT "Building unified web frontend (Vue 3 + Vite)..." + VERBATIM ) add_custom_target(web_frontend ALL DEPENDS ${WEB_STAMP}) add_dependencies(web_frontend ${EXECUTABLE_NAME}) diff --git a/config/rknn/models/helmet.json b/config/rknn/models/helmet.json new file mode 100644 index 000000000..90f325146 --- /dev/null +++ b/config/rknn/models/helmet.json @@ -0,0 +1,40 @@ +{ + "schema_version": 1, + "name": "helmet", + "model_type": "classify", + "source_repository_path": "data/resource/aiboxresource_x86/models/prod_X86_7982161_helmet_V1.0.0/model.onnx", + "source_sha256": "a0ea37d99416371c6ef073d5ac87b486b77bb822b1f8aa29f2f30a8a06c97cdd", + "conversion": { + "target_platform": "rk3576", + "maximum_onnx_opset": 19, + "optimization_level": 3, + "preprocessing_owner": "host" + }, + "input": { + "name": "images", + "shape": [1, 3, 224, 224], + "dtype": "float32", + "layout": "NCHW", + "color": "RGB", + "resize": "stretch", + "mean": [0.0, 0.0, 0.0], + "scale": 0.00392157, + "padding_color": [114, 114, 114] + }, + "outputs": [ + { + "name": "output0", + "shape": [1, 2], + "dtype": "float32" + } + ], + "calibration": { + "source": "person crops detected in data/test-video/Safety Helmet.mp4", + "minimum_samples": 32, + "labeled": false + }, + "validation": { + "fp16": {"minimum_cosine_similarity": 0.999, "maximum_absolute_error": 0.05}, + "int8": {"minimum_cosine_similarity": 0.99, "maximum_absolute_error": 0.25} + } +} diff --git a/config/rknn/models/yolov8.json b/config/rknn/models/yolov8.json new file mode 100644 index 000000000..89b1c5480 --- /dev/null +++ b/config/rknn/models/yolov8.json @@ -0,0 +1,64 @@ +{ + "schema_version": 1, + "name": "yolov8", + "model_type": "yolov8_det", + "source_repository_path": "data/resource/aiboxresource_x86/models/prod_X86_9275710_YOLOV8_V1.0.0/model.onnx", + "source_sha256": "5f8e91cb4507596b66cd5e3b7193bb16f7bd4779ed3b78e3613fcc51b83db8e1", + "conversion": { + "target_platform": "rk3576", + "input_sha256": "17a2cd603576afd1b5dd86a485933b857534355d25f517f6e1f2acd2a2fe4563", + "maximum_onnx_opset": 19, + "maximum_onnx_ir_version": 9, + "optimization_level": 3, + "preprocessing_owner": "host", + "output_adapter": "yolo_dfl_6head_v1" + }, + "input": { + "name": "images", + "shape": [1, 3, 640, 640], + "dtype": "float32", + "layout": "NCHW", + "color": "RGB", + "resize": "letterbox_center", + "mean": [0.0, 0.0, 0.0], + "scale": 0.00392157, + "padding_color": [114, 114, 114] + }, + "outputs": [ + { + "name": "output0", + "shape": [1, 84, 8400], + "dtype": "float32" + } + ], + "runtime_outputs": [ + {"name": "/model.22/cv2.0/cv2.0.2/Conv_output_0", "shape": [1, 64, 80, 80]}, + {"name": "/model.22/cv3.0/cv3.0.2/Conv_output_0", "shape": [1, 80, 80, 80]}, + {"name": "/model.22/cv2.1/cv2.1.2/Conv_output_0", "shape": [1, 64, 40, 40]}, + {"name": "/model.22/cv3.1/cv3.1.2/Conv_output_0", "shape": [1, 80, 40, 40]}, + {"name": "/model.22/cv2.2/cv2.2.2/Conv_output_0", "shape": [1, 64, 20, 20]}, + {"name": "/model.22/cv3.2/cv3.2.2/Conv_output_0", "shape": [1, 80, 20, 20]} + ], + "calibration": { + "source": "uniformly sampled frames from data/test-video/Safety Helmet.mp4", + "minimum_samples": 32, + "labeled": false + }, + "validation": { + "class_ids": [0], + "fp16": { + "minimum_cosine_similarity": 0.999, + "maximum_absolute_error": 20.0, + "minimum_detection_f1": 0.98, + "minimum_matched_iou": 0.9, + "maximum_matched_score_error": 0.1 + }, + "int8": { + "minimum_cosine_similarity": 0.98, + "maximum_absolute_error": 350.0, + "minimum_detection_f1": 0.9, + "minimum_matched_iou": 0.75, + "maximum_matched_score_error": 0.2 + } + } +} diff --git a/config/rknn/toolchain-lock.json b/config/rknn/toolchain-lock.json new file mode 100644 index 000000000..5decdd9cd --- /dev/null +++ b/config/rknn/toolchain-lock.json @@ -0,0 +1,48 @@ +{ + "schema_version": 1, + "target_platform": "rk3576", + "cosmo_edge_base_sha": "2eaf5fd7b096f98a9dca1ef298e03440484e15bc", + "tensorrt_reference_sha": "57c578616ba826f01921bb4e43d7a695549b6b9e", + "rknn_toolkit2": { + "version": "2.3.2", + "tag_sha": "42aa1d426c0a9e0869b6374edba009f7208a1926", + "python": "3.10", + "wheel_sha256": "6cb783ddf293ac509f39bf9127acf6a5492bbb67e4b4b4ac33a7c6d2cefb4f3c" + }, + "rknn_model_zoo": { + "version": "2.3.2", + "tag_sha": "bad6c7334531becaf90a561988519b7bec34d0ab" + }, + "offline_bundle": { + "file": "rk3576-offline-bundle-v2.3.2-20260804.tar.gz", + "sha256": "12960656f854ab8bfe0e2ee2292745245d82d1cd88b7acd0a8cb6c06c080c726", + "entry_count": 42 + }, + "runtime": { + "version": "2.3.2", + "librknnrt_sha256": "d31fc19c85b85f6091b2bd0f6af9d962d5264a4e410bfb536402ec92bac738e8", + "rknn_api_header_sha256": "c48e11a6f41b451a5fd1e4ad774ea60252d3d94f78bee9b21ea3d21b21deba9a", + "rknn_server_sha256": "eea12fe4270fad8aff015056319705b2eb871563ebd001eff8d8788bdd1c0cfa" + }, + "device_baseline": { + "kernel": "6.1.118", + "rknpu_driver": "0.9.8", + "system_runtime": "2.1.0", + "system_runtime_sha256": "0f1c5db6c649c8705759308aa56ecffc3295c7eb465f9ec9170882f44004aa8d" + }, + "models": { + "helmet": { + "onnx_sha256": "a0ea37d99416371c6ef073d5ac87b486b77bb822b1f8aa29f2f30a8a06c97cdd", + "opset": 19, + "input": [1, 3, 224, 224], + "output": [1, 2] + }, + "yolov8": { + "onnx_sha256": "5f8e91cb4507596b66cd5e3b7193bb16f7bd4779ed3b78e3613fcc51b83db8e1", + "opset": 22, + "required_opset": 19, + "input": [1, 3, 640, 640], + "output": [1, 84, 8400] + } + } +} diff --git a/data/resource/README.md b/data/resource/README.md new file mode 100644 index 000000000..fd84647a6 --- /dev/null +++ b/data/resource/README.md @@ -0,0 +1,30 @@ +# Runtime resource sets + +CosmoEdge selects one explicitly named resource set for each target build. BM1688 and CV186X use +separate top-level directories so package contents and GitHub paths identify the intended platform. + +| Target | Resource set | Open benchmark models | +| --- | --- | --- | +| BM1688 | `aiboxresource_bm1688` | `YOLOV8n V1.0.0` detector and `helmet V1.0.0` classifier | +| CV186X | `aiboxresource_cv186x` | Device-verified copies of the same benchmark detector and classifier | +| RK3576 | `aiboxresource_rknn` | Platform-specific RKNN resources | +| x86 | `aiboxresource_x86` | ONNX Runtime resources | + +The public ScenarioBench v1.1 Sophon models are present in both platform-scoped resource sets: + +| Model | Size | SHA-256 | Repository path | +| --- | ---: | --- | --- | +| YOLOV8n detector | 7,023,600 B | `56b207ef2876da76505e403a049d3c44a411b9fe707ab73dc64f1cd9d9b6c5c8` | `aiboxresource_/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/` | +| Helmet classifier | 6,001,416 B | `33b0fb4bcb29e41a92f9c1c518671aefc69cbf9207934deaba32ca7cd8cd7c8a` | `aiboxresource_/models/prod_BM1688_7486163_helmet_V1.0.0/` | + +The CV186X copies were retrieved from the benchmark device and match the recorded BM1688 files +byte for byte. The inner `prod_BM1688_` name and `chip_type` value are retained because they are +part of the exact device-loaded package. This measured exception applies only to these two hashes; +other BM1688 and CV186X artifacts remain target-specific. + +## 资源目录说明 + +BM1688 与 CV186X 分别使用 `aiboxresource_bm1688` 和 `aiboxresource_cv186x`。CV186X +目录中的 `YOLOV8n V1.0.0` 与 `helmet V1.0.0` 来自压测设备,文件大小和 SHA-256 已核对。 +其内部 `prod_BM1688_` 名称与 `chip_type` 保留设备原始内容;这只是上述两个固定哈希的实测 +例外,不代表其他 BM1688 与 CV186X 模型可互换。 diff --git a/data/resource/aiboxresource/algorithm/7463_No Safety Helmet_20260629094147.json b/data/resource/aiboxresource_bm1688/algorithm/7463_No Safety Helmet_20260629094147.json similarity index 100% rename from data/resource/aiboxresource/algorithm/7463_No Safety Helmet_20260629094147.json rename to data/resource/aiboxresource_bm1688/algorithm/7463_No Safety Helmet_20260629094147.json diff --git "a/data/resource/aiboxresource/algorithm_template/10_\347\201\253\347\204\260\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/10_\347\201\253\347\204\260\346\243\200\346\265\213_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/10_\347\201\253\347\204\260\346\243\200\346\265\213_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/10_\347\201\253\347\204\260\346\243\200\346\265\213_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/11_\345\220\270\347\203\237\346\243\200\346\265\213_1775100665.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/11_\345\220\270\347\203\237\346\243\200\346\265\213_1775100665.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/11_\345\220\270\347\203\237\346\243\200\346\265\213_1775100665.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/11_\345\220\270\347\203\237\346\243\200\346\265\213_1775100665.json" diff --git "a/data/resource/aiboxresource/algorithm_template/12_\346\211\223\347\224\265\350\257\235\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/12_\346\211\223\347\224\265\350\257\235\346\243\200\346\265\213_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/12_\346\211\223\347\224\265\350\257\235\346\243\200\346\265\213_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/12_\346\211\223\347\224\265\350\257\235\346\243\200\346\265\213_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/13_\344\272\272\346\265\201\351\207\217\347\273\237\350\256\241_1776302940.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/13_\344\272\272\346\265\201\351\207\217\347\273\237\350\256\241_1776302940.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/13_\344\272\272\346\265\201\351\207\217\347\273\237\350\256\241_1776302940.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/13_\344\272\272\346\265\201\351\207\217\347\273\237\350\256\241_1776302940.json" diff --git "a/data/resource/aiboxresource/algorithm_template/15760_\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213_20260413173835.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/15760_\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213_20260413173835.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/15760_\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213_20260413173835.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/15760_\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213_20260413173835.json" diff --git "a/data/resource/aiboxresource/algorithm_template/15_\346\234\252\346\210\264\345\256\211\345\205\250\345\270\275_1767592983.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/15_\346\234\252\346\210\264\345\256\211\345\205\250\345\270\275_1767592983.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/15_\346\234\252\346\210\264\345\256\211\345\205\250\345\270\275_1767592983.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/15_\346\234\252\346\210\264\345\256\211\345\205\250\345\270\275_1767592983.json" diff --git "a/data/resource/aiboxresource/algorithm_template/16_\347\246\273\345\262\227\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/16_\347\246\273\345\262\227\346\243\200\346\265\213_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/16_\347\246\273\345\262\227\346\243\200\346\265\213_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/16_\347\246\273\345\262\227\346\243\200\346\265\213_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/21283_\350\247\206\350\247\211\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175841.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/21283_\350\247\206\350\247\211\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175841.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/21283_\350\247\206\350\247\211\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175841.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/21283_\350\247\206\350\247\211\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175841.json" diff --git "a/data/resource/aiboxresource/algorithm_template/22_\347\216\251\346\211\213\346\234\272\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/22_\347\216\251\346\211\213\346\234\272\346\243\200\346\265\213_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/22_\347\216\251\346\211\213\346\234\272\346\243\200\346\265\213_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/22_\347\216\251\346\211\213\346\234\272\346\243\200\346\265\213_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/2935_\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213_20260413173822.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/2935_\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213_20260413173822.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/2935_\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213_20260413173822.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/2935_\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213_20260413173822.json" diff --git "a/data/resource/aiboxresource/algorithm/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" diff --git "a/data/resource/aiboxresource/algorithm_template/2_\344\272\272\350\204\270\350\257\206\345\210\253_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/2_\344\272\272\350\204\270\350\257\206\345\210\253_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/2_\344\272\272\350\204\270\350\257\206\345\210\253_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/2_\344\272\272\350\204\270\350\257\206\345\210\253_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/32_\346\234\252\347\251\277\345\217\215\345\205\211\350\241\243_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/32_\346\234\252\347\251\277\345\217\215\345\205\211\350\241\243_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/32_\346\234\252\347\251\277\345\217\215\345\205\211\350\241\243_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/32_\346\234\252\347\251\277\345\217\215\345\205\211\350\241\243_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/34707_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175854.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/34707_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175854.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/34707_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175854.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/34707_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175854.json" diff --git "a/data/resource/aiboxresource/algorithm_template/38873_\346\243\200\346\265\213\347\261\273\347\256\227\346\263\225_20260413173858.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/38873_\346\243\200\346\265\213\347\261\273\347\256\227\346\263\225_20260413173858.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/38873_\346\243\200\346\265\213\347\261\273\347\256\227\346\263\225_20260413173858.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/38873_\346\243\200\346\265\213\347\261\273\347\256\227\346\263\225_20260413173858.json" diff --git "a/data/resource/aiboxresource/algorithm_template/3_\345\214\272\345\237\237\345\205\245\344\276\265_1775112182.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/3_\345\214\272\345\237\237\345\205\245\344\276\265_1775112182.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/3_\345\214\272\345\237\237\345\205\245\344\276\265_1775112182.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/3_\345\214\272\345\237\237\345\205\245\344\276\265_1775112182.json" diff --git "a/data/resource/aiboxresource/algorithm_template/51_\345\214\272\345\237\237\344\272\272\346\225\260\347\273\237\350\256\241_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/51_\345\214\272\345\237\237\344\272\272\346\225\260\347\273\237\350\256\241_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/51_\345\214\272\345\237\237\344\272\272\346\225\260\347\273\237\350\256\241_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/51_\345\214\272\345\237\237\344\272\272\346\225\260\347\273\237\350\256\241_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/57_\347\273\212\347\272\277\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/57_\347\273\212\347\272\277\346\243\200\346\265\213_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/57_\347\273\212\347\272\277\346\243\200\346\265\213_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/57_\347\273\212\347\272\277\346\243\200\346\265\213_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/58_\346\234\252\347\251\277\345\267\245\346\234\215_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/58_\346\234\252\347\251\277\345\267\245\346\234\215_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/58_\346\234\252\347\251\277\345\267\245\346\234\215_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/58_\346\234\252\347\251\277\345\267\245\346\234\215_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/5_\344\272\272\345\221\230\350\201\232\351\233\206_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/5_\344\272\272\345\221\230\350\201\232\351\233\206_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/5_\344\272\272\345\221\230\350\201\232\351\233\206_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/5_\344\272\272\345\221\230\350\201\232\351\233\206_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/65_\347\235\241\345\262\227\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/65_\347\235\241\345\262\227\346\243\200\346\265\213_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/65_\347\235\241\345\262\227\346\243\200\346\265\213_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/65_\347\235\241\345\262\227\346\243\200\346\265\213_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/6_\344\272\272\345\221\230\350\267\214\345\200\222_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/6_\344\272\272\345\221\230\350\267\214\345\200\222_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/6_\344\272\272\345\221\230\350\267\214\345\200\222_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/6_\344\272\272\345\221\230\350\267\214\345\200\222_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/7602_\344\272\272\350\204\270\350\257\206\345\210\253\347\256\227\346\263\225_20260422103647.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/7602_\344\272\272\350\204\270\350\257\206\345\210\253\347\256\227\346\263\225_20260422103647.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/7602_\344\272\272\350\204\270\350\257\206\345\210\253\347\256\227\346\263\225_20260422103647.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/7602_\344\272\272\350\204\270\350\257\206\345\210\253\347\256\227\346\263\225_20260422103647.json" diff --git "a/data/resource/aiboxresource/algorithm_template/77380_\346\243\200\346\265\213\345\220\216\345\210\206\347\261\273\347\256\227\346\263\225_20260414160117.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/77380_\346\243\200\346\265\213\345\220\216\345\210\206\347\261\273\347\256\227\346\263\225_20260414160117.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/77380_\346\243\200\346\265\213\345\220\216\345\210\206\347\261\273\347\256\227\346\263\225_20260414160117.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/77380_\346\243\200\346\265\213\345\220\216\345\210\206\347\261\273\347\256\227\346\263\225_20260414160117.json" diff --git "a/data/resource/aiboxresource/algorithm_template/7_\350\275\246\350\276\206\350\277\235\345\201\234_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/7_\350\275\246\350\276\206\350\277\235\345\201\234_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/7_\350\275\246\350\276\206\350\277\235\345\201\234_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/7_\350\275\246\350\276\206\350\277\235\345\201\234_1759134672.json" diff --git "a/data/resource/aiboxresource/algorithm_template/82819_\346\243\200\346\265\213\345\220\216\345\210\206\345\211\262\347\256\227\346\263\225_20260414155302.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/82819_\346\243\200\346\265\213\345\220\216\345\210\206\345\211\262\347\256\227\346\263\225_20260414155302.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/82819_\346\243\200\346\265\213\345\220\216\345\210\206\345\211\262\347\256\227\346\263\225_20260414155302.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/82819_\346\243\200\346\265\213\345\220\216\345\210\206\345\211\262\347\256\227\346\263\225_20260414155302.json" diff --git "a/data/resource/aiboxresource/algorithm_template/8533_\350\247\206\350\247\211\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175828.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/8533_\350\247\206\350\247\211\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175828.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/8533_\350\247\206\350\247\211\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175828.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/8533_\350\247\206\350\247\211\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175828.json" diff --git "a/data/resource/aiboxresource/algorithm_template/89336_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213_20260413173809.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/89336_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213_20260413173809.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/89336_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213_20260413173809.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/89336_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213_20260413173809.json" diff --git "a/data/resource/aiboxresource/algorithm_template/9_\347\203\237\351\233\276\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_bm1688/algorithm_template/9_\347\203\237\351\233\276\346\243\200\346\265\213_1759134672.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/9_\347\203\237\351\233\276\346\243\200\346\265\213_1759134672.json" rename to "data/resource/aiboxresource_bm1688/algorithm_template/9_\347\203\237\351\233\276\346\243\200\346\265\213_1759134672.json" diff --git a/data/resource/aiboxresource/i18n/resource.en-US.json b/data/resource/aiboxresource_bm1688/i18n/resource.en-US.json similarity index 100% rename from data/resource/aiboxresource/i18n/resource.en-US.json rename to data/resource/aiboxresource_bm1688/i18n/resource.en-US.json diff --git a/data/resource/aiboxresource/i18n/resource.zh-CN.json b/data/resource/aiboxresource_bm1688/i18n/resource.zh-CN.json similarity index 100% rename from data/resource/aiboxresource/i18n/resource.zh-CN.json rename to data/resource/aiboxresource_bm1688/i18n/resource.zh-CN.json diff --git a/data/resource/aiboxresource/layout/actions.json b/data/resource/aiboxresource_bm1688/layout/actions.json similarity index 100% rename from data/resource/aiboxresource/layout/actions.json rename to data/resource/aiboxresource_bm1688/layout/actions.json diff --git a/data/resource/aiboxresource/layout/linkageStorages.json b/data/resource/aiboxresource_bm1688/layout/linkageStorages.json similarity index 100% rename from data/resource/aiboxresource/layout/linkageStorages.json rename to data/resource/aiboxresource_bm1688/layout/linkageStorages.json diff --git a/data/resource/aiboxresource/layout/modelComponents.json b/data/resource/aiboxresource_bm1688/layout/modelComponents.json similarity index 100% rename from data/resource/aiboxresource/layout/modelComponents.json rename to data/resource/aiboxresource_bm1688/layout/modelComponents.json diff --git a/data/resource/aiboxresource/model_template/classify.json b/data/resource/aiboxresource_bm1688/model_template/classify.json similarity index 100% rename from data/resource/aiboxresource/model_template/classify.json rename to data/resource/aiboxresource_bm1688/model_template/classify.json diff --git a/data/resource/aiboxresource/model_template/dino.json b/data/resource/aiboxresource_bm1688/model_template/dino.json similarity index 100% rename from data/resource/aiboxresource/model_template/dino.json rename to data/resource/aiboxresource_bm1688/model_template/dino.json diff --git a/data/resource/aiboxresource/model_template/feature.json b/data/resource/aiboxresource_bm1688/model_template/feature.json similarity index 100% rename from data/resource/aiboxresource/model_template/feature.json rename to data/resource/aiboxresource_bm1688/model_template/feature.json diff --git a/data/resource/aiboxresource/model_template/keypoints.json b/data/resource/aiboxresource_bm1688/model_template/keypoints.json similarity index 100% rename from data/resource/aiboxresource/model_template/keypoints.json rename to data/resource/aiboxresource_bm1688/model_template/keypoints.json diff --git a/data/resource/aiboxresource/model_template/ocr.json b/data/resource/aiboxresource_bm1688/model_template/ocr.json similarity index 100% rename from data/resource/aiboxresource/model_template/ocr.json rename to data/resource/aiboxresource_bm1688/model_template/ocr.json diff --git a/data/resource/aiboxresource/model_template/qwen3_5.json b/data/resource/aiboxresource_bm1688/model_template/qwen3_5.json similarity index 100% rename from data/resource/aiboxresource/model_template/qwen3_5.json rename to data/resource/aiboxresource_bm1688/model_template/qwen3_5.json diff --git a/data/resource/aiboxresource/model_template/qwen3vl.json b/data/resource/aiboxresource_bm1688/model_template/qwen3vl.json similarity index 100% rename from data/resource/aiboxresource/model_template/qwen3vl.json rename to data/resource/aiboxresource_bm1688/model_template/qwen3vl.json diff --git a/data/resource/aiboxresource/model_template/sam2.json b/data/resource/aiboxresource_bm1688/model_template/sam2.json similarity index 100% rename from data/resource/aiboxresource/model_template/sam2.json rename to data/resource/aiboxresource_bm1688/model_template/sam2.json diff --git a/data/resource/aiboxresource/model_template/yolo26_det.json b/data/resource/aiboxresource_bm1688/model_template/yolo26_det.json similarity index 100% rename from data/resource/aiboxresource/model_template/yolo26_det.json rename to data/resource/aiboxresource_bm1688/model_template/yolo26_det.json diff --git a/data/resource/aiboxresource/model_template/yolov11_det.json b/data/resource/aiboxresource_bm1688/model_template/yolov11_det.json similarity index 100% rename from data/resource/aiboxresource/model_template/yolov11_det.json rename to data/resource/aiboxresource_bm1688/model_template/yolov11_det.json diff --git a/data/resource/aiboxresource/model_template/yolov12_det.json b/data/resource/aiboxresource_bm1688/model_template/yolov12_det.json similarity index 100% rename from data/resource/aiboxresource/model_template/yolov12_det.json rename to data/resource/aiboxresource_bm1688/model_template/yolov12_det.json diff --git a/data/resource/aiboxresource/model_template/yolov5_det.json b/data/resource/aiboxresource_bm1688/model_template/yolov5_det.json similarity index 100% rename from data/resource/aiboxresource/model_template/yolov5_det.json rename to data/resource/aiboxresource_bm1688/model_template/yolov5_det.json diff --git a/data/resource/aiboxresource/model_template/yolov8_det.json b/data/resource/aiboxresource_bm1688/model_template/yolov8_det.json similarity index 100% rename from data/resource/aiboxresource/model_template/yolov8_det.json rename to data/resource/aiboxresource_bm1688/model_template/yolov8_det.json diff --git a/data/resource/aiboxresource/model_template/yolov9_det.json b/data/resource/aiboxresource_bm1688/model_template/yolov9_det.json similarity index 100% rename from data/resource/aiboxresource/model_template/yolov9_det.json rename to data/resource/aiboxresource_bm1688/model_template/yolov9_det.json diff --git a/data/resource/aiboxresource/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/config.json b/data/resource/aiboxresource_bm1688/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/config.json similarity index 100% rename from data/resource/aiboxresource/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/config.json rename to data/resource/aiboxresource_bm1688/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/config.json diff --git a/data/resource/aiboxresource/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/model.nn b/data/resource/aiboxresource_bm1688/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/model.nn similarity index 100% rename from data/resource/aiboxresource/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/model.nn rename to data/resource/aiboxresource_bm1688/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/model.nn diff --git a/data/resource/aiboxresource/models/prod_BM1688_7486163_helmet_V1.0.0/config.json b/data/resource/aiboxresource_bm1688/models/prod_BM1688_7486163_helmet_V1.0.0/config.json similarity index 100% rename from data/resource/aiboxresource/models/prod_BM1688_7486163_helmet_V1.0.0/config.json rename to data/resource/aiboxresource_bm1688/models/prod_BM1688_7486163_helmet_V1.0.0/config.json diff --git a/data/resource/aiboxresource/models/prod_BM1688_7486163_helmet_V1.0.0/model.nn b/data/resource/aiboxresource_bm1688/models/prod_BM1688_7486163_helmet_V1.0.0/model.nn similarity index 100% rename from data/resource/aiboxresource/models/prod_BM1688_7486163_helmet_V1.0.0/model.nn rename to data/resource/aiboxresource_bm1688/models/prod_BM1688_7486163_helmet_V1.0.0/model.nn diff --git a/data/resource/aiboxresource_cv186x/algorithm/7463_No Safety Helmet_20260629094147.json b/data/resource/aiboxresource_cv186x/algorithm/7463_No Safety Helmet_20260629094147.json new file mode 100644 index 000000000..53e8ee70d --- /dev/null +++ b/data/resource/aiboxresource_cv186x/algorithm/7463_No Safety Helmet_20260629094147.json @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 7463, + "algorithmId": "7463", + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"10\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_targetalarminterval.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_targetalarminterval.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_targetalarmcount.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_targetalarmcount.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_restrainswitch.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_overlaytrajectory.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_overlaytrajectory.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"Pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.Pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"Pedestrian置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"Pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.Pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"Pedestrian置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.Pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"Pedestrian检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\"},{\"name\":\"中心\",\"value\":\"1\"},{\"name\":\"顶部\",\"value\":\"2\"}],\"range\":null,\"senior\":0,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小Pedestrian尺寸:Pedestrian抓拍照片的最小图像尺寸。如输入值为100,则最小Pedestrian尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.Pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小Pedestrian尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"helmet置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.helmet.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"helmet置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"helmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.helmet.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"helmet置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"nohelmet置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.nohelmet.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"nohelmet置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"nohelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.nohelmet.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"nohelmet置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度计算命中数,范围:1-总数。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.senHitCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度计算命中数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"5\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.ba_10003.param_senhitcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_senhitcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_senhitcount.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"10\",\"dependsOn\":null,\"description\":\"灵敏度计算总数\",\"endValue\":null,\"failedTip\":\"请输入1-3600000的整数\",\"group\":null,\"key\":\"param.senTotalCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度计算总数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.ba_10003.param_sentotalcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_sentotalcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_sentotalcount.failedtip\"},{\"key\":\"aiParam.6047042.frames\",\"value\":\"10\",\"name\":\"YOLOV8n追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.6047042.motion\",\"value\":\"80.0\",\"name\":\"YOLOV8n静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.6047042.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"YOLOV8n追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.15.15.name.description\",\"failedTipI18nKey\":\"resource.param.15.15.name.failedtip\",\"nameI18nKey\":\"resource.param.15.15.name.name\"}],\"areasTitle\":null},\"regionType\":\"quadrilateral\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "No Safety Helmet", + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"3b63e86f\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.15.ba_00001.3b63e86f.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00001.3b63e86f.remark\",\"inputParamConfig\":\"[]\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"83b4eb95\",\"preFlowActionId\":\"3b63e86f\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"class_name\":\"Pedestrian\",\"label\":\"0\",\"nameCN\":\"Pedestrian\",\"threshold\":[0.5],\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"6047042\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.Pedestrian.confidence\",\"value\":\"\",\"name\":\"Pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"Pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.Pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"Pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"Pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.Pedestrian.detPostion\",\"value\":\"0\",\"name\":\"Pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\"},{\"name\":\"中心\",\"value\":\"1\"},{\"name\":\"顶部\",\"value\":\"2\"}]}],\"atomic\":{\"atomicCode\":\"6047042\",\"atomicName\":\"YOLOV8n\",\"position\":\"83b4eb95\",\"labelList\":[{\"class_name\":\"Pedestrian\",\"label\":\"0\",\"nameCN\":\"Pedestrian\",\"threshold\":[0.5],\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"6047042\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6047042\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"7\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00001.83b4eb95.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00001.83b4eb95.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"modelSelect_detector\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"选择原子模型\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"atomicCode\\\",\\\"name\\\":\\\"选择原子模型\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00001.atomiccode.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00001.atomiccode.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00001.atomiccode.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"自定义取帧频率:默认开启,关闭按全帧取帧。\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"Enableftp\\\",\\\"name\\\":\\\"自定义取帧频率\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00001.enableftp.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00001.enableftp.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00001.enableftp.name\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"-1\\\",\\\"description\\\":\\\"自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:-1全帧。\\\",\\\"failedTip\\\":\\\"请输入正确的值\\\",\\\"key\\\":\\\"fps\\\",\\\"name\\\":\\\"取帧频率\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"Enableftp\\\",\\\"value\\\":\\\"1\\\"},\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00001.fps.enableftp.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00001.fps.enableftp.1.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00001.fps.enableftp.1.name\\\"}]\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"e1a418ab\",\"preFlowActionId\":\"83b4eb95\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.6047042.frames\",\"value\":\"10\",\"name\":\"YOLOV8n追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.6047042.motion\",\"value\":\"80.0\",\"name\":\"YOLOV8n静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.6047042.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"YOLOV8n追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"6047042\"},{\"key\":\"motionStatus\",\"value\":\"1\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00003.e1a418ab.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00003.e1a418ab.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"trackSelect\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"trackSelect\\\",\\\"name\\\":\\\"标签过滤参数\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.trackselect.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.trackselect.name\\\"},{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"状态判断\\\",\\\"failedTip\\\":\\\"请选择正确的值\\\",\\\"key\\\":\\\"motionStatus\\\",\\\"name\\\":\\\"状态判断\\\",\\\"options\\\":[{\\\"name\\\":\\\"关闭\\\",\\\"value\\\":\\\"0\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.motionstatus.0.options_name\\\"},{\\\"name\\\":\\\"运动状态\\\",\\\"value\\\":\\\"1\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.motionstatus.1.options_name\\\"},{\\\"name\\\":\\\"静止状态\\\",\\\"value\\\":\\\"2\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.motionstatus.2.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-2]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00003.motionstatus.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.motionstatus.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.motionstatus.name\\\"},{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"形变状态判断\\\",\\\"failedTip\\\":\\\"请选择正确的值\\\",\\\"key\\\":\\\"shapeChangeStatus\\\",\\\"name\\\":\\\"形变状态判断\\\",\\\"options\\\":[{\\\"name\\\":\\\"不需要\\\",\\\"value\\\":\\\"0\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.shapechangestatus.0.options_name\\\"},{\\\"name\\\":\\\"需要形状发生变化的\\\",\\\"value\\\":\\\"1\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.shapechangestatus.1.options_name\\\"},{\\\"name\\\":\\\"需要形状不发生变的\\\",\\\"value\\\":\\\"2\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.shapechangestatus.2.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00003.shapechangestatus.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.shapechangestatus.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.shapechangestatus.name\\\"},{\\\"key\\\":\\\"shapeChangeThreshold\\\",\\\"name\\\":\\\"形变阈值\\\",\\\"defaultValue\\\":\\\"0.1\\\",\\\"description\\\":\\\"大于等于此阈值后认为目标形状发生了变化。取值范围:0.0-1.0\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTip\\\":\\\"请输入正确的数值\\\",\\\"level\\\":\\\"1\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"shapeChangeStatus\\\",\\\"value\\\":\\\"1\\\"},\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.failedtip\\\"},{\\\"key\\\":\\\"shapeChangeThreshold\\\",\\\"name\\\":\\\"形变阈值\\\",\\\"defaultValue\\\":\\\"0.1\\\",\\\"description\\\":\\\"小于此阈值后认为目标是静止不变的。取值范围:0.0-1.0\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTip\\\":\\\"请输入正确的数值\\\",\\\"level\\\":\\\"1\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"shapeChangeStatus\\\",\\\"value\\\":\\\"2\\\"},\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.failedtip\\\"}]\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别筛选\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"66fe69a4\",\"preFlowActionId\":\"e1a418ab\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"labelCode\":\"Pedestrian\",\"labelName\":\"Pedestrian\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"confidenceValue\":\"1\"}],\"metaDataParams\":[{\"key\":\"filter.Pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小Pedestrian尺寸\",\"defaultValue\":\"60\",\"description\":\"最小Pedestrian尺寸:Pedestrian抓拍照片的最小图像尺寸。如输入值为100,则最小Pedestrian尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.15.ba_00002.66fe69a4.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00002.66fe69a4.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"labelFilterList\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"\\\",\\\"name\\\":\\\"标签参数\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00002.0.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00002.0.name\\\"}]\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"检测目标送分类算法,需要选择一个分类模型\",\"flowActionId\":\"a0333a67\",\"preFlowActionId\":\"66fe69a4\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"class_name\":\"helmet\",\"label\":\"0\",\"nameCN\":\"helmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"},{\"class_name\":\"nohelmet\",\"label\":\"1\",\"nameCN\":\"nohelmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.helmet.confidence\",\"value\":\"\",\"name\":\"helmet置信度\",\"defaultValue\":\"\",\"description\":\"helmet置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.helmet.confidenceConfig\",\"value\":\"\",\"name\":\"helmet置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"helmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.nohelmet.confidence\",\"value\":\"\",\"name\":\"nohelmet置信度\",\"defaultValue\":\"\",\"description\":\"nohelmet置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.nohelmet.confidenceConfig\",\"value\":\"\",\"name\":\"nohelmet置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"nohelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1}],\"atomic\":{\"atomicCode\":\"7486163\",\"atomicName\":\"helmet\",\"position\":\"a0333a67\",\"labelList\":[{\"class_name\":\"helmet\",\"label\":\"0\",\"nameCN\":\"helmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"},{\"class_name\":\"nohelmet\",\"label\":\"1\",\"nameCN\":\"nohelmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"7486163\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"7\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00002.a0333a67.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00002.a0333a67.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"modelSelect_classify\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"选择原子模型\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"atomicCode\\\",\\\"name\\\":\\\"选择原子模型\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00002.atomiccode.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00002.atomiccode.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00002.atomiccode.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"自定义取帧频率:默认开启,关闭则按前面动作的取帧频率。\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"Enableftp\\\",\\\"name\\\":\\\"自定义取帧频率\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00002.enableftp.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00002.enableftp.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00002.enableftp.name\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"-1\\\",\\\"description\\\":\\\"active需要的帧率,不填就继承之前的方法。范围:0.01-1000.0,默认:-1全帧。\\\",\\\"failedTip\\\":\\\"请输入正确的值\\\",\\\"key\\\":\\\"fps\\\",\\\"name\\\":\\\"取帧帧率\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"Enableftp\\\",\\\"value\\\":\\\"1\\\"},\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00002.fps.enableftp.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00002.fps.enableftp.1.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00002.fps.enableftp.1.name\\\"}]\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"0d105731\",\"preFlowActionId\":\"a0333a67\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"0bf521be\",\"keyL\":\"aiOut.nohelmet.threshold\",\"keyR\":\"aiParam.nohelmet.confidence\",\"type\":14,\"list\":[],\"showTools\":false,\"level\":1,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.15.ba_90001.0d105731.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_90001.0d105731.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"condition\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"配置条件使其结果为真,并运行下面的动作\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"condition\\\",\\\"name\\\":\\\"条件配置\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_90001.condition.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_90001.condition.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_90001.condition.name\\\"}]\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"4fb8d95e\",\"preFlowActionId\":\"6447be05\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.failedtip\",\"value\":\"3\",\"position\":\"4fb8d95e\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.failedtip\",\"value\":\"1\",\"position\":\"4fb8d95e\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_restrainswitch.failedtip\",\"value\":\"0\",\"position\":\"4fb8d95e\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_overlaprate.failedtip\",\"value\":\"0.2\",\"position\":\"4fb8d95e\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_restraintime.failedtip\",\"value\":\"6\",\"position\":\"4fb8d95e\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"nameI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.failedtip\",\"value\":\"0\",\"position\":\"4fb8d95e\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.15.ba_00004.4fb8d95e.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00004.4fb8d95e.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"1\\\",\\\"description\\\":\\\"目标是否带跟踪,选择不同的告警抑制方式\\\",\\\"failedTip\\\":\\\"请选择正确的值\\\",\\\"key\\\":\\\"custParam.alarmType\\\",\\\"name\\\":\\\"目标是否带跟踪\\\",\\\"options\\\":[{\\\"name\\\":\\\"不带目标跟踪\\\",\\\"value\\\":\\\"1\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.custparam_alarmtype.1.options_name\\\"},{\\\"name\\\":\\\"带目标跟踪\\\",\\\"value\\\":\\\"2\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.custparam_alarmtype.2.options_name\\\"},{\\\"name\\\":\\\"不需要抑制\\\",\\\"value\\\":\\\"3\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.custparam_alarmtype.3.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.custparam_alarmtype.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.custparam_alarmtype.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.custparam_alarmtype.name\\\"},{\\\"key\\\":\\\"param.alarmInterval\\\",\\\"name\\\":\\\"告警时间间隔(秒)\\\",\\\"defaultValue\\\":\\\"3\\\",\\\"description\\\":\\\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\\\",\\\"failedTip\\\":\\\"请输入1-36000的整数\\\",\\\"level\\\":\\\"2\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"custParam.alarmType\\\",\\\"value\\\":\\\"1\\\"},\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.failedtip\\\"},{\\\"key\\\":\\\"param.targetAlarmInterval\\\",\\\"name\\\":\\\"告警时间间隔(秒)\\\",\\\"defaultValue\\\":\\\"3\\\",\\\"description\\\":\\\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\\\",\\\"failedTip\\\":\\\"请输入1-36000的整数\\\",\\\"level\\\":\\\"2\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"custParam.alarmType\\\",\\\"value\\\":\\\"2\\\"},\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.failedtip\\\"},{\\\"key\\\":\\\"param.targetAlarmCount\\\",\\\"name\\\":\\\"告警次数\\\",\\\"defaultValue\\\":\\\"1\\\",\\\"description\\\":\\\"告警次数:范围:0-100,默认为1。0表示不限次数。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^(0|[1-9]|[1-9][0-9]|100)$/\\\",\\\"failedTip\\\":\\\"请输入0-100的整数\\\",\\\"level\\\":\\\"2\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"custParam.alarmType\\\",\\\"value\\\":\\\"2\\\"},\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.failedtip\\\"},{\\\"key\\\":\\\"param.restrainSwitch\\\",\\\"name\\\":\\\"静止目标去重\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\\\",\\\"type\\\":\\\"switch\\\",\\\"regexpr\\\":\\\"/^[01]$/\\\",\\\"failedTip\\\":\\\"请选择是否打开告警抑制服务\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_restrainswitch.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_restrainswitch.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_restrainswitch.failedtip\\\"},{\\\"key\\\":\\\"param.overlapRate\\\",\\\"name\\\":\\\"静止目标重叠率\\\",\\\"defaultValue\\\":\\\"0.2\\\",\\\"description\\\":\\\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTip\\\":\\\"请输入0-1的三位小数。\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_overlaprate.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_overlaprate.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_overlaprate.failedtip\\\"},{\\\"key\\\":\\\"param.restrainTime\\\",\\\"name\\\":\\\"静止目标去重时间(小时)\\\",\\\"defaultValue\\\":\\\"6\\\",\\\"description\\\":\\\"静止目标去重时间,范围:1~24小时,默认:6小时。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^([0-9]|[1][0-9]|[2][0-4])$/\\\",\\\"failedTip\\\":\\\"请输入0-24的整数。\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_restraintime.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_restraintime.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_restraintime.failedtip\\\"},{\\\"key\\\":\\\"param.overlayTrajectory\\\",\\\"name\\\":\\\"全景图叠加轨迹\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"打开后会在全景图上叠加目标运动轨迹\\\",\\\"type\\\":\\\"switch\\\",\\\"regexpr\\\":\\\"/^[01]$/\\\",\\\"failedTip\\\":\\\"请选择是否打开叠加轨迹\\\",\\\"level\\\":\\\"2\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"custParam.alarmType\\\",\\\"value\\\":\\\"2\\\"},\\\"senior\\\":1,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.failedtip\\\"},{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"上报数据中,部分特殊事件需要额外送参数\\\",\\\"failedTip\\\":\\\"请选择正确的值\\\",\\\"key\\\":\\\"alarmProperty\\\",\\\"name\\\":\\\"事件扩展属性\\\",\\\"options\\\":[{\\\"name\\\":\\\"普通告警(无属性)\\\",\\\"value\\\":\\\"0\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.0.options_name\\\"},{\\\"name\\\":\\\"人脸检测/比对(特征属性)\\\",\\\"value\\\":\\\"1\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.1.options_name\\\"},{\\\"name\\\":\\\"车辆属性\\\",\\\"value\\\":\\\"3\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.3.options_name\\\"},{\\\"name\\\":\\\"机物类特殊检测属性(如滤波状态开关/机物比对结果)\\\",\\\"value\\\":\\\"5\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.5.options_name\\\"},{\\\"name\\\":\\\"人流量统计属性\\\",\\\"value\\\":\\\"6\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.6.options_name\\\"},{\\\"name\\\":\\\"车流量统计属性\\\",\\\"value\\\":\\\"7\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.7.options_name\\\"},{\\\"name\\\":\\\"聚集人数\\\",\\\"value\\\":\\\"8\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.8.options_name\\\"},{\\\"name\\\":\\\"人数统计属性(区域人数)\\\",\\\"value\\\":\\\"9\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.9.options_name\\\"},{\\\"name\\\":\\\"人体特征上报\\\",\\\"value\\\":\\\"10\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.10.options_name\\\"},{\\\"name\\\":\\\"工服比对结果\\\",\\\"value\\\":\\\"11\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.11.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.alarmproperty.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.alarmproperty.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.alarmproperty.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"1\\\",\\\"description\\\":\\\"触发类上报事件是否需要视频片段\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"triggerEventRecordType\\\",\\\"name\\\":\\\"触发类上报事件是否需要视频片段\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.triggereventrecordtype.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.triggereventrecordtype.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.triggereventrecordtype.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"定时上报事件是否需要视频片段\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"realtimeEventRecordType\\\",\\\"name\\\":\\\"定时上报事件是否需要视频片段\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.realtimeeventrecordtype.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.realtimeeventrecordtype.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.realtimeeventrecordtype.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"启用后,告警事件在上报前将由Qwen3VL大模型进行二次审核验证,过滤误报。仅对触发类事件生效。\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"enableLlmReview\\\",\\\"name\\\":\\\"大模型审核\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.enablellmreview.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.enablellmreview.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.enablellmreview.name\\\"},{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"local_model\\\",\\\"description\\\":\\\"Choose local review model or OpenAI-compatible API\\\",\\\"failedTip\\\":\\\"Please select a valid value\\\",\\\"key\\\":\\\"llmProvider\\\",\\\"name\\\":\\\"Review Inference Mode\\\",\\\"options\\\":[{\\\"name\\\":\\\"Local Atomic Model\\\",\\\"value\\\":\\\"local_model\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.llmprovider.local_model.options_name\\\"},{\\\"name\\\":\\\"OpenAI API\\\",\\\"value\\\":\\\"openai_vlm\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.llmprovider.openai_vlm.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"enableLlmReview\\\",\\\"value\\\":\\\"1\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmprovider.enablellmreview.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmprovider.enablellmreview.1.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.llmprovider.enablellmreview.1.name\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"http://127.0.0.1:8000/v1\\\",\\\"description\\\":\\\"OpenAI-compatible API base URL, for example http://127.0.0.1:8000/v1\\\",\\\"failedTip\\\":\\\"Please enter API base URL\\\",\\\"key\\\":\\\"llmOpenaiBaseUrl\\\",\\\"name\\\":\\\"base_url\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"OpenAI API key; leave empty when local vLLM authentication is disabled\\\",\\\"failedTip\\\":\\\"Please enter API key\\\",\\\"key\\\":\\\"llmOpenaiApiKey\\\",\\\"name\\\":\\\"api_key\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"Qwen/Qwen3-VL-2B-Instruct\\\",\\\"description\\\":\\\"OpenAI API model name\\\",\\\"failedTip\\\":\\\"Please enter model name\\\",\\\"key\\\":\\\"llmOpenaiModel\\\",\\\"name\\\":\\\"model\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"/chat/completions\\\",\\\"description\\\":\\\"OpenAI-compatible API path, default /chat/completions\\\",\\\"failedTip\\\":\\\"Please enter API path\\\",\\\"key\\\":\\\"llmOpenaiEndpoint\\\",\\\"name\\\":\\\"endpoint\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"60000\\\",\\\"description\\\":\\\"Request timeout in milliseconds\\\",\\\"failedTip\\\":\\\"Please enter timeout\\\",\\\"key\\\":\\\"llmOpenaiTimeoutMs\\\",\\\"name\\\":\\\"timeout_ms\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"256\\\",\\\"description\\\":\\\"Maximum output token count\\\",\\\"failedTip\\\":\\\"Please enter maximum output token count\\\",\\\"key\\\":\\\"llmOpenaiMaxTokens\\\",\\\"name\\\":\\\"max_tokens\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"modelSelect_qwen3vl\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"选择用于告警审核的Qwen3VL语言视觉大模型\\\",\\\"failedTip\\\":\\\"请选择审核模型\\\",\\\"key\\\":\\\"llmAtomicCode\\\",\\\"name\\\":\\\"审核模型\\\",\\\"level\\\":\\\"1\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"local_model\\\"},\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.name\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"用于审核的内容描述,比如:火焰、未带安全帽的人、烟雾等。留空则自动使用算法名称。\\\",\\\"failedTip\\\":\\\"\\\",\\\"key\\\":\\\"llmReviewContent\\\",\\\"name\\\":\\\"审核内容\\\",\\\"level\\\":\\\"1\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"enableLlmReview\\\",\\\"value\\\":\\\"1\\\"},\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmreviewcontent.enablellmreview.1.description\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.llmreviewcontent.enablellmreview.1.name\\\"}]\"},{\"actionId\":\"BA_10003\",\"actionName\":\"灵敏度计算-计数\",\"remark\":\"\",\"flowActionId\":\"6447be05\",\"preFlowActionId\":\"0d105731\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.senHitCount\",\"name\":\"灵敏度计算命中数\",\"defaultValue\":\"5\",\"description\":\"灵敏度计算命中数,范围:1-总数。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"senior\":0,\"dependsOn\":null,\"nameI18nKey\":\"resource.param.ba_10003.param_senhitcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_senhitcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_senhitcount.failedtip\",\"value\":\"5\",\"position\":\"6447be05\"},{\"key\":\"param.senTotalCount\",\"name\":\"灵敏度计算总数\",\"defaultValue\":\"10\",\"description\":\"灵敏度计算总数\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-3600000的整数\",\"level\":\"2\",\"senior\":0,\"dependsOn\":null,\"nameI18nKey\":\"resource.param.ba_10003.param_sentotalcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_sentotalcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_sentotalcount.failedtip\",\"value\":\"10\",\"position\":\"6447be05\"}],\"atomic\":{}},\"params\":[]},\"inputParamConfig\":\"[{\\\"key\\\":\\\"param.senHitCount\\\",\\\"name\\\":\\\"灵敏度计算命中数\\\",\\\"defaultValue\\\":\\\"5\\\",\\\"description\\\":\\\"灵敏度计算命中数,范围:1-总数。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\\\",\\\"failedTip\\\":\\\"请输入1-3600的整数\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"dependsOn\\\":null,\\\"nameI18nKey\\\":\\\"resource.param.ba_10003.param_senhitcount.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_10003.param_senhitcount.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_10003.param_senhitcount.failedtip\\\"},{\\\"key\\\":\\\"param.senTotalCount\\\",\\\"name\\\":\\\"灵敏度计算总数\\\",\\\"defaultValue\\\":\\\"10\\\",\\\"description\\\":\\\"灵敏度计算总数\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTip\\\":\\\"请输入1-3600000的整数\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"dependsOn\\\":null,\\\"nameI18nKey\\\":\\\"resource.param.ba_10003.param_sentotalcount.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_10003.param_sentotalcount.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_10003.param_sentotalcount.failedtip\\\"}]\"}]", + "algorithmUsage": 1, + "atomicList": "[{\"atomicCode\":\"6047042\",\"atomicName\":\"YOLOV8n\",\"position\":\"83b4eb95\",\"labelList\":[{\"class_name\":\"Pedestrian\",\"label\":\"0\",\"nameCN\":\"Pedestrian\",\"threshold\":[0.5],\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"6047042\"}],\"categoriesLabelList\":[]},{\"atomicCode\":\"7486163\",\"atomicName\":\"helmet\",\"position\":\"a0333a67\",\"labelList\":[{\"class_name\":\"helmet\",\"label\":\"0\",\"nameCN\":\"helmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"},{\"class_name\":\"nohelmet\",\"label\":\"1\",\"nameCN\":\"nohelmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"}],\"categoriesLabelList\":[]}]", + "checkType": 15382, + "confVersionId": "79c9d9bdf07445048b57602e1dce6b6e", + "configVersionList": [ + { + "algorithmCode": "7463", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[],\"areasTitle\":null},\"regionType\":\"0\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false,\"shieldedRegion\":{}}", + "algorithmProcessdata": "[]", + "algorithmUpdateTime": 1782697307000, + "atomicList": "[]", + "id": "default-7463", + "name": "默认", + "remark": "" + }, + { + "algorithmCode": 7463, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"10\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_targetalarminterval.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_targetalarminterval.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_targetalarmcount.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_targetalarmcount.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_restrainswitch.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.15.15.param_overlaytrajectory.name\",\"descriptionI18nKey\":\"resource.param.15.15.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_overlaytrajectory.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"Pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.Pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"Pedestrian置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"Pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.Pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"Pedestrian置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.Pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"Pedestrian检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\"},{\"name\":\"中心\",\"value\":\"1\"},{\"name\":\"顶部\",\"value\":\"2\"}],\"range\":null,\"senior\":0,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小Pedestrian尺寸:Pedestrian抓拍照片的最小图像尺寸。如输入值为100,则最小Pedestrian尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.Pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小Pedestrian尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"helmet置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.helmet.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"helmet置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"helmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.helmet.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"helmet置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"nohelmet置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.nohelmet.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"nohelmet置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"nohelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.nohelmet.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"nohelmet置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度计算命中数,范围:1-总数。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.senHitCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度计算命中数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"5\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.ba_10003.param_senhitcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_senhitcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_senhitcount.failedtip\"},{\"beginValue\":null,\"defaultValue\":\"10\",\"dependsOn\":null,\"description\":\"灵敏度计算总数\",\"endValue\":null,\"failedTip\":\"请输入1-3600000的整数\",\"group\":null,\"key\":\"param.senTotalCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度计算总数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.ba_10003.param_sentotalcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_sentotalcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_sentotalcount.failedtip\"},{\"key\":\"aiParam.6047042.frames\",\"value\":\"10\",\"name\":\"YOLOV8n追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.6047042.motion\",\"value\":\"80.0\",\"name\":\"YOLOV8n静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.6047042.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"YOLOV8n追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.15.15.name.description\",\"failedTipI18nKey\":\"resource.param.15.15.name.failedtip\",\"nameI18nKey\":\"resource.param.15.15.name.name\"}],\"areasTitle\":null},\"regionType\":\"quadrilateral\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"3b63e86f\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.15.ba_00001.3b63e86f.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00001.3b63e86f.remark\",\"inputParamConfig\":\"[]\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"83b4eb95\",\"preFlowActionId\":\"3b63e86f\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"class_name\":\"Pedestrian\",\"label\":\"0\",\"nameCN\":\"Pedestrian\",\"threshold\":[0.5],\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"6047042\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.Pedestrian.confidence\",\"value\":\"\",\"name\":\"Pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"Pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.Pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"Pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"Pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.Pedestrian.detPostion\",\"value\":\"0\",\"name\":\"Pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\"},{\"name\":\"中心\",\"value\":\"1\"},{\"name\":\"顶部\",\"value\":\"2\"}]}],\"atomic\":{\"atomicCode\":\"6047042\",\"atomicName\":\"YOLOV8n\",\"position\":\"83b4eb95\",\"labelList\":[{\"class_name\":\"Pedestrian\",\"label\":\"0\",\"nameCN\":\"Pedestrian\",\"threshold\":[0.5],\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"6047042\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6047042\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"7\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00001.83b4eb95.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00001.83b4eb95.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"modelSelect_detector\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"选择原子模型\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"atomicCode\\\",\\\"name\\\":\\\"选择原子模型\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00001.atomiccode.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00001.atomiccode.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00001.atomiccode.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"自定义取帧频率:默认开启,关闭按全帧取帧。\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"Enableftp\\\",\\\"name\\\":\\\"自定义取帧频率\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00001.enableftp.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00001.enableftp.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00001.enableftp.name\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"-1\\\",\\\"description\\\":\\\"自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:-1全帧。\\\",\\\"failedTip\\\":\\\"请输入正确的值\\\",\\\"key\\\":\\\"fps\\\",\\\"name\\\":\\\"取帧频率\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"Enableftp\\\",\\\"value\\\":\\\"1\\\"},\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00001.fps.enableftp.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00001.fps.enableftp.1.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00001.fps.enableftp.1.name\\\"}]\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"e1a418ab\",\"preFlowActionId\":\"83b4eb95\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.6047042.frames\",\"value\":\"10\",\"name\":\"YOLOV8n追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.6047042.motion\",\"value\":\"80.0\",\"name\":\"YOLOV8n静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.6047042.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"YOLOV8n追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"6047042\"},{\"key\":\"motionStatus\",\"value\":\"1\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00003.e1a418ab.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00003.e1a418ab.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"trackSelect\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"trackSelect\\\",\\\"name\\\":\\\"标签过滤参数\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.trackselect.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.trackselect.name\\\"},{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"状态判断\\\",\\\"failedTip\\\":\\\"请选择正确的值\\\",\\\"key\\\":\\\"motionStatus\\\",\\\"name\\\":\\\"状态判断\\\",\\\"options\\\":[{\\\"name\\\":\\\"关闭\\\",\\\"value\\\":\\\"0\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.motionstatus.0.options_name\\\"},{\\\"name\\\":\\\"运动状态\\\",\\\"value\\\":\\\"1\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.motionstatus.1.options_name\\\"},{\\\"name\\\":\\\"静止状态\\\",\\\"value\\\":\\\"2\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.motionstatus.2.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-2]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00003.motionstatus.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.motionstatus.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.motionstatus.name\\\"},{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"形变状态判断\\\",\\\"failedTip\\\":\\\"请选择正确的值\\\",\\\"key\\\":\\\"shapeChangeStatus\\\",\\\"name\\\":\\\"形变状态判断\\\",\\\"options\\\":[{\\\"name\\\":\\\"不需要\\\",\\\"value\\\":\\\"0\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.shapechangestatus.0.options_name\\\"},{\\\"name\\\":\\\"需要形状发生变化的\\\",\\\"value\\\":\\\"1\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.shapechangestatus.1.options_name\\\"},{\\\"name\\\":\\\"需要形状不发生变的\\\",\\\"value\\\":\\\"2\\\",\\\"labelI18nKey\\\":\\\"resource.option.aa_00003.shapechangestatus.2.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00003.shapechangestatus.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.shapechangestatus.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.shapechangestatus.name\\\"},{\\\"key\\\":\\\"shapeChangeThreshold\\\",\\\"name\\\":\\\"形变阈值\\\",\\\"defaultValue\\\":\\\"0.1\\\",\\\"description\\\":\\\"大于等于此阈值后认为目标形状发生了变化。取值范围:0.0-1.0\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTip\\\":\\\"请输入正确的数值\\\",\\\"level\\\":\\\"1\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"shapeChangeStatus\\\",\\\"value\\\":\\\"1\\\"},\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.failedtip\\\"},{\\\"key\\\":\\\"shapeChangeThreshold\\\",\\\"name\\\":\\\"形变阈值\\\",\\\"defaultValue\\\":\\\"0.1\\\",\\\"description\\\":\\\"小于此阈值后认为目标是静止不变的。取值范围:0.0-1.0\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTip\\\":\\\"请输入正确的数值\\\",\\\"level\\\":\\\"1\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"shapeChangeStatus\\\",\\\"value\\\":\\\"2\\\"},\\\"nameI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.failedtip\\\"}]\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别筛选\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"66fe69a4\",\"preFlowActionId\":\"e1a418ab\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"labelCode\":\"Pedestrian\",\"labelName\":\"Pedestrian\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"confidenceValue\":\"1\"}],\"metaDataParams\":[{\"key\":\"filter.Pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小Pedestrian尺寸\",\"defaultValue\":\"60\",\"description\":\"最小Pedestrian尺寸:Pedestrian抓拍照片的最小图像尺寸。如输入值为100,则最小Pedestrian尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.15.ba_00002.66fe69a4.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00002.66fe69a4.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"labelFilterList\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"\\\",\\\"name\\\":\\\"标签参数\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00002.0.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00002.0.name\\\"}]\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"检测目标送分类算法,需要选择一个分类模型\",\"flowActionId\":\"a0333a67\",\"preFlowActionId\":\"66fe69a4\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"class_name\":\"helmet\",\"label\":\"0\",\"nameCN\":\"helmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"},{\"class_name\":\"nohelmet\",\"label\":\"1\",\"nameCN\":\"nohelmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.helmet.confidence\",\"value\":\"\",\"name\":\"helmet置信度\",\"defaultValue\":\"\",\"description\":\"helmet置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.helmet.confidenceConfig\",\"value\":\"\",\"name\":\"helmet置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"helmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.nohelmet.confidence\",\"value\":\"\",\"name\":\"nohelmet置信度\",\"defaultValue\":\"\",\"description\":\"nohelmet置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1},{\"key\":\"aiParam.nohelmet.confidenceConfig\",\"value\":\"\",\"name\":\"nohelmet置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"nohelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1}],\"atomic\":{\"atomicCode\":\"7486163\",\"atomicName\":\"helmet\",\"position\":\"a0333a67\",\"labelList\":[{\"class_name\":\"helmet\",\"label\":\"0\",\"nameCN\":\"helmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"},{\"class_name\":\"nohelmet\",\"label\":\"1\",\"nameCN\":\"nohelmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"7486163\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"7\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00002.a0333a67.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00002.a0333a67.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"modelSelect_classify\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"选择原子模型\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"atomicCode\\\",\\\"name\\\":\\\"选择原子模型\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00002.atomiccode.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00002.atomiccode.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00002.atomiccode.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"自定义取帧频率:默认开启,关闭则按前面动作的取帧频率。\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"Enableftp\\\",\\\"name\\\":\\\"自定义取帧频率\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00002.enableftp.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00002.enableftp.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00002.enableftp.name\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"-1\\\",\\\"description\\\":\\\"active需要的帧率,不填就继承之前的方法。范围:0.01-1000.0,默认:-1全帧。\\\",\\\"failedTip\\\":\\\"请输入正确的值\\\",\\\"key\\\":\\\"fps\\\",\\\"name\\\":\\\"取帧帧率\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"Enableftp\\\",\\\"value\\\":\\\"1\\\"},\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.aa_00002.fps.enableftp.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.aa_00002.fps.enableftp.1.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.aa_00002.fps.enableftp.1.name\\\"}]\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"0d105731\",\"preFlowActionId\":\"a0333a67\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"0bf521be\",\"keyL\":\"aiOut.nohelmet.threshold\",\"keyR\":\"aiParam.nohelmet.confidence\",\"type\":14,\"list\":[],\"showTools\":false,\"level\":1,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.15.ba_90001.0d105731.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_90001.0d105731.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"condition\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"配置条件使其结果为真,并运行下面的动作\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"condition\\\",\\\"name\\\":\\\"条件配置\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_90001.condition.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_90001.condition.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_90001.condition.name\\\"}]\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"4fb8d95e\",\"preFlowActionId\":\"6447be05\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.failedtip\",\"value\":\"3\",\"position\":\"4fb8d95e\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.failedtip\",\"value\":\"1\",\"position\":\"4fb8d95e\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_restrainswitch.failedtip\",\"value\":\"0\",\"position\":\"4fb8d95e\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_overlaprate.failedtip\",\"value\":\"0.2\",\"position\":\"4fb8d95e\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_restraintime.failedtip\",\"value\":\"6\",\"position\":\"4fb8d95e\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"nameI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.failedtip\",\"value\":\"0\",\"position\":\"4fb8d95e\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.15.ba_00004.4fb8d95e.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00004.4fb8d95e.remark\",\"inputParamConfig\":\"[{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"1\\\",\\\"description\\\":\\\"目标是否带跟踪,选择不同的告警抑制方式\\\",\\\"failedTip\\\":\\\"请选择正确的值\\\",\\\"key\\\":\\\"custParam.alarmType\\\",\\\"name\\\":\\\"目标是否带跟踪\\\",\\\"options\\\":[{\\\"name\\\":\\\"不带目标跟踪\\\",\\\"value\\\":\\\"1\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.custparam_alarmtype.1.options_name\\\"},{\\\"name\\\":\\\"带目标跟踪\\\",\\\"value\\\":\\\"2\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.custparam_alarmtype.2.options_name\\\"},{\\\"name\\\":\\\"不需要抑制\\\",\\\"value\\\":\\\"3\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.custparam_alarmtype.3.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.custparam_alarmtype.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.custparam_alarmtype.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.custparam_alarmtype.name\\\"},{\\\"key\\\":\\\"param.alarmInterval\\\",\\\"name\\\":\\\"告警时间间隔(秒)\\\",\\\"defaultValue\\\":\\\"3\\\",\\\"description\\\":\\\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\\\",\\\"failedTip\\\":\\\"请输入1-36000的整数\\\",\\\"level\\\":\\\"2\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"custParam.alarmType\\\",\\\"value\\\":\\\"1\\\"},\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.failedtip\\\"},{\\\"key\\\":\\\"param.targetAlarmInterval\\\",\\\"name\\\":\\\"告警时间间隔(秒)\\\",\\\"defaultValue\\\":\\\"3\\\",\\\"description\\\":\\\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\\\",\\\"failedTip\\\":\\\"请输入1-36000的整数\\\",\\\"level\\\":\\\"2\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"custParam.alarmType\\\",\\\"value\\\":\\\"2\\\"},\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.failedtip\\\"},{\\\"key\\\":\\\"param.targetAlarmCount\\\",\\\"name\\\":\\\"告警次数\\\",\\\"defaultValue\\\":\\\"1\\\",\\\"description\\\":\\\"告警次数:范围:0-100,默认为1。0表示不限次数。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^(0|[1-9]|[1-9][0-9]|100)$/\\\",\\\"failedTip\\\":\\\"请输入0-100的整数\\\",\\\"level\\\":\\\"2\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"custParam.alarmType\\\",\\\"value\\\":\\\"2\\\"},\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.failedtip\\\"},{\\\"key\\\":\\\"param.restrainSwitch\\\",\\\"name\\\":\\\"静止目标去重\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\\\",\\\"type\\\":\\\"switch\\\",\\\"regexpr\\\":\\\"/^[01]$/\\\",\\\"failedTip\\\":\\\"请选择是否打开告警抑制服务\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_restrainswitch.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_restrainswitch.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_restrainswitch.failedtip\\\"},{\\\"key\\\":\\\"param.overlapRate\\\",\\\"name\\\":\\\"静止目标重叠率\\\",\\\"defaultValue\\\":\\\"0.2\\\",\\\"description\\\":\\\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTip\\\":\\\"请输入0-1的三位小数。\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_overlaprate.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_overlaprate.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_overlaprate.failedtip\\\"},{\\\"key\\\":\\\"param.restrainTime\\\",\\\"name\\\":\\\"静止目标去重时间(小时)\\\",\\\"defaultValue\\\":\\\"6\\\",\\\"description\\\":\\\"静止目标去重时间,范围:1~24小时,默认:6小时。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^([0-9]|[1][0-9]|[2][0-4])$/\\\",\\\"failedTip\\\":\\\"请输入0-24的整数。\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_restraintime.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_restraintime.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_restraintime.failedtip\\\"},{\\\"key\\\":\\\"param.overlayTrajectory\\\",\\\"name\\\":\\\"全景图叠加轨迹\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"打开后会在全景图上叠加目标运动轨迹\\\",\\\"type\\\":\\\"switch\\\",\\\"regexpr\\\":\\\"/^[01]$/\\\",\\\"failedTip\\\":\\\"请选择是否打开叠加轨迹\\\",\\\"level\\\":\\\"2\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"custParam.alarmType\\\",\\\"value\\\":\\\"2\\\"},\\\"senior\\\":1,\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.failedtip\\\"},{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"上报数据中,部分特殊事件需要额外送参数\\\",\\\"failedTip\\\":\\\"请选择正确的值\\\",\\\"key\\\":\\\"alarmProperty\\\",\\\"name\\\":\\\"事件扩展属性\\\",\\\"options\\\":[{\\\"name\\\":\\\"普通告警(无属性)\\\",\\\"value\\\":\\\"0\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.0.options_name\\\"},{\\\"name\\\":\\\"人脸检测/比对(特征属性)\\\",\\\"value\\\":\\\"1\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.1.options_name\\\"},{\\\"name\\\":\\\"车辆属性\\\",\\\"value\\\":\\\"3\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.3.options_name\\\"},{\\\"name\\\":\\\"机物类特殊检测属性(如滤波状态开关/机物比对结果)\\\",\\\"value\\\":\\\"5\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.5.options_name\\\"},{\\\"name\\\":\\\"人流量统计属性\\\",\\\"value\\\":\\\"6\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.6.options_name\\\"},{\\\"name\\\":\\\"车流量统计属性\\\",\\\"value\\\":\\\"7\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.7.options_name\\\"},{\\\"name\\\":\\\"聚集人数\\\",\\\"value\\\":\\\"8\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.8.options_name\\\"},{\\\"name\\\":\\\"人数统计属性(区域人数)\\\",\\\"value\\\":\\\"9\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.9.options_name\\\"},{\\\"name\\\":\\\"人体特征上报\\\",\\\"value\\\":\\\"10\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.10.options_name\\\"},{\\\"name\\\":\\\"工服比对结果\\\",\\\"value\\\":\\\"11\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.alarmproperty.11.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.alarmproperty.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.alarmproperty.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.alarmproperty.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"1\\\",\\\"description\\\":\\\"触发类上报事件是否需要视频片段\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"triggerEventRecordType\\\",\\\"name\\\":\\\"触发类上报事件是否需要视频片段\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.triggereventrecordtype.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.triggereventrecordtype.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.triggereventrecordtype.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"定时上报事件是否需要视频片段\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"realtimeEventRecordType\\\",\\\"name\\\":\\\"定时上报事件是否需要视频片段\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.realtimeeventrecordtype.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.realtimeeventrecordtype.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.realtimeeventrecordtype.name\\\"},{\\\"type\\\":\\\"switch\\\",\\\"defaultValue\\\":\\\"0\\\",\\\"description\\\":\\\"启用后,告警事件在上报前将由Qwen3VL大模型进行二次审核验证,过滤误报。仅对触发类事件生效。\\\",\\\"failedTip\\\":\\\"请选择\\\",\\\"key\\\":\\\"enableLlmReview\\\",\\\"name\\\":\\\"大模型审核\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"/^[0-1]$/\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.enablellmreview.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.enablellmreview.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.enablellmreview.name\\\"},{\\\"type\\\":\\\"select\\\",\\\"defaultValue\\\":\\\"local_model\\\",\\\"description\\\":\\\"Choose local review model or OpenAI-compatible API\\\",\\\"failedTip\\\":\\\"Please select a valid value\\\",\\\"key\\\":\\\"llmProvider\\\",\\\"name\\\":\\\"Review Inference Mode\\\",\\\"options\\\":[{\\\"name\\\":\\\"Local Atomic Model\\\",\\\"value\\\":\\\"local_model\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.llmprovider.local_model.options_name\\\"},{\\\"name\\\":\\\"OpenAI API\\\",\\\"value\\\":\\\"openai_vlm\\\",\\\"labelI18nKey\\\":\\\"resource.option.ba_00004.llmprovider.openai_vlm.options_name\\\"}],\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"enableLlmReview\\\",\\\"value\\\":\\\"1\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmprovider.enablellmreview.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmprovider.enablellmreview.1.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.llmprovider.enablellmreview.1.name\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"http://127.0.0.1:8000/v1\\\",\\\"description\\\":\\\"OpenAI-compatible API base URL, for example http://127.0.0.1:8000/v1\\\",\\\"failedTip\\\":\\\"Please enter API base URL\\\",\\\"key\\\":\\\"llmOpenaiBaseUrl\\\",\\\"name\\\":\\\"base_url\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"OpenAI API key; leave empty when local vLLM authentication is disabled\\\",\\\"failedTip\\\":\\\"Please enter API key\\\",\\\"key\\\":\\\"llmOpenaiApiKey\\\",\\\"name\\\":\\\"api_key\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"Qwen/Qwen3-VL-2B-Instruct\\\",\\\"description\\\":\\\"OpenAI API model name\\\",\\\"failedTip\\\":\\\"Please enter model name\\\",\\\"key\\\":\\\"llmOpenaiModel\\\",\\\"name\\\":\\\"model\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"/chat/completions\\\",\\\"description\\\":\\\"OpenAI-compatible API path, default /chat/completions\\\",\\\"failedTip\\\":\\\"Please enter API path\\\",\\\"key\\\":\\\"llmOpenaiEndpoint\\\",\\\"name\\\":\\\"endpoint\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"60000\\\",\\\"description\\\":\\\"Request timeout in milliseconds\\\",\\\"failedTip\\\":\\\"Please enter timeout\\\",\\\"key\\\":\\\"llmOpenaiTimeoutMs\\\",\\\"name\\\":\\\"timeout_ms\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"256\\\",\\\"description\\\":\\\"Maximum output token count\\\",\\\"failedTip\\\":\\\"Please enter maximum output token count\\\",\\\"key\\\":\\\"llmOpenaiMaxTokens\\\",\\\"name\\\":\\\"max_tokens\\\",\\\"level\\\":\\\"1\\\",\\\"regexpr\\\":\\\"\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"openai_vlm\\\"},\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.failedtip\\\"},{\\\"type\\\":\\\"modelSelect_qwen3vl\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"选择用于告警审核的Qwen3VL语言视觉大模型\\\",\\\"failedTip\\\":\\\"请选择审核模型\\\",\\\"key\\\":\\\"llmAtomicCode\\\",\\\"name\\\":\\\"审核模型\\\",\\\"level\\\":\\\"1\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"llmProvider\\\",\\\"value\\\":\\\"local_model\\\"},\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.failedtip\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.name\\\"},{\\\"type\\\":\\\"text\\\",\\\"defaultValue\\\":\\\"\\\",\\\"description\\\":\\\"用于审核的内容描述,比如:火焰、未带安全帽的人、烟雾等。留空则自动使用算法名称。\\\",\\\"failedTip\\\":\\\"\\\",\\\"key\\\":\\\"llmReviewContent\\\",\\\"name\\\":\\\"审核内容\\\",\\\"level\\\":\\\"1\\\",\\\"dependsOn\\\":{\\\"key\\\":\\\"enableLlmReview\\\",\\\"value\\\":\\\"1\\\"},\\\"regexpr\\\":\\\"\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_00004.llmreviewcontent.enablellmreview.1.description\\\",\\\"nameI18nKey\\\":\\\"resource.param.ba_00004.llmreviewcontent.enablellmreview.1.name\\\"}]\"},{\"actionId\":\"BA_10003\",\"actionName\":\"灵敏度计算-计数\",\"remark\":\"\",\"flowActionId\":\"6447be05\",\"preFlowActionId\":\"0d105731\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.senHitCount\",\"name\":\"灵敏度计算命中数\",\"defaultValue\":\"5\",\"description\":\"灵敏度计算命中数,范围:1-总数。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"senior\":0,\"dependsOn\":null,\"nameI18nKey\":\"resource.param.ba_10003.param_senhitcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_senhitcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_senhitcount.failedtip\",\"value\":\"5\",\"position\":\"6447be05\"},{\"key\":\"param.senTotalCount\",\"name\":\"灵敏度计算总数\",\"defaultValue\":\"10\",\"description\":\"灵敏度计算总数\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-3600000的整数\",\"level\":\"2\",\"senior\":0,\"dependsOn\":null,\"nameI18nKey\":\"resource.param.ba_10003.param_sentotalcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_sentotalcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_sentotalcount.failedtip\",\"value\":\"10\",\"position\":\"6447be05\"}],\"atomic\":{}},\"params\":[]},\"inputParamConfig\":\"[{\\\"key\\\":\\\"param.senHitCount\\\",\\\"name\\\":\\\"灵敏度计算命中数\\\",\\\"defaultValue\\\":\\\"5\\\",\\\"description\\\":\\\"灵敏度计算命中数,范围:1-总数。\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\\\",\\\"failedTip\\\":\\\"请输入1-3600的整数\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"dependsOn\\\":null,\\\"nameI18nKey\\\":\\\"resource.param.ba_10003.param_senhitcount.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_10003.param_senhitcount.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_10003.param_senhitcount.failedtip\\\"},{\\\"key\\\":\\\"param.senTotalCount\\\",\\\"name\\\":\\\"灵敏度计算总数\\\",\\\"defaultValue\\\":\\\"10\\\",\\\"description\\\":\\\"灵敏度计算总数\\\",\\\"type\\\":\\\"text\\\",\\\"regexpr\\\":\\\"\\\",\\\"failedTip\\\":\\\"请输入1-3600000的整数\\\",\\\"level\\\":\\\"2\\\",\\\"senior\\\":0,\\\"dependsOn\\\":null,\\\"nameI18nKey\\\":\\\"resource.param.ba_10003.param_sentotalcount.name\\\",\\\"descriptionI18nKey\\\":\\\"resource.param.ba_10003.param_sentotalcount.description\\\",\\\"failedTipI18nKey\\\":\\\"resource.param.ba_10003.param_sentotalcount.failedtip\\\"}]\"}]", + "algorithmUpdateTime": 1783049157000, + "atomicList": "[{\"atomicCode\":\"6047042\",\"atomicName\":\"YOLOV8n\",\"position\":\"83b4eb95\",\"labelList\":[{\"class_name\":\"Pedestrian\",\"label\":\"0\",\"nameCN\":\"Pedestrian\",\"threshold\":[0.5],\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"6047042\"}],\"categoriesLabelList\":[]},{\"atomicCode\":\"7486163\",\"atomicName\":\"helmet\",\"position\":\"a0333a67\",\"labelList\":[{\"class_name\":\"helmet\",\"label\":\"0\",\"nameCN\":\"helmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"},{\"class_name\":\"nohelmet\",\"label\":\"1\",\"nameCN\":\"nohelmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"7486163\"}],\"categoriesLabelList\":[]}]", + "id": "79c9d9bdf07445048b57602e1dce6b6e", + "name": "默认" + } + ], + "createTime": 1782697307000, + "description": "", + "remark": "", + "updateTime": 1782697307000 +} \ No newline at end of file diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/10_\347\201\253\347\204\260\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/10_\347\201\253\347\204\260\346\243\200\346\265\213_1759134672.json" new file mode 100644 index 000000000..cdb4c2951 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/10_\347\201\253\347\204\260\346\243\200\346\265\213_1759134672.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 3, + "algorithmCode": 10, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"火焰置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.fire.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"火焰置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.aiparam_fire_confidence.description\",\"failedTipI18nKey\":\"resource.param.10.10.aiparam_fire_confidence.failedtip\",\"nameI18nKey\":\"resource.param.10.10.aiparam_fire_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"火焰置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.fire.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"火焰置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.aiparam_fire_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.10.10.aiparam_fire_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.fire.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"火焰检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.10.10.aiparam_fire_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.10.10.aiparam_fire_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.10.10.aiparam_fire_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.aiparam_fire_detpostion.description\",\"failedTipI18nKey\":\"resource.param.10.10.aiparam_fire_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.10.10.aiparam_fire_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小火焰尺寸:火焰抓拍照片的最小图像尺寸。如输入值为100,则最小火焰尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.fire.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小火焰尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.filter_fire_side_min.description\",\"failedTipI18nKey\":\"resource.param.10.10.filter_fire_side_min.failedtip\",\"nameI18nKey\":\"resource.param.10.10.filter_fire_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.alarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_alarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"endValue\":null,\"failedTip\":\"请输入1-100的整数\",\"group\":null,\"key\":\"param.videoRepeatCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"离线视频播放次数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_videorepeatcount.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_videorepeatcount.name\"},{\"beginValue\":null,\"defaultValue\":\"-1\",\"dependsOn\":null,\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"endValue\":null,\"failedTip\":\"请输入正确的值\",\"group\":null,\"key\":\"param.videoReadFps\",\"maxValue\":null,\"minValue\":null,\"name\":\"离线视频播放取帧帧率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"-1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_videoreadfps.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.2001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"火焰、烟雾检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.aiparam_2001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.10.10.aiparam_2001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.10.10.aiparam_2001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.10.10.name.description\",\"failedTipI18nKey\":\"resource.param.10.10.name.failedtip\",\"nameI18nKey\":\"resource.param.10.10.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "火焰检测", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"ba9c7d80\",\"preFlowActionId\":\"b62ab911\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"fire\",\"nameCN\":\"fire\",\"threshold\":[0.550000011920929],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.fire.confidence\",\"value\":\"\",\"name\":\"fire置信度\",\"defaultValue\":\"\",\"description\":\"fire置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.name\",\"descriptionI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.description\",\"failedTipI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.failedtip\"},{\"key\":\"aiParam.fire.confidenceConfig\",\"value\":\"\",\"name\":\"fire置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"fire置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidenceconfig.description\"},{\"key\":\"aiParam.fire.detPostion\",\"value\":\"0\",\"name\":\"fire检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.name\",\"descriptionI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.description\",\"failedTipI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"2001003\",\"atomicName\":\"FireDetection\",\"position\":\"ba9c7d80\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"fire\",\"nameCN\":\"fire\",\"threshold\":[0.550000011920929],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.10.aa_00001.ba9c7d80.actionname\",\"remarkI18nKey\":\"resource.action.10.aa_00001.ba9c7d80.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"a59e0a7e\",\"preFlowActionId\":\"674483de\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"2001003\",\"labelCode\":\"fire\",\"labelName\":\"火焰\",\"position\":\"ba9c7d80\",\"sideMinIsEnable\":\"1\",\"collapse\":true}],\"metaDataParams\":[{\"key\":\"filter.fire.side.min\",\"value\":\"60\",\"name\":\"最小火焰尺寸\",\"defaultValue\":\"60\",\"description\":\"最小火焰尺寸:火焰抓拍照片的最小图像尺寸。如输入值为100,则最小火焰尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.10.ba_00002.a59e0a7e.actionname\",\"remarkI18nKey\":\"resource.action.10.ba_00002.a59e0a7e.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"1478c130\",\"preFlowActionId\":\"2c1f8a2b\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.10.ba_00004.1478c130.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00004.1478c130.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00004.1478c130.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.10.ba_00004.1478c130.actionname\",\"remarkI18nKey\":\"resource.action.10.ba_00004.1478c130.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"b62ab911\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.10.ba_00001.b62ab911.actionname\",\"remarkI18nKey\":\"resource.action.10.ba_00001.b62ab911.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"674483de\",\"preFlowActionId\":\"ba9c7d80\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.2001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"火焰、烟雾检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"2001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"1\"},{\"key\":\"shapeChangeThreshold\",\"value\":\"0.1\"}]},\"actionNameI18nKey\":\"resource.action.10.aa_00003.674483de.actionname\",\"remarkI18nKey\":\"resource.action.10.aa_00003.674483de.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"2c1f8a2b\",\"preFlowActionId\":\"a59e0a7e\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"2c1f8a2b\",\"nameI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"2c1f8a2b\",\"nameI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.10.ba_00003.2c1f8a2b.actionname\",\"remarkI18nKey\":\"resource.action.10.ba_00003.2c1f8a2b.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758699326632", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\",\"atomicName\":\"FireDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"fire\",\"nameCN\":\"fire\",\"threshold\":[0.550000011920929],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}]}]", + "checkType": 4, + "confVersionId": "928c62d8411647b59f09fc3ad88346fe", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683602000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "motorCommodity", + "extraFormat": null, + "gafAlgorithmId": 10, + "gafAlgorithmName": "FireAndFaceAalrm", + "id": "10", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_commodity004", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用火焰检测算法,对检测区域内的火焰超过阈值时间的事件进行告警。\n仅支持白天场景,摄像机转红外图像后,将自动停止分析。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758699327000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "928c62d8411647b59f09fc3ad88346fe", + "name": "默认", + "algorithmCode": 10, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"火焰置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.fire.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"火焰置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.aiparam_fire_confidence.description\",\"failedTipI18nKey\":\"resource.param.10.10.aiparam_fire_confidence.failedtip\",\"nameI18nKey\":\"resource.param.10.10.aiparam_fire_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"火焰置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.fire.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"火焰置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.aiparam_fire_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.10.10.aiparam_fire_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.fire.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"火焰检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.10.10.aiparam_fire_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.10.10.aiparam_fire_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.10.10.aiparam_fire_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.aiparam_fire_detpostion.description\",\"failedTipI18nKey\":\"resource.param.10.10.aiparam_fire_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.10.10.aiparam_fire_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小火焰尺寸:火焰抓拍照片的最小图像尺寸。如输入值为100,则最小火焰尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.fire.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小火焰尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.filter_fire_side_min.description\",\"failedTipI18nKey\":\"resource.param.10.10.filter_fire_side_min.failedtip\",\"nameI18nKey\":\"resource.param.10.10.filter_fire_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.alarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_alarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"endValue\":null,\"failedTip\":\"请输入1-100的整数\",\"group\":null,\"key\":\"param.videoRepeatCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"离线视频播放次数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_videorepeatcount.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_videorepeatcount.name\"},{\"beginValue\":null,\"defaultValue\":\"-1\",\"dependsOn\":null,\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"endValue\":null,\"failedTip\":\"请输入正确的值\",\"group\":null,\"key\":\"param.videoReadFps\",\"maxValue\":null,\"minValue\":null,\"name\":\"离线视频播放取帧帧率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"-1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_videoreadfps.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.2001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"火焰、烟雾检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.aiparam_2001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.10.10.aiparam_2001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.10.10.aiparam_2001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.10.10.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.10.10.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.10.10.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.10.10.name.description\",\"failedTipI18nKey\":\"resource.param.10.10.name.failedtip\",\"nameI18nKey\":\"resource.param.10.10.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"ba9c7d80\",\"preFlowActionId\":\"b62ab911\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"fire\",\"nameCN\":\"fire\",\"threshold\":[0.550000011920929],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.fire.confidence\",\"value\":\"\",\"name\":\"fire置信度\",\"defaultValue\":\"\",\"description\":\"fire置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.name\",\"descriptionI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.description\",\"failedTipI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.failedtip\"},{\"key\":\"aiParam.fire.confidenceConfig\",\"value\":\"\",\"name\":\"fire置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"fire置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidenceconfig.description\"},{\"key\":\"aiParam.fire.detPostion\",\"value\":\"0\",\"name\":\"fire检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.name\",\"descriptionI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.description\",\"failedTipI18nKey\":\"resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"2001003\",\"atomicName\":\"FireDetection\",\"position\":\"ba9c7d80\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"fire\",\"nameCN\":\"fire\",\"threshold\":[0.550000011920929],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.10.aa_00001.ba9c7d80.actionname\",\"remarkI18nKey\":\"resource.action.10.aa_00001.ba9c7d80.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"a59e0a7e\",\"preFlowActionId\":\"674483de\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"2001003\",\"labelCode\":\"fire\",\"labelName\":\"火焰\",\"position\":\"ba9c7d80\",\"sideMinIsEnable\":\"1\",\"collapse\":true}],\"metaDataParams\":[{\"key\":\"filter.fire.side.min\",\"value\":\"60\",\"name\":\"最小火焰尺寸\",\"defaultValue\":\"60\",\"description\":\"最小火焰尺寸:火焰抓拍照片的最小图像尺寸。如输入值为100,则最小火焰尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.10.ba_00002.a59e0a7e.actionname\",\"remarkI18nKey\":\"resource.action.10.ba_00002.a59e0a7e.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"1478c130\",\"preFlowActionId\":\"2c1f8a2b\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.10.ba_00004.1478c130.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00004.1478c130.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00004.1478c130.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00004.1478c130.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.10.ba_00004.1478c130.actionname\",\"remarkI18nKey\":\"resource.action.10.ba_00004.1478c130.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"b62ab911\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.10.ba_00001.b62ab911.actionname\",\"remarkI18nKey\":\"resource.action.10.ba_00001.b62ab911.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"674483de\",\"preFlowActionId\":\"ba9c7d80\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.2001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"火焰、烟雾检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"2001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"1\"},{\"key\":\"shapeChangeThreshold\",\"value\":\"0.1\"}]},\"actionNameI18nKey\":\"resource.action.10.aa_00003.674483de.actionname\",\"remarkI18nKey\":\"resource.action.10.aa_00003.674483de.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"2c1f8a2b\",\"preFlowActionId\":\"a59e0a7e\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"2c1f8a2b\",\"nameI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"2c1f8a2b\",\"nameI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.10.ba_00003.2c1f8a2b.actionname\",\"remarkI18nKey\":\"resource.action.10.ba_00003.2c1f8a2b.remark\"}]", + "atomicList": "[{\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\",\"atomicName\":\"FireDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"fire\",\"nameCN\":\"fire\",\"threshold\":[0.550000011920929],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}]}]", + "algorithmUpdateTime": 1776930536000, + "nameI18nKey": "resource.param.10.10.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.10.algorithmname", + "remarkI18nKey": "resource.algorithm.10.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/11_\345\220\270\347\203\237\346\243\200\346\265\213_1775100665.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/11_\345\220\270\347\203\237\346\243\200\346\265\213_1775100665.json" new file mode 100644 index 000000000..bbb7573c7 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/11_\345\220\270\347\203\237\346\243\200\346\265\213_1775100665.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 11, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.11.11.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.11.11.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.11.11.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.11.11.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.11.11.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.11.11.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"抽烟置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedSmoking.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"抽烟置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidence.description\",\"failedTipI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidence.failedtip\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"抽烟置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedSmoking.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"抽烟置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.11.11.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.11.11.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.11.11.name.description\",\"failedTipI18nKey\":\"resource.param.11.11.name.failedtip\",\"nameI18nKey\":\"resource.param.11.11.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "吸烟检测", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"487c1cf0\",\"preFlowActionId\":\"01fc708c\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"487c1cf0\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.11.aa_00001.487c1cf0.actionname\",\"remarkI18nKey\":\"resource.action.11.aa_00001.487c1cf0.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"c232a753\",\"preFlowActionId\":\"487c1cf0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"PedestrianDetection追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.11.aa_00003.c232a753.actionname\",\"remarkI18nKey\":\"resource.action.11.aa_00003.c232a753.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"c37b8e34\",\"preFlowActionId\":\"5a2f08ca\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"3\",\"class_name\":\"pedSmoking\",\"nameCN\":\"pedSmoking\",\"threshold\":[0.8399999737739563],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedSmoking.confidence\",\"value\":\"\",\"name\":\"pedSmoking置信度\",\"defaultValue\":\"\",\"description\":\"pedSmoking置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.description\",\"failedTipI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.failedtip\"},{\"key\":\"aiParam.pedSmoking.confidenceConfig\",\"value\":\"\",\"name\":\"pedSmoking置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedSmoking置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2002011\",\"atomicName\":\"PhoneSmoking\",\"position\":\"c37b8e34\",\"labelList\":[{\"label\":\"3\",\"class_name\":\"pedSmoking\",\"nameCN\":\"pedSmoking\",\"threshold\":[0.8399999737739563],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2002011\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.11.aa_00002.c37b8e34.actionname\",\"remarkI18nKey\":\"resource.action.11.aa_00002.c37b8e34.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"e02bf44c\",\"preFlowActionId\":\"c37b8e34\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"69b8d4c8\",\"level\":1,\"type\":14,\"keyL\":\"aiOut.pedSmoking.threshold\",\"keyR\":\"aiParam.pedSmoking.confidence\",\"list\":[],\"showTools\":false,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.11.ba_90001.e02bf44c.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_90001.e02bf44c.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"0f53b331\",\"preFlowActionId\":\"b90c6769\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.11.ba_00004.0f53b331.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_00004.0f53b331.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"5a2f08ca\",\"preFlowActionId\":\"c232a753\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"487c1cf0\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.11.ba_00002.5a2f08ca.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_00002.5a2f08ca.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"01fc708c\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.11.ba_00001.01fc708c.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_00001.01fc708c.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"b90c6769\",\"preFlowActionId\":\"e02bf44c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"b90c6769\",\"nameI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"b90c6769\",\"nameI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.11.ba_00003.b90c6769.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_00003.b90c6769.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1775100665732", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}]},{\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\",\"atomicName\":\"PhoneSmoking\",\"labelList\":[{\"label\":\"3\",\"class_name\":\"pedSmoking\",\"nameCN\":\"pedSmoking\",\"threshold\":[0.8399999737739563],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}]}]", + "checkType": 4, + "confVersionId": "2ab2a768a22e4b348691db25152a0209", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 11, + "gafAlgorithmName": "Smoking", + "id": "11", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior004", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用行人检测跟踪算法、吸烟分类算法,对进入检测区域的行人进行吸烟检测,对超过阈值的行人进行吸烟告警。吸烟算法,对吸烟姿态、烟进行同时分析。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1775100666000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "2ab2a768a22e4b348691db25152a0209", + "name": "默认", + "algorithmCode": 11, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.11.11.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.11.11.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.11.11.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.11.11.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.11.11.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.11.11.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"抽烟置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedSmoking.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"抽烟置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidence.description\",\"failedTipI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidence.failedtip\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"抽烟置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedSmoking.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"抽烟置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.11.11.aiparam_pedsmoking_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.11.11.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.11.11.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.11.11.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.11.11.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.11.11.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.11.11.name.description\",\"failedTipI18nKey\":\"resource.param.11.11.name.failedtip\",\"nameI18nKey\":\"resource.param.11.11.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"487c1cf0\",\"preFlowActionId\":\"01fc708c\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"487c1cf0\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.11.aa_00001.487c1cf0.actionname\",\"remarkI18nKey\":\"resource.action.11.aa_00001.487c1cf0.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"c232a753\",\"preFlowActionId\":\"487c1cf0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"PedestrianDetection追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.11.aa_00003.c232a753.actionname\",\"remarkI18nKey\":\"resource.action.11.aa_00003.c232a753.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"c37b8e34\",\"preFlowActionId\":\"5a2f08ca\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"3\",\"class_name\":\"pedSmoking\",\"nameCN\":\"pedSmoking\",\"threshold\":[0.8399999737739563],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedSmoking.confidence\",\"value\":\"\",\"name\":\"pedSmoking置信度\",\"defaultValue\":\"\",\"description\":\"pedSmoking置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.description\",\"failedTipI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.failedtip\"},{\"key\":\"aiParam.pedSmoking.confidenceConfig\",\"value\":\"\",\"name\":\"pedSmoking置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedSmoking置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2002011\",\"atomicName\":\"PhoneSmoking\",\"position\":\"c37b8e34\",\"labelList\":[{\"label\":\"3\",\"class_name\":\"pedSmoking\",\"nameCN\":\"pedSmoking\",\"threshold\":[0.8399999737739563],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2002011\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.11.aa_00002.c37b8e34.actionname\",\"remarkI18nKey\":\"resource.action.11.aa_00002.c37b8e34.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"e02bf44c\",\"preFlowActionId\":\"c37b8e34\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"69b8d4c8\",\"level\":1,\"type\":14,\"keyL\":\"aiOut.pedSmoking.threshold\",\"keyR\":\"aiParam.pedSmoking.confidence\",\"list\":[],\"showTools\":false,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.11.ba_90001.e02bf44c.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_90001.e02bf44c.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"0f53b331\",\"preFlowActionId\":\"b90c6769\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.11.ba_00004.0f53b331.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_00004.0f53b331.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"5a2f08ca\",\"preFlowActionId\":\"c232a753\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"487c1cf0\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.11.ba_00002.5a2f08ca.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_00002.5a2f08ca.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"01fc708c\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.11.ba_00001.01fc708c.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_00001.01fc708c.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"b90c6769\",\"preFlowActionId\":\"e02bf44c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"b90c6769\",\"nameI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"b90c6769\",\"nameI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.11.ba_00003.b90c6769.actionname\",\"remarkI18nKey\":\"resource.action.11.ba_00003.b90c6769.remark\"}]", + "atomicList": "[{\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}]},{\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\",\"atomicName\":\"PhoneSmoking\",\"labelList\":[{\"label\":\"3\",\"class_name\":\"pedSmoking\",\"nameCN\":\"pedSmoking\",\"threshold\":[0.8399999737739563],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}]}]", + "algorithmUpdateTime": 1776924863000, + "nameI18nKey": "resource.param.11.11.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.11.algorithmname", + "remarkI18nKey": "resource.algorithm.11.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/12_\346\211\223\347\224\265\350\257\235\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/12_\346\211\223\347\224\265\350\257\235\346\243\200\346\265\213_1759134672.json" new file mode 100644 index 000000000..2550e6f71 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/12_\346\211\223\347\224\265\350\257\235\346\243\200\346\265\213_1759134672.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 12, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedestrian.confidence\",\"name\":\"行人置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.12.12.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.12.12.aiparam_pedestrian_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedestrian.confidenceConfig\",\"name\":\"行人置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.12.12.aiparam_pedestrian_confidenceconfig.name\"},{\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.pedestrian.detPostion\",\"name\":\"行人检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.12.12.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.12.12.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.12.12.aiparam_pedestrian_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.12.12.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.12.12.aiparam_pedestrian_detpostion.name\"},{\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"failedTip\":\"请输入0-100的两位小数\",\"key\":\"aiParam.1001003.trackDynamicMatch\",\"name\":\"行人检测追踪半径\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.12.12.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.12.12.aiparam_1001003_trackdynamicmatch.name\"},{\"defaultValue\":\"\",\"description\":\"打电话置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedPhoneAnswer.confidence\",\"name\":\"打电话置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.aiparam_pedphoneanswer_confidence.description\",\"failedTipI18nKey\":\"resource.param.12.12.aiparam_pedphoneanswer_confidence.failedtip\",\"nameI18nKey\":\"resource.param.12.12.aiparam_pedphoneanswer_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"打电话置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedPhoneAnswer.confidenceConfig\",\"name\":\"打电话置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.aiparam_pedphoneanswer_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.12.12.aiparam_pedphoneanswer_confidenceconfig.name\"},{\"defaultValue\":\"60\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"failedTip\":\"请输入1-36000的整数\",\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.12.12.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.12.12.param_targetalarminterval.name\"},{\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"failedTip\":\"请输入0-100的整数\",\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.12.12.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.12.12.param_targetalarmcount.name\"},{\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.12.12.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.12.12.param_restrainswitch.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.12.12.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.12.12.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.12.12.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.12.12.param_restraintime.param_restrainswitch.1.name\"},{\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"senior\":1,\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.12.12.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.12.12.param_overlaytrajectory.name\"},{\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"failedTip\":\"请输入0-10000的整数\",\"key\":\"filter.pedestrian.side.min\",\"name\":\"最小行人尺寸\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.12.12.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.12.12.filter_pedestrian_side_min.name\"},{\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"failedTip\":\"请输入1-10的整数\",\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.12.12.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.12.12.param_sensitivity.name\"},{\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"failedTip\":\"请输入1-3600的整数\",\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.12.12.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.12.12.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.12.12.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.12.12.name.description\",\"failedTipI18nKey\":\"resource.param.12.12.name.failedtip\",\"nameI18nKey\":\"resource.param.12.12.name.name\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmName": "打电话检测", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"487c1cf0\",\"preFlowActionId\":\"94b4ca49\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.12.aa_00001.487c1cf0.1001003.0.pedestrian.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"行人置信度\",\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"行人置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"行人检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"行人检测\",\"position\":\"487c1cf0\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.12.aa_00001.487c1cf0.1001003.0.pedestrian.namecn\"}]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.12.aa_00001.487c1cf0.actionname\",\"remarkI18nKey\":\"resource.action.12.aa_00001.487c1cf0.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"c232a753\",\"preFlowActionId\":\"487c1cf0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.12.aa_00003.c232a753.actionname\",\"remarkI18nKey\":\"resource.action.12.aa_00003.c232a753.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"c37b8e34\",\"preFlowActionId\":\"ccc378e3\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"nameCN\":\"打电话\",\"label\":\"0\",\"class_name\":\"pedPhoneAnswer\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\",\"nameCNI18nKey\":\"resource.param.12.aa_00002.c37b8e34.2002011.0.pedphoneanswer.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedPhoneAnswer.confidence\",\"value\":\"\",\"name\":\"打电话置信度\",\"defaultValue\":\"\",\"description\":\"打电话置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.name\",\"descriptionI18nKey\":\"resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.description\",\"failedTipI18nKey\":\"resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.failedtip\"},{\"key\":\"aiParam.pedPhoneAnswer.confidenceConfig\",\"value\":\"\",\"name\":\"打电话置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"打电话置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2002011\",\"atomicName\":\"打电话、玩手机和吸烟检测\",\"position\":\"c37b8e34\",\"labelList\":[{\"nameCN\":\"打电话\",\"label\":\"0\",\"class_name\":\"pedPhoneAnswer\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\",\"nameCNI18nKey\":\"resource.param.12.aa_00002.c37b8e34.2002011.0.pedphoneanswer.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2002011\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.12.aa_00002.c37b8e34.actionname\",\"remarkI18nKey\":\"resource.action.12.aa_00002.c37b8e34.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"e02bf44c\",\"preFlowActionId\":\"c37b8e34\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"b27b4ce8\",\"level\":1,\"type\":14,\"keyL\":\"aiOut.pedPhoneAnswer.threshold\",\"keyR\":\"aiParam.pedPhoneAnswer.confidence\",\"list\":[],\"showTools\":false,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.12.ba_90001.e02bf44c.actionname\",\"remarkI18nKey\":\"resource.action.12.ba_90001.e02bf44c.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"0f53b331\",\"preFlowActionId\":\"0d015957\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"3\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_targetalarminterval.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_targetalarminterval.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"1\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_targetalarmcount.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_targetalarmcount.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.12.ba_00004.0f53b331.actionname\",\"remarkI18nKey\":\"resource.action.12.ba_00004.0f53b331.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"ccc378e3\",\"preFlowActionId\":\"c232a753\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"487c1cf0\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.12.ba_00002.ccc378e3.actionname\",\"remarkI18nKey\":\"resource.action.12.ba_00002.ccc378e3.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"94b4ca49\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.12.ba_00001.94b4ca49.actionname\",\"remarkI18nKey\":\"resource.action.12.ba_00001.94b4ca49.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"0d015957\",\"preFlowActionId\":\"e02bf44c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"0d015957\",\"nameI18nKey\":\"resource.param.12.ba_00003.0d015957.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00003.0d015957.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00003.0d015957.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"value\":\"2\",\"position\":\"0d015957\",\"nameI18nKey\":\"resource.param.12.ba_00003.0d015957.param_detectionduration.name\",\"descriptionI18nKey\":\"resource.param.12.ba_00003.0d015957.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.12.ba_00003.0d015957.param_detectionduration.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.12.ba_00003.0d015957.actionname\",\"remarkI18nKey\":\"resource.action.12.ba_00003.0d015957.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758685255758", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.12.12.1001003.0.pedestrian.namecn\"}],\"atomicName\":\"行人检测\",\"atomicCode\":\"1001003\",\"position\":\"487c1cf0\"},{\"labelList\":[{\"nameCN\":\"打电话\",\"label\":\"0\",\"class_name\":\"pedPhoneAnswer\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\",\"nameCNI18nKey\":\"resource.param.12.12.2002011.0.pedphoneanswer.namecn\"}],\"atomicName\":\"打电话、玩手机和吸烟检测\",\"categoriesLabelList\":[],\"atomicCode\":\"2002011\",\"position\":\"c37b8e34\"}]", + "checkType": 5, + "confVersionId": "6b45952f24024cd180084017cca618ff", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683602000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 12, + "gafAlgorithmName": "AnswerPhone", + "id": "12", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior005", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用行人检测跟踪算法、打电话分类算法,对进入检测区域的行人进行打电话检测,对超过阈值时间的行人进行打电话告警。打电话算法,对打电话姿态、电话进行同时分析。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758685256000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.12.algorithmname", + "remarkI18nKey": "resource.algorithm.12.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/13_\344\272\272\346\265\201\351\207\217\347\273\237\350\256\241_1776302940.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/13_\344\272\272\346\265\201\351\207\217\347\273\237\350\256\241_1776302940.json" new file mode 100644 index 000000000..adaa69c0b --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/13_\344\272\272\346\265\201\351\207\217\347\273\237\350\256\241_1776302940.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 8, + "algorithmCode": 13, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedestrian.confidence\",\"name\":\"行人置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.13.13.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.13.13.aiparam_pedestrian_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedestrian.confidenceConfig\",\"name\":\"行人置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.13.13.aiparam_pedestrian_confidenceconfig.name\"},{\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.pedestrian.detPostion\",\"name\":\"行人检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.13.13.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.13.13.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.13.13.aiparam_pedestrian_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.13.13.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.13.13.aiparam_pedestrian_detpostion.name\"},{\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"failedTip\":\"请输入0-100的两位小数\",\"key\":\"aiParam.1001003.trackDynamicMatch\",\"name\":\"行人检测追踪半径\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.13.13.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.13.13.aiparam_1001003_trackdynamicmatch.name\"},{\"defaultValue\":\"1\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"failedTip\":\"请输入1-36000的整数\",\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"senior\":0,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.13.13.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.13.13.param_alarminterval.name\"},{\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.13.13.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.13.13.param_restrainswitch.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.13.13.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.13.13.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.13.13.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.13.13.param_restraintime.param_restrainswitch.1.name\"},{\"defaultValue\":\"5\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"failedTip\":\"请输入正确的数值\",\"key\":\"param.areaCalcDuration\",\"name\":\"人数上报间隔\",\"regexpr\":\"\",\"type\":\"text\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.param_areacalcduration.description\",\"failedTipI18nKey\":\"resource.param.13.13.param_areacalcduration.failedtip\",\"nameI18nKey\":\"resource.param.13.13.param_areacalcduration.name\"},{\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"failedTip\":\"请选择正确的数值\",\"key\":\"param.areaCalcDurationTimeType\",\"name\":\"检测时间单位\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.13.13.param_areacalcdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.13.13.param_areacalcdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.13.13.param_areacalcdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.13.13.param_areacalcdurationtimetype.3600000.options_name\"}],\"regexpr\":\"\",\"type\":\"select\",\"value\":\"1000\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.param_areacalcdurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.13.13.param_areacalcdurationtimetype.failedtip\",\"nameI18nKey\":\"resource.param.13.13.param_areacalcdurationtimetype.name\"},{\"defaultValue\":\"1\",\"description\":\"目标统计方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.targetCalcType\",\"name\":\"目标统计方式\",\"options\":[{\"name\":\"瞬时(区域人数统计)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.13.13.param_targetcalctype.0.options_name\"},{\"name\":\"周期总人数 (人流量)\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.13.13.param_targetcalctype.1.options_name\"}],\"senior\":1,\"regexpr\":\"/^[0-1]$/\",\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.13.13.param_targetcalctype.description\",\"failedTipI18nKey\":\"resource.param.13.13.param_targetcalctype.failedtip\",\"nameI18nKey\":\"resource.param.13.13.param_targetcalctype.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.13.13.name.description\",\"failedTipI18nKey\":\"resource.param.13.13.name.failedtip\",\"nameI18nKey\":\"resource.param.13.13.name.name\"}],\"areasTitle\":[{\"name\":\"人流线\",\"nameI18nKey\":\"resource.param.13.13.0.name\"},{\"name\":\"区域\",\"regionType\":\"quadrilateral\",\"nameI18nKey\":\"resource.param.13.13.1.name\"}]},\"regionType\":\"oneWayCordon\",\"scheduleSupport\":true,\"maxAreaCount\":1,\"shieldedRegion\":{},\"enableShieldedRegion\":false,\"defaultFullScreen\":false}", + "algorithmName": "人流量统计", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"e9173765\",\"preFlowActionId\":\"cc54dbba\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.13.aa_00001.e9173765.1001003.0.pedestrian.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"行人置信度\",\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"行人置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"行人检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"行人检测\",\"position\":\"e9173765\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.13.aa_00001.e9173765.1001003.0.pedestrian.namecn\"}]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"5\"}]},\"actionNameI18nKey\":\"resource.action.13.aa_00001.e9173765.actionname\",\"remarkI18nKey\":\"resource.action.13.aa_00001.e9173765.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"9253e062\",\"preFlowActionId\":\"e9173765\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.13.aa_00003.9253e062.actionname\",\"remarkI18nKey\":\"resource.action.13.aa_00003.9253e062.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"a5c23881\",\"preFlowActionId\":\"97085574\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"3\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_alarminterval.name\",\"descriptionI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_alarminterval.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.13.ba_00004.a5c23881.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"6\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.13.ba_00004.a5c23881.actionname\",\"remarkI18nKey\":\"resource.action.13.ba_00004.a5c23881.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"97085574\",\"preFlowActionId\":\"9253e062\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.areaCalcDuration\",\"name\":\"数量上报间隔\",\"defaultValue\":\"0\",\"description\":\"数量上报间隔:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"97085574\",\"nameI18nKey\":\"resource.param.13.ba_00005.97085574.param_areacalcduration.name\",\"descriptionI18nKey\":\"resource.param.13.ba_00005.97085574.param_areacalcduration.description\",\"failedTipI18nKey\":\"resource.param.13.ba_00005.97085574.param_areacalcduration.failedtip\"},{\"key\":\"param.areaCalcDurationTimeType\",\"name\":\"数量上报间隔时间单位\",\"defaultValue\":\"1000\",\"description\":\"数量上报间隔时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的单位\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"senior\":0,\"value\":\"1000\",\"position\":\"97085574\",\"nameI18nKey\":\"resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.name\",\"descriptionI18nKey\":\"resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"目标统计方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.targetCalcType\",\"name\":\"目标统计方式\",\"options\":[{\"name\":\"瞬时(区域人数统计)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.13.ba_00005.97085574.param_targetcalctype.0.options_name\"},{\"name\":\"周期总人数 (人流量)\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.13.ba_00005.97085574.param_targetcalctype.1.options_name\"}],\"regexpr\":\"/^[0-1]$/\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"97085574\",\"descriptionI18nKey\":\"resource.param.13.ba_00005.97085574.param_targetcalctype.description\",\"failedTipI18nKey\":\"resource.param.13.ba_00005.97085574.param_targetcalctype.failedtip\",\"nameI18nKey\":\"resource.param.13.ba_00005.97085574.param_targetcalctype.name\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"1\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"countBreakAreaType\",\"value\":\"103\"},{\"key\":\"targetCountChange\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.13.ba_00005.97085574.actionname\",\"remarkI18nKey\":\"resource.action.13.ba_00005.97085574.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"cc54dbba\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.13.ba_00001.cc54dbba.actionname\",\"remarkI18nKey\":\"resource.action.13.ba_00001.cc54dbba.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1776302939832", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.13.13.1001003.0.pedestrian.namecn\"}],\"atomicName\":\"行人检测\",\"atomicCode\":\"1001003\",\"position\":\"e9173765\"}]", + "checkType": 1, + "confVersionId": "7b6cf6a26c044c4bba51d8814db70493", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683602000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "passengerNumber", + "extraFormat": null, + "gafAlgorithmId": 13, + "gafAlgorithmName": "PassStatistics", + "id": "13", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior012", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用头肩检测算法,对经过规则线的进出人数进行统计,并按时间粒度保存。(最小时间粒度小时)", + "status": 1, + "supplier": "CWAI", + "updateTime": 1776302940000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.13.algorithmname", + "remarkI18nKey": "resource.algorithm.13.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/15760_\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213_20260413173835.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/15760_\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213_20260413173835.json" new file mode 100644 index 000000000..31ae1e1cf --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/15760_\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213_20260413173835.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "15760", + "algorithmCode": 15760, + "algorithmName": "分割大模型", + "algorithmCategory": 2, + "algorithmUsage": 2, + "checkType": 23679, + "createTime": 1776073115000, + "updateTime": 1776073115000, + "confVersionId": "default-15760", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.15760.15760.name.description\",\"failedTipI18nKey\":\"resource.param.15760.15760.name.failedtip\",\"nameI18nKey\":\"resource.param.15760.15760.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-15760", + "name": "默认", + "algorithmCode": "15760", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.15760.15760.name.description\",\"failedTipI18nKey\":\"resource.param.15760.15760.name.failedtip\",\"nameI18nKey\":\"resource.param.15760.15760.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"PDA_00002\",\"actionName\":\"分割视觉大模型\",\"remark\":\"\",\"flowActionId\":\"ea49228d\",\"preFlowActionId\":\"b7fe1598\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"position\":\"ea49228d\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6666688\"},{\"key\":\"inputType\",\"value\":\"box\"}]},\"actionNameI18nKey\":\"resource.action.15760.pda_00002.ea49228d.actionname\"},{\"actionId\":\"PA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"b7fe1598\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.25],\"used\":true,\"position\":\"b7fe1598\",\"atomicCode\":\"6666111\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"6666111\",\"atomicName\":\"yolo26\",\"position\":\"b7fe1598\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.25],\"used\":true,\"position\":\"b7fe1598\",\"atomicCode\":\"6666111\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6666111\"}]},\"actionNameI18nKey\":\"resource.action.15760.pa_00001.b7fe1598.actionname\"}]", + "atomicList": "[{\"position\":\"ea49228d\",\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"labelList\":[]},{\"position\":\"b7fe1598\",\"atomicCode\":\"6666111\",\"atomicName\":\"yolo26\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.25],\"used\":true,\"position\":\"b7fe1598\",\"atomicCode\":\"6666111\"}]}]", + "algorithmUpdateTime": 1776073208000, + "remark": "", + "nameI18nKey": "resource.param.15760.15760.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"PDA_00002\",\"actionName\":\"分割视觉大模型\",\"remark\":\"\",\"flowActionId\":\"ea49228d\",\"preFlowActionId\":\"b7fe1598\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"position\":\"ea49228d\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6666688\"},{\"key\":\"inputType\",\"value\":\"box\"}]},\"actionNameI18nKey\":\"resource.action.15760.pda_00002.ea49228d.actionname\"},{\"actionId\":\"PA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"b7fe1598\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.25],\"used\":true,\"position\":\"b7fe1598\",\"atomicCode\":\"6666111\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"6666111\",\"atomicName\":\"yolo26\",\"position\":\"b7fe1598\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.25],\"used\":true,\"position\":\"b7fe1598\",\"atomicCode\":\"6666111\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6666111\"}]},\"actionNameI18nKey\":\"resource.action.15760.pa_00001.b7fe1598.actionname\"}]", + "atomicList": "[{\"position\":\"ea49228d\",\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"labelList\":[]},{\"position\":\"b7fe1598\",\"atomicCode\":\"6666111\",\"atomicName\":\"yolo26\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.25],\"used\":true,\"position\":\"b7fe1598\",\"atomicCode\":\"6666111\"}]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.15760.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/15_\346\234\252\346\210\264\345\256\211\345\205\250\345\270\275_1767592983.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/15_\346\234\252\346\210\264\345\256\211\345\205\250\345\270\275_1767592983.json" new file mode 100644 index 000000000..ad6dd4b00 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/15_\346\234\252\346\210\264\345\256\211\345\205\250\345\270\275_1767592983.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 15, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"安全帽置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedSafeHelmet.confidence\",\"name\":\"安全帽置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_pedsafehelmet_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_pedsafehelmet_confidence.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_pedsafehelmet_confidence.name\"},{\"defaultValue\":\"1,0\",\"description\":\"安全帽置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedSafeHelmet.confidenceConfig\",\"name\":\"安全帽置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"1,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_pedsafehelmet_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.15.15.aiparam_pedsafehelmet_confidenceconfig.name\"},{\"defaultValue\":\"60\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"failedTip\":\"请输入1-36000的整数\",\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.15.15.param_targetalarminterval.name\"},{\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"failedTip\":\"请输入0-100的整数\",\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.15.15.param_targetalarmcount.name\"},{\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.15.15.param_restrainswitch.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.15.15.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.15.15.param_restraintime.param_restrainswitch.1.name\"},{\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"senior\":1,\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.15.15.param_overlaytrajectory.name\"},{\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedestrian.confidence\",\"name\":\"行人置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_pedestrian_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedestrian.confidenceConfig\",\"name\":\"行人置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.15.15.aiparam_pedestrian_confidenceconfig.name\"},{\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.pedestrian.detPostion\",\"name\":\"行人检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.15.15.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.15.15.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.15.15.aiparam_pedestrian_detpostion.2.options_name\"}],\"senior\":0,\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_pedestrian_detpostion.name\"},{\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"failedTip\":\"请输入0-100的两位小数\",\"key\":\"aiParam.1001003.trackDynamicMatch\",\"name\":\"行人检测追踪半径\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_1001003_trackdynamicmatch.name\"},{\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"failedTip\":\"请输入2-100的整数\",\"key\":\"aiParam.1001003.frames\",\"name\":\"行人检测追踪历史帧数\",\"senior\":1,\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_1001003_frames.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_1001003_frames.name\"},{\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"failedTip\":\"请输入1-99的一位小数\",\"key\":\"aiParam.1001003.motion\",\"name\":\"行人检测静止阈值\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"80.0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_1001003_motion.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_1001003_motion.name\"},{\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"failedTip\":\"请输入0-10000的整数\",\"key\":\"filter.pedestrian.side.min\",\"name\":\"最小行人尺寸\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.15.15.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.15.15.filter_pedestrian_side_min.name\"},{\"defaultValue\":\"\",\"description\":\"头盔置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedHelmet.confidence\",\"name\":\"头盔置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_pedhelmet_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_pedhelmet_confidence.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_pedhelmet_confidence.name\"},{\"defaultValue\":\"1,0\",\"description\":\"头盔置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedHelmet.confidenceConfig\",\"name\":\"头盔置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"1,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_pedhelmet_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.15.15.aiparam_pedhelmet_confidenceconfig.name\"},{\"defaultValue\":\"\",\"description\":\"无帽置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.hatless.confidence\",\"name\":\"无帽置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_hatless_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_hatless_confidence.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_hatless_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"无帽置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.hatless.confidenceConfig\",\"name\":\"无帽置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_hatless_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.15.15.aiparam_hatless_confidenceconfig.name\"},{\"defaultValue\":\"\",\"description\":\"不确定置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.unsure.confidence\",\"name\":\"不确定置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_unsure_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.15.aiparam_unsure_confidence.failedtip\",\"nameI18nKey\":\"resource.param.15.15.aiparam_unsure_confidence.name\"},{\"defaultValue\":\"1,0\",\"description\":\"不确定置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.unsure.confidenceConfig\",\"name\":\"不确定置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"1,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.aiparam_unsure_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.15.15.aiparam_unsure_confidenceconfig.name\"},{\"defaultValue\":\"2\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"failedTip\":\"请输入1-10的整数\",\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"type\":\"slider\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.15.15.param_sensitivity.name\"},{\"defaultValue\":\"3\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"failedTip\":\"请输入1-3600的整数\",\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"type\":\"text\",\"value\":\"3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.15.15.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.15.15.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.15.15.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.15.15.name.description\",\"failedTipI18nKey\":\"resource.param.15.15.name.failedtip\",\"nameI18nKey\":\"resource.param.15.15.name.name\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "未戴安全帽", + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"3b63e86f\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.15.ba_00001.3b63e86f.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00001.3b63e86f.remark\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"83b4eb95\",\"preFlowActionId\":\"3b63e86f\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.15.aa_00001.83b4eb95.1001003.0.pedestrian.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"行人置信度\",\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"行人置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"行人检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"行人检测\",\"position\":\"83b4eb95\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.15.aa_00001.83b4eb95.1001003.0.pedestrian.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00001.83b4eb95.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00001.83b4eb95.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"e1a418ab\",\"preFlowActionId\":\"83b4eb95\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.frames\",\"value\":\"10\",\"name\":\"行人检测追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.failedtip\"},{\"key\":\"aiParam.1001003.motion\",\"value\":\"80.0\",\"name\":\"行人检测静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.failedtip\"},{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"1\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00003.e1a418ab.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00003.e1a418ab.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"66fe69a4\",\"preFlowActionId\":\"e1a418ab\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"confidenceValue\":\"1\",\"position\":\"83b4eb95\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.15.ba_00002.66fe69a4.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00002.66fe69a4.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"检测目标送分类算法,需要选择一个分类模型\",\"flowActionId\":\"a0333a67\",\"preFlowActionId\":\"66fe69a4\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"threshold\":[0.39,0.39],\"nameCN\":\"头盔\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.aa_00002.a0333a67.2001036.0.pedhelmet.namecn\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"threshold\":[0.1,0.1],\"nameCN\":\"安全帽\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.aa_00002.a0333a67.2001036.1.pedsafehelmet.namecn\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"threshold\":[0.95,0.95],\"nameCN\":\"无帽\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.aa_00002.a0333a67.2001036.3.hatless.namecn\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"threshold\":[0.3,0.3],\"nameCN\":\"不确定\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.aa_00002.a0333a67.2001036.4.unsure.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedHelmet.confidence\",\"value\":\"\",\"name\":\"头盔置信度\",\"defaultValue\":\"\",\"description\":\"头盔置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.failedtip\"},{\"key\":\"aiParam.pedHelmet.confidenceConfig\",\"value\":\"\",\"name\":\"头盔置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"头盔置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidenceconfig.description\"},{\"key\":\"aiParam.pedSafeHelmet.confidence\",\"value\":\"\",\"name\":\"安全帽置信度\",\"defaultValue\":\"\",\"description\":\"安全帽置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.failedtip\"},{\"key\":\"aiParam.pedSafeHelmet.confidenceConfig\",\"value\":\"\",\"name\":\"安全帽置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"安全帽置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidenceconfig.description\"},{\"key\":\"aiParam.hatless.confidence\",\"value\":\"\",\"name\":\"无帽置信度\",\"defaultValue\":\"\",\"description\":\"无帽置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.failedtip\"},{\"key\":\"aiParam.hatless.confidenceConfig\",\"value\":\"\",\"name\":\"无帽置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"无帽置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidenceconfig.description\"},{\"key\":\"aiParam.unsure.confidence\",\"value\":\"\",\"name\":\"不确定置信度\",\"defaultValue\":\"\",\"description\":\"不确定置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.description\",\"failedTipI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.failedtip\"},{\"key\":\"aiParam.unsure.confidenceConfig\",\"value\":\"\",\"name\":\"不确定置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"不确定置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2001036\",\"atomicName\":\"行人安全帽检测\",\"position\":\"a0333a67\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"threshold\":[0.39,0.39],\"nameCN\":\"头盔\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.aa_00002.a0333a67.2001036.0.pedhelmet.namecn\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"threshold\":[0.1,0.1],\"nameCN\":\"安全帽\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.aa_00002.a0333a67.2001036.1.pedsafehelmet.namecn\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"threshold\":[0.95,0.95],\"nameCN\":\"无帽\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.aa_00002.a0333a67.2001036.3.hatless.namecn\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"threshold\":[0.3,0.3],\"nameCN\":\"不确定\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.aa_00002.a0333a67.2001036.4.unsure.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2001036\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.15.aa_00002.a0333a67.actionname\",\"remarkI18nKey\":\"resource.action.15.aa_00002.a0333a67.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"0d105731\",\"preFlowActionId\":\"a0333a67\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"type\":1,\"list\":[{\"type\":2,\"list\":[{\"key\":\"1534a222\",\"keyL\":\"aiOut.hatless.threshold\",\"keyR\":\"aiParam.hatless.confidence\",\"type\":14,\"list\":[],\"showTools\":false,\"level\":3,\"rightType\":\"select\"},{\"key\":\"cbdfa9ec\",\"keyL\":\"aiOut.unsure.threshold\",\"keyR\":\"aiParam.unsure.confidence\",\"type\":15,\"list\":[],\"showTools\":false,\"level\":3,\"rightType\":\"select\"}],\"showTools\":false,\"level\":2,\"rightType\":\"select\"},{\"type\":2,\"list\":[{\"key\":\"befb6c82\",\"keyL\":\"aiOut.hatless.threshold\",\"keyR\":\"aiParam.hatless.confidence\",\"type\":15,\"list\":[],\"showTools\":false,\"level\":3,\"rightType\":\"select\"},{\"key\":\"1dce35d2\",\"keyL\":\"aiOut.pedHelmet.threshold\",\"keyR\":\"aiParam.pedHelmet.confidence\",\"type\":15,\"list\":[],\"showTools\":false,\"level\":3,\"rightType\":\"select\"},{\"key\":\"c6130512\",\"keyL\":\"aiOut.pedSafeHelmet.threshold\",\"keyR\":\"aiParam.pedSafeHelmet.confidence\",\"type\":15,\"list\":[],\"showTools\":false,\"level\":3,\"rightType\":\"select\"},{\"key\":\"59adbdaf\",\"keyL\":\"aiOut.unsure.threshold\",\"keyR\":\"aiParam.unsure.confidence\",\"type\":15,\"list\":[],\"showTools\":false,\"level\":3,\"rightType\":\"select\"}],\"showTools\":false,\"level\":2,\"rightType\":\"select\"}],\"showTools\":false,\"level\":1,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.15.ba_90001.0d105731.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_90001.0d105731.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"4fb8d95e\",\"preFlowActionId\":\"b4b02c33\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"3\",\"position\":\"4fb8d95e\",\"nameI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"1\",\"position\":\"4fb8d95e\",\"nameI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"4fb8d95e\",\"nameI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"4fb8d95e\",\"nameI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"4fb8d95e\",\"nameI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"4fb8d95e\",\"nameI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.15.ba_00004.4fb8d95e.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00004.4fb8d95e.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"b4b02c33\",\"preFlowActionId\":\"0d105731\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"b4b02c33\",\"nameI18nKey\":\"resource.param.15.ba_00003.b4b02c33.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00003.b4b02c33.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00003.b4b02c33.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"value\":\"2\",\"position\":\"b4b02c33\",\"nameI18nKey\":\"resource.param.15.ba_00003.b4b02c33.param_detectionduration.name\",\"descriptionI18nKey\":\"resource.param.15.ba_00003.b4b02c33.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.15.ba_00003.b4b02c33.param_detectionduration.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.15.ba_00003.b4b02c33.actionname\",\"remarkI18nKey\":\"resource.action.15.ba_00003.b4b02c33.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1767592983474", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"83b4eb95\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.15.15.1001003.0.pedestrian.namecn\"}],\"atomicName\":\"行人检测\",\"categoriesLabelList\":[],\"atomicCode\":\"1001003\",\"position\":\"83b4eb95\"},{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"threshold\":[0.39,0.39],\"nameCN\":\"头盔\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.15.2001036.0.pedhelmet.namecn\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"threshold\":[0.1,0.1],\"nameCN\":\"安全帽\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.15.2001036.1.pedsafehelmet.namecn\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"threshold\":[0.95,0.95],\"nameCN\":\"无帽\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.15.2001036.3.hatless.namecn\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"threshold\":[0.3,0.3],\"nameCN\":\"不确定\",\"used\":true,\"position\":\"a0333a67\",\"atomicCode\":\"2001036\",\"nameCNI18nKey\":\"resource.param.15.15.2001036.4.unsure.namecn\"}],\"atomicName\":\"行人安全帽检测\",\"categoriesLabelList\":[],\"atomicCode\":\"2001036\",\"position\":\"a0333a67\"}]", + "checkType": 6, + "confVersionId": "79c9d9bdf07445048b57602e1dce6b6e", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1765505466000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 15, + "gafAlgorithmName": "SafetyHat", + "id": "15", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior006", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用头肩检测、跟踪算法、安全帽分类算法,进行人员是否带安全帽的检测,并进行未带安全帽的预警。安全帽颜色有:红、蓝、黄、白、黑。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1767592983000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.15.algorithmname", + "remarkI18nKey": "resource.algorithm.15.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/16_\347\246\273\345\262\227\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/16_\347\246\273\345\262\227\346\243\200\346\265\213_1759134672.json" new file mode 100644 index 000000000..1d2556c7b --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/16_\347\246\273\345\262\227\346\243\200\346\265\213_1759134672.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 16, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":{\"key\":\"custom.detection\",\"value\":\"0\"},\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.description\",\"failedTipI18nKey\":\"resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.failedtip\",\"nameI18nKey\":\"resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":{\"key\":\"custom.detection\",\"value\":\"0\"},\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.description\",\"failedTipI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.failedtip\",\"nameI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.name\"},{\"beginValue\":null,\"defaultValue\":\"1,0\",\"dependsOn\":{\"key\":\"custom.detection\",\"value\":\"0\"},\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"1,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidenceconfig.custom_detection.0.description\",\"nameI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidenceconfig.custom_detection.0.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":{\"key\":\"custom.detection\",\"value\":\"0\"},\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.16.16.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.16.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.16.16.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.description\",\"failedTipI18nKey\":\"resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.failedtip\",\"nameI18nKey\":\"resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.alarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_alarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"区域中的目标数\",\"endValue\":null,\"failedTip\":\"请输入0-3600的整数\",\"group\":null,\"key\":\"param.areaLimitTargetCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"区域中的目标数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_arealimittargetcount.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_arealimittargetcount.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_arealimittargetcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"区域中目标数限制类型\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"param.areaLimitTargetType\",\"maxValue\":null,\"minValue\":null,\"name\":\"区域中目标数限制类型\",\"negative\":null,\"options\":[{\"name\":\"小于目标数告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.0.options_name\"},{\"name\":\"大于目标数告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.1.options_name\"},{\"name\":\"小于等于目标数告警\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.2.options_name\"},{\"name\":\"大于等于目标数告警\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.3.options_name\"},{\"name\":\"等于目标数告警\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.4.options_name\"}],\"range\":null,\"senior\":1,\"regexpr\":\"/^[0-4]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_arealimittargettype.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_arealimittargettype.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_arealimittargettype.name\"},{\"beginValue\":null,\"defaultValue\":\"10\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"endValue\":null,\"failedTip\":\"请输入正确的数值\",\"group\":null,\"key\":\"param.areaLimitDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_arealimitduration.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_arealimitduration.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_arealimitduration.name\"},{\"beginValue\":null,\"defaultValue\":\"1000\",\"dependsOn\":null,\"description\":\"检测时间单位\",\"endValue\":null,\"failedTip\":\"请选择正确的数值\",\"group\":null,\"key\":\"param.areaLimitDurationTimeType\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间单位\",\"negative\":null,\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.16.param_arealimitdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.16.16.param_arealimitdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.16.16.param_arealimitdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.16.16.param_arealimitdurationtimetype.3600000.options_name\"}],\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"select\",\"value\":\"1000\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_arealimitdurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_arealimitdurationtimetype.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_arealimitdurationtimetype.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.16.16.name.description\",\"failedTipI18nKey\":\"resource.param.16.16.name.failedtip\",\"nameI18nKey\":\"resource.param.16.16.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "离岗检测", + "algorithmProcessdata": "[{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"72ec426d\",\"preFlowActionId\":\"bc4f4b27\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"bc4f4b27\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.16.ba_00002.72ec426d.actionname\",\"remarkI18nKey\":\"resource.action.16.ba_00002.72ec426d.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"fdc4d661\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.16.ba_00001.fdc4d661.actionname\",\"remarkI18nKey\":\"resource.action.16.ba_00001.fdc4d661.remark\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"bc4f4b27\",\"preFlowActionId\":\"fdc4d661\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"bc4f4b27\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.16.aa_00001.bc4f4b27.actionname\",\"remarkI18nKey\":\"resource.action.16.aa_00001.bc4f4b27.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"f0c9e210\",\"preFlowActionId\":\"ab935f8a\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.16.ba_00004.f0c9e210.actionname\",\"remarkI18nKey\":\"resource.action.16.ba_00004.f0c9e210.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"ab935f8a\",\"preFlowActionId\":\"72ec426d\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.areaLimitTargetCount\",\"name\":\"目标数量阈值\",\"defaultValue\":\"0\",\"description\":\"用于和区域内实际有效目标数量进行比较的阈值\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入0-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"value\":\"0\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"区域中目标数限制类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.areaLimitTargetType\",\"name\":\"触发条件\",\"options\":[{\"name\":\"小于目标数告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.0.options_name\"},{\"name\":\"大于目标数告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.1.options_name\"},{\"name\":\"小于等于目标数告警\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.2.options_name\"},{\"name\":\"大于等于目标数告警\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.3.options_name\"},{\"name\":\"等于目标数告警\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.4.options_name\"}],\"regexpr\":\"/^[0-4]$/\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":1,\"value\":\"0\",\"position\":\"ab935f8a\",\"descriptionI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.failedtip\",\"nameI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.name\"},{\"key\":\"param.areaLimitDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"value\":\"0\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.failedtip\"},{\"key\":\"param.areaLimitDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"value\":\"1000\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"0\"},{\"key\":\"inputAreaType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.16.ba_00005.ab935f8a.actionname\",\"remarkI18nKey\":\"resource.action.16.ba_00005.ab935f8a.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758685398590", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\"}]}]", + "checkType": 16, + "confVersionId": "77d349f6db4348d9be2cd4ed5b0e3b74", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 16, + "gafAlgorithmName": "Leave", + "id": "16", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior008", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用头肩检测或人体检测算法,对区域内人员数量进行计数,如少于相应的人数且时间超过设定的阈值,则进行告警。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758685399000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "77d349f6db4348d9be2cd4ed5b0e3b74", + "name": "默认", + "algorithmCode": 16, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":{\"key\":\"custom.detection\",\"value\":\"0\"},\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.description\",\"failedTipI18nKey\":\"resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.failedtip\",\"nameI18nKey\":\"resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":{\"key\":\"custom.detection\",\"value\":\"0\"},\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.description\",\"failedTipI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.failedtip\",\"nameI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.name\"},{\"beginValue\":null,\"defaultValue\":\"1,0\",\"dependsOn\":{\"key\":\"custom.detection\",\"value\":\"0\"},\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"1,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidenceconfig.custom_detection.0.description\",\"nameI18nKey\":\"resource.param.16.16.aiparam_pedestrian_confidenceconfig.custom_detection.0.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":{\"key\":\"custom.detection\",\"value\":\"0\"},\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.16.16.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.16.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.16.16.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.description\",\"failedTipI18nKey\":\"resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.failedtip\",\"nameI18nKey\":\"resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.alarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_alarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"区域中的目标数\",\"endValue\":null,\"failedTip\":\"请输入0-3600的整数\",\"group\":null,\"key\":\"param.areaLimitTargetCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"区域中的目标数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_arealimittargetcount.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_arealimittargetcount.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_arealimittargetcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"区域中目标数限制类型\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"param.areaLimitTargetType\",\"maxValue\":null,\"minValue\":null,\"name\":\"区域中目标数限制类型\",\"negative\":null,\"options\":[{\"name\":\"小于目标数告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.0.options_name\"},{\"name\":\"大于目标数告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.1.options_name\"},{\"name\":\"小于等于目标数告警\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.2.options_name\"},{\"name\":\"大于等于目标数告警\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.3.options_name\"},{\"name\":\"等于目标数告警\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.16.16.param_arealimittargettype.4.options_name\"}],\"range\":null,\"senior\":1,\"regexpr\":\"/^[0-4]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_arealimittargettype.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_arealimittargettype.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_arealimittargettype.name\"},{\"beginValue\":null,\"defaultValue\":\"10\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"endValue\":null,\"failedTip\":\"请输入正确的数值\",\"group\":null,\"key\":\"param.areaLimitDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_arealimitduration.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_arealimitduration.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_arealimitduration.name\"},{\"beginValue\":null,\"defaultValue\":\"1000\",\"dependsOn\":null,\"description\":\"检测时间单位\",\"endValue\":null,\"failedTip\":\"请选择正确的数值\",\"group\":null,\"key\":\"param.areaLimitDurationTimeType\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间单位\",\"negative\":null,\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.16.param_arealimitdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.16.16.param_arealimitdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.16.16.param_arealimitdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.16.16.param_arealimitdurationtimetype.3600000.options_name\"}],\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"select\",\"value\":\"1000\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.16.16.param_arealimitdurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.16.16.param_arealimitdurationtimetype.failedtip\",\"nameI18nKey\":\"resource.param.16.16.param_arealimitdurationtimetype.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.16.16.name.description\",\"failedTipI18nKey\":\"resource.param.16.16.name.failedtip\",\"nameI18nKey\":\"resource.param.16.16.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmProcessdata": "[{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"72ec426d\",\"preFlowActionId\":\"bc4f4b27\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"bc4f4b27\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.16.ba_00002.72ec426d.actionname\",\"remarkI18nKey\":\"resource.action.16.ba_00002.72ec426d.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"fdc4d661\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.16.ba_00001.fdc4d661.actionname\",\"remarkI18nKey\":\"resource.action.16.ba_00001.fdc4d661.remark\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"bc4f4b27\",\"preFlowActionId\":\"fdc4d661\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"bc4f4b27\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.16.aa_00001.bc4f4b27.actionname\",\"remarkI18nKey\":\"resource.action.16.aa_00001.bc4f4b27.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"f0c9e210\",\"preFlowActionId\":\"ab935f8a\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00004.f0c9e210.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.16.ba_00004.f0c9e210.actionname\",\"remarkI18nKey\":\"resource.action.16.ba_00004.f0c9e210.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"ab935f8a\",\"preFlowActionId\":\"72ec426d\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.areaLimitTargetCount\",\"name\":\"目标数量阈值\",\"defaultValue\":\"0\",\"description\":\"用于和区域内实际有效目标数量进行比较的阈值\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入0-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"value\":\"0\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"区域中目标数限制类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.areaLimitTargetType\",\"name\":\"触发条件\",\"options\":[{\"name\":\"小于目标数告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.0.options_name\"},{\"name\":\"大于目标数告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.1.options_name\"},{\"name\":\"小于等于目标数告警\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.2.options_name\"},{\"name\":\"大于等于目标数告警\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.3.options_name\"},{\"name\":\"等于目标数告警\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.4.options_name\"}],\"regexpr\":\"/^[0-4]$/\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":1,\"value\":\"0\",\"position\":\"ab935f8a\",\"descriptionI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.failedtip\",\"nameI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.name\"},{\"key\":\"param.areaLimitDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"value\":\"0\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.failedtip\"},{\"key\":\"param.areaLimitDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"value\":\"1000\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"0\"},{\"key\":\"inputAreaType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.16.ba_00005.ab935f8a.actionname\",\"remarkI18nKey\":\"resource.action.16.ba_00005.ab935f8a.remark\"}]", + "atomicList": "[{\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\"}]}]", + "algorithmUpdateTime": 1776927766000, + "nameI18nKey": "resource.param.16.16.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.16.algorithmname", + "remarkI18nKey": "resource.algorithm.16.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/21283_\350\247\206\350\247\211\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175841.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/21283_\350\247\206\350\247\211\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175841.json" new file mode 100644 index 000000000..74f2d3cba --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/21283_\350\247\206\350\247\211\345\210\206\345\211\262\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175841.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "21283", + "algorithmCode": 21283, + "algorithmName": "视觉分割大模型分析", + "algorithmCategory": 2, + "algorithmUsage": 1, + "checkType": 29202, + "createTime": 1776074321000, + "updateTime": 1776074321000, + "confVersionId": "default-21283", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.21283.21283.name.description\",\"failedTipI18nKey\":\"resource.param.21283.21283.name.failedtip\",\"nameI18nKey\":\"resource.param.21283.21283.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-21283", + "name": "默认", + "algorithmCode": "21283", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.21283.21283.name.description\",\"failedTipI18nKey\":\"resource.param.21283.21283.name.failedtip\",\"nameI18nKey\":\"resource.param.21283.21283.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"\",\"flowActionId\":\"f865585c\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.21283.ba_00001.f865585c.actionname\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"4f8ba85c\",\"preFlowActionId\":\"f865585c\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"4f8ba85c\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"4f8ba85c\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"4f8ba85c\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"5\"}]},\"actionNameI18nKey\":\"resource.action.21283.aa_00001.4f8ba85c.actionname\"},{\"actionId\":\"DA_00002\",\"actionName\":\"分割视觉大模型\",\"remark\":\"\",\"flowActionId\":\"e9ee0bc1\",\"preFlowActionId\":\"4f8ba85c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"position\":\"e9ee0bc1\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6666688\"},{\"key\":\"fps\",\"value\":\"1\"},{\"key\":\"inputType\",\"value\":\"box\"}]},\"actionNameI18nKey\":\"resource.action.21283.da_00002.e9ee0bc1.actionname\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"\",\"flowActionId\":\"308335b0\",\"preFlowActionId\":\"e9ee0bc1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"5\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"detectBreakAreaType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.21283.ba_00005.308335b0.actionname\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"\",\"flowActionId\":\"fd4e2090\",\"preFlowActionId\":\"308335b0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"fd4e2090\",\"nameI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"fd4e2090\",\"nameI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"fd4e2090\",\"nameI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"fd4e2090\",\"nameI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.21283.ba_00004.fd4e2090.actionname\"}]", + "atomicList": "[{\"position\":\"4f8ba85c\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"4f8ba85c\",\"atomicCode\":\"1001003\"}]},{\"position\":\"e9ee0bc1\",\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"labelList\":[]}]", + "algorithmUpdateTime": 1776074541000, + "remark": "", + "nameI18nKey": "resource.param.21283.21283.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"\",\"flowActionId\":\"f865585c\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.21283.ba_00001.f865585c.actionname\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"4f8ba85c\",\"preFlowActionId\":\"f865585c\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"4f8ba85c\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"4f8ba85c\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"4f8ba85c\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"5\"}]},\"actionNameI18nKey\":\"resource.action.21283.aa_00001.4f8ba85c.actionname\"},{\"actionId\":\"DA_00002\",\"actionName\":\"分割视觉大模型\",\"remark\":\"\",\"flowActionId\":\"e9ee0bc1\",\"preFlowActionId\":\"4f8ba85c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"position\":\"e9ee0bc1\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6666688\"},{\"key\":\"fps\",\"value\":\"1\"},{\"key\":\"inputType\",\"value\":\"box\"}]},\"actionNameI18nKey\":\"resource.action.21283.da_00002.e9ee0bc1.actionname\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"\",\"flowActionId\":\"308335b0\",\"preFlowActionId\":\"e9ee0bc1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"5\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"detectBreakAreaType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.21283.ba_00005.308335b0.actionname\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"\",\"flowActionId\":\"fd4e2090\",\"preFlowActionId\":\"308335b0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"fd4e2090\",\"nameI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"fd4e2090\",\"nameI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"fd4e2090\",\"nameI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"fd4e2090\",\"nameI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.21283.ba_00004.fd4e2090.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.21283.ba_00004.fd4e2090.actionname\"}]", + "atomicList": "[{\"position\":\"4f8ba85c\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"4f8ba85c\",\"atomicCode\":\"1001003\"}]},{\"position\":\"e9ee0bc1\",\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"labelList\":[]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.21283.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/22_\347\216\251\346\211\213\346\234\272\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/22_\347\216\251\346\211\213\346\234\272\346\243\200\346\265\213_1759134672.json" new file mode 100644 index 000000000..3800d2efa --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/22_\347\216\251\346\211\213\346\234\272\346\243\200\346\265\213_1759134672.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 22, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.22.22.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.22.22.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.22.22.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.22.22.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.22.22.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.22.22.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"玩手机置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedPhonePlay.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"玩手机置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidence.description\",\"failedTipI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidence.failedtip\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"玩手机置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedPhonePlay.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"玩手机置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.22.22.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.22.22.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.22.22.name.description\",\"failedTipI18nKey\":\"resource.param.22.22.name.failedtip\",\"nameI18nKey\":\"resource.param.22.22.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "玩手机检测", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"487c1cf0\",\"preFlowActionId\":\"df5884a8\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"487c1cf0\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.22.aa_00001.487c1cf0.actionname\",\"remarkI18nKey\":\"resource.action.22.aa_00001.487c1cf0.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"c232a753\",\"preFlowActionId\":\"487c1cf0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.22.aa_00003.c232a753.actionname\",\"remarkI18nKey\":\"resource.action.22.aa_00003.c232a753.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"c37b8e34\",\"preFlowActionId\":\"ffac0ae1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"2\",\"class_name\":\"pedPhonePlay\",\"nameCN\":\"pedPhonePlay\",\"threshold\":[0.9700000286102295],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedPhonePlay.confidence\",\"value\":\"\",\"name\":\"pedPhonePlay置信度\",\"defaultValue\":\"\",\"description\":\"pedPhonePlay置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.description\",\"failedTipI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.failedtip\"},{\"key\":\"aiParam.pedPhonePlay.confidenceConfig\",\"value\":\"\",\"name\":\"pedPhonePlay置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedPhonePlay置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2002011\",\"atomicName\":\"PhoneSmoking\",\"position\":\"c37b8e34\",\"labelList\":[{\"label\":\"2\",\"class_name\":\"pedPhonePlay\",\"nameCN\":\"pedPhonePlay\",\"threshold\":[0.9700000286102295],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2002011\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.22.aa_00002.c37b8e34.actionname\",\"remarkI18nKey\":\"resource.action.22.aa_00002.c37b8e34.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"e02bf44c\",\"preFlowActionId\":\"c37b8e34\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"1895e8bc\",\"level\":1,\"type\":14,\"keyL\":\"aiOut.pedPhonePlay.threshold\",\"keyR\":\"aiParam.pedPhonePlay.confidence\",\"list\":[],\"showTools\":false,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.22.ba_90001.e02bf44c.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_90001.e02bf44c.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"0f53b331\",\"preFlowActionId\":\"181f8b5a\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.22.ba_00004.0f53b331.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_00004.0f53b331.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"ffac0ae1\",\"preFlowActionId\":\"c232a753\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"487c1cf0\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.22.ba_00002.ffac0ae1.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_00002.ffac0ae1.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"df5884a8\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.22.ba_00001.df5884a8.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_00001.df5884a8.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"灵敏度计算\",\"flowActionId\":\"181f8b5a\",\"preFlowActionId\":\"e02bf44c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"181f8b5a\",\"nameI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"181f8b5a\",\"nameI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.22.ba_00003.181f8b5a.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_00003.181f8b5a.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758692982874", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}]},{\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\",\"atomicName\":\"PhoneSmoking\",\"labelList\":[{\"label\":\"2\",\"class_name\":\"pedPhonePlay\",\"nameCN\":\"pedPhonePlay\",\"threshold\":[0.9700000286102295],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}]}]", + "checkType": 7, + "confVersionId": "ca42bd63f90b4691b13450e412408626", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 22, + "gafAlgorithmName": "PlayPhone", + "id": "22", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior009", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用行人检测跟踪算法、玩手机分类算法,对进入检测区域的行人进行玩手机检测,对超过阈值时间的行人进行玩手机告警。玩手机算法,对玩手机姿态、电话进行同时分析。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758692983000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "ca42bd63f90b4691b13450e412408626", + "name": "默认", + "algorithmCode": 22, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.22.22.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.22.22.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.22.22.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.22.22.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.22.22.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.22.22.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"玩手机置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedPhonePlay.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"玩手机置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidence.description\",\"failedTipI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidence.failedtip\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"玩手机置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedPhonePlay.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"玩手机置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.22.22.aiparam_pedphoneplay_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.22.22.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.22.22.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.22.22.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.22.22.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.22.22.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.22.22.name.description\",\"failedTipI18nKey\":\"resource.param.22.22.name.failedtip\",\"nameI18nKey\":\"resource.param.22.22.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"487c1cf0\",\"preFlowActionId\":\"df5884a8\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"487c1cf0\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.22.aa_00001.487c1cf0.actionname\",\"remarkI18nKey\":\"resource.action.22.aa_00001.487c1cf0.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"c232a753\",\"preFlowActionId\":\"487c1cf0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.22.aa_00003.c232a753.actionname\",\"remarkI18nKey\":\"resource.action.22.aa_00003.c232a753.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"c37b8e34\",\"preFlowActionId\":\"ffac0ae1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"2\",\"class_name\":\"pedPhonePlay\",\"nameCN\":\"pedPhonePlay\",\"threshold\":[0.9700000286102295],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedPhonePlay.confidence\",\"value\":\"\",\"name\":\"pedPhonePlay置信度\",\"defaultValue\":\"\",\"description\":\"pedPhonePlay置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.description\",\"failedTipI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.failedtip\"},{\"key\":\"aiParam.pedPhonePlay.confidenceConfig\",\"value\":\"\",\"name\":\"pedPhonePlay置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedPhonePlay置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2002011\",\"atomicName\":\"PhoneSmoking\",\"position\":\"c37b8e34\",\"labelList\":[{\"label\":\"2\",\"class_name\":\"pedPhonePlay\",\"nameCN\":\"pedPhonePlay\",\"threshold\":[0.9700000286102295],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2002011\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.22.aa_00002.c37b8e34.actionname\",\"remarkI18nKey\":\"resource.action.22.aa_00002.c37b8e34.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"e02bf44c\",\"preFlowActionId\":\"c37b8e34\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"1895e8bc\",\"level\":1,\"type\":14,\"keyL\":\"aiOut.pedPhonePlay.threshold\",\"keyR\":\"aiParam.pedPhonePlay.confidence\",\"list\":[],\"showTools\":false,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.22.ba_90001.e02bf44c.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_90001.e02bf44c.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"0f53b331\",\"preFlowActionId\":\"181f8b5a\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.22.ba_00004.0f53b331.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_00004.0f53b331.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"ffac0ae1\",\"preFlowActionId\":\"c232a753\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"487c1cf0\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.22.ba_00002.ffac0ae1.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_00002.ffac0ae1.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"df5884a8\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.22.ba_00001.df5884a8.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_00001.df5884a8.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"灵敏度计算\",\"flowActionId\":\"181f8b5a\",\"preFlowActionId\":\"e02bf44c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"181f8b5a\",\"nameI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"181f8b5a\",\"nameI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.22.ba_00003.181f8b5a.actionname\",\"remarkI18nKey\":\"resource.action.22.ba_00003.181f8b5a.remark\"}]", + "atomicList": "[{\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}]},{\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\",\"atomicName\":\"PhoneSmoking\",\"labelList\":[{\"label\":\"2\",\"class_name\":\"pedPhonePlay\",\"nameCN\":\"pedPhonePlay\",\"threshold\":[0.9700000286102295],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002011\"}]}]", + "algorithmUpdateTime": 1776924687000, + "nameI18nKey": "resource.param.22.22.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.22.algorithmname", + "remarkI18nKey": "resource.algorithm.22.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/2935_\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213_20260413173822.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/2935_\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213_20260413173822.json" new file mode 100644 index 000000000..3719569e0 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/2935_\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213_20260413173822.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "2935", + "algorithmCode": 2935, + "algorithmName": "检测大模型", + "algorithmCategory": 2, + "algorithmUsage": 2, + "checkType": 10854, + "createTime": 1776073102000, + "updateTime": 1776073102000, + "confVersionId": "default-2935", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.2935.2935.name.description\",\"failedTipI18nKey\":\"resource.param.2935.2935.name.failedtip\",\"nameI18nKey\":\"resource.param.2935.2935.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-2935", + "name": "默认", + "algorithmCode": "2935", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.2935.2935.name.description\",\"failedTipI18nKey\":\"resource.param.2935.2935.name.failedtip\",\"nameI18nKey\":\"resource.param.2935.2935.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"PDA_00001\",\"actionName\":\"检测视觉大模型\",\"remark\":\"\",\"flowActionId\":\"0c349519\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"position\":\"0c349519\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888890\"},{\"key\":\"keywords\",\"value\":\"person\"},{\"key\":\"aiParam.box.confidence\",\"value\":\"0.25\"},{\"key\":\"aiParam.text.confidence\",\"value\":\"0.3\"}]},\"actionNameI18nKey\":\"resource.action.2935.pda_00001.0c349519.actionname\"}]", + "atomicList": "[{\"position\":\"0c349519\",\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"labelList\":[]}]", + "algorithmUpdateTime": 1776073620000, + "remark": "", + "nameI18nKey": "resource.param.2935.2935.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"PDA_00001\",\"actionName\":\"检测视觉大模型\",\"remark\":\"\",\"flowActionId\":\"0c349519\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"position\":\"0c349519\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888890\"},{\"key\":\"keywords\",\"value\":\"person\"},{\"key\":\"aiParam.box.confidence\",\"value\":\"0.25\"},{\"key\":\"aiParam.text.confidence\",\"value\":\"0.3\"}]},\"actionNameI18nKey\":\"resource.action.2935.pda_00001.0c349519.actionname\"}]", + "atomicList": "[{\"position\":\"0c349519\",\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"labelList\":[]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.2935.algorithmname" +} diff --git "a/data/resource/aiboxresource/algorithm_template/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" similarity index 100% rename from "data/resource/aiboxresource/algorithm_template/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" rename to "data/resource/aiboxresource_cv186x/algorithm_template/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/2_\344\272\272\350\204\270\350\257\206\345\210\253_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/2_\344\272\272\350\204\270\350\257\206\345\210\253_1759134672.json" new file mode 100644 index 000000000..d8eddd6f1 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/2_\344\272\272\350\204\270\350\257\206\345\210\253_1759134672.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 1, + "algorithmCode": 2, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"face置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.face.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"face置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_face_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_face_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_face_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.face.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"face置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_face_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_face_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.face.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"face检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.2.2.aiparam_face_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.2.2.aiparam_face_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.2.2.aiparam_face_detpostion.2.options_name\"}],\"range\":null,\"senior\":0,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_face_detpostion.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_face_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_face_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1000001.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"FaceRGBDetection追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_1000001_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_1000001_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_1000001_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"slantedFace置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.slantedFace.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"slantedFace置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"slantedFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.slantedFace.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"slantedFace置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"frontFace置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.frontFace.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"frontFace置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_frontface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_frontface_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_frontface_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.frontFace.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"frontFace置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_frontface_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_frontface_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"fullFace置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.fullFace.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"fullFace置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_fullface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_fullface_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_fullface_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.fullFace.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"fullFace置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_fullface_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_fullface_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"faceBlur0置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.faceBlur0.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur0置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"faceBlur0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.faceBlur0.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur0置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"faceBlur1置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.faceBlur1.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur1置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"faceBlur1置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.faceBlur1.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur1置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"faceBlur2置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.faceBlur2.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur2置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"faceBlur2置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.faceBlur2.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur2置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"选择需要比对的脸库分组\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"param.faceSet\",\"maxValue\":null,\"minValue\":null,\"name\":\"绑定人脸分组\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"faceSet\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_faceset.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_faceset.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_faceset.name\"},{\"beginValue\":null,\"defaultValue\":\"3\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":null,\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_overlaprate.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_overlaprate.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":null,\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_restraintime.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_restraintime.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小face尺寸:face抓拍照片的最小图像尺寸。如输入值为100,则最小face尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.face.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小face尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.filter_face_side_min.description\",\"failedTipI18nKey\":\"resource.param.2.2.filter_face_side_min.failedtip\",\"nameI18nKey\":\"resource.param.2.2.filter_face_side_min.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.2.2.name.description\",\"failedTipI18nKey\":\"resource.param.2.2.name.failedtip\",\"nameI18nKey\":\"resource.param.2.2.name.name\"}],\"areasTitle\":null},\"regionType\":\"quadrilateral\",\"scheduleSupport\":true,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":true}", + "algorithmName": "人脸比对", + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"\",\"flowActionId\":\"4874a700\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.2.ba_00001.4874a700.actionname\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"aaa71a68\",\"preFlowActionId\":\"4874a700\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"aaa71a68\",\"atomicCode\":\"1000001\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.face.confidence\",\"value\":\"\",\"name\":\"face置信度\",\"defaultValue\":\"\",\"description\":\"face置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.failedtip\"},{\"key\":\"aiParam.face.confidenceConfig\",\"value\":\"\",\"name\":\"face置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidenceconfig.description\"},{\"key\":\"aiParam.face.detPostion\",\"value\":\"0\",\"name\":\"face检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"position\":\"aaa71a68\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"aaa71a68\",\"atomicCode\":\"1000001\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000001\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"5\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00001.aaa71a68.actionname\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"\",\"flowActionId\":\"6f833257\",\"preFlowActionId\":\"aaa71a68\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1000001.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"FaceRGBDetection追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1000001\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00003.6f833257.actionname\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"\",\"flowActionId\":\"12564ac1\",\"preFlowActionId\":\"5c3ea492\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"slantedFace\",\"nameCN\":\"slantedFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"3\",\"class_name\":\"faceBlur0\",\"nameCN\":\"faceBlur0\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"4\",\"class_name\":\"faceBlur1\",\"nameCN\":\"faceBlur1\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"5\",\"class_name\":\"faceBlur2\",\"nameCN\":\"faceBlur2\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.slantedFace.confidence\",\"value\":\"\",\"name\":\"slantedFace置信度\",\"defaultValue\":\"\",\"description\":\"slantedFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.failedtip\"},{\"key\":\"aiParam.slantedFace.confidenceConfig\",\"value\":\"\",\"name\":\"slantedFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"slantedFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidenceconfig.description\"},{\"key\":\"aiParam.frontFace.confidence\",\"value\":\"\",\"name\":\"frontFace置信度\",\"defaultValue\":\"\",\"description\":\"frontFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.failedtip\"},{\"key\":\"aiParam.frontFace.confidenceConfig\",\"value\":\"\",\"name\":\"frontFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidenceconfig.description\"},{\"key\":\"aiParam.fullFace.confidence\",\"value\":\"\",\"name\":\"fullFace置信度\",\"defaultValue\":\"\",\"description\":\"fullFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.failedtip\"},{\"key\":\"aiParam.fullFace.confidenceConfig\",\"value\":\"\",\"name\":\"fullFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidenceconfig.description\"},{\"key\":\"aiParam.faceBlur0.confidence\",\"value\":\"\",\"name\":\"faceBlur0置信度\",\"defaultValue\":\"\",\"description\":\"faceBlur0置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.failedtip\"},{\"key\":\"aiParam.faceBlur0.confidenceConfig\",\"value\":\"\",\"name\":\"faceBlur0置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"faceBlur0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidenceconfig.description\"},{\"key\":\"aiParam.faceBlur1.confidence\",\"value\":\"\",\"name\":\"faceBlur1置信度\",\"defaultValue\":\"\",\"description\":\"faceBlur1置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.failedtip\"},{\"key\":\"aiParam.faceBlur1.confidenceConfig\",\"value\":\"\",\"name\":\"faceBlur1置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"faceBlur1置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidenceconfig.description\"},{\"key\":\"aiParam.faceBlur2.confidence\",\"value\":\"\",\"name\":\"faceBlur2置信度\",\"defaultValue\":\"\",\"description\":\"faceBlur2置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.failedtip\"},{\"key\":\"aiParam.faceBlur2.confidenceConfig\",\"value\":\"\",\"name\":\"faceBlur2置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"faceBlur2置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"1000012\",\"atomicName\":\"FaceQuality\",\"position\":\"12564ac1\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"slantedFace\",\"nameCN\":\"slantedFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"3\",\"class_name\":\"faceBlur0\",\"nameCN\":\"faceBlur0\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"4\",\"class_name\":\"faceBlur1\",\"nameCN\":\"faceBlur1\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"5\",\"class_name\":\"faceBlur2\",\"nameCN\":\"faceBlur2\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000012\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00002.12564ac1.actionname\"},{\"actionId\":\"AA_00005\",\"actionName\":\"特征提取算法\",\"remark\":\"\",\"flowActionId\":\"061f82a7\",\"preFlowActionId\":\"f225eab6\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"type\":\"faceSet\",\"description\":\"选择需要比对的脸库分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.faceSet\",\"name\":\"绑定人脸分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"0\"},\"level\":\"2\",\"regexpr\":\"\",\"value\":\"\",\"position\":\"061f82a7\",\"descriptionI18nKey\":\"resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.failedtip\",\"nameI18nKey\":\"resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.name\"}],\"atomic\":{\"atomicCode\":\"1000005\",\"atomicName\":\"FaceRGBRecognition\",\"position\":\"061f82a7\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000005\"},{\"key\":\"fps\",\"value\":\"-1\"},{\"key\":\"featureInput\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00005.061f82a7.actionname\"},{\"actionId\":\"AA_00004\",\"actionName\":\"关键点算法\",\"remark\":\"\",\"flowActionId\":\"f225eab6\",\"preFlowActionId\":\"12564ac1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"1000016\",\"atomicName\":\"FaceLandmark\",\"position\":\"f225eab6\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000016\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00004.f225eab6.actionname\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"\",\"flowActionId\":\"bdf891b9\",\"preFlowActionId\":\"061f82a7\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"1\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.2.ba_00004.bdf891b9.actionname\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别筛选\",\"remark\":\"\",\"flowActionId\":\"5c3ea492\",\"preFlowActionId\":\"6f833257\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"labelCode\":\"face\",\"labelName\":\"face\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"confidenceValue\":\"1\"}],\"metaDataParams\":[{\"key\":\"filter.face.side.min\",\"value\":\"60\",\"name\":\"最小face尺寸\",\"defaultValue\":\"60\",\"description\":\"最小face尺寸:face抓拍照片的最小图像尺寸。如输入值为100,则最小face尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.2.ba_00002.5c3ea492.filter_face_side_min.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00002.5c3ea492.filter_face_side_min.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00002.5c3ea492.filter_face_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.2.ba_00002.5c3ea492.actionname\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758699749133", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"aaa71a68\",\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"aaa71a68\",\"atomicCode\":\"1000001\"}]},{\"position\":\"12564ac1\",\"atomicCode\":\"1000012\",\"atomicName\":\"FaceQuality\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"slantedFace\",\"nameCN\":\"slantedFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"3\",\"class_name\":\"faceBlur0\",\"nameCN\":\"faceBlur0\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"4\",\"class_name\":\"faceBlur1\",\"nameCN\":\"faceBlur1\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"5\",\"class_name\":\"faceBlur2\",\"nameCN\":\"faceBlur2\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"}]},{\"position\":\"061f82a7\",\"atomicCode\":\"1000005\",\"atomicName\":\"FaceRGBRecognition\",\"labelList\":[]},{\"position\":\"f225eab6\",\"atomicCode\":\"1000016\",\"atomicName\":\"FaceLandmark\",\"labelList\":[]}]", + "checkType": 2, + "confVersionId": "default-59734", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "face", + "extraFormat": null, + "gafAlgorithmId": 2, + "gafAlgorithmName": "FaceRecognizer", + "id": "2", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_person002", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "人脸1比N比对,主要用于重点关注人员布控、陌生人提醒、人员久居未出、久出未归分析。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758699749000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "default-59734", + "name": "默认", + "algorithmCode": 2, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"face置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.face.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"face置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_face_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_face_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_face_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.face.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"face置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_face_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_face_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.face.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"face检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.2.2.aiparam_face_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.2.2.aiparam_face_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.2.2.aiparam_face_detpostion.2.options_name\"}],\"range\":null,\"senior\":0,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_face_detpostion.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_face_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_face_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1000001.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"FaceRGBDetection追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_1000001_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_1000001_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_1000001_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"slantedFace置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.slantedFace.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"slantedFace置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"slantedFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.slantedFace.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"slantedFace置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_slantedface_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"frontFace置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.frontFace.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"frontFace置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_frontface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_frontface_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_frontface_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.frontFace.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"frontFace置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_frontface_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_frontface_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"fullFace置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.fullFace.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"fullFace置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_fullface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_fullface_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_fullface_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.fullFace.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"fullFace置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_fullface_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_fullface_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"faceBlur0置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.faceBlur0.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur0置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"faceBlur0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.faceBlur0.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur0置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur0_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"faceBlur1置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.faceBlur1.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur1置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"faceBlur1置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.faceBlur1.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur1置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur1_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"faceBlur2置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.faceBlur2.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur2置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidence.failedtip\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"faceBlur2置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.faceBlur2.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"faceBlur2置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.2.2.aiparam_faceblur2_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"选择需要比对的脸库分组\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"param.faceSet\",\"maxValue\":null,\"minValue\":null,\"name\":\"绑定人脸分组\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"faceSet\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_faceset.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_faceset.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_faceset.name\"},{\"beginValue\":null,\"defaultValue\":\"3\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":null,\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_overlaprate.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_overlaprate.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":null,\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_restraintime.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_restraintime.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.2.2.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.2.2.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小face尺寸:face抓拍照片的最小图像尺寸。如输入值为100,则最小face尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.face.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小face尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.2.2.filter_face_side_min.description\",\"failedTipI18nKey\":\"resource.param.2.2.filter_face_side_min.failedtip\",\"nameI18nKey\":\"resource.param.2.2.filter_face_side_min.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.2.2.name.description\",\"failedTipI18nKey\":\"resource.param.2.2.name.failedtip\",\"nameI18nKey\":\"resource.param.2.2.name.name\"}],\"areasTitle\":null},\"regionType\":\"quadrilateral\",\"scheduleSupport\":true,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":true}", + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"\",\"flowActionId\":\"4874a700\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.2.ba_00001.4874a700.actionname\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"aaa71a68\",\"preFlowActionId\":\"4874a700\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"aaa71a68\",\"atomicCode\":\"1000001\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.face.confidence\",\"value\":\"\",\"name\":\"face置信度\",\"defaultValue\":\"\",\"description\":\"face置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.failedtip\"},{\"key\":\"aiParam.face.confidenceConfig\",\"value\":\"\",\"name\":\"face置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_confidenceconfig.description\"},{\"key\":\"aiParam.face.detPostion\",\"value\":\"0\",\"name\":\"face检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"position\":\"aaa71a68\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"aaa71a68\",\"atomicCode\":\"1000001\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000001\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"5\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00001.aaa71a68.actionname\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"\",\"flowActionId\":\"6f833257\",\"preFlowActionId\":\"aaa71a68\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1000001.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"FaceRGBDetection追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1000001\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00003.6f833257.actionname\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"\",\"flowActionId\":\"12564ac1\",\"preFlowActionId\":\"5c3ea492\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"slantedFace\",\"nameCN\":\"slantedFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"3\",\"class_name\":\"faceBlur0\",\"nameCN\":\"faceBlur0\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"4\",\"class_name\":\"faceBlur1\",\"nameCN\":\"faceBlur1\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"5\",\"class_name\":\"faceBlur2\",\"nameCN\":\"faceBlur2\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.slantedFace.confidence\",\"value\":\"\",\"name\":\"slantedFace置信度\",\"defaultValue\":\"\",\"description\":\"slantedFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.failedtip\"},{\"key\":\"aiParam.slantedFace.confidenceConfig\",\"value\":\"\",\"name\":\"slantedFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"slantedFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidenceconfig.description\"},{\"key\":\"aiParam.frontFace.confidence\",\"value\":\"\",\"name\":\"frontFace置信度\",\"defaultValue\":\"\",\"description\":\"frontFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.failedtip\"},{\"key\":\"aiParam.frontFace.confidenceConfig\",\"value\":\"\",\"name\":\"frontFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidenceconfig.description\"},{\"key\":\"aiParam.fullFace.confidence\",\"value\":\"\",\"name\":\"fullFace置信度\",\"defaultValue\":\"\",\"description\":\"fullFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.failedtip\"},{\"key\":\"aiParam.fullFace.confidenceConfig\",\"value\":\"\",\"name\":\"fullFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidenceconfig.description\"},{\"key\":\"aiParam.faceBlur0.confidence\",\"value\":\"\",\"name\":\"faceBlur0置信度\",\"defaultValue\":\"\",\"description\":\"faceBlur0置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.failedtip\"},{\"key\":\"aiParam.faceBlur0.confidenceConfig\",\"value\":\"\",\"name\":\"faceBlur0置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"faceBlur0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidenceconfig.description\"},{\"key\":\"aiParam.faceBlur1.confidence\",\"value\":\"\",\"name\":\"faceBlur1置信度\",\"defaultValue\":\"\",\"description\":\"faceBlur1置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.failedtip\"},{\"key\":\"aiParam.faceBlur1.confidenceConfig\",\"value\":\"\",\"name\":\"faceBlur1置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"faceBlur1置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidenceconfig.description\"},{\"key\":\"aiParam.faceBlur2.confidence\",\"value\":\"\",\"name\":\"faceBlur2置信度\",\"defaultValue\":\"\",\"description\":\"faceBlur2置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.failedtip\"},{\"key\":\"aiParam.faceBlur2.confidenceConfig\",\"value\":\"\",\"name\":\"faceBlur2置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"faceBlur2置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"1000012\",\"atomicName\":\"FaceQuality\",\"position\":\"12564ac1\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"slantedFace\",\"nameCN\":\"slantedFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"3\",\"class_name\":\"faceBlur0\",\"nameCN\":\"faceBlur0\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"4\",\"class_name\":\"faceBlur1\",\"nameCN\":\"faceBlur1\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"5\",\"class_name\":\"faceBlur2\",\"nameCN\":\"faceBlur2\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000012\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00002.12564ac1.actionname\"},{\"actionId\":\"AA_00005\",\"actionName\":\"特征提取算法\",\"remark\":\"\",\"flowActionId\":\"061f82a7\",\"preFlowActionId\":\"f225eab6\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"type\":\"faceSet\",\"description\":\"选择需要比对的脸库分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.faceSet\",\"name\":\"绑定人脸分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"0\"},\"level\":\"2\",\"regexpr\":\"\",\"value\":\"\",\"position\":\"061f82a7\",\"descriptionI18nKey\":\"resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.description\",\"failedTipI18nKey\":\"resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.failedtip\",\"nameI18nKey\":\"resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.name\"}],\"atomic\":{\"atomicCode\":\"1000005\",\"atomicName\":\"FaceRGBRecognition\",\"position\":\"061f82a7\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000005\"},{\"key\":\"fps\",\"value\":\"-1\"},{\"key\":\"featureInput\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00005.061f82a7.actionname\"},{\"actionId\":\"AA_00004\",\"actionName\":\"关键点算法\",\"remark\":\"\",\"flowActionId\":\"f225eab6\",\"preFlowActionId\":\"12564ac1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"1000016\",\"atomicName\":\"FaceLandmark\",\"position\":\"f225eab6\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000016\"}]},\"actionNameI18nKey\":\"resource.action.2.aa_00004.f225eab6.actionname\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"\",\"flowActionId\":\"bdf891b9\",\"preFlowActionId\":\"061f82a7\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"bdf891b9\",\"nameI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"1\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.2.ba_00004.bdf891b9.actionname\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别筛选\",\"remark\":\"\",\"flowActionId\":\"5c3ea492\",\"preFlowActionId\":\"6f833257\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"labelCode\":\"face\",\"labelName\":\"face\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"confidenceValue\":\"1\"}],\"metaDataParams\":[{\"key\":\"filter.face.side.min\",\"value\":\"60\",\"name\":\"最小face尺寸\",\"defaultValue\":\"60\",\"description\":\"最小face尺寸:face抓拍照片的最小图像尺寸。如输入值为100,则最小face尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.2.ba_00002.5c3ea492.filter_face_side_min.name\",\"descriptionI18nKey\":\"resource.param.2.ba_00002.5c3ea492.filter_face_side_min.description\",\"failedTipI18nKey\":\"resource.param.2.ba_00002.5c3ea492.filter_face_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.2.ba_00002.5c3ea492.actionname\"}]", + "atomicList": "[{\"position\":\"aaa71a68\",\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"aaa71a68\",\"atomicCode\":\"1000001\"}]},{\"position\":\"12564ac1\",\"atomicCode\":\"1000012\",\"atomicName\":\"FaceQuality\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"slantedFace\",\"nameCN\":\"slantedFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"3\",\"class_name\":\"faceBlur0\",\"nameCN\":\"faceBlur0\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"4\",\"class_name\":\"faceBlur1\",\"nameCN\":\"faceBlur1\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"},{\"label\":\"5\",\"class_name\":\"faceBlur2\",\"nameCN\":\"faceBlur2\",\"threshold\":[0],\"used\":true,\"position\":\"12564ac1\",\"atomicCode\":\"1000012\"}]},{\"position\":\"061f82a7\",\"atomicCode\":\"1000005\",\"atomicName\":\"FaceRGBRecognition\",\"labelList\":[]},{\"position\":\"f225eab6\",\"atomicCode\":\"1000016\",\"atomicName\":\"FaceLandmark\",\"labelList\":[]}]", + "algorithmUpdateTime": 1776997065000, + "nameI18nKey": "resource.param.2.2.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.2.algorithmname", + "remarkI18nKey": "resource.algorithm.2.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/32_\346\234\252\347\251\277\345\217\215\345\205\211\350\241\243_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/32_\346\234\252\347\251\277\345\217\215\345\205\211\350\241\243_1759134672.json" new file mode 100644 index 000000000..835e2798c --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/32_\346\234\252\347\251\277\345\217\215\345\205\211\350\241\243_1759134672.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 32, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedestrian.confidence\",\"name\":\"行人置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.32.32.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.32.32.aiparam_pedestrian_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedestrian.confidenceConfig\",\"name\":\"行人置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.32.32.aiparam_pedestrian_confidenceconfig.name\"},{\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.pedestrian.detPostion\",\"name\":\"行人检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.32.32.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.32.32.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.32.32.aiparam_pedestrian_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.32.32.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.32.32.aiparam_pedestrian_detpostion.name\"},{\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"failedTip\":\"请输入0-100的两位小数\",\"key\":\"aiParam.1001003.trackDynamicMatch\",\"name\":\"行人检测追踪半径\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.32.32.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.32.32.aiparam_1001003_trackdynamicmatch.name\"},{\"defaultValue\":\"\",\"description\":\"选择需要比对的工服分组\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.workClothesSet\",\"name\":\"绑定工服分组\",\"regexpr\":\"\",\"type\":\"workClothesSet\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_workclothesset.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_workclothesset.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_workclothesset.name\"},{\"defaultValue\":\"60\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"failedTip\":\"请输入1-36000的整数\",\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_targetalarminterval.name\"},{\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"failedTip\":\"请输入0-100的整数\",\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_targetalarmcount.name\"},{\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_restrainswitch.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_restraintime.param_restrainswitch.1.name\"},{\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"senior\":1,\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_overlaytrajectory.name\"},{\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"failedTip\":\"请输入0-10000的整数\",\"key\":\"filter.pedestrian.side.min\",\"name\":\"最小行人尺寸\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.32.32.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.32.32.filter_pedestrian_side_min.name\"},{\"defaultValue\":\"\",\"description\":\"行人质量0置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.quality0.confidence\",\"name\":\"行人质量0置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.aiparam_quality0_confidence.description\",\"failedTipI18nKey\":\"resource.param.32.32.aiparam_quality0_confidence.failedtip\",\"nameI18nKey\":\"resource.param.32.32.aiparam_quality0_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人质量0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.quality0.confidenceConfig\",\"name\":\"行人质量0置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.aiparam_quality0_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.32.32.aiparam_quality0_confidenceconfig.name\"},{\"defaultValue\":\"1\",\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"failedTip\":\"请输入1-100的整数\",\"key\":\"param.videoRepeatCount\",\"name\":\"离线视频播放次数\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_videorepeatcount.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_videorepeatcount.name\"},{\"defaultValue\":\"-1\",\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"param.videoReadFps\",\"name\":\"离线视频播放取帧帧率\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"-1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_videoreadfps.name\"},{\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"failedTip\":\"请输入2-100的整数\",\"key\":\"aiParam.1001003.frames\",\"name\":\"行人检测追踪历史帧数\",\"senior\":1,\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.32.32.aiparam_1001003_frames.failedtip\",\"nameI18nKey\":\"resource.param.32.32.aiparam_1001003_frames.name\"},{\"defaultValue\":\"50.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"failedTip\":\"请输入1-99的一位小数\",\"key\":\"aiParam.1001003.motion\",\"name\":\"行人检测静止阈值\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"50.0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.32.32.aiparam_1001003_motion.failedtip\",\"nameI18nKey\":\"resource.param.32.32.aiparam_1001003_motion.name\"},{\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"failedTip\":\"请输入1-10的整数\",\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_sensitivity.name\"},{\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"failedTip\":\"请输入1-3600的整数\",\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.32.32.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.32.32.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.32.32.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.32.32.name.description\",\"failedTipI18nKey\":\"resource.param.32.32.name.failedtip\",\"nameI18nKey\":\"resource.param.32.32.name.name\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmName": "未穿反光衣", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"1ffc7361\",\"preFlowActionId\":\"551596af\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"1ffc7361\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.32.aa_00001.1ffc7361.1001003.0.pedestrian.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"行人置信度\",\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"行人置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"行人检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"行人检测\",\"position\":\"1ffc7361\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"1ffc7361\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.32.aa_00001.1ffc7361.1001003.0.pedestrian.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.32.aa_00001.1ffc7361.actionname\",\"remarkI18nKey\":\"resource.action.32.aa_00001.1ffc7361.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"0ca3cfc7\",\"preFlowActionId\":\"1ffc7361\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.frames\",\"value\":\"10\",\"name\":\"行人检测追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.name\",\"descriptionI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.failedtip\"},{\"key\":\"aiParam.1001003.motion\",\"value\":\"80.0\",\"name\":\"行人检测静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.name\",\"descriptionI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.failedtip\"},{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"1\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.32.aa_00003.0ca3cfc7.actionname\",\"remarkI18nKey\":\"resource.action.32.aa_00003.0ca3cfc7.remark\"},{\"actionId\":\"AA_00005\",\"actionName\":\"特征提取算法\",\"remark\":\"支持人脸、人体、机物提取特征\",\"flowActionId\":\"247f620f\",\"preFlowActionId\":\"40a88def\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"type\":\"workClothesSet\",\"description\":\"选择需要比对的工服分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.workClothesSet\",\"name\":\"绑定工服分组\",\"senior\":0,\"level\":\"2\",\"regexpr\":\"\",\"value\":\"\",\"position\":\"247f620f\",\"descriptionI18nKey\":\"resource.param.32.aa_00005.247f620f.param_workclothesset.description\",\"failedTipI18nKey\":\"resource.param.32.aa_00005.247f620f.param_workclothesset.failedtip\",\"nameI18nKey\":\"resource.param.32.aa_00005.247f620f.param_workclothesset.name\"}],\"atomic\":{\"atomicCode\":\"1001007\",\"atomicName\":\"ReID特征\",\"position\":\"247f620f\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001007\"},{\"key\":\"fps\",\"value\":\"1\"},{\"key\":\"featureInput\",\"value\":\"1\"},{\"key\":\"matchFlag\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.32.aa_00005.247f620f.actionname\",\"remarkI18nKey\":\"resource.action.32.aa_00005.247f620f.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"da078adb\",\"preFlowActionId\":\"22705515\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"3\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.32.ba_00004.da078adb.param_targetalarminterval.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00004.da078adb.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00004.da078adb.param_targetalarminterval.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"1\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.32.ba_00004.da078adb.param_targetalarmcount.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00004.da078adb.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00004.da078adb.param_targetalarmcount.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.32.ba_00004.da078adb.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00004.da078adb.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00004.da078adb.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.32.ba_00004.da078adb.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00004.da078adb.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00004.da078adb.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.32.ba_00004.da078adb.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00004.da078adb.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00004.da078adb.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.32.ba_00004.da078adb.param_overlaytrajectory.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00004.da078adb.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00004.da078adb.param_overlaytrajectory.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"11\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.32.ba_00004.da078adb.actionname\",\"remarkI18nKey\":\"resource.action.32.ba_00004.da078adb.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"6cdfc847\",\"preFlowActionId\":\"0ca3cfc7\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"1ffc7361\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.32.ba_00002.6cdfc847.actionname\",\"remarkI18nKey\":\"resource.action.32.ba_00002.6cdfc847.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"40a88def\",\"preFlowActionId\":\"6cdfc847\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"quality0\",\"threshold\":[0],\"nameCN\":\"行人质量0\",\"used\":true,\"position\":\"40a88def\",\"atomicCode\":\"1001008\",\"nameCNI18nKey\":\"resource.param.32.aa_00002.40a88def.1001008.0.quality0.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.quality0.confidence\",\"value\":\"\",\"name\":\"行人质量0置信度\",\"defaultValue\":\"\",\"description\":\"行人质量0置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.name\",\"descriptionI18nKey\":\"resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.description\",\"failedTipI18nKey\":\"resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.failedtip\"},{\"key\":\"aiParam.quality0.confidenceConfig\",\"value\":\"\",\"name\":\"行人质量0置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人质量0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.32.aa_00002.40a88def.aiparam_quality0_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.32.aa_00002.40a88def.aiparam_quality0_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"1001008\",\"atomicName\":\"行人质量\",\"position\":\"40a88def\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"quality0\",\"threshold\":[0],\"nameCN\":\"行人质量0\",\"used\":true,\"position\":\"40a88def\",\"atomicCode\":\"1001008\",\"nameCNI18nKey\":\"resource.param.32.aa_00002.40a88def.1001008.0.quality0.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001008\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.32.aa_00002.40a88def.actionname\",\"remarkI18nKey\":\"resource.action.32.aa_00002.40a88def.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"551596af\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.videoRepeatCount\",\"name\":\"离线视频播放次数\",\"defaultValue\":\"1\",\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-100的整数\",\"level\":\"2\",\"senior\":1,\"value\":\"1\",\"position\":\"551596af\",\"nameI18nKey\":\"resource.param.32.ba_00001.551596af.param_videorepeatcount.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00001.551596af.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00001.551596af.param_videorepeatcount.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"-1\",\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"param.videoReadFps\",\"name\":\"离线视频播放取帧帧率\",\"level\":\"2\",\"regexpr\":\"\",\"senior\":1,\"value\":\"-1\",\"position\":\"551596af\",\"descriptionI18nKey\":\"resource.param.32.ba_00001.551596af.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00001.551596af.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.32.ba_00001.551596af.param_videoreadfps.name\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.32.ba_00001.551596af.actionname\",\"remarkI18nKey\":\"resource.action.32.ba_00001.551596af.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"22705515\",\"preFlowActionId\":\"247f620f\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"22705515\",\"nameI18nKey\":\"resource.param.32.ba_00003.22705515.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00003.22705515.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00003.22705515.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"value\":\"2\",\"position\":\"22705515\",\"nameI18nKey\":\"resource.param.32.ba_00003.22705515.param_detectionduration.name\",\"descriptionI18nKey\":\"resource.param.32.ba_00003.22705515.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.32.ba_00003.22705515.param_detectionduration.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.32.ba_00003.22705515.actionname\",\"remarkI18nKey\":\"resource.action.32.ba_00003.22705515.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758699891436", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"1ffc7361\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.32.32.1001003.0.pedestrian.namecn\"}],\"atomicName\":\"行人检测\",\"categoriesLabelList\":[],\"atomicCode\":\"1001003\",\"position\":\"1ffc7361\"},{\"labelList\":[],\"atomicName\":\"ReID特征\",\"atomicCode\":\"1001007\",\"position\":\"247f620f\"},{\"labelList\":[{\"label\":\"0\",\"class_name\":\"quality0\",\"threshold\":[0],\"nameCN\":\"行人质量0\",\"used\":true,\"position\":\"40a88def\",\"atomicCode\":\"1001008\",\"nameCNI18nKey\":\"resource.param.32.32.1001008.0.quality0.namecn\"}],\"atomicName\":\"行人质量\",\"categoriesLabelList\":[],\"atomicCode\":\"1001008\",\"position\":\"40a88def\"}]", + "checkType": 32, + "confVersionId": "3fcb87fe13e249a890743dd5a98f838b", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 32, + "gafAlgorithmName": "RadiantDetect", + "id": "32", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior014", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "工地检测人员是否穿戴反光衣,对于未穿人员进行告警提醒", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758699891000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.32.algorithmname", + "remarkI18nKey": "resource.algorithm.32.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/34707_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175854.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/34707_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175854.json" new file mode 100644 index 000000000..4930711ae --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/34707_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175854.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "34707", + "algorithmCode": 34707, + "algorithmName": "视觉语言大模型分析", + "algorithmCategory": 2, + "algorithmUsage": 1, + "checkType": 42626, + "createTime": 1776074334000, + "updateTime": 1776074334000, + "confVersionId": "default-34707", + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"3\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.alarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.34707.34707.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.param_alarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.34707.34707.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":null,\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.34707.34707.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.param_overlaprate.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.param_overlaprate.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":null,\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.34707.34707.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.param_restraintime.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.param_restraintime.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.34707.34707.name.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.name.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.name.name\"}],\"areasTitle\":null},\"regionType\":\"quadrilateral\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-34707", + "name": "默认", + "algorithmCode": "34707", + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"3\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.alarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.34707.34707.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.param_alarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.34707.34707.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":null,\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.34707.34707.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.param_overlaprate.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.param_overlaprate.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":null,\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.34707.34707.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.param_restraintime.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.param_restraintime.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.34707.34707.name.description\",\"failedTipI18nKey\":\"resource.param.34707.34707.name.failedtip\",\"nameI18nKey\":\"resource.param.34707.34707.name.name\"}],\"areasTitle\":null},\"regionType\":\"quadrilateral\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"\",\"flowActionId\":\"3c61bba4\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.34707.ba_00001.3c61bba4.actionname\"},{\"actionId\":\"DA_00003\",\"actionName\":\"语言视觉大模型\",\"remark\":\"\",\"flowActionId\":\"4a05a806\",\"preFlowActionId\":\"3c61bba4\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888999\",\"atomicName\":\"Qwen3VL\",\"position\":\"4a05a806\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888999\"},{\"key\":\"fps\",\"value\":\"0.3\"},{\"key\":\"advanced_mode\",\"value\":\"0\"},{\"key\":\"keywords\",\"value\":\"穿红色衣服的人\"},{\"key\":\"generationStyle\",\"value\":\"standard\"}]},\"actionNameI18nKey\":\"resource.action.34707.da_00003.4a05a806.actionname\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"\",\"flowActionId\":\"7ec477cd\",\"preFlowActionId\":\"4a05a806\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"7ec477cd\",\"nameI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"7ec477cd\",\"nameI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"7ec477cd\",\"nameI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"7ec477cd\",\"nameI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.34707.ba_00004.7ec477cd.actionname\"}]", + "atomicList": "[{\"position\":\"4a05a806\",\"atomicCode\":\"8888999\",\"atomicName\":\"Qwen3VL\",\"labelList\":[]}]", + "algorithmUpdateTime": 1776160689000, + "remark": "", + "nameI18nKey": "resource.param.34707.34707.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"\",\"flowActionId\":\"3c61bba4\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.34707.ba_00001.3c61bba4.actionname\"},{\"actionId\":\"DA_00003\",\"actionName\":\"语言视觉大模型\",\"remark\":\"\",\"flowActionId\":\"4a05a806\",\"preFlowActionId\":\"3c61bba4\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888999\",\"atomicName\":\"Qwen3VL\",\"position\":\"4a05a806\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888999\"},{\"key\":\"fps\",\"value\":\"0.3\"},{\"key\":\"advanced_mode\",\"value\":\"0\"},{\"key\":\"keywords\",\"value\":\"穿红色衣服的人\"},{\"key\":\"generationStyle\",\"value\":\"standard\"}]},\"actionNameI18nKey\":\"resource.action.34707.da_00003.4a05a806.actionname\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"\",\"flowActionId\":\"7ec477cd\",\"preFlowActionId\":\"4a05a806\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"7ec477cd\",\"nameI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"7ec477cd\",\"nameI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"7ec477cd\",\"nameI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"7ec477cd\",\"nameI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.34707.ba_00004.7ec477cd.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.34707.ba_00004.7ec477cd.actionname\"}]", + "atomicList": "[{\"position\":\"4a05a806\",\"atomicCode\":\"8888999\",\"atomicName\":\"Qwen3VL\",\"labelList\":[]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.34707.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/38873_\346\243\200\346\265\213\347\261\273\347\256\227\346\263\225_20260413173858.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/38873_\346\243\200\346\265\213\347\261\273\347\256\227\346\263\225_20260413173858.json" new file mode 100644 index 000000000..b5fe6c7c0 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/38873_\346\243\200\346\265\213\347\261\273\347\256\227\346\263\225_20260413173858.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "38873", + "algorithmCode": 38873, + "algorithmName": "检测类算法", + "algorithmCategory": 2, + "algorithmUsage": 2, + "checkType": 46792, + "createTime": 1776073138000, + "updateTime": 1776073138000, + "confVersionId": "default-38873", + "algorithmMetadata": "{\"params\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.38873.38873.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.38873.38873.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.38873.38873.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_detpostion.failedtip\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.38873.38873.name.description\",\"failedTipI18nKey\":\"resource.param.38873.38873.name.failedtip\",\"nameI18nKey\":\"resource.param.38873.38873.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-38873", + "name": "默认", + "algorithmCode": "38873", + "algorithmMetadata": "{\"params\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.38873.38873.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.38873.38873.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.38873.38873.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.38873.38873.aiparam_pedestrian_detpostion.failedtip\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.38873.38873.name.description\",\"failedTipI18nKey\":\"resource.param.38873.38873.name.failedtip\",\"nameI18nKey\":\"resource.param.38873.38873.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"PA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"0fa44adc\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"0fa44adc\",\"atomicCode\":\"1000001\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.face.confidence\",\"value\":\"\",\"name\":\"face置信度\",\"defaultValue\":\"\",\"description\":\"face置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.name\",\"descriptionI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.description\",\"failedTipI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.failedtip\"},{\"key\":\"aiParam.face.confidenceConfig\",\"value\":\"\",\"name\":\"face置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidenceconfig.description\"},{\"key\":\"aiParam.face.detPostion\",\"value\":\"0\",\"name\":\"face检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.name\",\"descriptionI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.description\",\"failedTipI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"position\":\"0fa44adc\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"0fa44adc\",\"atomicCode\":\"1000001\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000001\"}]},\"actionNameI18nKey\":\"resource.action.38873.pa_00001.0fa44adc.actionname\"}]", + "atomicList": "[{\"position\":\"0fa44adc\",\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"0fa44adc\",\"atomicCode\":\"1000001\"}]}]", + "algorithmUpdateTime": 1776738386000, + "remark": "", + "nameI18nKey": "resource.param.38873.38873.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"PA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"0fa44adc\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"0fa44adc\",\"atomicCode\":\"1000001\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.face.confidence\",\"value\":\"\",\"name\":\"face置信度\",\"defaultValue\":\"\",\"description\":\"face置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.name\",\"descriptionI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.description\",\"failedTipI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.failedtip\"},{\"key\":\"aiParam.face.confidenceConfig\",\"value\":\"\",\"name\":\"face置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidenceconfig.description\"},{\"key\":\"aiParam.face.detPostion\",\"value\":\"0\",\"name\":\"face检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.name\",\"descriptionI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.description\",\"failedTipI18nKey\":\"resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"position\":\"0fa44adc\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"0fa44adc\",\"atomicCode\":\"1000001\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000001\"}]},\"actionNameI18nKey\":\"resource.action.38873.pa_00001.0fa44adc.actionname\"}]", + "atomicList": "[{\"position\":\"0fa44adc\",\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"0fa44adc\",\"atomicCode\":\"1000001\"}]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.38873.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/3_\345\214\272\345\237\237\345\205\245\344\276\265_1775112182.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/3_\345\214\272\345\237\237\345\205\245\344\276\265_1775112182.json" new file mode 100644 index 000000000..531b7a413 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/3_\345\214\272\345\237\237\345\205\245\344\276\265_1775112182.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 3, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.3.3.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.3.3.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.3.3.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.3.3.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.3.3.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.3.3.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.3.3.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.3.3.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.3.3.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"20\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"endValue\":null,\"failedTip\":\"请输入正确的数值\",\"group\":null,\"key\":\"param.areaDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"20\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_areaduration.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_areaduration.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_areaduration.name\"},{\"beginValue\":null,\"defaultValue\":\"1000\",\"dependsOn\":null,\"description\":\"检测时间单位\",\"endValue\":null,\"failedTip\":\"请选择正确的数值\",\"group\":null,\"key\":\"param.areaDurationTimeType\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间单位\",\"negative\":null,\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.3.3.param_areadurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.3.3.param_areadurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.3.3.param_areadurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.3.3.param_areadurationtimetype.3600000.options_name\"}],\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"select\",\"value\":\"1000\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_areadurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_areadurationtimetype.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_areadurationtimetype.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.3.3.name.description\",\"failedTipI18nKey\":\"resource.param.3.3.name.failedtip\",\"nameI18nKey\":\"resource.param.3.3.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "区域入侵", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"e9173765\",\"preFlowActionId\":\"8d29063d\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"e9173765\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.3.aa_00001.e9173765.actionname\",\"remarkI18nKey\":\"resource.action.3.aa_00001.e9173765.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"9253e062\",\"preFlowActionId\":\"e9173765\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.3.aa_00003.9253e062.actionname\",\"remarkI18nKey\":\"resource.action.3.aa_00003.9253e062.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"fdd2a4cd\",\"preFlowActionId\":\"9253e062\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"e9173765\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.3.ba_00002.fdd2a4cd.actionname\",\"remarkI18nKey\":\"resource.action.3.ba_00002.fdd2a4cd.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"a5c23881\",\"preFlowActionId\":\"f21131a5\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.3.ba_00004.a5c23881.actionname\",\"remarkI18nKey\":\"resource.action.3.ba_00004.a5c23881.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"8d29063d\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.3.ba_00001.8d29063d.actionname\",\"remarkI18nKey\":\"resource.action.3.ba_00001.8d29063d.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"f21131a5\",\"preFlowActionId\":\"fdd2a4cd\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.areaDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"4\"},\"senior\":0,\"value\":\"0\",\"position\":\"f21131a5\",\"nameI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.failedtip\"},{\"key\":\"param.areaDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"4\"},\"senior\":0,\"value\":\"1000\",\"position\":\"f21131a5\",\"nameI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"4\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"durationBreakAreaType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.3.ba_00005.f21131a5.actionname\",\"remarkI18nKey\":\"resource.action.3.ba_00005.f21131a5.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1775112182348", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}]}]", + "checkType": 1, + "confVersionId": "eac39e3d64a043e1b3c734a60ffab0b4", + "confVersionName": "V1.2", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 3, + "gafAlgorithmName": "Intrude", + "id": "3", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior001", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "在视频中设定检测区域,对行人进入该区域超过一定时间的事件进行检测。行人由检测框外到内的过程进行检测、跟踪。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1775112182000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "eac39e3d64a043e1b3c734a60ffab0b4", + "name": "默认", + "algorithmCode": 3, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.3.3.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.3.3.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.3.3.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.3.3.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.3.3.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.3.3.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.3.3.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.3.3.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.3.3.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.3.3.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"20\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"endValue\":null,\"failedTip\":\"请输入正确的数值\",\"group\":null,\"key\":\"param.areaDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"20\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_areaduration.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_areaduration.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_areaduration.name\"},{\"beginValue\":null,\"defaultValue\":\"1000\",\"dependsOn\":null,\"description\":\"检测时间单位\",\"endValue\":null,\"failedTip\":\"请选择正确的数值\",\"group\":null,\"key\":\"param.areaDurationTimeType\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间单位\",\"negative\":null,\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.3.3.param_areadurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.3.3.param_areadurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.3.3.param_areadurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.3.3.param_areadurationtimetype.3600000.options_name\"}],\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"select\",\"value\":\"1000\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.3.3.param_areadurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.3.3.param_areadurationtimetype.failedtip\",\"nameI18nKey\":\"resource.param.3.3.param_areadurationtimetype.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.3.3.name.description\",\"failedTipI18nKey\":\"resource.param.3.3.name.failedtip\",\"nameI18nKey\":\"resource.param.3.3.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"e9173765\",\"preFlowActionId\":\"8d29063d\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"e9173765\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.3.aa_00001.e9173765.actionname\",\"remarkI18nKey\":\"resource.action.3.aa_00001.e9173765.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"9253e062\",\"preFlowActionId\":\"e9173765\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.3.aa_00003.9253e062.actionname\",\"remarkI18nKey\":\"resource.action.3.aa_00003.9253e062.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"fdd2a4cd\",\"preFlowActionId\":\"9253e062\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"e9173765\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.3.ba_00002.fdd2a4cd.actionname\",\"remarkI18nKey\":\"resource.action.3.ba_00002.fdd2a4cd.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"a5c23881\",\"preFlowActionId\":\"f21131a5\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.3.ba_00004.a5c23881.actionname\",\"remarkI18nKey\":\"resource.action.3.ba_00004.a5c23881.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"8d29063d\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.3.ba_00001.8d29063d.actionname\",\"remarkI18nKey\":\"resource.action.3.ba_00001.8d29063d.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"f21131a5\",\"preFlowActionId\":\"fdd2a4cd\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.areaDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"4\"},\"senior\":0,\"value\":\"0\",\"position\":\"f21131a5\",\"nameI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.failedtip\"},{\"key\":\"param.areaDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"4\"},\"senior\":0,\"value\":\"1000\",\"position\":\"f21131a5\",\"nameI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.name\",\"descriptionI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.description\",\"failedTipI18nKey\":\"resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"4\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"durationBreakAreaType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.3.ba_00005.f21131a5.actionname\",\"remarkI18nKey\":\"resource.action.3.ba_00005.f21131a5.remark\"}]", + "atomicList": "[{\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}]}]", + "algorithmUpdateTime": 1776923649000, + "nameI18nKey": "resource.param.3.3.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.3.algorithmname", + "remarkI18nKey": "resource.algorithm.3.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/51_\345\214\272\345\237\237\344\272\272\346\225\260\347\273\237\350\256\241_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/51_\345\214\272\345\237\237\344\272\272\346\225\260\347\273\237\350\256\241_1759134672.json" new file mode 100644 index 000000000..80242c33c --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/51_\345\214\272\345\237\237\344\272\272\346\225\260\347\273\237\350\256\241_1759134672.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 9, + "algorithmCode": 51, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedestrian.confidence\",\"name\":\"行人置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.51.51.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.51.51.aiparam_pedestrian_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedestrian.confidenceConfig\",\"name\":\"行人置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.51.51.aiparam_pedestrian_confidenceconfig.name\"},{\"defaultValue\":\"1\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.pedestrian.detPostion\",\"name\":\"行人检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.51.51.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.51.51.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.51.51.aiparam_pedestrian_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.51.51.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.51.51.aiparam_pedestrian_detpostion.name\"},{\"defaultValue\":\"5\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"failedTip\":\"请输入正确的数值\",\"key\":\"param.areaCalcDuration\",\"name\":\"区域人数上报间隔\",\"regexpr\":\"\",\"type\":\"text\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.param_areacalcduration.description\",\"failedTipI18nKey\":\"resource.param.51.51.param_areacalcduration.failedtip\",\"nameI18nKey\":\"resource.param.51.51.param_areacalcduration.name\"},{\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"failedTip\":\"请选择正确的数值\",\"key\":\"param.areaCalcDurationTimeType\",\"name\":\"检测时间单位\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.51.51.param_areacalcdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.51.51.param_areacalcdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.51.51.param_areacalcdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.51.51.param_areacalcdurationtimetype.3600000.options_name\"}],\"regexpr\":\"\",\"type\":\"select\",\"value\":\"1000\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.param_areacalcdurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.51.51.param_areacalcdurationtimetype.failedtip\",\"nameI18nKey\":\"resource.param.51.51.param_areacalcdurationtimetype.name\"},{\"defaultValue\":\"0\",\"description\":\"目标统计方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.targetCalcType\",\"name\":\"目标统计方式\",\"options\":[{\"name\":\"瞬时(区域人数统计)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.51.51.param_targetcalctype.0.options_name\"},{\"name\":\"周期总人数 (人流量)\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.51.51.param_targetcalctype.1.options_name\"}],\"senior\":1,\"regexpr\":\"/^[0-1]$/\",\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.param_targetcalctype.description\",\"failedTipI18nKey\":\"resource.param.51.51.param_targetcalctype.failedtip\",\"nameI18nKey\":\"resource.param.51.51.param_targetcalctype.name\"},{\"defaultValue\":\"1\",\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"failedTip\":\"请输入1-100的整数\",\"key\":\"param.videoRepeatCount\",\"name\":\"离线视频播放次数\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.51.51.param_videorepeatcount.failedtip\",\"nameI18nKey\":\"resource.param.51.51.param_videorepeatcount.name\"},{\"defaultValue\":\"-1\",\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"param.videoReadFps\",\"name\":\"离线视频播放取帧帧率\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"-1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.51.51.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.51.51.param_videoreadfps.name\"},{\"defaultValue\":\"1\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"senior\":1,\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.51.51.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.51.51.param_restrainswitch.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.51.51.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.51.51.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"senior\":1,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.51.51.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.51.51.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.51.51.param_restraintime.param_restrainswitch.1.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.51.51.name.description\",\"failedTipI18nKey\":\"resource.param.51.51.name.failedtip\",\"nameI18nKey\":\"resource.param.51.51.name.name\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmName": "区域人数统计", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"e9173765\",\"preFlowActionId\":\"4053a96d\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.51.aa_00001.e9173765.1001003.0.pedestrian.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"行人置信度\",\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"行人置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"行人检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"行人检测\",\"position\":\"e9173765\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.51.aa_00001.e9173765.1001003.0.pedestrian.namecn\"}]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.51.aa_00001.e9173765.actionname\",\"remarkI18nKey\":\"resource.action.51.aa_00001.e9173765.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"667e48b6\",\"preFlowActionId\":\"e9173765\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.areaCalcDuration\",\"name\":\"数量上报间隔\",\"defaultValue\":\"0\",\"description\":\"数量上报间隔:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"667e48b6\",\"nameI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_areacalcduration.name\",\"descriptionI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_areacalcduration.description\",\"failedTipI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_areacalcduration.failedtip\"},{\"key\":\"param.areaCalcDurationTimeType\",\"name\":\"数量上报间隔时间单位\",\"defaultValue\":\"1000\",\"description\":\"数量上报间隔时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的单位\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"senior\":0,\"value\":\"1000\",\"position\":\"667e48b6\",\"nameI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.name\",\"descriptionI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"目标统计方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.targetCalcType\",\"name\":\"目标统计方式\",\"options\":[{\"name\":\"瞬时(区域人数统计)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.51.ba_00005.667e48b6.param_targetcalctype.0.options_name\"},{\"name\":\"周期总人数 (人流量)\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.51.ba_00005.667e48b6.param_targetcalctype.1.options_name\"}],\"regexpr\":\"/^[0-1]$/\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"667e48b6\",\"descriptionI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_targetcalctype.description\",\"failedTipI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_targetcalctype.failedtip\",\"nameI18nKey\":\"resource.param.51.ba_00005.667e48b6.param_targetcalctype.name\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"1\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"countBreakAreaType\",\"value\":\"0\"},{\"key\":\"targetCountChange\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.51.ba_00005.667e48b6.actionname\",\"remarkI18nKey\":\"resource.action.51.ba_00005.667e48b6.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"4053a96d\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.videoRepeatCount\",\"name\":\"离线视频播放次数\",\"defaultValue\":\"1\",\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-100的整数\",\"level\":\"2\",\"senior\":1,\"value\":\"1\",\"position\":\"4053a96d\",\"nameI18nKey\":\"resource.param.51.ba_00001.4053a96d.param_videorepeatcount.name\",\"descriptionI18nKey\":\"resource.param.51.ba_00001.4053a96d.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.51.ba_00001.4053a96d.param_videorepeatcount.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"-1\",\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"param.videoReadFps\",\"name\":\"离线视频播放取帧帧率\",\"level\":\"2\",\"regexpr\":\"\",\"senior\":1,\"value\":\"-1\",\"position\":\"4053a96d\",\"descriptionI18nKey\":\"resource.param.51.ba_00001.4053a96d.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.51.ba_00001.4053a96d.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.51.ba_00001.4053a96d.param_videoreadfps.name\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.51.ba_00001.4053a96d.actionname\",\"remarkI18nKey\":\"resource.action.51.ba_00001.4053a96d.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"9de4af16\",\"preFlowActionId\":\"667e48b6\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"9de4af16\",\"nameI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"9de4af16\",\"nameI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"9de4af16\",\"nameI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.51.ba_00004.9de4af16.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"3\"},{\"key\":\"alarmProperty\",\"value\":\"9\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.51.ba_00004.9de4af16.actionname\",\"remarkI18nKey\":\"resource.action.51.ba_00004.9de4af16.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1756353226741", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.5926,0.5646],\"nameCN\":\"行人\",\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.51.51.1001003.0.pedestrian.namecn\"}],\"atomicName\":\"行人检测\",\"atomicCode\":\"1001003\",\"position\":\"e9173765\"}]", + "checkType": 1, + "confVersionId": "ea2a3d153f714732bdd7888a02f1ab2a", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683602000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "peopleCountByArea", + "extraFormat": null, + "gafAlgorithmId": 51, + "gafAlgorithmName": "PeopleStatisticsByArea", + "id": "51", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": null, + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用头肩检测算法,对检测框内的人数进行统计实时统计。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758683602000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.51.algorithmname", + "remarkI18nKey": "resource.algorithm.51.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/57_\347\273\212\347\272\277\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/57_\347\273\212\347\272\277\346\243\200\346\265\213_1759134672.json" new file mode 100644 index 000000000..044e33641 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/57_\347\273\212\347\272\277\346\243\200\346\265\213_1759134672.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 57, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.57.57.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.57.57.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.57.57.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.57.57.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.57.57.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.57.57.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.57.57.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.57.57.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.57.57.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警条件:目标过线的数量\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"param.trippingWireType\",\"maxValue\":null,\"minValue\":null,\"name\":\"绊线类型\",\"negative\":null,\"options\":[{\"name\":\"单线\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.57.57.param_trippingwiretype.1.options_name\"},{\"name\":\"双线\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.57.57.param_trippingwiretype.2.options_name\"}],\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_trippingwiretype.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_trippingwiretype.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_trippingwiretype.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_overlaytrajectory.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.57.57.name.description\",\"failedTipI18nKey\":\"resource.param.57.57.name.failedtip\",\"nameI18nKey\":\"resource.param.57.57.name.name\"}],\"areasTitle\":null},\"regionType\":\"cordon\",\"scheduleSupport\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false,\"defaultFullScreen\":false}", + "algorithmName": "绊线检测", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"e9173765\",\"preFlowActionId\":\"251d0f78\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"e9173765\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.57.aa_00001.e9173765.actionname\",\"remarkI18nKey\":\"resource.action.57.aa_00001.e9173765.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"9253e062\",\"preFlowActionId\":\"e9173765\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.57.aa_00003.9253e062.actionname\",\"remarkI18nKey\":\"resource.action.57.aa_00003.9253e062.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"fdd2a4cd\",\"preFlowActionId\":\"9253e062\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"e9173765\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.57.ba_00002.fdd2a4cd.actionname\",\"remarkI18nKey\":\"resource.action.57.ba_00002.fdd2a4cd.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"f7750059\",\"preFlowActionId\":\"fdd2a4cd\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"type\":\"select\",\"defaultValue\":\"1\",\"description\":\"告警条件:目标过线的数量\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.trippingWireType\",\"name\":\"绊线类型\",\"options\":[{\"name\":\"单线\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.57.ba_00005.f7750059.param_trippingwiretype.1.options_name\"},{\"name\":\"双线\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.57.ba_00005.f7750059.param_trippingwiretype.2.options_name\"}],\"regexpr\":\"\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"f7750059\",\"descriptionI18nKey\":\"resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.failedtip\",\"nameI18nKey\":\"resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.name\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"2\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"breakAreaType\",\"value\":\"101\"}]},\"actionNameI18nKey\":\"resource.action.57.ba_00005.f7750059.actionname\",\"remarkI18nKey\":\"resource.action.57.ba_00005.f7750059.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"a5c23881\",\"preFlowActionId\":\"f7750059\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.57.ba_00004.a5c23881.actionname\",\"remarkI18nKey\":\"resource.action.57.ba_00004.a5c23881.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"251d0f78\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.57.ba_00001.251d0f78.actionname\",\"remarkI18nKey\":\"resource.action.57.ba_00001.251d0f78.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758698597012", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}]}]", + "checkType": 12, + "confVersionId": "fcf2bc708435417085c3e9d03cbc035a", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 57, + "gafAlgorithmName": "LineBreakIn", + "id": "57", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior017", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用行人跟踪算法对人员绊线行为进行告警。可设置单向、双向绊线检测。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758698597000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "fcf2bc708435417085c3e9d03cbc035a", + "name": "默认", + "algorithmCode": 57, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.57.57.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.57.57.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.57.57.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.57.57.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.57.57.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.57.57.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.57.57.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.57.57.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.57.57.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.57.57.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警条件:目标过线的数量\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"param.trippingWireType\",\"maxValue\":null,\"minValue\":null,\"name\":\"绊线类型\",\"negative\":null,\"options\":[{\"name\":\"单线\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.57.57.param_trippingwiretype.1.options_name\"},{\"name\":\"双线\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.57.57.param_trippingwiretype.2.options_name\"}],\"range\":null,\"regexpr\":\"\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_trippingwiretype.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_trippingwiretype.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_trippingwiretype.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.57.57.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.57.57.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.57.57.param_overlaytrajectory.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.57.57.name.description\",\"failedTipI18nKey\":\"resource.param.57.57.name.failedtip\",\"nameI18nKey\":\"resource.param.57.57.name.name\"}],\"areasTitle\":null},\"regionType\":\"cordon\",\"scheduleSupport\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"e9173765\",\"preFlowActionId\":\"251d0f78\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"e9173765\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.57.aa_00001.e9173765.actionname\",\"remarkI18nKey\":\"resource.action.57.aa_00001.e9173765.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"9253e062\",\"preFlowActionId\":\"e9173765\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.57.aa_00003.9253e062.actionname\",\"remarkI18nKey\":\"resource.action.57.aa_00003.9253e062.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"fdd2a4cd\",\"preFlowActionId\":\"9253e062\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"e9173765\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.57.ba_00002.fdd2a4cd.actionname\",\"remarkI18nKey\":\"resource.action.57.ba_00002.fdd2a4cd.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"f7750059\",\"preFlowActionId\":\"fdd2a4cd\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"type\":\"select\",\"defaultValue\":\"1\",\"description\":\"告警条件:目标过线的数量\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.trippingWireType\",\"name\":\"绊线类型\",\"options\":[{\"name\":\"单线\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.57.ba_00005.f7750059.param_trippingwiretype.1.options_name\"},{\"name\":\"双线\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.57.ba_00005.f7750059.param_trippingwiretype.2.options_name\"}],\"regexpr\":\"\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"f7750059\",\"descriptionI18nKey\":\"resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.failedtip\",\"nameI18nKey\":\"resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.name\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"2\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"breakAreaType\",\"value\":\"101\"}]},\"actionNameI18nKey\":\"resource.action.57.ba_00005.f7750059.actionname\",\"remarkI18nKey\":\"resource.action.57.ba_00005.f7750059.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"a5c23881\",\"preFlowActionId\":\"f7750059\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"a5c23881\",\"nameI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.57.ba_00004.a5c23881.actionname\",\"remarkI18nKey\":\"resource.action.57.ba_00004.a5c23881.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"251d0f78\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.57.ba_00001.251d0f78.actionname\",\"remarkI18nKey\":\"resource.action.57.ba_00001.251d0f78.remark\"}]", + "atomicList": "[{\"position\":\"e9173765\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"e9173765\",\"atomicCode\":\"1001003\"}]}]", + "algorithmUpdateTime": 1776924279000, + "nameI18nKey": "resource.param.57.57.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.57.algorithmname", + "remarkI18nKey": "resource.algorithm.57.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/58_\346\234\252\347\251\277\345\267\245\346\234\215_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/58_\346\234\252\347\251\277\345\267\245\346\234\215_1759134672.json" new file mode 100644 index 000000000..c2bc037eb --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/58_\346\234\252\347\251\277\345\267\245\346\234\215_1759134672.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 58, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedestrian.confidence\",\"name\":\"行人置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.58.58.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.58.58.aiparam_pedestrian_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedestrian.confidenceConfig\",\"name\":\"行人置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.58.58.aiparam_pedestrian_confidenceconfig.name\"},{\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.pedestrian.detPostion\",\"name\":\"行人检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.58.58.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.58.58.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.58.58.aiparam_pedestrian_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.58.58.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.58.58.aiparam_pedestrian_detpostion.name\"},{\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"failedTip\":\"请输入0-100的两位小数\",\"key\":\"aiParam.1001003.trackDynamicMatch\",\"name\":\"行人检测追踪半径\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.58.58.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.58.58.aiparam_1001003_trackdynamicmatch.name\"},{\"defaultValue\":\"\",\"description\":\"选择需要比对的工服分组\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.workClothesSet\",\"name\":\"绑定工服分组\",\"regexpr\":\"\",\"type\":\"workClothesSet\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_workclothesset.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_workclothesset.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_workclothesset.name\"},{\"defaultValue\":\"60\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"failedTip\":\"请输入1-36000的整数\",\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_targetalarminterval.name\"},{\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"failedTip\":\"请输入0-100的整数\",\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_targetalarmcount.name\"},{\"defaultValue\":\"1\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_restrainswitch.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_restraintime.param_restrainswitch.1.name\"},{\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"senior\":1,\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_overlaytrajectory.name\"},{\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"failedTip\":\"请输入0-10000的整数\",\"key\":\"filter.pedestrian.side.min\",\"name\":\"最小行人尺寸\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.58.58.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.58.58.filter_pedestrian_side_min.name\"},{\"defaultValue\":\"\",\"description\":\"行人质量0置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.quality0.confidence\",\"name\":\"行人质量0置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.aiparam_quality0_confidence.description\",\"failedTipI18nKey\":\"resource.param.58.58.aiparam_quality0_confidence.failedtip\",\"nameI18nKey\":\"resource.param.58.58.aiparam_quality0_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人质量0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.quality0.confidenceConfig\",\"name\":\"行人质量0置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.aiparam_quality0_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.58.58.aiparam_quality0_confidenceconfig.name\"},{\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"failedTip\":\"请输入1-10的整数\",\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_sensitivity.name\"},{\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"failedTip\":\"请输入1-3600的整数\",\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.58.58.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.58.58.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.58.58.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.58.58.name.description\",\"failedTipI18nKey\":\"resource.param.58.58.name.failedtip\",\"nameI18nKey\":\"resource.param.58.58.name.name\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmName": "未穿工服", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"1ffc7361\",\"preFlowActionId\":\"03ef5862\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"1ffc7361\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.58.aa_00001.1ffc7361.1001003.0.pedestrian.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"行人置信度\",\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"行人置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"行人检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"行人检测\",\"position\":\"1ffc7361\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"1ffc7361\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.58.aa_00001.1ffc7361.1001003.0.pedestrian.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.58.aa_00001.1ffc7361.actionname\",\"remarkI18nKey\":\"resource.action.58.aa_00001.1ffc7361.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"0ca3cfc7\",\"preFlowActionId\":\"1ffc7361\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"0\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.58.aa_00003.0ca3cfc7.actionname\",\"remarkI18nKey\":\"resource.action.58.aa_00003.0ca3cfc7.remark\"},{\"actionId\":\"AA_00005\",\"actionName\":\"特征提取算法\",\"remark\":\"支持人脸、人体、机物提取特征\",\"flowActionId\":\"247f620f\",\"preFlowActionId\":\"40a88def\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"type\":\"workClothesSet\",\"description\":\"选择需要比对的工服分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.workClothesSet\",\"name\":\"绑定工服分组\",\"senior\":0,\"level\":\"2\",\"regexpr\":\"\",\"value\":\"\",\"position\":\"247f620f\",\"descriptionI18nKey\":\"resource.param.58.aa_00005.247f620f.param_workclothesset.description\",\"failedTipI18nKey\":\"resource.param.58.aa_00005.247f620f.param_workclothesset.failedtip\",\"nameI18nKey\":\"resource.param.58.aa_00005.247f620f.param_workclothesset.name\"}],\"atomic\":{\"atomicCode\":\"1001007\",\"atomicName\":\"ReID特征\",\"position\":\"247f620f\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001007\"},{\"key\":\"fps\",\"value\":\"1\"},{\"key\":\"featureInput\",\"value\":\"1\"},{\"key\":\"matchFlag\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.58.aa_00005.247f620f.actionname\",\"remarkI18nKey\":\"resource.action.58.aa_00005.247f620f.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"da078adb\",\"preFlowActionId\":\"bc6d90f2\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"3\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.58.ba_00004.da078adb.param_targetalarminterval.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00004.da078adb.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00004.da078adb.param_targetalarminterval.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"1\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.58.ba_00004.da078adb.param_targetalarmcount.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00004.da078adb.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00004.da078adb.param_targetalarmcount.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.58.ba_00004.da078adb.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00004.da078adb.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00004.da078adb.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.58.ba_00004.da078adb.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00004.da078adb.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00004.da078adb.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.58.ba_00004.da078adb.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00004.da078adb.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00004.da078adb.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"da078adb\",\"nameI18nKey\":\"resource.param.58.ba_00004.da078adb.param_overlaytrajectory.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00004.da078adb.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00004.da078adb.param_overlaytrajectory.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"11\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.58.ba_00004.da078adb.actionname\",\"remarkI18nKey\":\"resource.action.58.ba_00004.da078adb.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"6cdfc847\",\"preFlowActionId\":\"0ca3cfc7\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"1ffc7361\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.58.ba_00002.6cdfc847.actionname\",\"remarkI18nKey\":\"resource.action.58.ba_00002.6cdfc847.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"40a88def\",\"preFlowActionId\":\"6cdfc847\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"quality0\",\"threshold\":[0],\"nameCN\":\"行人质量0\",\"used\":true,\"position\":\"40a88def\",\"atomicCode\":\"1001008\",\"nameCNI18nKey\":\"resource.param.58.aa_00002.40a88def.1001008.0.quality0.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.quality0.confidence\",\"value\":\"\",\"name\":\"行人质量0置信度\",\"defaultValue\":\"\",\"description\":\"行人质量0置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.name\",\"descriptionI18nKey\":\"resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.description\",\"failedTipI18nKey\":\"resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.failedtip\"},{\"key\":\"aiParam.quality0.confidenceConfig\",\"value\":\"\",\"name\":\"行人质量0置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人质量0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.58.aa_00002.40a88def.aiparam_quality0_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.58.aa_00002.40a88def.aiparam_quality0_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"1001008\",\"atomicName\":\"行人质量\",\"position\":\"40a88def\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"quality0\",\"threshold\":[0],\"nameCN\":\"行人质量0\",\"used\":true,\"position\":\"40a88def\",\"atomicCode\":\"1001008\",\"nameCNI18nKey\":\"resource.param.58.aa_00002.40a88def.1001008.0.quality0.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001008\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.58.aa_00002.40a88def.actionname\",\"remarkI18nKey\":\"resource.action.58.aa_00002.40a88def.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"03ef5862\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.58.ba_00001.03ef5862.actionname\",\"remarkI18nKey\":\"resource.action.58.ba_00001.03ef5862.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"bc6d90f2\",\"preFlowActionId\":\"247f620f\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"bc6d90f2\",\"nameI18nKey\":\"resource.param.58.ba_00003.bc6d90f2.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00003.bc6d90f2.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00003.bc6d90f2.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"value\":\"2\",\"position\":\"bc6d90f2\",\"nameI18nKey\":\"resource.param.58.ba_00003.bc6d90f2.param_detectionduration.name\",\"descriptionI18nKey\":\"resource.param.58.ba_00003.bc6d90f2.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.58.ba_00003.bc6d90f2.param_detectionduration.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.58.ba_00003.bc6d90f2.actionname\",\"remarkI18nKey\":\"resource.action.58.ba_00003.bc6d90f2.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758699942716", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"1ffc7361\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.58.58.1001003.0.pedestrian.namecn\"}],\"atomicName\":\"行人检测\",\"categoriesLabelList\":[],\"atomicCode\":\"1001003\",\"position\":\"1ffc7361\"},{\"labelList\":[],\"atomicName\":\"ReID特征\",\"atomicCode\":\"1001007\",\"position\":\"247f620f\"},{\"labelList\":[{\"label\":\"0\",\"class_name\":\"quality0\",\"threshold\":[0],\"nameCN\":\"行人质量0\",\"used\":true,\"position\":\"40a88def\",\"atomicCode\":\"1001008\",\"nameCNI18nKey\":\"resource.param.58.58.1001008.0.quality0.namecn\"}],\"atomicName\":\"行人质量\",\"categoriesLabelList\":[],\"atomicCode\":\"1001008\",\"position\":\"40a88def\"}]", + "checkType": 13, + "confVersionId": "60d3af0b1aae4e51a7e1009e8bed5bad", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 58, + "gafAlgorithmName": "NoWorkClothes", + "id": "58", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior018", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用人体识别算法对工服库内未命中的人体进行报警。可基于客户场景进行工服库的自定义。支持多种工服样式、颜色的检测。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758699943000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.58.algorithmname", + "remarkI18nKey": "resource.algorithm.58.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/5_\344\272\272\345\221\230\350\201\232\351\233\206_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/5_\344\272\272\345\221\230\350\201\232\351\233\206_1759134672.json" new file mode 100644 index 000000000..c457ada09 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/5_\344\272\272\345\221\230\350\201\232\351\233\206_1759134672.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 5, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"failedTip\":\"请输入0-10000的整数\",\"key\":\"filter.pedestrian.side.min\",\"name\":\"最小行人尺寸\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.5.5.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.5.5.filter_pedestrian_side_min.name\"},{\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedestrian.confidence\",\"name\":\"行人置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.5.5.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.5.5.aiparam_pedestrian_confidence.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.5.5.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.5.5.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedestrian.confidenceConfig\",\"name\":\"行人置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.5.5.aiparam_pedestrian_confidenceconfig.name\"},{\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.pedestrian.detPostion\",\"name\":\"行人检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.5.5.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.5.5.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.5.5.aiparam_pedestrian_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.5.5.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.5.5.aiparam_pedestrian_detpostion.name\"},{\"defaultValue\":\"60\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"failedTip\":\"请输入1-36000的整数\",\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.5.5.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.5.5.param_alarminterval.name\"},{\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.5.5.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.5.5.param_restrainswitch.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.5.5.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.5.5.param_restraintime.param_restrainswitch.1.name\"},{\"defaultValue\":\"10\",\"description\":\"区域中的目标数\",\"failedTip\":\"请输入0-3600的整数\",\"key\":\"param.areaLimitTargetCount\",\"name\":\"区域中的目标数\",\"regexpr\":\"/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.param_arealimittargetcount.description\",\"failedTipI18nKey\":\"resource.param.5.5.param_arealimittargetcount.failedtip\",\"nameI18nKey\":\"resource.param.5.5.param_arealimittargetcount.name\"},{\"defaultValue\":\"1\",\"description\":\"区域中目标数限制类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.areaLimitTargetType\",\"name\":\"区域中目标数限制类型\",\"options\":[{\"name\":\"小于目标数告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.5.5.param_arealimittargettype.0.options_name\"},{\"name\":\"大于目标数告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.5.5.param_arealimittargettype.1.options_name\"},{\"name\":\"小于等于目标数告警\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.5.5.param_arealimittargettype.2.options_name\"},{\"name\":\"大于等于目标数告警\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.5.5.param_arealimittargettype.3.options_name\"},{\"name\":\"等于目标数告警\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.5.5.param_arealimittargettype.4.options_name\"}],\"senior\":1,\"regexpr\":\"/^[0-4]$/\",\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.param_arealimittargettype.description\",\"failedTipI18nKey\":\"resource.param.5.5.param_arealimittargettype.failedtip\",\"nameI18nKey\":\"resource.param.5.5.param_arealimittargettype.name\"},{\"defaultValue\":\"60\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"failedTip\":\"请输入正确的数值\",\"key\":\"param.areaLimitDuration\",\"name\":\"检测时间\",\"regexpr\":\"\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.param_arealimitduration.description\",\"failedTipI18nKey\":\"resource.param.5.5.param_arealimitduration.failedtip\",\"nameI18nKey\":\"resource.param.5.5.param_arealimitduration.name\"},{\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"failedTip\":\"请选择正确的数值\",\"key\":\"param.areaLimitDurationTimeType\",\"name\":\"检测时间单位\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.5.5.param_arealimitdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.5.5.param_arealimitdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.5.5.param_arealimitdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.5.5.param_arealimitdurationtimetype.3600000.options_name\"}],\"regexpr\":\"\",\"type\":\"select\",\"value\":\"1000\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.5.5.param_arealimitdurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.5.5.param_arealimitdurationtimetype.failedtip\",\"nameI18nKey\":\"resource.param.5.5.param_arealimitdurationtimetype.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.5.5.name.description\",\"failedTipI18nKey\":\"resource.param.5.5.name.failedtip\",\"nameI18nKey\":\"resource.param.5.5.name.name\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmName": "人员聚集", + "algorithmProcessdata": "[{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"72ec426d\",\"preFlowActionId\":\"bc4f4b27\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"bc4f4b27\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.5.ba_00002.72ec426d.actionname\",\"remarkI18nKey\":\"resource.action.5.ba_00002.72ec426d.remark\"},{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"bc4f4b27\",\"preFlowActionId\":\"991da170\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.1001003.0.pedestrian.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"行人置信度\",\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"行人置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"行人检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"行人检测\",\"position\":\"bc4f4b27\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.5.aa_00001.bc4f4b27.1001003.0.pedestrian.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.5.aa_00001.bc4f4b27.actionname\",\"remarkI18nKey\":\"resource.action.5.aa_00001.bc4f4b27.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"f0c9e210\",\"preFlowActionId\":\"ab935f8a\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"3\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_alarminterval.name\",\"descriptionI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_alarminterval.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"f0c9e210\",\"nameI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00004.f0c9e210.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"8\"},{\"key\":\"faceScaleSide\",\"value\":\"1.00\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.5.ba_00004.f0c9e210.actionname\",\"remarkI18nKey\":\"resource.action.5.ba_00004.f0c9e210.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"ab935f8a\",\"preFlowActionId\":\"72ec426d\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.areaLimitTargetCount\",\"name\":\"目标数量阈值\",\"defaultValue\":\"0\",\"description\":\"用于和区域内实际有效目标数量进行比较的阈值\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入0-3600的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.name\",\"descriptionI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"区域中目标数限制类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.areaLimitTargetType\",\"name\":\"触发条件\",\"options\":[{\"name\":\"小于目标数告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.0.options_name\"},{\"name\":\"大于目标数告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.1.options_name\"},{\"name\":\"小于等于目标数告警\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.2.options_name\"},{\"name\":\"大于等于目标数告警\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.3.options_name\"},{\"name\":\"等于目标数告警\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.4.options_name\"}],\"regexpr\":\"/^[0-4]$/\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"ab935f8a\",\"descriptionI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.failedtip\",\"nameI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.name\"},{\"key\":\"param.areaLimitDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimitduration.name\",\"descriptionI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimitduration.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimitduration.failedtip\"},{\"key\":\"param.areaLimitDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"senior\":0,\"value\":\"1000\",\"position\":\"ab935f8a\",\"nameI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.name\",\"descriptionI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"0\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"enableAreaSensitivity\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.5.ba_00005.ab935f8a.actionname\",\"remarkI18nKey\":\"resource.action.5.ba_00005.ab935f8a.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"991da170\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.5.ba_00001.991da170.actionname\",\"remarkI18nKey\":\"resource.action.5.ba_00001.991da170.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758684668206", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"bc4f4b27\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.5.5.1001003.0.pedestrian.namecn\"}],\"atomicName\":\"行人检测\",\"categoriesLabelList\":[],\"atomicCode\":\"1001003\",\"position\":\"bc4f4b27\"}]", + "checkType": 227, + "confVersionId": "15834f1589f04e6ba359ab76b65829f0", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 5, + "gafAlgorithmName": "Converge", + "id": "5", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior007", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用头肩或人体检测算法,对进入检测区域的行人进行计数,对超过阈值人数的事件进行告警。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758684668000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.5.algorithmname", + "remarkI18nKey": "resource.algorithm.5.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/65_\347\235\241\345\262\227\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/65_\347\235\241\345\262\227\346\243\200\346\265\213_1759134672.json" new file mode 100644 index 000000000..f947836c9 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/65_\347\235\241\345\262\227\346\243\200\346\265\213_1759134672.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 65, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedestrian.confidence\",\"name\":\"行人置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.65.65.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.65.65.aiparam_pedestrian_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedestrian.confidenceConfig\",\"name\":\"行人置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.65.65.aiparam_pedestrian_confidenceconfig.name\"},{\"defaultValue\":\"1\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.pedestrian.detPostion\",\"name\":\"行人检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.65.65.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.65.65.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.65.65.aiparam_pedestrian_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.65.65.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.65.65.aiparam_pedestrian_detpostion.name\"},{\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"failedTip\":\"请输入2-100的整数\",\"key\":\"aiParam.1001003.frames\",\"name\":\"行人检测追踪历史帧数\",\"senior\":1,\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.65.65.aiparam_1001003_frames.failedtip\",\"nameI18nKey\":\"resource.param.65.65.aiparam_1001003_frames.name\"},{\"defaultValue\":\"50.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"failedTip\":\"请输入1-99的一位小数\",\"key\":\"aiParam.1001003.motion\",\"name\":\"行人检测静止阈值\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"50.0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.65.65.aiparam_1001003_motion.failedtip\",\"nameI18nKey\":\"resource.param.65.65.aiparam_1001003_motion.name\"},{\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"failedTip\":\"请输入0-100的两位小数\",\"key\":\"aiParam.1001003.trackDynamicMatch\",\"name\":\"行人检测追踪半径\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.65.65.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.65.65.aiparam_1001003_trackdynamicmatch.name\"},{\"defaultValue\":\"\",\"description\":\"行人睡姿-趴睡置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedSleepStomach.confidence\",\"name\":\"行人睡姿-趴睡置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_pedsleepstomach_confidence.description\",\"failedTipI18nKey\":\"resource.param.65.65.aiparam_pedsleepstomach_confidence.failedtip\",\"nameI18nKey\":\"resource.param.65.65.aiparam_pedsleepstomach_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人睡姿-趴睡置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedSleepStomach.confidenceConfig\",\"name\":\"行人睡姿-趴睡置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_pedsleepstomach_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.65.65.aiparam_pedsleepstomach_confidenceconfig.name\"},{\"defaultValue\":\"\",\"description\":\"行人睡姿-躺着睡置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.pedSleepLieDown.confidence\",\"name\":\"行人睡姿-躺着睡置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_pedsleepliedown_confidence.description\",\"failedTipI18nKey\":\"resource.param.65.65.aiparam_pedsleepliedown_confidence.failedtip\",\"nameI18nKey\":\"resource.param.65.65.aiparam_pedsleepliedown_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"行人睡姿-躺着睡置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.pedSleepLieDown.confidenceConfig\",\"name\":\"行人睡姿-躺着睡置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.aiparam_pedsleepliedown_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.65.65.aiparam_pedsleepliedown_confidenceconfig.name\"},{\"defaultValue\":\"60\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"failedTip\":\"请输入1-36000的整数\",\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.65.65.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.65.65.param_targetalarminterval.name\"},{\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"failedTip\":\"请输入0-100的整数\",\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.65.65.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.65.65.param_targetalarmcount.name\"},{\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.65.65.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.65.65.param_restrainswitch.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.65.65.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.65.65.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.65.65.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.65.65.param_restraintime.param_restrainswitch.1.name\"},{\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"senior\":1,\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.65.65.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.65.65.param_overlaytrajectory.name\"},{\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"failedTip\":\"请输入0-10000的整数\",\"key\":\"filter.pedestrian.side.min\",\"name\":\"最小行人尺寸\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.65.65.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.65.65.filter_pedestrian_side_min.name\"},{\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"failedTip\":\"请输入1-10的整数\",\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.65.65.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.65.65.param_sensitivity.name\"},{\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"failedTip\":\"请输入1-3600的整数\",\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.65.65.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.65.65.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.65.65.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.65.65.name.description\",\"failedTipI18nKey\":\"resource.param.65.65.name.failedtip\",\"nameI18nKey\":\"resource.param.65.65.name.name\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmName": "睡岗检测", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"487c1cf0\",\"preFlowActionId\":\"55e37370\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.65.aa_00001.487c1cf0.1001003.0.pedestrian.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"行人置信度\",\"defaultValue\":\"\",\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"行人置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"行人检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"行人检测\",\"position\":\"487c1cf0\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.65.aa_00001.487c1cf0.1001003.0.pedestrian.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.65.aa_00001.487c1cf0.actionname\",\"remarkI18nKey\":\"resource.action.65.aa_00001.487c1cf0.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"c232a753\",\"preFlowActionId\":\"487c1cf0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.frames\",\"value\":\"10\",\"name\":\"行人检测追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.failedtip\"},{\"key\":\"aiParam.1001003.motion\",\"value\":\"80.0\",\"name\":\"行人检测静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.failedtip\"},{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"2\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.65.aa_00003.c232a753.actionname\",\"remarkI18nKey\":\"resource.action.65.aa_00003.c232a753.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"c37b8e34\",\"preFlowActionId\":\"d56fc47d\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedSleepStomach\",\"threshold\":[0.954,0.9],\"nameCN\":\"行人睡姿-趴睡\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"1001010\",\"nameCNI18nKey\":\"resource.param.65.aa_00002.c37b8e34.1001010.0.pedsleepstomach.namecn\"},{\"label\":\"5\",\"class_name\":\"pedSleepLieDown\",\"threshold\":[0.98,0.55],\"nameCN\":\"行人睡姿-躺着睡\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"1001010\",\"nameCNI18nKey\":\"resource.param.65.aa_00002.c37b8e34.1001010.5.pedsleepliedown.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedSleepStomach.confidence\",\"value\":\"\",\"name\":\"行人睡姿-趴睡置信度\",\"defaultValue\":\"\",\"description\":\"行人睡姿-趴睡置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.description\",\"failedTipI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.failedtip\"},{\"key\":\"aiParam.pedSleepStomach.confidenceConfig\",\"value\":\"\",\"name\":\"行人睡姿-趴睡置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人睡姿-趴睡置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidenceconfig.description\"},{\"key\":\"aiParam.pedSleepLieDown.confidence\",\"value\":\"\",\"name\":\"行人睡姿-躺着睡置信度\",\"defaultValue\":\"\",\"description\":\"行人睡姿-躺着睡置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.description\",\"failedTipI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.failedtip\"},{\"key\":\"aiParam.pedSleepLieDown.confidenceConfig\",\"value\":\"\",\"name\":\"行人睡姿-躺着睡置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"行人睡姿-躺着睡置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"1001010\",\"atomicName\":\"睡岗\",\"position\":\"c37b8e34\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedSleepStomach\",\"threshold\":[0.954,0.9],\"nameCN\":\"行人睡姿-趴睡\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"1001010\",\"nameCNI18nKey\":\"resource.param.65.aa_00002.c37b8e34.1001010.0.pedsleepstomach.namecn\"},{\"label\":\"5\",\"class_name\":\"pedSleepLieDown\",\"threshold\":[0.98,0.55],\"nameCN\":\"行人睡姿-躺着睡\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"1001010\",\"nameCNI18nKey\":\"resource.param.65.aa_00002.c37b8e34.1001010.5.pedsleepliedown.namecn\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001010\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.65.aa_00002.c37b8e34.actionname\",\"remarkI18nKey\":\"resource.action.65.aa_00002.c37b8e34.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"e02bf44c\",\"preFlowActionId\":\"c37b8e34\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"level\":1,\"type\":1,\"list\":[{\"key\":\"f82446a6\",\"level\":2,\"type\":14,\"keyL\":\"aiOut.pedSleepStomach.threshold\",\"keyR\":\"aiParam.pedSleepStomach.confidence\",\"list\":[],\"showTools\":false,\"rightType\":\"select\"},{\"key\":\"d0cf899f\",\"keyL\":\"aiOut.pedSleepLieDown.threshold\",\"keyR\":\"aiParam.pedSleepLieDown.confidence\",\"type\":14,\"list\":[],\"showTools\":false,\"level\":2,\"rightType\":\"select\"}],\"showTools\":false,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.65.ba_90001.e02bf44c.actionname\",\"remarkI18nKey\":\"resource.action.65.ba_90001.e02bf44c.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"0f53b331\",\"preFlowActionId\":\"b00198a1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"3\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_targetalarminterval.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_targetalarminterval.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"1\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_targetalarmcount.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_targetalarmcount.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.65.ba_00004.0f53b331.actionname\",\"remarkI18nKey\":\"resource.action.65.ba_00004.0f53b331.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"d56fc47d\",\"preFlowActionId\":\"c232a753\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"487c1cf0\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.65.ba_00002.d56fc47d.actionname\",\"remarkI18nKey\":\"resource.action.65.ba_00002.d56fc47d.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"55e37370\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.65.ba_00001.55e37370.actionname\",\"remarkI18nKey\":\"resource.action.65.ba_00001.55e37370.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"b00198a1\",\"preFlowActionId\":\"e02bf44c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"b00198a1\",\"nameI18nKey\":\"resource.param.65.ba_00003.b00198a1.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00003.b00198a1.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00003.b00198a1.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"value\":\"2\",\"position\":\"b00198a1\",\"nameI18nKey\":\"resource.param.65.ba_00003.b00198a1.param_detectionduration.name\",\"descriptionI18nKey\":\"resource.param.65.ba_00003.b00198a1.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.65.ba_00003.b00198a1.param_detectionduration.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.65.ba_00003.b00198a1.actionname\",\"remarkI18nKey\":\"resource.action.65.ba_00003.b00198a1.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758698875507", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"threshold\":[0.63,0.63],\"nameCN\":\"行人\",\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"nameCNI18nKey\":\"resource.param.65.65.1001003.0.pedestrian.namecn\"}],\"atomicName\":\"行人检测\",\"categoriesLabelList\":[],\"atomicCode\":\"1001003\",\"position\":\"487c1cf0\"},{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedSleepStomach\",\"threshold\":[0.954,0.9],\"nameCN\":\"行人睡姿-趴睡\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"1001010\",\"nameCNI18nKey\":\"resource.param.65.65.1001010.0.pedsleepstomach.namecn\"},{\"label\":\"5\",\"class_name\":\"pedSleepLieDown\",\"threshold\":[0.98,0.55],\"nameCN\":\"行人睡姿-躺着睡\",\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"1001010\",\"nameCNI18nKey\":\"resource.param.65.65.1001010.5.pedsleepliedown.namecn\"}],\"atomicName\":\"睡岗\",\"categoriesLabelList\":[],\"atomicCode\":\"1001010\",\"position\":\"c37b8e34\"}]", + "checkType": 65, + "confVersionId": "ca695c3076a340b78fc9428fda59ed9e", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683602000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 65, + "gafAlgorithmName": "Sleep", + "id": "65", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": null, + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用人体检测、跟踪、睡岗分类算法,对人员的睡岗行为进行告警。支持卧睡、趴睡2种睡岗行为", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758698876000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.65.algorithmname", + "remarkI18nKey": "resource.algorithm.65.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/6_\344\272\272\345\221\230\350\267\214\345\200\222_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/6_\344\272\272\345\221\230\350\267\214\345\200\222_1759134672.json" new file mode 100644 index 000000000..fad9b02d0 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/6_\344\272\272\345\221\230\350\267\214\345\200\222_1759134672.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 6, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.6.6.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.6.6.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.6.6.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"跌倒置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedfalldown.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"跌倒置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidence.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidence.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"跌倒置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedfalldown.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"跌倒置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.6.6.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.6.6.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"10\",\"dependsOn\":null,\"description\":\"追踪历史帧数。范围:2~100\",\"endValue\":null,\"failedTip\":\"请输入2-100的整数\",\"group\":null,\"key\":\"aiParam.1001003.frames\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪历史帧数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_1001003_frames.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_1001003_frames.name\"},{\"beginValue\":null,\"defaultValue\":\"50.0\",\"dependsOn\":null,\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"endValue\":null,\"failedTip\":\"请输入1-99的一位小数\",\"group\":null,\"key\":\"aiParam.1001003.motion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测静止阈值\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"50.0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_1001003_motion.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_1001003_motion.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.6.6.name.description\",\"failedTipI18nKey\":\"resource.param.6.6.name.failedtip\",\"nameI18nKey\":\"resource.param.6.6.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "人员跌倒", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"487c1cf0\",\"preFlowActionId\":\"e7eadb5a\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"487c1cf0\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.6.aa_00001.487c1cf0.actionname\",\"remarkI18nKey\":\"resource.action.6.aa_00001.487c1cf0.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"c232a753\",\"preFlowActionId\":\"487c1cf0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.frames\",\"value\":\"10\",\"name\":\"行人检测追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.failedtip\"},{\"key\":\"aiParam.1001003.motion\",\"value\":\"80.0\",\"name\":\"行人检测静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.failedtip\"},{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"2\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.6.aa_00003.c232a753.actionname\",\"remarkI18nKey\":\"resource.action.6.aa_00003.c232a753.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"c37b8e34\",\"preFlowActionId\":\"d56fc47d\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"1\",\"class_name\":\"pedfalldown\",\"nameCN\":\"pedfalldown\",\"threshold\":[0.800000011920929],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002008\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedfalldown.confidence\",\"value\":\"\",\"name\":\"pedfalldown置信度\",\"defaultValue\":\"\",\"description\":\"pedfalldown置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.failedtip\"},{\"key\":\"aiParam.pedfalldown.confidenceConfig\",\"value\":\"\",\"name\":\"pedfalldown置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedfalldown置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2002008\",\"atomicName\":\"PedFalldown\",\"position\":\"c37b8e34\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"pedfalldown\",\"nameCN\":\"pedfalldown\",\"threshold\":[0.800000011920929],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002008\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2002008\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.6.aa_00002.c37b8e34.actionname\",\"remarkI18nKey\":\"resource.action.6.aa_00002.c37b8e34.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"e02bf44c\",\"preFlowActionId\":\"c37b8e34\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"7d6e8021\",\"level\":1,\"type\":14,\"keyL\":\"aiOut.pedfalldown.threshold\",\"keyR\":\"aiParam.pedfalldown.confidence\",\"list\":[],\"showTools\":false,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.6.ba_90001.e02bf44c.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_90001.e02bf44c.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"0f53b331\",\"preFlowActionId\":\"6dbede3b\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.6.ba_00004.0f53b331.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_00004.0f53b331.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"d56fc47d\",\"preFlowActionId\":\"c232a753\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"487c1cf0\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.6.ba_00002.d56fc47d.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_00002.d56fc47d.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"e7eadb5a\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.6.ba_00001.e7eadb5a.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_00001.e7eadb5a.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"6dbede3b\",\"preFlowActionId\":\"e02bf44c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"6dbede3b\",\"nameI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"6dbede3b\",\"nameI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.6.ba_00003.6dbede3b.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_00003.6dbede3b.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758684452877", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}]},{\"position\":\"c37b8e34\",\"atomicCode\":\"2002008\",\"atomicName\":\"PedFalldown\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"pedfalldown\",\"nameCN\":\"pedfalldown\",\"threshold\":[0.800000011920929],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002008\"}]}]", + "checkType": 3, + "confVersionId": "dcf739f37258473782863b9db9dcc12c", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683602000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "behavior", + "extraFormat": null, + "gafAlgorithmId": 6, + "gafAlgorithmName": "FallingDown", + "id": "6", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_behavior003", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用行人检测、跟踪算法,对进入检测区域的行人进行跌倒检测,对超过阈值的行人进行跌倒告警", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758684453000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "dcf739f37258473782863b9db9dcc12c", + "name": "默认", + "algorithmCode": 6, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"行人置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedestrian.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidence.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedestrian.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedestrian_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.pedestrian.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.6.6.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.6.6.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.6.6.aiparam_pedestrian_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_pedestrian_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedestrian_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"2.3\",\"dependsOn\":null,\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"endValue\":null,\"failedTip\":\"请输入0-100的两位小数\",\"group\":null,\"key\":\"aiParam.1001003.trackDynamicMatch\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪半径\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_1001003_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_1001003_trackdynamicmatch.name\"},{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"跌倒置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.pedfalldown.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"跌倒置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidence.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidence.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"跌倒置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.pedfalldown.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"跌倒置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.6.6.aiparam_pedfalldown_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.targetAlarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_targetalarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"endValue\":null,\"failedTip\":\"请输入0-100的整数\",\"group\":null,\"key\":\"param.targetAlarmCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警次数\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_targetalarmcount.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"endValue\":null,\"failedTip\":\"请选择是否打开叠加轨迹\",\"group\":null,\"key\":\"param.overlayTrajectory\",\"maxValue\":null,\"minValue\":null,\"name\":\"全景图叠加轨迹\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_overlaytrajectory.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.pedestrian.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小行人尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.6.6.filter_pedestrian_side_min.failedtip\",\"nameI18nKey\":\"resource.param.6.6.filter_pedestrian_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"10\",\"dependsOn\":null,\"description\":\"追踪历史帧数。范围:2~100\",\"endValue\":null,\"failedTip\":\"请输入2-100的整数\",\"group\":null,\"key\":\"aiParam.1001003.frames\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测追踪历史帧数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"step\":null,\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_1001003_frames.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_1001003_frames.name\"},{\"beginValue\":null,\"defaultValue\":\"50.0\",\"dependsOn\":null,\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"endValue\":null,\"failedTip\":\"请输入1-99的一位小数\",\"group\":null,\"key\":\"aiParam.1001003.motion\",\"maxValue\":null,\"minValue\":null,\"name\":\"行人检测静止阈值\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"50.0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.6.6.aiparam_1001003_motion.failedtip\",\"nameI18nKey\":\"resource.param.6.6.aiparam_1001003_motion.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.6.6.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.6.6.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.6.6.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.6.6.name.description\",\"failedTipI18nKey\":\"resource.param.6.6.name.failedtip\",\"nameI18nKey\":\"resource.param.6.6.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"487c1cf0\",\"preFlowActionId\":\"e7eadb5a\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"487c1cf0\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"3\"}]},\"actionNameI18nKey\":\"resource.action.6.aa_00001.487c1cf0.actionname\",\"remarkI18nKey\":\"resource.action.6.aa_00001.487c1cf0.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"c232a753\",\"preFlowActionId\":\"487c1cf0\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.1001003.frames\",\"value\":\"10\",\"name\":\"行人检测追踪历史帧数\",\"defaultValue\":\"10\",\"description\":\"追踪历史帧数。范围:2~100\",\"type\":\"text\",\"regexpr\":\"/^([2-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入2-100的整数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.failedtip\"},{\"key\":\"aiParam.1001003.motion\",\"value\":\"80.0\",\"name\":\"行人检测静止阈值\",\"defaultValue\":\"80.0\",\"description\":\"静止阈值。范围:1~99,例如:80.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-99的一位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.failedtip\"},{\"key\":\"aiParam.1001003.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"行人检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"1001003\"},{\"key\":\"motionStatus\",\"value\":\"2\"},{\"key\":\"shapeChangeStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.6.aa_00003.c232a753.actionname\",\"remarkI18nKey\":\"resource.action.6.aa_00003.c232a753.remark\"},{\"actionId\":\"AA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"分类算法,需要选择一个分类模型\",\"flowActionId\":\"c37b8e34\",\"preFlowActionId\":\"d56fc47d\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"1\",\"class_name\":\"pedfalldown\",\"nameCN\":\"pedfalldown\",\"threshold\":[0.800000011920929],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002008\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedfalldown.confidence\",\"value\":\"\",\"name\":\"pedfalldown置信度\",\"defaultValue\":\"\",\"description\":\"pedfalldown置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.description\",\"failedTipI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.failedtip\"},{\"key\":\"aiParam.pedfalldown.confidenceConfig\",\"value\":\"\",\"name\":\"pedfalldown置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedfalldown置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2002008\",\"atomicName\":\"PedFalldown\",\"position\":\"c37b8e34\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"pedfalldown\",\"nameCN\":\"pedfalldown\",\"threshold\":[0.800000011920929],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002008\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2002008\"},{\"key\":\"Enableftp\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.6.aa_00002.c37b8e34.actionname\",\"remarkI18nKey\":\"resource.action.6.aa_00002.c37b8e34.remark\"},{\"actionId\":\"BA_90001\",\"actionName\":\"目标判断\",\"remark\":\"目标判断\",\"flowActionId\":\"e02bf44c\",\"preFlowActionId\":\"c37b8e34\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[],\"condition\":{\"key\":\"7d6e8021\",\"level\":1,\"type\":14,\"keyL\":\"aiOut.pedfalldown.threshold\",\"keyR\":\"aiParam.pedfalldown.confidence\",\"list\":[],\"showTools\":false,\"rightType\":\"select\"}},\"actionNameI18nKey\":\"resource.action.6.ba_90001.e02bf44c.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_90001.e02bf44c.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"0f53b331\",\"preFlowActionId\":\"6dbede3b\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"3\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"value\":\"1\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"value\":\"0\",\"position\":\"0f53b331\",\"nameI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.6.ba_00004.0f53b331.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_00004.0f53b331.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"d56fc47d\",\"preFlowActionId\":\"c232a753\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"1001003\",\"labelCode\":\"pedestrian\",\"labelName\":\"行人\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"487c1cf0\"}],\"metaDataParams\":[{\"key\":\"filter.pedestrian.side.min\",\"value\":\"60\",\"name\":\"最小行人尺寸\",\"defaultValue\":\"60\",\"description\":\"最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.6.ba_00002.d56fc47d.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_00002.d56fc47d.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"e7eadb5a\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.6.ba_00001.e7eadb5a.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_00001.e7eadb5a.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"6dbede3b\",\"preFlowActionId\":\"e02bf44c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"6dbede3b\",\"nameI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"6dbede3b\",\"nameI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.6.ba_00003.6dbede3b.actionname\",\"remarkI18nKey\":\"resource.action.6.ba_00003.6dbede3b.remark\"}]", + "atomicList": "[{\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"487c1cf0\",\"atomicCode\":\"1001003\"}]},{\"position\":\"c37b8e34\",\"atomicCode\":\"2002008\",\"atomicName\":\"PedFalldown\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"pedfalldown\",\"nameCN\":\"pedfalldown\",\"threshold\":[0.800000011920929],\"used\":true,\"position\":\"c37b8e34\",\"atomicCode\":\"2002008\"}]}]", + "algorithmUpdateTime": 1776926024000, + "nameI18nKey": "resource.param.6.6.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.6.algorithmname", + "remarkI18nKey": "resource.algorithm.6.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/7602_\344\272\272\350\204\270\350\257\206\345\210\253\347\256\227\346\263\225_20260422103647.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/7602_\344\272\272\350\204\270\350\257\206\345\210\253\347\256\227\346\263\225_20260422103647.json" new file mode 100644 index 000000000..201fd6b57 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/7602_\344\272\272\350\204\270\350\257\206\345\210\253\347\256\227\346\263\225_20260422103647.json" @@ -0,0 +1,31 @@ +{ + "algorithmId": "7602", + "algorithmCode": 7602, + "algorithmName": "人脸识别算法", + "algorithmCategory": 1, + "algorithmUsage": 2, + "checkType": 15521, + "createTime": 1776825407000, + "updateTime": 1776825407000, + "confVersionId": "default-7602", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.7602.7602.name.description\",\"failedTipI18nKey\":\"resource.param.7602.7602.name.failedtip\",\"nameI18nKey\":\"resource.param.7602.7602.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-7602", + "name": "默认", + "algorithmCode": "7602", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.7602.7602.name.description\",\"failedTipI18nKey\":\"resource.param.7602.7602.name.failedtip\",\"nameI18nKey\":\"resource.param.7602.7602.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"PA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"d8241567\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"d8241567\",\"atomicCode\":\"1000001\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.face.confidence\",\"value\":\"\",\"name\":\"face置信度\",\"defaultValue\":\"\",\"description\":\"face置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.failedtip\"},{\"key\":\"aiParam.face.confidenceConfig\",\"value\":\"\",\"name\":\"face置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidenceconfig.description\"},{\"key\":\"aiParam.face.detPostion\",\"value\":\"0\",\"name\":\"face检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"position\":\"d8241567\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"d8241567\",\"atomicCode\":\"1000001\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000001\"}]},\"actionNameI18nKey\":\"resource.action.7602.pa_00001.d8241567.actionname\"},{\"actionId\":\"PA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"\",\"flowActionId\":\"2337df82\",\"preFlowActionId\":\"d8241567\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.frontFace.confidence\",\"value\":\"\",\"name\":\"frontFace置信度\",\"defaultValue\":\"\",\"description\":\"frontFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.failedtip\"},{\"key\":\"aiParam.frontFace.confidenceConfig\",\"value\":\"\",\"name\":\"frontFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidenceconfig.description\"},{\"key\":\"aiParam.fullFace.confidence\",\"value\":\"\",\"name\":\"fullFace置信度\",\"defaultValue\":\"\",\"description\":\"fullFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.failedtip\"},{\"key\":\"aiParam.fullFace.confidenceConfig\",\"value\":\"\",\"name\":\"fullFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"1000012\",\"atomicName\":\"FaceQuality\",\"position\":\"2337df82\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000012\"}]},\"actionNameI18nKey\":\"resource.action.7602.pa_00002.2337df82.actionname\"},{\"actionId\":\"PA_00004\",\"actionName\":\"关键点算法\",\"remark\":\"\",\"flowActionId\":\"34499952\",\"preFlowActionId\":\"2337df82\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"1000016\",\"atomicName\":\"FaceLandmark\",\"position\":\"34499952\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000016\"}]},\"actionNameI18nKey\":\"resource.action.7602.pa_00004.34499952.actionname\"},{\"actionId\":\"PA_00005\",\"actionName\":\"特征提取算法\",\"remark\":\"\",\"flowActionId\":\"c0d31881\",\"preFlowActionId\":\"34499952\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"type\":\"faceSet\",\"description\":\"选择需要比对的脸库分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.faceSet\",\"name\":\"绑定人脸分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"0\"},\"level\":\"2\",\"regexpr\":\"\",\"value\":\"\",\"position\":\"c0d31881\",\"descriptionI18nKey\":\"resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.failedtip\",\"nameI18nKey\":\"resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.name\"}],\"atomic\":{\"atomicCode\":\"1000005\",\"atomicName\":\"FaceRGBRecognition\",\"position\":\"c0d31881\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000005\"},{\"key\":\"featureInput\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.7602.pa_00005.c0d31881.actionname\"}]", + "atomicList": "[{\"position\":\"d8241567\",\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"d8241567\",\"atomicCode\":\"1000001\"}]},{\"position\":\"2337df82\",\"atomicCode\":\"1000012\",\"atomicName\":\"FaceQuality\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"}]},{\"position\":\"34499952\",\"atomicCode\":\"1000016\",\"atomicName\":\"FaceLandmark\",\"labelList\":[]},{\"position\":\"c0d31881\",\"atomicCode\":\"1000005\",\"atomicName\":\"FaceRGBRecognition\",\"labelList\":[]}]", + "algorithmUpdateTime": 1776825902000, + "remark": "人脸特征值提取", + "nameI18nKey": "resource.param.7602.7602.0.name", + "remarkI18nKey": "resource.algorithm.7602.remark" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"PA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"d8241567\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"d8241567\",\"atomicCode\":\"1000001\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.face.confidence\",\"value\":\"\",\"name\":\"face置信度\",\"defaultValue\":\"\",\"description\":\"face置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.failedtip\"},{\"key\":\"aiParam.face.confidenceConfig\",\"value\":\"\",\"name\":\"face置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_confidenceconfig.description\"},{\"key\":\"aiParam.face.detPostion\",\"value\":\"0\",\"name\":\"face检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"position\":\"d8241567\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"d8241567\",\"atomicCode\":\"1000001\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000001\"}]},\"actionNameI18nKey\":\"resource.action.7602.pa_00001.d8241567.actionname\"},{\"actionId\":\"PA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"\",\"flowActionId\":\"2337df82\",\"preFlowActionId\":\"d8241567\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.frontFace.confidence\",\"value\":\"\",\"name\":\"frontFace置信度\",\"defaultValue\":\"\",\"description\":\"frontFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.failedtip\"},{\"key\":\"aiParam.frontFace.confidenceConfig\",\"value\":\"\",\"name\":\"frontFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidenceconfig.description\"},{\"key\":\"aiParam.fullFace.confidence\",\"value\":\"\",\"name\":\"fullFace置信度\",\"defaultValue\":\"\",\"description\":\"fullFace置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.failedtip\"},{\"key\":\"aiParam.fullFace.confidenceConfig\",\"value\":\"\",\"name\":\"fullFace置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"1000012\",\"atomicName\":\"FaceQuality\",\"position\":\"2337df82\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000012\"}]},\"actionNameI18nKey\":\"resource.action.7602.pa_00002.2337df82.actionname\"},{\"actionId\":\"PA_00004\",\"actionName\":\"关键点算法\",\"remark\":\"\",\"flowActionId\":\"34499952\",\"preFlowActionId\":\"2337df82\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"1000016\",\"atomicName\":\"FaceLandmark\",\"position\":\"34499952\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000016\"}]},\"actionNameI18nKey\":\"resource.action.7602.pa_00004.34499952.actionname\"},{\"actionId\":\"PA_00005\",\"actionName\":\"特征提取算法\",\"remark\":\"\",\"flowActionId\":\"c0d31881\",\"preFlowActionId\":\"34499952\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"type\":\"faceSet\",\"description\":\"选择需要比对的脸库分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.faceSet\",\"name\":\"绑定人脸分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"0\"},\"level\":\"2\",\"regexpr\":\"\",\"value\":\"\",\"position\":\"c0d31881\",\"descriptionI18nKey\":\"resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.description\",\"failedTipI18nKey\":\"resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.failedtip\",\"nameI18nKey\":\"resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.name\"}],\"atomic\":{\"atomicCode\":\"1000005\",\"atomicName\":\"FaceRGBRecognition\",\"position\":\"c0d31881\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1000005\"},{\"key\":\"featureInput\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.7602.pa_00005.c0d31881.actionname\"}]", + "atomicList": "[{\"position\":\"d8241567\",\"atomicCode\":\"1000001\",\"atomicName\":\"FaceRGBDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"face\",\"nameCN\":\"face\",\"threshold\":[0.6600000262260437],\"used\":true,\"position\":\"d8241567\",\"atomicCode\":\"1000001\"}]},{\"position\":\"2337df82\",\"atomicCode\":\"1000012\",\"atomicName\":\"FaceQuality\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"frontFace\",\"nameCN\":\"frontFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"},{\"label\":\"2\",\"class_name\":\"fullFace\",\"nameCN\":\"fullFace\",\"threshold\":[0],\"used\":true,\"position\":\"2337df82\",\"atomicCode\":\"1000012\"}]},{\"position\":\"34499952\",\"atomicCode\":\"1000016\",\"atomicName\":\"FaceLandmark\",\"labelList\":[]},{\"position\":\"c0d31881\",\"atomicCode\":\"1000005\",\"atomicName\":\"FaceRGBRecognition\",\"labelList\":[]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.7602.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/77380_\346\243\200\346\265\213\345\220\216\345\210\206\347\261\273\347\256\227\346\263\225_20260414160117.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/77380_\346\243\200\346\265\213\345\220\216\345\210\206\347\261\273\347\256\227\346\263\225_20260414160117.json" new file mode 100644 index 000000000..72e46e7dd --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/77380_\346\243\200\346\265\213\345\220\216\345\210\206\347\261\273\347\256\227\346\263\225_20260414160117.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "77380", + "algorithmCode": 77380, + "algorithmName": "检测后分类算法", + "algorithmCategory": 2, + "algorithmUsage": 2, + "checkType": 85299, + "createTime": 1776153677000, + "updateTime": 1776153677000, + "confVersionId": "default-77380", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.77380.77380.name.description\",\"failedTipI18nKey\":\"resource.param.77380.77380.name.failedtip\",\"nameI18nKey\":\"resource.param.77380.77380.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-77380", + "name": "默认", + "algorithmCode": "77380", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.77380.77380.name.description\",\"failedTipI18nKey\":\"resource.param.77380.77380.name.failedtip\",\"nameI18nKey\":\"resource.param.77380.77380.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"PA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"27f515bd\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"27f515bd\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"27f515bd\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"27f515bd\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"}]},\"actionNameI18nKey\":\"resource.action.77380.pa_00001.27f515bd.actionname\"},{\"actionId\":\"PA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"\",\"flowActionId\":\"27e33c9b\",\"preFlowActionId\":\"27f515bd\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"nameCN\":\"pedHelmet\",\"threshold\":[0.38999998569488525],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"nameCN\":\"pedSafeHelmet\",\"threshold\":[0.10000000149011612],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"2\",\"class_name\":\"normalHat\",\"nameCN\":\"normalHat\",\"threshold\":[0.75],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"nameCN\":\"hatless\",\"threshold\":[0.949999988079071],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"nameCN\":\"unsure\",\"threshold\":[0.30000001192092896],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedHelmet.confidence\",\"value\":\"\",\"name\":\"pedHelmet置信度\",\"defaultValue\":\"\",\"description\":\"pedHelmet置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.failedtip\"},{\"key\":\"aiParam.pedHelmet.confidenceConfig\",\"value\":\"\",\"name\":\"pedHelmet置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.description\"},{\"key\":\"aiParam.pedSafeHelmet.confidence\",\"value\":\"\",\"name\":\"pedSafeHelmet置信度\",\"defaultValue\":\"\",\"description\":\"pedSafeHelmet置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.failedtip\"},{\"key\":\"aiParam.pedSafeHelmet.confidenceConfig\",\"value\":\"\",\"name\":\"pedSafeHelmet置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedSafeHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.description\"},{\"key\":\"aiParam.normalHat.confidence\",\"value\":\"\",\"name\":\"normalHat置信度\",\"defaultValue\":\"\",\"description\":\"normalHat置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.failedtip\"},{\"key\":\"aiParam.normalHat.confidenceConfig\",\"value\":\"\",\"name\":\"normalHat置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"normalHat置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.description\"},{\"key\":\"aiParam.hatless.confidence\",\"value\":\"\",\"name\":\"hatless置信度\",\"defaultValue\":\"\",\"description\":\"hatless置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.failedtip\"},{\"key\":\"aiParam.hatless.confidenceConfig\",\"value\":\"\",\"name\":\"hatless置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"hatless置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.description\"},{\"key\":\"aiParam.unsure.confidence\",\"value\":\"\",\"name\":\"unsure置信度\",\"defaultValue\":\"\",\"description\":\"unsure置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.failedtip\"},{\"key\":\"aiParam.unsure.confidenceConfig\",\"value\":\"\",\"name\":\"unsure置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"unsure置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2001036\",\"atomicName\":\"PedHelemet\",\"position\":\"27e33c9b\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"nameCN\":\"pedHelmet\",\"threshold\":[0.38999998569488525],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"nameCN\":\"pedSafeHelmet\",\"threshold\":[0.10000000149011612],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"2\",\"class_name\":\"normalHat\",\"nameCN\":\"normalHat\",\"threshold\":[0.75],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"nameCN\":\"hatless\",\"threshold\":[0.949999988079071],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"nameCN\":\"unsure\",\"threshold\":[0.30000001192092896],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2001036\"}]},\"actionNameI18nKey\":\"resource.action.77380.pa_00002.27e33c9b.actionname\"}]", + "atomicList": "[{\"position\":\"27f515bd\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"27f515bd\",\"atomicCode\":\"1001003\"}]},{\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\",\"atomicName\":\"PedHelemet\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"nameCN\":\"pedHelmet\",\"threshold\":[0.38999998569488525],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"nameCN\":\"pedSafeHelmet\",\"threshold\":[0.10000000149011612],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"2\",\"class_name\":\"normalHat\",\"nameCN\":\"normalHat\",\"threshold\":[0.75],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"nameCN\":\"hatless\",\"threshold\":[0.949999988079071],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"nameCN\":\"unsure\",\"threshold\":[0.30000001192092896],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"}]}]", + "algorithmUpdateTime": 1776153740000, + "remark": "", + "nameI18nKey": "resource.param.77380.77380.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"PA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"\",\"flowActionId\":\"27f515bd\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"27f515bd\",\"atomicCode\":\"1001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedestrian.confidence\",\"value\":\"\",\"name\":\"pedestrian置信度\",\"defaultValue\":\"\",\"description\":\"pedestrian置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.failedtip\"},{\"key\":\"aiParam.pedestrian.confidenceConfig\",\"value\":\"\",\"name\":\"pedestrian置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.description\"},{\"key\":\"aiParam.pedestrian.detPostion\",\"value\":\"0\",\"name\":\"pedestrian检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"position\":\"27f515bd\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"27f515bd\",\"atomicCode\":\"1001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"1001003\"}]},\"actionNameI18nKey\":\"resource.action.77380.pa_00001.27f515bd.actionname\"},{\"actionId\":\"PA_00002\",\"actionName\":\"目标分类算法\",\"remark\":\"\",\"flowActionId\":\"27e33c9b\",\"preFlowActionId\":\"27f515bd\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"nameCN\":\"pedHelmet\",\"threshold\":[0.38999998569488525],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"nameCN\":\"pedSafeHelmet\",\"threshold\":[0.10000000149011612],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"2\",\"class_name\":\"normalHat\",\"nameCN\":\"normalHat\",\"threshold\":[0.75],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"nameCN\":\"hatless\",\"threshold\":[0.949999988079071],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"nameCN\":\"unsure\",\"threshold\":[0.30000001192092896],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.pedHelmet.confidence\",\"value\":\"\",\"name\":\"pedHelmet置信度\",\"defaultValue\":\"\",\"description\":\"pedHelmet置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.failedtip\"},{\"key\":\"aiParam.pedHelmet.confidenceConfig\",\"value\":\"\",\"name\":\"pedHelmet置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.description\"},{\"key\":\"aiParam.pedSafeHelmet.confidence\",\"value\":\"\",\"name\":\"pedSafeHelmet置信度\",\"defaultValue\":\"\",\"description\":\"pedSafeHelmet置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.failedtip\"},{\"key\":\"aiParam.pedSafeHelmet.confidenceConfig\",\"value\":\"\",\"name\":\"pedSafeHelmet置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"pedSafeHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.description\"},{\"key\":\"aiParam.normalHat.confidence\",\"value\":\"\",\"name\":\"normalHat置信度\",\"defaultValue\":\"\",\"description\":\"normalHat置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.failedtip\"},{\"key\":\"aiParam.normalHat.confidenceConfig\",\"value\":\"\",\"name\":\"normalHat置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"normalHat置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.description\"},{\"key\":\"aiParam.hatless.confidence\",\"value\":\"\",\"name\":\"hatless置信度\",\"defaultValue\":\"\",\"description\":\"hatless置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.failedtip\"},{\"key\":\"aiParam.hatless.confidenceConfig\",\"value\":\"\",\"name\":\"hatless置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"hatless置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.description\"},{\"key\":\"aiParam.unsure.confidence\",\"value\":\"\",\"name\":\"unsure置信度\",\"defaultValue\":\"\",\"description\":\"unsure置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.description\",\"failedTipI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.failedtip\"},{\"key\":\"aiParam.unsure.confidenceConfig\",\"value\":\"\",\"name\":\"unsure置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"unsure置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.description\"}],\"atomic\":{\"atomicCode\":\"2001036\",\"atomicName\":\"PedHelemet\",\"position\":\"27e33c9b\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"nameCN\":\"pedHelmet\",\"threshold\":[0.38999998569488525],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"nameCN\":\"pedSafeHelmet\",\"threshold\":[0.10000000149011612],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"2\",\"class_name\":\"normalHat\",\"nameCN\":\"normalHat\",\"threshold\":[0.75],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"nameCN\":\"hatless\",\"threshold\":[0.949999988079071],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"nameCN\":\"unsure\",\"threshold\":[0.30000001192092896],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2001036\"}]},\"actionNameI18nKey\":\"resource.action.77380.pa_00002.27e33c9b.actionname\"}]", + "atomicList": "[{\"position\":\"27f515bd\",\"atomicCode\":\"1001003\",\"atomicName\":\"PedestrianDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedestrian\",\"nameCN\":\"pedestrian\",\"threshold\":[0.6299999952316284],\"used\":true,\"position\":\"27f515bd\",\"atomicCode\":\"1001003\"}]},{\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\",\"atomicName\":\"PedHelemet\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"pedHelmet\",\"nameCN\":\"pedHelmet\",\"threshold\":[0.38999998569488525],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"1\",\"class_name\":\"pedSafeHelmet\",\"nameCN\":\"pedSafeHelmet\",\"threshold\":[0.10000000149011612],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"2\",\"class_name\":\"normalHat\",\"nameCN\":\"normalHat\",\"threshold\":[0.75],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"3\",\"class_name\":\"hatless\",\"nameCN\":\"hatless\",\"threshold\":[0.949999988079071],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"},{\"label\":\"4\",\"class_name\":\"unsure\",\"nameCN\":\"unsure\",\"threshold\":[0.30000001192092896],\"used\":true,\"position\":\"27e33c9b\",\"atomicCode\":\"2001036\"}]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.77380.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/7_\350\275\246\350\276\206\350\277\235\345\201\234_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/7_\350\275\246\350\276\206\350\277\235\345\201\234_1759134672.json" new file mode 100644 index 000000000..749306186 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/7_\350\275\246\350\276\206\350\277\235\345\201\234_1759134672.json" @@ -0,0 +1,37 @@ +{ + "algorithmCategory": 3, + "algorithmCode": 7, + "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"非机动车置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.nonMotorVehicle.confidence\",\"name\":\"非机动车置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.aiparam_nonmotorvehicle_confidence.description\",\"failedTipI18nKey\":\"resource.param.7.7.aiparam_nonmotorvehicle_confidence.failedtip\",\"nameI18nKey\":\"resource.param.7.7.aiparam_nonmotorvehicle_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"非机动车置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.nonMotorVehicle.confidenceConfig\",\"name\":\"非机动车置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.aiparam_nonmotorvehicle_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.7.7.aiparam_nonmotorvehicle_confidenceconfig.name\"},{\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.nonMotorVehicle.detPostion\",\"name\":\"非机动车检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.7.7.aiparam_nonmotorvehicle_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.7.7.aiparam_nonmotorvehicle_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.7.7.aiparam_nonmotorvehicle_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.aiparam_nonmotorvehicle_detpostion.description\",\"failedTipI18nKey\":\"resource.param.7.7.aiparam_nonmotorvehicle_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.7.7.aiparam_nonmotorvehicle_detpostion.name\"},{\"defaultValue\":\"\",\"description\":\"车辆置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.vehicle.confidence\",\"name\":\"车辆置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.aiparam_vehicle_confidence.description\",\"failedTipI18nKey\":\"resource.param.7.7.aiparam_vehicle_confidence.failedtip\",\"nameI18nKey\":\"resource.param.7.7.aiparam_vehicle_confidence.name\"},{\"defaultValue\":\"0,0\",\"description\":\"车辆置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"failedTip\":\"\",\"key\":\"aiParam.vehicle.confidenceConfig\",\"name\":\"车辆置信度偏移\",\"senior\":1,\"regexpr\":\"\",\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.aiparam_vehicle_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.7.7.aiparam_vehicle_confidenceconfig.name\"},{\"defaultValue\":\"1\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"failedTip\":\"请选择正确的值\",\"key\":\"aiParam.vehicle.detPostion\",\"name\":\"车辆检测方式\",\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.7.7.aiparam_vehicle_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.7.7.aiparam_vehicle_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.7.7.aiparam_vehicle_detpostion.2.options_name\"}],\"regexpr\":\"/^[0-2]$/\",\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.aiparam_vehicle_detpostion.description\",\"failedTipI18nKey\":\"resource.param.7.7.aiparam_vehicle_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.7.7.aiparam_vehicle_detpostion.name\"},{\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"failedTip\":\"请输入0-100的两位小数\",\"key\":\"aiParam.2000001.trackDynamicMatch\",\"name\":\"车辆检测追踪半径\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"2.3\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.aiparam_2000001_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.7.7.aiparam_2000001_trackdynamicmatch.failedtip\",\"nameI18nKey\":\"resource.param.7.7.aiparam_2000001_trackdynamicmatch.name\"},{\"defaultValue\":\"60\",\"description\":\"最小车辆尺寸:车辆抓拍照片的最小图像尺寸。如输入值为100,则最小车辆尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"failedTip\":\"请输入0-10000的整数\",\"key\":\"filter.vehicle.side.min\",\"name\":\"最小车辆尺寸\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.filter_vehicle_side_min.description\",\"failedTipI18nKey\":\"resource.param.7.7.filter_vehicle_side_min.failedtip\",\"nameI18nKey\":\"resource.param.7.7.filter_vehicle_side_min.name\"},{\"defaultValue\":\"60\",\"description\":\"最小非机动车尺寸:非机动车抓拍照片的最小图像尺寸。如输入值为100,则最小非机动车尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"failedTip\":\"请输入0-10000的整数\",\"key\":\"filter.nonMotorVehicle.side.min\",\"name\":\"最小非机动车尺寸\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.filter_nonmotorvehicle_side_min.description\",\"failedTipI18nKey\":\"resource.param.7.7.filter_nonmotorvehicle_side_min.failedtip\",\"nameI18nKey\":\"resource.param.7.7.filter_nonmotorvehicle_side_min.name\"},{\"defaultValue\":\"60\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"failedTip\":\"请输入1-36000的整数\",\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_targetalarminterval.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_targetalarminterval.name\"},{\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"failedTip\":\"请输入0-100的整数\",\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_targetalarmcount.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_targetalarmcount.name\"},{\"defaultValue\":\"1\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_restrainswitch.name\"},{\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_overlaprate.param_restrainswitch.1.name\"},{\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"failedTip\":\"请输入0-24的整数。\",\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_restraintime.param_restrainswitch.1.name\"},{\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"senior\":1,\"regexpr\":\"/^[01]$/\",\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_overlaytrajectory.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_overlaytrajectory.name\"},{\"defaultValue\":\"10\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"failedTip\":\"请输入正确的数值\",\"key\":\"param.areaDuration\",\"name\":\"检测时间\",\"regexpr\":\"\",\"type\":\"text\",\"value\":\"10\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_areaduration.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_areaduration.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_areaduration.name\"},{\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"failedTip\":\"请选择正确的数值\",\"key\":\"param.areaDurationTimeType\",\"name\":\"检测时间单位\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.7.7.param_areadurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.7.7.param_areadurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.7.7.param_areadurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.7.7.param_areadurationtimetype.3600000.options_name\"}],\"regexpr\":\"\",\"type\":\"select\",\"value\":\"1000\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_areadurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_areadurationtimetype.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_areadurationtimetype.name\"},{\"defaultValue\":\"1\",\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"failedTip\":\"请输入1-100的整数\",\"key\":\"param.videoRepeatCount\",\"name\":\"离线视频播放次数\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_videorepeatcount.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_videorepeatcount.name\"},{\"defaultValue\":\"-1\",\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"param.videoReadFps\",\"name\":\"离线视频播放取帧帧率\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"-1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.7.7.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.7.7.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.7.7.param_videoreadfps.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.7.7.name.description\",\"failedTipI18nKey\":\"resource.param.7.7.name.failedtip\",\"nameI18nKey\":\"resource.param.7.7.name.name\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmName": "车辆违停", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"ddd59411\",\"preFlowActionId\":\"20a13b0a\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"1\",\"class_name\":\"nonMotorVehicle\",\"threshold\":[0.908,0.908],\"nameCN\":\"非机动车\",\"used\":true,\"position\":\"ddd59411\",\"atomicCode\":\"2000001\",\"nameCNI18nKey\":\"resource.param.7.aa_00001.ddd59411.2000001.1.nonmotorvehicle.namecn\"},{\"label\":\"2\",\"class_name\":\"vehicle\",\"threshold\":[0.91,0.91],\"nameCN\":\"车辆\",\"used\":true,\"position\":\"ddd59411\",\"atomicCode\":\"2000001\",\"nameCNI18nKey\":\"resource.param.7.aa_00001.ddd59411.2000001.2.vehicle.namecn\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.nonMotorVehicle.confidence\",\"value\":\"\",\"name\":\"非机动车置信度\",\"defaultValue\":\"\",\"description\":\"非机动车置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.name\",\"descriptionI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.description\",\"failedTipI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.failedtip\"},{\"key\":\"aiParam.nonMotorVehicle.confidenceConfig\",\"value\":\"\",\"name\":\"非机动车置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"非机动车置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidenceconfig.description\"},{\"key\":\"aiParam.nonMotorVehicle.detPostion\",\"value\":\"0\",\"name\":\"非机动车检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.name\",\"descriptionI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.description\",\"failedTipI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.failedtip\"},{\"key\":\"aiParam.vehicle.confidence\",\"value\":\"\",\"name\":\"车辆置信度\",\"defaultValue\":\"\",\"description\":\"车辆置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.name\",\"descriptionI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.description\",\"failedTipI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.failedtip\"},{\"key\":\"aiParam.vehicle.confidenceConfig\",\"value\":\"\",\"name\":\"车辆置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"车辆置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidenceconfig.description\"},{\"key\":\"aiParam.vehicle.detPostion\",\"value\":\"0\",\"name\":\"车辆检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.name\",\"descriptionI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.description\",\"failedTipI18nKey\":\"resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"2000001\",\"atomicName\":\"车辆检测\",\"position\":\"ddd59411\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"nonMotorVehicle\",\"threshold\":[0.908,0.908],\"nameCN\":\"非机动车\",\"used\":true,\"position\":\"ddd59411\",\"atomicCode\":\"2000001\",\"nameCNI18nKey\":\"resource.param.7.aa_00001.ddd59411.2000001.1.nonmotorvehicle.namecn\"},{\"label\":\"2\",\"class_name\":\"vehicle\",\"threshold\":[0.91,0.91],\"nameCN\":\"车辆\",\"used\":true,\"position\":\"ddd59411\",\"atomicCode\":\"2000001\",\"nameCNI18nKey\":\"resource.param.7.aa_00001.ddd59411.2000001.2.vehicle.namecn\"}]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2000001\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.7.aa_00001.ddd59411.actionname\",\"remarkI18nKey\":\"resource.action.7.aa_00001.ddd59411.remark\"},{\"actionId\":\"AA_00003\",\"actionName\":\"追踪算法\",\"remark\":\"需要人体追踪时放在检测算法后\",\"flowActionId\":\"10a89d8c\",\"preFlowActionId\":\"ddd59411\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.2000001.trackDynamicMatch\",\"value\":\"2.3\",\"name\":\"车辆检测追踪半径\",\"defaultValue\":\"2.3\",\"description\":\"追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-100的两位小数\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.name\",\"descriptionI18nKey\":\"resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.description\",\"failedTipI18nKey\":\"resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"trackSelect\",\"value\":\"2000001\"},{\"key\":\"motionStatus\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.7.aa_00003.10a89d8c.actionname\",\"remarkI18nKey\":\"resource.action.7.aa_00003.10a89d8c.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"498141de\",\"preFlowActionId\":\"10a89d8c\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"2000001\",\"labelCode\":\"vehicle\",\"labelName\":\"车辆\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"ddd59411\"},{\"atomicCode\":\"2000001\",\"labelCode\":\"nonMotorVehicle\",\"labelName\":\"非机动车\",\"position\":\"ddd59411\",\"sideMinIsEnable\":\"1\",\"collapse\":true}],\"metaDataParams\":[{\"key\":\"filter.vehicle.side.min\",\"value\":\"60\",\"name\":\"最小车辆尺寸\",\"defaultValue\":\"60\",\"description\":\"最小车辆尺寸:车辆抓拍照片的最小图像尺寸。如输入值为100,则最小车辆尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.7.ba_00002.498141de.filter_vehicle_side_min.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00002.498141de.filter_vehicle_side_min.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00002.498141de.filter_vehicle_side_min.failedtip\"},{\"key\":\"filter.nonMotorVehicle.side.min\",\"value\":\"60\",\"name\":\"最小非机动车尺寸\",\"defaultValue\":\"60\",\"description\":\"最小非机动车尺寸:非机动车抓拍照片的最小图像尺寸。如输入值为100,则最小非机动车尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.7.ba_00002.498141de.actionname\",\"remarkI18nKey\":\"resource.action.7.ba_00002.498141de.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"2add29ef\",\"preFlowActionId\":\"7d7b0fa3\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"3\",\"position\":\"2add29ef\",\"nameI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_targetalarminterval.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_targetalarminterval.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_targetalarminterval.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"senior\":0,\"value\":\"1\",\"position\":\"2add29ef\",\"nameI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_targetalarmcount.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_targetalarmcount.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_targetalarmcount.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"2add29ef\",\"nameI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"2add29ef\",\"nameI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"2add29ef\",\"nameI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"senior\":1,\"value\":\"0\",\"position\":\"2add29ef\",\"nameI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"2\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.7.ba_00004.2add29ef.actionname\",\"remarkI18nKey\":\"resource.action.7.ba_00004.2add29ef.remark\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法\",\"flowActionId\":\"7d7b0fa3\",\"preFlowActionId\":\"498141de\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.areaDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"7d7b0fa3\",\"nameI18nKey\":\"resource.param.7.ba_00005.7d7b0fa3.param_areaduration.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00005.7d7b0fa3.param_areaduration.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00005.7d7b0fa3.param_areaduration.failedtip\"},{\"key\":\"param.areaDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"senior\":0,\"value\":\"1000\",\"position\":\"7d7b0fa3\",\"nameI18nKey\":\"resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"4\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"durationBreakAreaType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.7.ba_00005.7d7b0fa3.actionname\",\"remarkI18nKey\":\"resource.action.7.ba_00005.7d7b0fa3.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"20a13b0a\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.videoRepeatCount\",\"name\":\"离线视频播放次数\",\"defaultValue\":\"1\",\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-100的整数\",\"level\":\"2\",\"senior\":1,\"value\":\"1\",\"position\":\"20a13b0a\",\"nameI18nKey\":\"resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.name\",\"descriptionI18nKey\":\"resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"-1\",\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"param.videoReadFps\",\"name\":\"离线视频播放取帧帧率\",\"level\":\"2\",\"regexpr\":\"\",\"senior\":1,\"value\":\"-1\",\"position\":\"20a13b0a\",\"descriptionI18nKey\":\"resource.param.7.ba_00001.20a13b0a.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.7.ba_00001.20a13b0a.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.7.ba_00001.20a13b0a.param_videoreadfps.name\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.7.ba_00001.20a13b0a.actionname\",\"remarkI18nKey\":\"resource.action.7.ba_00001.20a13b0a.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758699227973", + "algorithmUsage": 1, + "atomicList": "[{\"labelList\":[{\"label\":\"1\",\"class_name\":\"nonMotorVehicle\",\"threshold\":[0.908,0.908],\"nameCN\":\"非机动车\",\"used\":true,\"position\":\"ddd59411\",\"atomicCode\":\"2000001\",\"nameCNI18nKey\":\"resource.param.7.7.2000001.1.nonmotorvehicle.namecn\"},{\"label\":\"2\",\"class_name\":\"vehicle\",\"threshold\":[0.91,0.91],\"nameCN\":\"车辆\",\"used\":true,\"position\":\"ddd59411\",\"atomicCode\":\"2000001\",\"nameCNI18nKey\":\"resource.param.7.7.2000001.2.vehicle.namecn\"}],\"atomicName\":\"车辆检测\",\"atomicCode\":\"2000001\",\"position\":\"ddd59411\"}]", + "checkType": 1, + "confVersionId": "4ddf6e7111014fc39ed72e767d6a7421", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683602000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "motorCommodity", + "extraFormat": null, + "gafAlgorithmId": 7, + "gafAlgorithmName": "ParkingDetect", + "id": "7", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_commodity001", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用机动车检测、跟踪算法,对进入检测区域的机动车进行检测,对超过阈值时间的机动车进行告警。\n机动车:支持三轮电动车、摩托车(带排气管)、轿车、SUV、卡车。\n应用非机动车检测算法,对进入检测区域的非机动车进行检测,对超过阈值时间的非机动车进行告警。\n非机动车:支持两轮电动车、自行车、人力三轮车", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758699228000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "algorithmNameI18nKey": "resource.algorithm.7.algorithmname", + "remarkI18nKey": "resource.algorithm.7.remark" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/82819_\346\243\200\346\265\213\345\220\216\345\210\206\345\211\262\347\256\227\346\263\225_20260414155302.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/82819_\346\243\200\346\265\213\345\220\216\345\210\206\345\211\262\347\256\227\346\263\225_20260414155302.json" new file mode 100644 index 000000000..ab5e3423f --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/82819_\346\243\200\346\265\213\345\220\216\345\210\206\345\211\262\347\256\227\346\263\225_20260414155302.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "82819", + "algorithmCode": 82819, + "algorithmName": "检测后分割算法", + "algorithmCategory": 2, + "algorithmUsage": 2, + "checkType": 90738, + "createTime": 1776153182000, + "updateTime": 1776153182000, + "confVersionId": "default-82819", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.82819.82819.name.description\",\"failedTipI18nKey\":\"resource.param.82819.82819.name.failedtip\",\"nameI18nKey\":\"resource.param.82819.82819.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-82819", + "name": "默认", + "algorithmCode": "82819", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.82819.82819.name.description\",\"failedTipI18nKey\":\"resource.param.82819.82819.name.failedtip\",\"nameI18nKey\":\"resource.param.82819.82819.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"PDA_00001\",\"actionName\":\"检测视觉大模型\",\"remark\":\"\",\"flowActionId\":\"f15b0a07\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"position\":\"f15b0a07\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888890\"},{\"key\":\"keywords\",\"value\":\"person\"},{\"key\":\"aiParam.box.confidence\",\"value\":\"0.25\"},{\"key\":\"aiParam.text.confidence\",\"value\":\"0.3\"}]},\"actionNameI18nKey\":\"resource.action.82819.pda_00001.f15b0a07.actionname\"},{\"actionId\":\"PDA_00002\",\"actionName\":\"分割视觉大模型\",\"remark\":\"\",\"flowActionId\":\"ff07761f\",\"preFlowActionId\":\"f15b0a07\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"position\":\"ff07761f\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6666688\"},{\"key\":\"inputType\",\"value\":\"box\"}]},\"actionNameI18nKey\":\"resource.action.82819.pda_00002.ff07761f.actionname\"}]", + "atomicList": "[{\"position\":\"f15b0a07\",\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"labelList\":[]},{\"position\":\"ff07761f\",\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"labelList\":[]}]", + "algorithmUpdateTime": 1776153215000, + "remark": "", + "nameI18nKey": "resource.param.82819.82819.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"PDA_00001\",\"actionName\":\"检测视觉大模型\",\"remark\":\"\",\"flowActionId\":\"f15b0a07\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"position\":\"f15b0a07\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888890\"},{\"key\":\"keywords\",\"value\":\"person\"},{\"key\":\"aiParam.box.confidence\",\"value\":\"0.25\"},{\"key\":\"aiParam.text.confidence\",\"value\":\"0.3\"}]},\"actionNameI18nKey\":\"resource.action.82819.pda_00001.f15b0a07.actionname\"},{\"actionId\":\"PDA_00002\",\"actionName\":\"分割视觉大模型\",\"remark\":\"\",\"flowActionId\":\"ff07761f\",\"preFlowActionId\":\"f15b0a07\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"position\":\"ff07761f\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6666688\"},{\"key\":\"inputType\",\"value\":\"box\"}]},\"actionNameI18nKey\":\"resource.action.82819.pda_00002.ff07761f.actionname\"}]", + "atomicList": "[{\"position\":\"f15b0a07\",\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"labelList\":[]},{\"position\":\"ff07761f\",\"atomicCode\":\"6666688\",\"atomicName\":\"SAM2ImageEncoder\",\"labelList\":[]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.82819.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/8533_\350\247\206\350\247\211\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175828.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/8533_\350\247\206\350\247\211\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175828.json" new file mode 100644 index 000000000..dc9ebdda9 --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/8533_\350\247\206\350\247\211\346\243\200\346\265\213\345\244\247\346\250\241\345\236\213\345\210\206\346\236\220_20260413175828.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "8533", + "algorithmCode": 8533, + "algorithmName": "视觉检测大模型分析", + "algorithmCategory": 2, + "algorithmUsage": 1, + "checkType": 16452, + "createTime": 1776074308000, + "updateTime": 1776074308000, + "confVersionId": "default-8533", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.8533.8533.name.description\",\"failedTipI18nKey\":\"resource.param.8533.8533.name.failedtip\",\"nameI18nKey\":\"resource.param.8533.8533.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-8533", + "name": "默认", + "algorithmCode": "8533", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.8533.8533.name.description\",\"failedTipI18nKey\":\"resource.param.8533.8533.name.failedtip\",\"nameI18nKey\":\"resource.param.8533.8533.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"\",\"flowActionId\":\"7d004992\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.8533.ba_00001.7d004992.actionname\"},{\"actionId\":\"DA_00001\",\"actionName\":\"检测视觉大模型\",\"remark\":\"\",\"flowActionId\":\"9599adc7\",\"preFlowActionId\":\"7d004992\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"position\":\"9599adc7\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888890\"},{\"key\":\"fps\",\"value\":\"0.5\"},{\"key\":\"keywords\",\"value\":\"person\"},{\"key\":\"aiParam.box.confidence\",\"value\":\"0.25\"},{\"key\":\"aiParam.text.confidence\",\"value\":\"0.3\"}]},\"actionNameI18nKey\":\"resource.action.8533.da_00001.9599adc7.actionname\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"\",\"flowActionId\":\"f53ea7bb\",\"preFlowActionId\":\"9599adc7\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"5\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"detectBreakAreaType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.8533.ba_00005.f53ea7bb.actionname\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"\",\"flowActionId\":\"051ea786\",\"preFlowActionId\":\"f53ea7bb\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"051ea786\",\"nameI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"051ea786\",\"nameI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"051ea786\",\"nameI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"051ea786\",\"nameI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.8533.ba_00004.051ea786.actionname\"}]", + "atomicList": "[{\"position\":\"9599adc7\",\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"labelList\":[]}]", + "algorithmUpdateTime": 1776074475000, + "remark": "", + "nameI18nKey": "resource.param.8533.8533.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"\",\"flowActionId\":\"7d004992\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.8533.ba_00001.7d004992.actionname\"},{\"actionId\":\"DA_00001\",\"actionName\":\"检测视觉大模型\",\"remark\":\"\",\"flowActionId\":\"9599adc7\",\"preFlowActionId\":\"7d004992\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"position\":\"9599adc7\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888890\"},{\"key\":\"fps\",\"value\":\"0.5\"},{\"key\":\"keywords\",\"value\":\"person\"},{\"key\":\"aiParam.box.confidence\",\"value\":\"0.25\"},{\"key\":\"aiParam.text.confidence\",\"value\":\"0.3\"}]},\"actionNameI18nKey\":\"resource.action.8533.da_00001.9599adc7.actionname\"},{\"actionId\":\"BA_00005\",\"actionName\":\"区域告警判断\",\"remark\":\"\",\"flowActionId\":\"f53ea7bb\",\"preFlowActionId\":\"9599adc7\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[{\"key\":\"areaAlarmType\",\"value\":\"5\"},{\"key\":\"inputAreaType\",\"value\":\"1\"},{\"key\":\"detectBreakAreaType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.8533.ba_00005.f53ea7bb.actionname\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"\",\"flowActionId\":\"051ea786\",\"preFlowActionId\":\"f53ea7bb\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"051ea786\",\"nameI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"051ea786\",\"nameI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"051ea786\",\"nameI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"051ea786\",\"nameI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.8533.ba_00004.051ea786.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"0\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.8533.ba_00004.051ea786.actionname\"}]", + "atomicList": "[{\"position\":\"9599adc7\",\"atomicCode\":\"8888890\",\"atomicName\":\"dino2\",\"labelList\":[]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.8533.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/89336_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213_20260413173809.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/89336_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213_20260413173809.json" new file mode 100644 index 000000000..1b008c95d --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/89336_\350\247\206\350\247\211\350\257\255\350\250\200\345\244\247\346\250\241\345\236\213_20260413173809.json" @@ -0,0 +1,30 @@ +{ + "algorithmId": "89336", + "algorithmCode": 89336, + "algorithmName": "视觉语言大模型", + "algorithmCategory": 2, + "algorithmUsage": 2, + "checkType": 97255, + "createTime": 1776073089000, + "updateTime": 1776073089000, + "confVersionId": "default-89336", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.89336.89336.name.description\",\"failedTipI18nKey\":\"resource.param.89336.89336.name.failedtip\",\"nameI18nKey\":\"resource.param.89336.89336.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "configVersionList": [ + { + "id": "default-89336", + "name": "默认", + "algorithmCode": "89336", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"options\":null,\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"step\":null,\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.89336.89336.name.description\",\"failedTipI18nKey\":\"resource.param.89336.89336.name.failedtip\",\"nameI18nKey\":\"resource.param.89336.89336.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":false,\"enableShieldedRegion\":false,\"maxAreaCount\":4,\"defaultFullScreen\":false}", + "algorithmProcessdata": "[{\"actionId\":\"PDA_00003\",\"actionName\":\"语言视觉大模型\",\"remark\":\"\",\"flowActionId\":\"da2e695d\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888999\",\"atomicName\":\"Qwen3VL\",\"position\":\"da2e695d\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888999\"},{\"key\":\"advanced_mode\",\"value\":\"0\"},{\"key\":\"keywords\",\"value\":\"穿红色衣服的人\"},{\"key\":\"generationStyle\",\"value\":\"standard\"}]},\"actionNameI18nKey\":\"resource.action.89336.pda_00003.da2e695d.actionname\"}]", + "atomicList": "[{\"position\":\"da2e695d\",\"atomicCode\":\"8888999\",\"atomicName\":\"Qwen3VL\",\"labelList\":[]}]", + "algorithmUpdateTime": 1776866297000, + "remark": "", + "nameI18nKey": "resource.param.89336.89336.0.name" + } + ], + "algorithmProcessdata": "[{\"actionId\":\"PDA_00003\",\"actionName\":\"语言视觉大模型\",\"remark\":\"\",\"flowActionId\":\"da2e695d\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"8888999\",\"atomicName\":\"Qwen3VL\",\"position\":\"da2e695d\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"8888999\"},{\"key\":\"advanced_mode\",\"value\":\"0\"},{\"key\":\"keywords\",\"value\":\"穿红色衣服的人\"},{\"key\":\"generationStyle\",\"value\":\"standard\"}]},\"actionNameI18nKey\":\"resource.action.89336.pda_00003.da2e695d.actionname\"}]", + "atomicList": "[{\"position\":\"da2e695d\",\"atomicCode\":\"8888999\",\"atomicName\":\"Qwen3VL\",\"labelList\":[]}]", + "remark": "", + "description": "", + "algorithmNameI18nKey": "resource.algorithm.89336.algorithmname" +} diff --git "a/data/resource/aiboxresource_cv186x/algorithm_template/9_\347\203\237\351\233\276\346\243\200\346\265\213_1759134672.json" "b/data/resource/aiboxresource_cv186x/algorithm_template/9_\347\203\237\351\233\276\346\243\200\346\265\213_1759134672.json" new file mode 100644 index 000000000..419ee40de --- /dev/null +++ "b/data/resource/aiboxresource_cv186x/algorithm_template/9_\347\203\237\351\233\276\346\243\200\346\265\213_1759134672.json" @@ -0,0 +1,49 @@ +{ + "algorithmCategory": 3, + "algorithmCode": 9, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"烟雾置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.smog.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"烟雾置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.aiparam_smog_confidence.description\",\"failedTipI18nKey\":\"resource.param.9.9.aiparam_smog_confidence.failedtip\",\"nameI18nKey\":\"resource.param.9.9.aiparam_smog_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"烟雾置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.smog.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"烟雾置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.aiparam_smog_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.9.9.aiparam_smog_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.smog.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"烟雾检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.9.9.aiparam_smog_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.9.9.aiparam_smog_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.9.9.aiparam_smog_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.aiparam_smog_detpostion.description\",\"failedTipI18nKey\":\"resource.param.9.9.aiparam_smog_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.9.9.aiparam_smog_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小烟雾尺寸:烟雾抓拍照片的最小图像尺寸。如输入值为100,则最小烟雾尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.smog.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小烟雾尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.filter_smog_side_min.description\",\"failedTipI18nKey\":\"resource.param.9.9.filter_smog_side_min.failedtip\",\"nameI18nKey\":\"resource.param.9.9.filter_smog_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.alarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_alarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"endValue\":null,\"failedTip\":\"请输入1-100的整数\",\"group\":null,\"key\":\"param.videoRepeatCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"离线视频播放次数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_videorepeatcount.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_videorepeatcount.name\"},{\"beginValue\":null,\"defaultValue\":\"-1\",\"dependsOn\":null,\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"endValue\":null,\"failedTip\":\"请输入正确的值\",\"group\":null,\"key\":\"param.videoReadFps\",\"maxValue\":null,\"minValue\":null,\"name\":\"离线视频播放取帧帧率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"-1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_videoreadfps.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.9.9.name.description\",\"failedTipI18nKey\":\"resource.param.9.9.name.failedtip\",\"nameI18nKey\":\"resource.param.9.9.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmName": "烟雾检测", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"ba9c7d80\",\"preFlowActionId\":\"eaf547cb\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"1\",\"class_name\":\"smog\",\"nameCN\":\"smog\",\"threshold\":[0.6200000047683716],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.smog.confidence\",\"value\":\"\",\"name\":\"smog置信度\",\"defaultValue\":\"\",\"description\":\"smog置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.name\",\"descriptionI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.description\",\"failedTipI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.failedtip\"},{\"key\":\"aiParam.smog.confidenceConfig\",\"value\":\"\",\"name\":\"smog置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"smog置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidenceconfig.description\"},{\"key\":\"aiParam.smog.detPostion\",\"value\":\"0\",\"name\":\"smog检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.name\",\"descriptionI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.description\",\"failedTipI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"2001003\",\"atomicName\":\"FireDetection\",\"position\":\"ba9c7d80\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"smog\",\"nameCN\":\"smog\",\"threshold\":[0.6200000047683716],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.9.aa_00001.ba9c7d80.actionname\",\"remarkI18nKey\":\"resource.action.9.aa_00001.ba9c7d80.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"a59e0a7e\",\"preFlowActionId\":\"ba9c7d80\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"2001003\",\"labelCode\":\"smog\",\"labelName\":\"烟雾\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"ba9c7d80\"}],\"metaDataParams\":[{\"key\":\"filter.smog.side.min\",\"value\":\"60\",\"name\":\"最小烟雾尺寸\",\"defaultValue\":\"60\",\"description\":\"最小烟雾尺寸:烟雾抓拍照片的最小图像尺寸。如输入值为100,则最小烟雾尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.9.ba_00002.a59e0a7e.actionname\",\"remarkI18nKey\":\"resource.action.9.ba_00002.a59e0a7e.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"1478c130\",\"preFlowActionId\":\"e37ea9c1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.9.ba_00004.1478c130.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00004.1478c130.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00004.1478c130.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.9.ba_00004.1478c130.actionname\",\"remarkI18nKey\":\"resource.action.9.ba_00004.1478c130.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"eaf547cb\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.9.ba_00001.eaf547cb.actionname\",\"remarkI18nKey\":\"resource.action.9.ba_00001.eaf547cb.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"e37ea9c1\",\"preFlowActionId\":\"a59e0a7e\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"e37ea9c1\",\"nameI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"e37ea9c1\",\"nameI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.9.ba_00003.e37ea9c1.actionname\",\"remarkI18nKey\":\"resource.action.9.ba_00003.e37ea9c1.remark\"}]", + "algorithmSource": 1, + "algorithmUpdateTime": "1758699263659", + "algorithmUsage": 1, + "atomicList": "[{\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\",\"atomicName\":\"FireDetection\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"smog\",\"nameCN\":\"smog\",\"threshold\":[0.6200000047683716],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}]}]", + "checkType": 3, + "confVersionId": "1a29c9f7afff4446805a494fa8b2be9b", + "confVersionName": "CWAI-AIBOX_V1.0.1", + "configType": "2", + "createTime": 1758683601000, + "creator": "0816610fd67748e7a72f1dd759ac57b5", + "dlComplexity": null, + "eventType": "motorCommodity", + "extraFormat": null, + "gafAlgorithmId": 9, + "gafAlgorithmName": "SmogDetect", + "id": "9", + "instructionCode": null, + "isDelete": 0, + "packageAlgorithmName": "cwai_commodity003", + "pageNo": 1, + "pageSize": 10, + "pollingSupport": 1, + "remark": "应用烟雾检测算法,对检测区域内的烟雾超过阈值时间的事件进行告警。\n仅支持白天场景,摄像机转红外图像后,将自动停止分析。", + "status": 1, + "supplier": "CWAI", + "updateTime": 1758699264000, + "updator": "0816610fd67748e7a72f1dd759ac57b5", + "visualized": 1, + "configVersionList": [ + { + "id": "1a29c9f7afff4446805a494fa8b2be9b", + "name": "默认", + "algorithmCode": 9, + "algorithmMetadata": "{\"params\":[{\"beginValue\":null,\"defaultValue\":\"\",\"dependsOn\":null,\"description\":\"烟雾置信度,范围:0.0~1.0,限小数点后3位。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"aiParam.smog.confidence\",\"maxValue\":null,\"minValue\":null,\"name\":\"烟雾置信度\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.aiparam_smog_confidence.description\",\"failedTipI18nKey\":\"resource.param.9.9.aiparam_smog_confidence.failedtip\",\"nameI18nKey\":\"resource.param.9.9.aiparam_smog_confidence.name\"},{\"beginValue\":null,\"defaultValue\":\"0,0\",\"dependsOn\":null,\"description\":\"烟雾置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"endValue\":null,\"failedTip\":\"\",\"group\":null,\"key\":\"aiParam.smog.confidenceConfig\",\"maxValue\":null,\"minValue\":null,\"name\":\"烟雾置信度偏移\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":0,\"regexpr\":\"\",\"step\":null,\"type\":\"confidenceConfig\",\"value\":\"0,0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.aiparam_smog_confidenceconfig.description\",\"nameI18nKey\":\"resource.param.9.9.aiparam_smog_confidenceconfig.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"endValue\":null,\"failedTip\":\"请选择正确的值\",\"group\":null,\"key\":\"aiParam.smog.detPostion\",\"maxValue\":null,\"minValue\":null,\"name\":\"烟雾检测方式\",\"negative\":null,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.9.9.aiparam_smog_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.9.9.aiparam_smog_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.9.9.aiparam_smog_detpostion.2.options_name\"}],\"range\":null,\"regexpr\":\"/^[0-2]$/\",\"step\":null,\"type\":\"select\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.aiparam_smog_detpostion.description\",\"failedTipI18nKey\":\"resource.param.9.9.aiparam_smog_detpostion.failedtip\",\"nameI18nKey\":\"resource.param.9.9.aiparam_smog_detpostion.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"最小烟雾尺寸:烟雾抓拍照片的最小图像尺寸。如输入值为100,则最小烟雾尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"endValue\":null,\"failedTip\":\"请输入0-10000的整数\",\"group\":null,\"key\":\"filter.smog.side.min\",\"maxValue\":null,\"minValue\":null,\"name\":\"最小烟雾尺寸\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.filter_smog_side_min.description\",\"failedTipI18nKey\":\"resource.param.9.9.filter_smog_side_min.failedtip\",\"nameI18nKey\":\"resource.param.9.9.filter_smog_side_min.name\"},{\"beginValue\":null,\"defaultValue\":\"60\",\"dependsOn\":null,\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。\",\"endValue\":null,\"failedTip\":\"请输入1-36000的整数\",\"group\":null,\"key\":\"param.alarmInterval\",\"maxValue\":null,\"minValue\":null,\"name\":\"告警时间间隔(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"step\":null,\"type\":\"text\",\"value\":\"60\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_alarminterval.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_alarminterval.name\"},{\"beginValue\":null,\"defaultValue\":\"0\",\"dependsOn\":null,\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"endValue\":null,\"failedTip\":\"请选择是否打开告警抑制服务\",\"group\":null,\"key\":\"param.restrainSwitch\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^[01]$/\",\"step\":null,\"type\":\"switch\",\"value\":\"0\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_restrainswitch.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_restrainswitch.name\"},{\"beginValue\":null,\"defaultValue\":\"0.2\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"endValue\":null,\"failedTip\":\"请输入0-1的三位小数。\",\"group\":null,\"key\":\"param.overlapRate\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标重叠率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^(0(\\\\.\\\\d{1,3})?|1(\\\\.0{1,3})?)$/\",\"step\":null,\"type\":\"text\",\"value\":\"0.2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_overlaprate.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_overlaprate.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_overlaprate.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"6\",\"dependsOn\":{\"key\":\"param.restrainSwitch\",\"value\":\"1\"},\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"endValue\":null,\"failedTip\":\"请输入0-24的整数。\",\"group\":null,\"key\":\"param.restrainTime\",\"maxValue\":null,\"minValue\":null,\"name\":\"静止目标去重时间(小时)\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":2,\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"step\":null,\"type\":\"text\",\"value\":\"6\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_restraintime.param_restrainswitch.1.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_restraintime.param_restrainswitch.1.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_restraintime.param_restrainswitch.1.name\"},{\"beginValue\":null,\"defaultValue\":\"1\",\"dependsOn\":null,\"description\":\"离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次\",\"endValue\":null,\"failedTip\":\"请输入1-100的整数\",\"group\":null,\"key\":\"param.videoRepeatCount\",\"maxValue\":null,\"minValue\":null,\"name\":\"离线视频播放次数\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_videorepeatcount.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_videorepeatcount.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_videorepeatcount.name\"},{\"beginValue\":null,\"defaultValue\":\"-1\",\"dependsOn\":null,\"description\":\"离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。\",\"endValue\":null,\"failedTip\":\"请输入正确的值\",\"group\":null,\"key\":\"param.videoReadFps\",\"maxValue\":null,\"minValue\":null,\"name\":\"离线视频播放取帧帧率\",\"negative\":null,\"options\":null,\"range\":null,\"senior\":1,\"regexpr\":\"\",\"step\":null,\"type\":\"text\",\"value\":\"-1\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_videoreadfps.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_videoreadfps.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_videoreadfps.name\"},{\"beginValue\":null,\"defaultValue\":\"5\",\"dependsOn\":null,\"description\":\"灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。\",\"endValue\":null,\"failedTip\":\"请输入1-10的整数\",\"group\":null,\"key\":\"param.sensitivity\",\"maxValue\":null,\"minValue\":null,\"name\":\"灵敏度\",\"negative\":null,\"options\":null,\"range\":\"1,10\",\"regexpr\":\"/^([1-9]|10)$/\",\"step\":null,\"type\":\"slider\",\"value\":\"5\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_sensitivity.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_sensitivity.name\"},{\"beginValue\":null,\"defaultValue\":\"2\",\"dependsOn\":null,\"description\":\"检测时间:范围:1-3600。默认2。\",\"endValue\":null,\"failedTip\":\"请输入1-3600的整数\",\"group\":null,\"key\":\"param.detectionDuration\",\"maxValue\":null,\"minValue\":null,\"name\":\"检测时间(秒)\",\"negative\":null,\"options\":null,\"range\":null,\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"step\":null,\"type\":\"text\",\"value\":\"2\",\"level\":\"2\",\"descriptionI18nKey\":\"resource.param.9.9.param_detectionduration.description\",\"failedTipI18nKey\":\"resource.param.9.9.param_detectionduration.failedtip\",\"nameI18nKey\":\"resource.param.9.9.param_detectionduration.name\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"descriptionI18nKey\":\"resource.param.9.9.name.description\",\"failedTipI18nKey\":\"resource.param.9.9.name.failedtip\",\"nameI18nKey\":\"resource.param.9.9.name.name\"}],\"areasTitle\":null},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{},\"enableShieldedRegion\":false}", + "algorithmProcessdata": "[{\"actionId\":\"AA_00001\",\"actionName\":\"目标检测算法\",\"remark\":\"检测算法,需要选择算法模型\",\"flowActionId\":\"ba9c7d80\",\"preFlowActionId\":\"eaf547cb\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"1\",\"class_name\":\"smog\",\"nameCN\":\"smog\",\"threshold\":[0.6200000047683716],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.smog.confidence\",\"value\":\"\",\"name\":\"smog置信度\",\"defaultValue\":\"\",\"description\":\"smog置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.name\",\"descriptionI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.description\",\"failedTipI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.failedtip\"},{\"key\":\"aiParam.smog.confidenceConfig\",\"value\":\"\",\"name\":\"smog置信度偏移\",\"defaultValue\":\"0,0\",\"description\":\"smog置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。\",\"type\":\"confidenceConfig\",\"regexpr\":\"\",\"failedTip\":\"\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidenceconfig.name\",\"descriptionI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidenceconfig.description\"},{\"key\":\"aiParam.smog.detPostion\",\"value\":\"0\",\"name\":\"smog检测方式\",\"defaultValue\":\"0\",\"description\":\"检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。\",\"type\":\"select\",\"regexpr\":\"/^[0-2]$/\",\"failedTip\":\"请选择正确的值\",\"level\":\"2\",\"senior\":0,\"options\":[{\"name\":\"底部\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.0.options_name\"},{\"name\":\"中心\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.1.options_name\"},{\"name\":\"顶部\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.2.options_name\"}],\"nameI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.name\",\"descriptionI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.description\",\"failedTipI18nKey\":\"resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.failedtip\"}],\"atomic\":{\"atomicCode\":\"2001003\",\"atomicName\":\"FireDetection\",\"position\":\"ba9c7d80\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"smog\",\"nameCN\":\"smog\",\"threshold\":[0.6200000047683716],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}],\"categoriesLabelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"2001003\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.9.aa_00001.ba9c7d80.actionname\",\"remarkI18nKey\":\"resource.action.9.aa_00001.ba9c7d80.remark\"},{\"actionId\":\"BA_00002\",\"actionName\":\"类别过滤\",\"remark\":\"对目标进行过滤\",\"flowActionId\":\"a59e0a7e\",\"preFlowActionId\":\"ba9c7d80\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[{\"atomicCode\":\"2001003\",\"labelCode\":\"smog\",\"labelName\":\"烟雾\",\"sideMinIsEnable\":\"1\",\"collapse\":true,\"position\":\"ba9c7d80\"}],\"metaDataParams\":[{\"key\":\"filter.smog.side.min\",\"value\":\"60\",\"name\":\"最小烟雾尺寸\",\"defaultValue\":\"60\",\"description\":\"最小烟雾尺寸:烟雾抓拍照片的最小图像尺寸。如输入值为100,则最小烟雾尺寸为100*100像素。范围:10px~1000像素 默认:100像素。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|10000)$/\",\"level\":\"2\",\"failedTip\":\"请输入0-10000的整数\",\"nameI18nKey\":\"resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.failedtip\"}],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.9.ba_00002.a59e0a7e.actionname\",\"remarkI18nKey\":\"resource.action.9.ba_00002.a59e0a7e.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"事件上报\",\"flowActionId\":\"1478c130\",\"preFlowActionId\":\"e37ea9c1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"value\":\"3\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"value\":\"0\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"value\":\"0.2\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.9.ba_00004.1478c130.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00004.1478c130.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00004.1478c130.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"value\":\"6\",\"position\":\"1478c130\",\"nameI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00004.1478c130.param_restraintime.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"alarmProperty\",\"value\":\"0\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"},{\"key\":\"enableLlmReview\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.9.ba_00004.1478c130.actionname\",\"remarkI18nKey\":\"resource.action.9.ba_00004.1478c130.remark\"},{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"eaf547cb\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.9.ba_00001.eaf547cb.actionname\",\"remarkI18nKey\":\"resource.action.9.ba_00001.eaf547cb.remark\"},{\"actionId\":\"BA_00003\",\"actionName\":\"灵敏度计算-计时\",\"remark\":\"用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5\",\"flowActionId\":\"e37ea9c1\",\"preFlowActionId\":\"a59e0a7e\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"value\":\"5\",\"position\":\"e37ea9c1\",\"nameI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_sensitivity.failedtip\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"value\":\"2\",\"position\":\"e37ea9c1\",\"nameI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"detectionTimeType\",\"value\":\"1\"}]},\"actionNameI18nKey\":\"resource.action.9.ba_00003.e37ea9c1.actionname\",\"remarkI18nKey\":\"resource.action.9.ba_00003.e37ea9c1.remark\"}]", + "atomicList": "[{\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\",\"atomicName\":\"FireDetection\",\"labelList\":[{\"label\":\"1\",\"class_name\":\"smog\",\"nameCN\":\"smog\",\"threshold\":[0.6200000047683716],\"used\":true,\"position\":\"ba9c7d80\",\"atomicCode\":\"2001003\"}]}]", + "algorithmUpdateTime": 1776930560000, + "nameI18nKey": "resource.param.9.9.0.name" + } + ], + "algorithmNameI18nKey": "resource.algorithm.9.algorithmname", + "remarkI18nKey": "resource.algorithm.9.remark" +} diff --git a/data/resource/aiboxresource_cv186x/i18n/resource.en-US.json b/data/resource/aiboxresource_cv186x/i18n/resource.en-US.json new file mode 100644 index 000000000..1f5acfbfd --- /dev/null +++ b/data/resource/aiboxresource_cv186x/i18n/resource.en-US.json @@ -0,0 +1,3589 @@ +{ + "resource.action.10.aa_00001.ba9c7d80.actionname": "Object Detection", + "resource.action.10.aa_00001.ba9c7d80.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.10.aa_00003.674483de.actionname": "Tracking", + "resource.action.10.aa_00003.674483de.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.10.ba_00001.b62ab911.actionname": "Video Decode", + "resource.action.10.ba_00001.b62ab911.remark": "Video Decode", + "resource.action.10.ba_00002.a59e0a7e.actionname": "Category Filter", + "resource.action.10.ba_00002.a59e0a7e.remark": "Filter targets", + "resource.action.10.ba_00003.2c1f8a2b.actionname": "Sensitivity (Timer)", + "resource.action.10.ba_00003.2c1f8a2b.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.10.ba_00004.1478c130.actionname": "Event Report", + "resource.action.10.ba_00004.1478c130.remark": "Event Report", + "resource.action.11.aa_00001.487c1cf0.actionname": "Object Detection", + "resource.action.11.aa_00001.487c1cf0.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.11.aa_00002.c37b8e34.actionname": "Object Classification", + "resource.action.11.aa_00002.c37b8e34.remark": "Classification algorithm, requires selecting a classification model", + "resource.action.11.aa_00003.c232a753.actionname": "Tracking", + "resource.action.11.aa_00003.c232a753.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.11.ba_00001.01fc708c.actionname": "Video Decode", + "resource.action.11.ba_00001.01fc708c.remark": "Video Decode", + "resource.action.11.ba_00002.5a2f08ca.actionname": "Category Filter", + "resource.action.11.ba_00002.5a2f08ca.remark": "Filter targets", + "resource.action.11.ba_00003.b90c6769.actionname": "Sensitivity (Timer)", + "resource.action.11.ba_00003.b90c6769.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.11.ba_00004.0f53b331.actionname": "Event Report", + "resource.action.11.ba_00004.0f53b331.remark": "Event Report", + "resource.action.11.ba_90001.e02bf44c.actionname": "Target Eval", + "resource.action.11.ba_90001.e02bf44c.remark": "Target Eval", + "resource.action.12.aa_00001.487c1cf0.actionname": "Object Detection", + "resource.action.12.aa_00001.487c1cf0.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.12.aa_00002.c37b8e34.actionname": "Object Classification", + "resource.action.12.aa_00002.c37b8e34.remark": "Classification algorithm, requires selecting a classification model", + "resource.action.12.aa_00003.c232a753.actionname": "Tracking", + "resource.action.12.aa_00003.c232a753.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.12.ba_00001.94b4ca49.actionname": "Video Decode", + "resource.action.12.ba_00001.94b4ca49.remark": "Video Decode", + "resource.action.12.ba_00002.ccc378e3.actionname": "Category Filter", + "resource.action.12.ba_00002.ccc378e3.remark": "Filter targets", + "resource.action.12.ba_00003.0d015957.actionname": "Sensitivity (Timer)", + "resource.action.12.ba_00003.0d015957.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.12.ba_00004.0f53b331.actionname": "Event Report", + "resource.action.12.ba_00004.0f53b331.remark": "Event Report", + "resource.action.12.ba_90001.e02bf44c.actionname": "Target Eval", + "resource.action.12.ba_90001.e02bf44c.remark": "Target Eval", + "resource.action.13.aa_00001.e9173765.actionname": "Object Detection", + "resource.action.13.aa_00001.e9173765.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.13.aa_00003.9253e062.actionname": "Tracking", + "resource.action.13.aa_00003.9253e062.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.13.ba_00001.cc54dbba.actionname": "Video Decode", + "resource.action.13.ba_00001.cc54dbba.remark": "Video Decode", + "resource.action.13.ba_00004.a5c23881.actionname": "Event Report", + "resource.action.13.ba_00004.a5c23881.remark": "Event Report", + "resource.action.13.ba_00005.97085574.actionname": "Region Alarm", + "resource.action.13.ba_00005.97085574.remark": "Handles special region parameters such as intrusion/tripwire/area people counting and other region-based alarm algorithms", + "resource.action.15.aa_00001.83b4eb95.actionname": "Object Detection", + "resource.action.15.aa_00001.83b4eb95.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.15.aa_00002.a0333a67.actionname": "Object Classification", + "resource.action.15.aa_00002.a0333a67.remark": "Send detected targets to classification algorithm, requires selecting a classification model", + "resource.action.15.aa_00003.e1a418ab.actionname": "Tracking", + "resource.action.15.aa_00003.e1a418ab.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.15.ba_00001.3b63e86f.actionname": "Video Decode", + "resource.action.15.ba_00001.3b63e86f.remark": "Video Decode", + "resource.action.15.ba_00002.66fe69a4.actionname": "Category Filter", + "resource.action.15.ba_00002.66fe69a4.remark": "Filter targets", + "resource.action.15.ba_00003.b4b02c33.actionname": "Sensitivity (Timer)", + "resource.action.15.ba_00003.b4b02c33.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.15.ba_00004.4fb8d95e.actionname": "Event Report", + "resource.action.15.ba_00004.4fb8d95e.remark": "Event Report", + "resource.action.15.ba_90001.0d105731.actionname": "Target Eval", + "resource.action.15.ba_90001.0d105731.remark": "Target Eval", + "resource.action.15760.pa_00001.b7fe1598.actionname": "Object Detection", + "resource.action.15760.pda_00002.ea49228d.actionname": "Segmentation VFM", + "resource.action.16.aa_00001.bc4f4b27.actionname": "Object Detection", + "resource.action.16.aa_00001.bc4f4b27.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.16.ba_00001.fdc4d661.actionname": "Video Decode", + "resource.action.16.ba_00001.fdc4d661.remark": "Video Decode", + "resource.action.16.ba_00002.72ec426d.actionname": "Category Filter", + "resource.action.16.ba_00002.72ec426d.remark": "Filter targets", + "resource.action.16.ba_00004.f0c9e210.actionname": "Event Report", + "resource.action.16.ba_00004.f0c9e210.remark": "Event Report", + "resource.action.16.ba_00005.ab935f8a.actionname": "Region Alarm", + "resource.action.16.ba_00005.ab935f8a.remark": "Handles special region parameters such as intrusion/tripwire/area people counting and other region-based alarm algorithms", + "resource.action.1917.pa_00001.b7fe1598.actionname": "Object Detection", + "resource.action.1917.pda_00002.ea49228d.actionname": "Segmentation VFM", + "resource.action.2.aa_00001.aaa71a68.actionname": "Object Detection", + "resource.action.2.aa_00002.12564ac1.actionname": "Object Classification", + "resource.action.2.aa_00003.6f833257.actionname": "Tracking", + "resource.action.2.aa_00004.f225eab6.actionname": "Landmark", + "resource.action.2.aa_00005.061f82a7.actionname": "Feature Extraction", + "resource.action.2.ba_00001.4874a700.actionname": "Video Decode", + "resource.action.2.ba_00002.5c3ea492.actionname": "Category Filter", + "resource.action.2.ba_00004.bdf891b9.actionname": "Event Report", + "resource.action.21283.aa_00001.4f8ba85c.actionname": "Object Detection", + "resource.action.21283.ba_00001.f865585c.actionname": "Video Decode", + "resource.action.21283.ba_00004.fd4e2090.actionname": "Event Report", + "resource.action.21283.ba_00005.308335b0.actionname": "Region Alarm", + "resource.action.21283.da_00002.e9ee0bc1.actionname": "Segmentation VFM", + "resource.action.22.aa_00001.487c1cf0.actionname": "Object Detection", + "resource.action.22.aa_00001.487c1cf0.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.22.aa_00002.c37b8e34.actionname": "Object Classification", + "resource.action.22.aa_00002.c37b8e34.remark": "Classification algorithm, requires selecting a classification model", + "resource.action.22.aa_00003.c232a753.actionname": "Tracking", + "resource.action.22.aa_00003.c232a753.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.22.ba_00001.df5884a8.actionname": "Video Decode", + "resource.action.22.ba_00001.df5884a8.remark": "Video Decode", + "resource.action.22.ba_00002.ffac0ae1.actionname": "Category Filter", + "resource.action.22.ba_00002.ffac0ae1.remark": "Filter targets", + "resource.action.22.ba_00003.181f8b5a.actionname": "Sensitivity (Timer)", + "resource.action.22.ba_00003.181f8b5a.remark": "Sensitivity Calculation", + "resource.action.22.ba_00004.0f53b331.actionname": "Event Report", + "resource.action.22.ba_00004.0f53b331.remark": "Event Report", + "resource.action.22.ba_90001.e02bf44c.actionname": "Target Eval", + "resource.action.22.ba_90001.e02bf44c.remark": "Target Eval", + "resource.action.28862.aa_00001.4f8ba85c.actionname": "Object Detection", + "resource.action.28862.ba_00001.f865585c.actionname": "Video Decode", + "resource.action.28862.ba_00004.fd4e2090.actionname": "Event Report", + "resource.action.28862.ba_00005.308335b0.actionname": "Region Alarm", + "resource.action.28862.da_00002.e9ee0bc1.actionname": "Segmentation VFM", + "resource.action.2935.pda_00001.0c349519.actionname": "Detection VFM", + "resource.action.3.aa_00001.e9173765.actionname": "Object Detection", + "resource.action.3.aa_00001.e9173765.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.3.aa_00003.9253e062.actionname": "Tracking", + "resource.action.3.aa_00003.9253e062.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.3.ba_00001.8d29063d.actionname": "Video Decode", + "resource.action.3.ba_00001.8d29063d.remark": "Video Decode", + "resource.action.3.ba_00002.fdd2a4cd.actionname": "Category Filter", + "resource.action.3.ba_00002.fdd2a4cd.remark": "Filter targets", + "resource.action.3.ba_00004.a5c23881.actionname": "Event Report", + "resource.action.3.ba_00004.a5c23881.remark": "Event Report", + "resource.action.3.ba_00005.f21131a5.actionname": "Region Alarm", + "resource.action.3.ba_00005.f21131a5.remark": "Handles special region parameters such as intrusion/tripwire/area people counting and other region-based alarm algorithms", + "resource.action.32.aa_00001.1ffc7361.actionname": "Object Detection", + "resource.action.32.aa_00001.1ffc7361.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.32.aa_00002.40a88def.actionname": "Object Classification", + "resource.action.32.aa_00002.40a88def.remark": "Classification algorithm, requires selecting a classification model", + "resource.action.32.aa_00003.0ca3cfc7.actionname": "Tracking", + "resource.action.32.aa_00003.0ca3cfc7.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.32.aa_00005.247f620f.actionname": "Feature Extraction", + "resource.action.32.aa_00005.247f620f.remark": "Supports face, body, and object feature extraction", + "resource.action.32.ba_00001.551596af.actionname": "Video Decode", + "resource.action.32.ba_00001.551596af.remark": "Video Decode", + "resource.action.32.ba_00002.6cdfc847.actionname": "Category Filter", + "resource.action.32.ba_00002.6cdfc847.remark": "Filter targets", + "resource.action.32.ba_00003.22705515.actionname": "Sensitivity (Timer)", + "resource.action.32.ba_00003.22705515.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.32.ba_00004.da078adb.actionname": "Event Report", + "resource.action.32.ba_00004.da078adb.remark": "Event Report", + "resource.action.34707.ba_00001.3c61bba4.actionname": "Video Decode", + "resource.action.34707.ba_00004.7ec477cd.actionname": "Event Report", + "resource.action.34707.da_00003.4a05a806.actionname": "Vision-Language Model", + "resource.action.38873.pa_00001.0fa44adc.actionname": "Object Detection", + "resource.action.5.aa_00001.bc4f4b27.actionname": "Object Detection", + "resource.action.5.aa_00001.bc4f4b27.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.5.ba_00001.991da170.actionname": "Video Decode", + "resource.action.5.ba_00001.991da170.remark": "Video Decode", + "resource.action.5.ba_00002.72ec426d.actionname": "Category Filter", + "resource.action.5.ba_00002.72ec426d.remark": "Filter targets", + "resource.action.5.ba_00004.f0c9e210.actionname": "Event Report", + "resource.action.5.ba_00004.f0c9e210.remark": "Event Report", + "resource.action.5.ba_00005.ab935f8a.actionname": "Region Alarm", + "resource.action.5.ba_00005.ab935f8a.remark": "Handles special region parameters such as intrusion/tripwire/area people counting and other region-based alarm algorithms", + "resource.action.50813.pa_00001.27f515bd.actionname": "Object Detection", + "resource.action.50813.pa_00002.27e33c9b.actionname": "Object Classification", + "resource.action.51.aa_00001.e9173765.actionname": "Object Detection", + "resource.action.51.aa_00001.e9173765.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.51.ba_00001.4053a96d.actionname": "Video Decode", + "resource.action.51.ba_00001.4053a96d.remark": "Video Decode", + "resource.action.51.ba_00004.9de4af16.actionname": "Event Report", + "resource.action.51.ba_00004.9de4af16.remark": "Event Report", + "resource.action.51.ba_00005.667e48b6.actionname": "Region Alarm", + "resource.action.51.ba_00005.667e48b6.remark": "Handles special region parameters such as intrusion/tripwire/area people counting and other region-based alarm algorithms", + "resource.action.57.aa_00001.e9173765.actionname": "Object Detection", + "resource.action.57.aa_00001.e9173765.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.57.aa_00003.9253e062.actionname": "Tracking", + "resource.action.57.aa_00003.9253e062.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.57.ba_00001.251d0f78.actionname": "Video Decode", + "resource.action.57.ba_00001.251d0f78.remark": "Video Decode", + "resource.action.57.ba_00002.fdd2a4cd.actionname": "Category Filter", + "resource.action.57.ba_00002.fdd2a4cd.remark": "Filter targets", + "resource.action.57.ba_00004.a5c23881.actionname": "Event Report", + "resource.action.57.ba_00004.a5c23881.remark": "Event Report", + "resource.action.57.ba_00005.f7750059.actionname": "Region Alarm", + "resource.action.57.ba_00005.f7750059.remark": "Handles special region parameters such as intrusion/tripwire/area people counting and other region-based alarm algorithms", + "resource.action.58.aa_00001.1ffc7361.actionname": "Object Detection", + "resource.action.58.aa_00001.1ffc7361.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.58.aa_00002.40a88def.actionname": "Object Classification", + "resource.action.58.aa_00002.40a88def.remark": "Classification algorithm, requires selecting a classification model", + "resource.action.58.aa_00003.0ca3cfc7.actionname": "Tracking", + "resource.action.58.aa_00003.0ca3cfc7.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.58.aa_00005.247f620f.actionname": "Feature Extraction", + "resource.action.58.aa_00005.247f620f.remark": "Supports face, body, and object feature extraction", + "resource.action.58.ba_00001.03ef5862.actionname": "Video Decode", + "resource.action.58.ba_00001.03ef5862.remark": "Video Decode", + "resource.action.58.ba_00002.6cdfc847.actionname": "Category Filter", + "resource.action.58.ba_00002.6cdfc847.remark": "Filter targets", + "resource.action.58.ba_00003.bc6d90f2.actionname": "Sensitivity (Timer)", + "resource.action.58.ba_00003.bc6d90f2.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.58.ba_00004.da078adb.actionname": "Event Report", + "resource.action.58.ba_00004.da078adb.remark": "Event Report", + "resource.action.6.aa_00001.487c1cf0.actionname": "Object Detection", + "resource.action.6.aa_00001.487c1cf0.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.6.aa_00002.c37b8e34.actionname": "Object Classification", + "resource.action.6.aa_00002.c37b8e34.remark": "Classification algorithm, requires selecting a classification model", + "resource.action.6.aa_00003.c232a753.actionname": "Tracking", + "resource.action.6.aa_00003.c232a753.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.6.ba_00001.e7eadb5a.actionname": "Video Decode", + "resource.action.6.ba_00001.e7eadb5a.remark": "Video Decode", + "resource.action.6.ba_00002.d56fc47d.actionname": "Category Filter", + "resource.action.6.ba_00002.d56fc47d.remark": "Filter targets", + "resource.action.6.ba_00003.6dbede3b.actionname": "Sensitivity (Timer)", + "resource.action.6.ba_00003.6dbede3b.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.6.ba_00004.0f53b331.actionname": "Event Report", + "resource.action.6.ba_00004.0f53b331.remark": "Event Report", + "resource.action.6.ba_90001.e02bf44c.actionname": "Target Eval", + "resource.action.6.ba_90001.e02bf44c.remark": "Target Eval", + "resource.action.60460.pda_00003.da2e695d.actionname": "Vision-Language Model", + "resource.action.65.aa_00001.487c1cf0.actionname": "Object Detection", + "resource.action.65.aa_00001.487c1cf0.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.65.aa_00002.c37b8e34.actionname": "Object Classification", + "resource.action.65.aa_00002.c37b8e34.remark": "Classification algorithm, requires selecting a classification model", + "resource.action.65.aa_00003.c232a753.actionname": "Tracking", + "resource.action.65.aa_00003.c232a753.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.65.ba_00001.55e37370.actionname": "Video Decode", + "resource.action.65.ba_00001.55e37370.remark": "Video Decode", + "resource.action.65.ba_00002.d56fc47d.actionname": "Category Filter", + "resource.action.65.ba_00002.d56fc47d.remark": "Filter targets", + "resource.action.65.ba_00003.b00198a1.actionname": "Sensitivity (Timer)", + "resource.action.65.ba_00003.b00198a1.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.65.ba_00004.0f53b331.actionname": "Event Report", + "resource.action.65.ba_00004.0f53b331.remark": "Event Report", + "resource.action.65.ba_90001.e02bf44c.actionname": "Target Eval", + "resource.action.65.ba_90001.e02bf44c.remark": "Target Eval", + "resource.action.67093.ba_00001.3c61bba4.actionname": "Video Decode", + "resource.action.67093.ba_00004.7ec477cd.actionname": "Event Report", + "resource.action.67093.da_00003.4a05a806.actionname": "Vision-Language Model", + "resource.action.7.aa_00001.ddd59411.actionname": "Object Detection", + "resource.action.7.aa_00001.ddd59411.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.7.aa_00003.10a89d8c.actionname": "Tracking", + "resource.action.7.aa_00003.10a89d8c.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.7.ba_00001.20a13b0a.actionname": "Video Decode", + "resource.action.7.ba_00001.20a13b0a.remark": "Video Decode", + "resource.action.7.ba_00002.498141de.actionname": "Category Filter", + "resource.action.7.ba_00002.498141de.remark": "Filter targets", + "resource.action.7.ba_00004.2add29ef.actionname": "Event Report", + "resource.action.7.ba_00004.2add29ef.remark": "Event Report", + "resource.action.7.ba_00005.7d7b0fa3.actionname": "Region Alarm", + "resource.action.7.ba_00005.7d7b0fa3.remark": "Handles special region parameters such as intrusion/tripwire/area people counting and other region-based alarm algorithms", + "resource.action.7602.pa_00001.d8241567.actionname": "Object Detection", + "resource.action.7602.pa_00002.2337df82.actionname": "Object Classification", + "resource.action.7602.pa_00004.34499952.actionname": "Landmark", + "resource.action.7602.pa_00005.c0d31881.actionname": "Feature Extraction", + "resource.action.77380.pa_00001.27f515bd.actionname": "Object Detection", + "resource.action.77380.pa_00002.27e33c9b.actionname": "Object Classification", + "resource.action.80498.ba_00001.7d004992.actionname": "Video Decode", + "resource.action.80498.ba_00004.051ea786.actionname": "Event Report", + "resource.action.80498.ba_00005.f53ea7bb.actionname": "Region Alarm", + "resource.action.80498.da_00001.9599adc7.actionname": "Detection VFM", + "resource.action.82819.pda_00001.f15b0a07.actionname": "Detection VFM", + "resource.action.82819.pda_00002.ff07761f.actionname": "Segmentation VFM", + "resource.action.83708.pa_00001.0fa44adc.actionname": "Object Detection", + "resource.action.8533.ba_00001.7d004992.actionname": "Video Decode", + "resource.action.8533.ba_00004.051ea786.actionname": "Event Report", + "resource.action.8533.ba_00005.f53ea7bb.actionname": "Region Alarm", + "resource.action.8533.da_00001.9599adc7.actionname": "Detection VFM", + "resource.action.89336.pda_00003.da2e695d.actionname": "Vision-Language Model", + "resource.action.9.aa_00001.ba9c7d80.actionname": "Object Detection", + "resource.action.9.aa_00001.ba9c7d80.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.9.ba_00001.eaf547cb.actionname": "Video Decode", + "resource.action.9.ba_00001.eaf547cb.remark": "Video Decode", + "resource.action.9.ba_00002.a59e0a7e.actionname": "Category Filter", + "resource.action.9.ba_00002.a59e0a7e.remark": "Filter targets", + "resource.action.9.ba_00003.e37ea9c1.actionname": "Sensitivity (Timer)", + "resource.action.9.ba_00003.e37ea9c1.remark": "Calculates hit count within detection time. E.g., if detection time is 3 sec, frame rate is 3, sensitivity is 5, alarm triggers when hits ≥ 3×3×(11-5)/10. May alarm before detection time expires. Range: 1–10, default: 5", + "resource.action.9.ba_00004.1478c130.actionname": "Event Report", + "resource.action.9.ba_00004.1478c130.remark": "Event Report", + "resource.action.91435.pda_00001.0c349519.actionname": "Detection VFM", + "resource.action.aa_00001.actionname": "Object Detection", + "resource.action.aa_00001.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.aa_00002.actionname": "Object Classification", + "resource.action.aa_00002.remark": "Send detected targets to classification algorithm, requires selecting a classification model", + "resource.action.aa_00003.actionname": "Tracking", + "resource.action.aa_00003.remark": "Place after detection algorithm when body tracking is needed", + "resource.action.aa_00004.actionname": "Landmark", + "resource.action.aa_00004.remark": "Face Landmark", + "resource.action.aa_00005.actionname": "Feature Extraction", + "resource.action.aa_00005.remark": "Supports face, body, and object feature extraction", + "resource.action.aa_00011.actionname": "Text Recognition", + "resource.action.aa_00011.remark": "Recognizes license plates located by landmarks; requires an OCR model", + "resource.action.ba_00001.actionname": "Video Decode", + "resource.action.ba_00001.remark": "Video Decode", + "resource.action.ba_00002.actionname": "Category Filter", + "resource.action.ba_00002.remark": "Filter targets", + "resource.action.ba_00003.actionname": "Sensitivity (Timer)", + "resource.action.ba_00003.remark": "Sensitivity Calculation", + "resource.action.ba_00004.actionname": "Event Report", + "resource.action.ba_00004.remark": "Event Report", + "resource.action.ba_00005.actionname": "Region Alarm", + "resource.action.ba_00005.remark": "Handles special region parameters such as intrusion/tripwire/area people counting and other region-based alarm algorithms", + "resource.action.ba_10003.actionname": "Sensitivity (Counter)", + "resource.action.ba_10003.remark": "Sensitivity Calculation", + "resource.action.ba_90001.actionname": "Target Eval", + "resource.action.ba_90001.remark": "Target Eval", + "resource.action.da_00001.actionname": "Detection VFM", + "resource.action.da_00001.remark": "Detection VFM", + "resource.action.da_00002.actionname": "Segmentation VFM", + "resource.action.da_00002.remark": "Segmentation VFM", + "resource.action.da_00003.actionname": "Vision-Language Model", + "resource.action.da_00003.remark": "Vision-Language Model", + "resource.action.ip0001.componentname": "Input Node Component", + "resource.action.la_alarmdata_code.actionname": "Alarm Data", + "resource.action.la_alarmdata_code.remark": "Configure algorithm alarm data in channel to trigger linkage workflow", + "resource.action.la_audiodevice_code.actionname": "Audio Speaker Link", + "resource.action.la_audiodevice_code.remark": "Configure IP audio device for alarm broadcasting", + "resource.action.lb0001.componentname": "Configuration Component", + "resource.action.on0001.componentname": "Output Node Component", + "resource.action.pa_00001.actionname": "Object Detection", + "resource.action.pa_00001.remark": "Detection algorithm, requires selecting an algorithm model", + "resource.action.pa_00002.actionname": "Object Classification", + "resource.action.pa_00002.remark": "Send detected targets to classification algorithm, requires selecting a classification model", + "resource.action.pa_00005.actionname": "Feature Extraction", + "resource.action.pa_00005.remark": "Supports face, body, and object feature extraction", + "resource.action.pb_90001.actionname": "Target Eval", + "resource.action.pb_90001.remark": "Target Eval", + "resource.action.pda_00001.actionname": "Detection VFM", + "resource.action.pda_00001.remark": "Vision Detection Foundation Model (Image)", + "resource.action.pda_00002.actionname": "Segmentation VFM", + "resource.action.pda_00002.remark": "Vision Segmentation Foundation Model (Image)", + "resource.action.pda_00003.actionname": "Vision-Language Model", + "resource.action.pda_00003.remark": "Vision-Language Model (Image)", + "resource.action.pr0001.componentname": "Resize Component", + "resource.action.pr0002.componentname": "Normalize Component", + "resource.action.pr0003.componentname": "Crop Component", + "resource.action.pr0004.componentname": "Expand Component", + "resource.action.pr0005.componentname": "Affine Crop Component", + "resource.action.pr0006.componentname": "Sequence Component", + "resource.action.pr0007.componentname": "Combine Image Component", + "resource.action.pr0008.componentname": "DINO Encode Component", + "resource.action.pt0001.componentname": "YOLO Post-process Component", + "resource.action.pt0002.componentname": "YOLO NPU Post-process Component", + "resource.action.pt0003.componentname": "YOLOv8 Post-process Component", + "resource.action.pt0004.componentname": "Sum Component", + "resource.action.pt0005.componentname": "ArgMax Component", + "resource.action.pt0006.componentname": "Split Component", + "resource.action.pt0007.componentname": "Split ArgMax Component", + "resource.action.pt0008.componentname": "DINO Decode Component", + "resource.action.pt0009.componentname": "YOLO E2E Post-process Component", + "resource.algorithm.10.algorithmname": "Flame Detection", + "resource.algorithm.10.remark": "Applies flame detection algorithm. Alarms when flames exceed threshold duration in the detection region.\nOnly supports daytime scenes; analysis stops automatically when camera switches to infrared.", + "resource.algorithm.11.algorithmname": "Smoking Detection", + "resource.algorithm.11.remark": "Applies pedestrian detection/tracking and smoking classification algorithms to detect smoking in the detection region. Triggers alarm when threshold is exceeded. Analyzes both smoking posture and cigarette simultaneously.", + "resource.algorithm.12.algorithmname": "Phone Call Detection", + "resource.algorithm.12.remark": "Applies pedestrian detection/tracking and phone call classification algorithms. Triggers alarm when a person makes a phone call exceeding the threshold duration. Analyzes both phone call posture and phone simultaneously.", + "resource.algorithm.13.algorithmname": "People Flow Counting", + "resource.algorithm.13.remark": "Applies head-shoulder detection algorithm to count people passing through the rule line, saved by time granularity (minimum: hourly).", + "resource.algorithm.15.algorithmname": "No Safety Helmet", + "resource.algorithm.15.remark": "Applies head-shoulder detection, tracking, and safety helmet classification algorithms to detect whether personnel are wearing safety helmets. Helmet colors: red, blue, yellow, white, black.", + "resource.algorithm.15760.algorithmname": "Segmentation Foundation Model", + "resource.algorithm.16.algorithmname": "Off-post Detection", + "resource.algorithm.16.remark": "Applies head-shoulder or body detection algorithm. Triggers alarm when the number of people in the region falls below the threshold for a specified duration.", + "resource.algorithm.1917.algorithmname": "Image Segmentation Foundation Model", + "resource.algorithm.1917.remark": "Image Segmentation Foundation Model", + "resource.algorithm.2.algorithmname": "Face Comparison", + "resource.algorithm.2.remark": "Face 1:N comparison, primarily used for watchlist alerts, stranger reminders, and prolonged absence/presence analysis.", + "resource.algorithm.21283.algorithmname": "Vision Segmentation Foundation Model Analysis", + "resource.algorithm.22.algorithmname": "Phone Usage Detection", + "resource.algorithm.22.remark": "Applies pedestrian detection/tracking and phone usage classification algorithms. Triggers alarm when phone usage exceeds the threshold duration. Analyzes both phone usage posture and phone simultaneously.", + "resource.algorithm.28862.algorithmname": "Segmentation VFM", + "resource.algorithm.28862.remark": "Segmentation VFM", + "resource.algorithm.2935.algorithmname": "Detection Foundation Model", + "resource.algorithm.029.algorithmname": "License Plate Recognition", + "resource.algorithm.029.process.aa_00001.remark": "Detects license plates in the video.", + "resource.algorithm.029.process.aa_00004.remark": "Locates the top-left, bottom-left, bottom-right, and top-right landmarks of each license plate.", + "resource.algorithm.029.process.ba_00004.remark": "Reports license plate recognition events with vehicle attributes.", + "resource.algorithm.029.remark": "Detects license plates, extracts four landmarks, recognizes the text, and reports vehicle-property events.", + "resource.param.029.029.aiparam_car_plate_confidence.description": "License plate confidence threshold. Range: 0.0–1.0, with up to three decimal places.", + "resource.param.029.029.aiparam_car_plate_confidence.failedtip": "Enter a value from 0 to 1 with up to three decimal places.", + "resource.param.029.029.aiparam_car_plate_confidence.name": "License Plate Confidence", + "resource.param.029.029.alarmproperty.name": "Vehicle Attributes", + "resource.param.029.029.name.description": "Region name. Required, with a maximum of 32 characters.", + "resource.param.029.029.name.failedtip": "Enter a string shorter than 32 characters without spaces.", + "resource.param.029.029.name.name": "Region Name", + "resource.param.029.029.param_alarminterval.description": "Minimum interval between two license plate alarms. Range: 1–36000 seconds.", + "resource.param.029.029.param_alarminterval.failedtip": "Enter an integer from 1 to 36000.", + "resource.param.029.029.param_alarminterval.name": "Alarm Interval (seconds)", + "resource.algorithm.3.algorithmname": "Region Intrusion", + "resource.algorithm.3.remark": "Sets detection regions in video. Detects events where pedestrians enter the region for a specified duration. Tracks pedestrians from outside to inside the detection boundary.", + "resource.algorithm.32.algorithmname": "No Reflective Vest", + "resource.algorithm.32.remark": "Detects whether on-site personnel are wearing reflective vests. Triggers alarm for non-compliant personnel.", + "resource.algorithm.34707.algorithmname": "Vision-Language Model Analysis", + "resource.algorithm.38873.algorithmname": "Detection-class Algorithm", + "resource.algorithm.5.algorithmname": "Crowd Gathering", + "resource.algorithm.5.remark": "Applies head-shoulder or body detection algorithm to count pedestrians in the detection region. Triggers alarm when count exceeds the threshold.", + "resource.algorithm.50813.algorithmname": "Image Detection Classification Task", + "resource.algorithm.50813.remark": "Image Detection Classification Task", + "resource.algorithm.51.algorithmname": "Area People Counting", + "resource.algorithm.51.remark": "Applies head-shoulder detection algorithm for real-time people counting within the detection region.", + "resource.algorithm.57.algorithmname": "Tripwire Detection", + "resource.algorithm.57.remark": "Applies pedestrian tracking algorithm for tripwire alerts. Supports unidirectional and bidirectional tripwire detection.", + "resource.algorithm.58.algorithmname": "No Work Uniform", + "resource.algorithm.58.remark": "Applies body recognition algorithm to alarm when detected bodies do not match the work uniform library. Supports custom uniform libraries and multiple uniform styles/colors.", + "resource.algorithm.6.algorithmname": "Person Falling", + "resource.algorithm.6.remark": "Applies pedestrian detection/tracking algorithms for fall detection. Triggers alarm when threshold is exceeded.", + "resource.algorithm.60460.algorithmname": "Image Vision-Language Model", + "resource.algorithm.60460.remark": "Image Vision-Language Model", + "resource.algorithm.65.algorithmname": "Sleeping on Duty Detection", + "resource.algorithm.65.remark": "Applies body detection, tracking, and sleeping classification algorithms. Supports 2 types: lying down and face-down sleeping.", + "resource.algorithm.67093.algorithmname": "Vision-Language Model", + "resource.algorithm.67093.remark": "Vision-Language Model", + "resource.algorithm.7.algorithmname": "Illegal Vehicle Parking", + "resource.algorithm.7.remark": "Applies motor vehicle detection/tracking for vehicles exceeding threshold duration.\nMotor vehicles: electric tricycles, motorcycles, sedans, SUVs, trucks.\nApplies non-motor vehicle detection for non-motor vehicles exceeding threshold duration.\nNon-motor vehicles: e-bikes, bicycles, pedal tricycles.", + "resource.algorithm.7602.algorithmname": "Face Recognition Algorithm", + "resource.algorithm.7602.remark": "Face Feature Extraction", + "resource.algorithm.77380.algorithmname": "Post-detection Classification Algorithm", + "resource.algorithm.80498.algorithmname": "Detection VFM", + "resource.algorithm.80498.remark": "Detection VFM", + "resource.algorithm.82819.algorithmname": "Post-detection Segmentation Algorithm", + "resource.algorithm.83708.algorithmname": "Image Detection Task", + "resource.algorithm.83708.remark": "Image-class Detection Task", + "resource.algorithm.8533.algorithmname": "Vision Detection Foundation Model Analysis", + "resource.algorithm.89336.algorithmname": "Vision-Language Model", + "resource.algorithm.9.algorithmname": "Smoke Detection", + "resource.algorithm.9.remark": "Applies smoke detection algorithm. Alarms when smoke exceeds threshold duration in the detection region.\nOnly supports daytime scenes; analysis stops automatically when camera switches to infrared.", + "resource.algorithm.91435.algorithmname": "Image Detection Foundation Model", + "resource.algorithm.91435.remark": "Image Detection Foundation Model", + "resource.label.1000001.face.1000001.0.face.namecn": "Face", + "resource.label.1000001.name": "RGB Face Detection", + "resource.label.1000005.name": "RGB Face Recognition", + "resource.label.1000010.mask.1000010.0.mask.namecn": "Wearing Mask", + "resource.label.1000010.name": "Mask Attribute Recognition", + "resource.label.1000010.normal.1000010.1.normal.namecn": "No Mask", + "resource.label.1000012.faceblur0.1000012.0.faceblur0.namecn": "Face Blur 1", + "resource.label.1000012.faceblur1.1000012.1.faceblur1.namecn": "Face Blur 2", + "resource.label.1000012.faceblur2.1000012.2.faceblur2.namecn": "Face Blur 3", + "resource.label.1000012.frontface.1000012.3.frontface.namecn": "Frontal Face", + "resource.label.1000012.fullface.1000012.4.fullface.namecn": "Complete Face", + "resource.label.1000012.name": "Face Quality Assessment", + "resource.label.1000012.slantedface.1000012.5.slantedface.namecn": "Partially Tilted Face", + "resource.label.1000016.name": "Face Landmarks", + "resource.label.1001001.headshoulder.1001001.0.headshoulder.namecn": "Head & Shoulder", + "resource.label.1001001.name": "Head-shoulder Detection", + "resource.label.1001003.description": "Body Detection", + "resource.label.1001003.name": "Pedestrian Detection", + "resource.label.1001003.pedestrian.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.label.1001005.apron_long.1001005.62.apron_long.namecn": "Long Apron", + "resource.label.1001005.apron_none.1001005.63.apron_none.namecn": "No Apron", + "resource.label.1001005.apron_short.1001005.64.apron_short.namecn": "Short Apron", + "resource.label.1001005.apron_uncertain.1001005.65.apron_uncertain.namecn": "Uncertain Apron", + "resource.label.1001005.bag_handling_carried_suitcase.1001005.44.bag_handling_carried_suitcase.namecn": "Bag - Handbag/Suitcase", + "resource.label.1001005.bag_handling_crossbody_bag.1001005.45.bag_handling_crossbody_bag.namecn": "Bag - Crossbody Bag", + "resource.label.1001005.bag_handling_double_shoulder_backpack.1001005.46.bag_handling_double_shoulder_backpack.namecn": "Bag - Backpack", + "resource.label.1001005.bag_handling_luggage.1001005.47.bag_handling_luggage.namecn": "Bag - Luggage", + "resource.label.1001005.bag_handling_none.1001005.48.bag_handling_none.namecn": "Bag - None", + "resource.label.1001005.bag_handling_plastic_bag_shopping_bag.1001005.49.bag_handling_plastic_bag_shopping_bag.namecn": "Bag - Plastic/Shopping Bag", + "resource.label.1001005.bag_handling_shopping_cart.1001005.50.bag_handling_shopping_cart.namecn": "Bag - Shopping Cart", + "resource.label.1001005.bag_handling_single_shoulder_backpack.1001005.51.bag_handling_single_shoulder_backpack.namecn": "Bag - Shoulder Bag", + "resource.label.1001005.bag_handling_stroller_carrying_a_child.1001005.52.bag_handling_stroller_carrying_a_child.namecn": "Bag - Stroller/Carrying Child", + "resource.label.1001005.bag_handling_umbrella.1001005.53.bag_handling_umbrella.namecn": "Bag - Umbrella", + "resource.label.1001005.bag_handling_uncertain.1001005.54.bag_handling_uncertain.namecn": "Bag - Uncertain", + "resource.label.1001005.bag_handling_waist_pack.1001005.55.bag_handling_waist_pack.namecn": "Bag - Waist Bag", + "resource.label.1001005.bottom_color_black.1001005.21.bottom_color_black.namecn": "Bottom Color - Black", + "resource.label.1001005.bottom_color_blue.1001005.22.bottom_color_blue.namecn": "Bottom Color - Blue", + "resource.label.1001005.bottom_color_brown_camel.1001005.23.bottom_color_brown_camel.namecn": "Bottom Color - Brown/Camel", + "resource.label.1001005.bottom_color_floral.1001005.24.bottom_color_floral.namecn": "Bottom Color - Patterned", + "resource.label.1001005.bottom_color_gray.1001005.25.bottom_color_gray.namecn": "Bottom Color - Gray", + "resource.label.1001005.bottom_color_green.1001005.26.bottom_color_green.namecn": "Bottom Color - Green", + "resource.label.1001005.bottom_color_nude_flesh.1001005.27.bottom_color_nude_flesh.namecn": "Bottom Color - Nude/Skin", + "resource.label.1001005.bottom_color_orange.1001005.28.bottom_color_orange.namecn": "Bottom Color - Orange", + "resource.label.1001005.bottom_color_pink.1001005.29.bottom_color_pink.namecn": "Bottom Color - Pink", + "resource.label.1001005.bottom_color_polka_dot.1001005.30.bottom_color_polka_dot.namecn": "Bottom Color - Polka Dot", + "resource.label.1001005.bottom_color_purple.1001005.31.bottom_color_purple.namecn": "Bottom Color - Purple", + "resource.label.1001005.bottom_color_red.1001005.32.bottom_color_red.namecn": "Bottom Color - Red", + "resource.label.1001005.bottom_color_striped.1001005.33.bottom_color_striped.namecn": "Bottom Color - Striped", + "resource.label.1001005.bottom_color_uncertain.1001005.34.bottom_color_uncertain.namecn": "Bottom Color - Uncertain", + "resource.label.1001005.bottom_color_white.1001005.35.bottom_color_white.namecn": "Bottom Color - White", + "resource.label.1001005.bottom_color_yellow.1001005.36.bottom_color_yellow.namecn": "Bottom Color - Yellow", + "resource.label.1001005.cycling.1001005.56.cycling.namecn": "Cycling", + "resource.label.1001005.hat_none.1001005.57.hat_none.namecn": "No Hat", + "resource.label.1001005.hat_uncertain.1001005.58.hat_uncertain.namecn": "Uncertain Hat", + "resource.label.1001005.helmet.1001005.59.helmet.namecn": "Helmet", + "resource.label.1001005.lower_garment_length_long_pants.1001005.37.lower_garment_length_long_pants.namecn": "Bottom Length - Long Pants", + "resource.label.1001005.lower_garment_length_long_skirt.1001005.38.lower_garment_length_long_skirt.namecn": "Bottom Length - Long Skirt", + "resource.label.1001005.lower_garment_length_mid_length_pants.1001005.39.lower_garment_length_mid_length_pants.namecn": "Bottom Length - Capri Pants", + "resource.label.1001005.lower_garment_length_mid_length_skirt.1001005.40.lower_garment_length_mid_length_skirt.namecn": "Bottom Length - Midi Skirt", + "resource.label.1001005.lower_garment_length_short_skirt.1001005.41.lower_garment_length_short_skirt.namecn": "Bottom Length - Short Skirt", + "resource.label.1001005.lower_garment_length_shorts.1001005.42.lower_garment_length_shorts.namecn": "Bottom Length - Shorts", + "resource.label.1001005.lower_garment_length_uncertain.1001005.43.lower_garment_length_uncertain.namecn": "Bottom Length - Uncertain", + "resource.label.1001005.name": "Pedestrian Attribute Recognition & Chef Uniform Detection", + "resource.label.1001005.ordinary_hat.1001005.60.ordinary_hat.namecn": "Regular Hat", + "resource.label.1001005.safety_helmet.1001005.61.safety_helmet.namecn": "Safety Helmet", + "resource.label.1001005.top_color_black.1001005.5.top_color_black.namecn": "Top Color - Black", + "resource.label.1001005.top_color_blue.1001005.6.top_color_blue.namecn": "Top Color - Blue", + "resource.label.1001005.top_color_brown_camel.1001005.7.top_color_brown_camel.namecn": "Top Color - Brown/Camel", + "resource.label.1001005.top_color_floral.1001005.8.top_color_floral.namecn": "Top Color - Patterned", + "resource.label.1001005.top_color_gray.1001005.9.top_color_gray.namecn": "Top Color - Gray", + "resource.label.1001005.top_color_green.1001005.10.top_color_green.namecn": "Top Color - Green", + "resource.label.1001005.top_color_nude_flesh.1001005.11.top_color_nude_flesh.namecn": "Top Color - Nude/Skin", + "resource.label.1001005.top_color_orange.1001005.12.top_color_orange.namecn": "Top Color - Orange", + "resource.label.1001005.top_color_pink.1001005.13.top_color_pink.namecn": "Top Color - Pink", + "resource.label.1001005.top_color_polka_dot.1001005.14.top_color_polka_dot.namecn": "Top Color - Polka Dot", + "resource.label.1001005.top_color_purple.1001005.15.top_color_purple.namecn": "Top Color - Purple", + "resource.label.1001005.top_color_red.1001005.16.top_color_red.namecn": "Top Color - Red", + "resource.label.1001005.top_color_striped.1001005.17.top_color_striped.namecn": "Top Color - Striped", + "resource.label.1001005.top_color_uncertain.1001005.18.top_color_uncertain.namecn": "Top Color - Uncertain", + "resource.label.1001005.top_color_white.1001005.19.top_color_white.namecn": "Top Color - White", + "resource.label.1001005.top_color_yellow.1001005.20.top_color_yellow.namecn": "Top Color - Yellow", + "resource.label.1001005.upper_garment_sleeve_length_long_sleeves.1001005.0.upper_garment_sleeve_length_long_sleeves.namecn": "Sleeve Length - Long", + "resource.label.1001005.upper_garment_sleeve_length_mid_length_sleeves.1001005.1.upper_garment_sleeve_length_mid_length_sleeves.namecn": "Sleeve Length - Mid-length", + "resource.label.1001005.upper_garment_sleeve_length_short_sleeves.1001005.2.upper_garment_sleeve_length_short_sleeves.namecn": "Sleeve Length - Short", + "resource.label.1001005.upper_garment_sleeve_length_sleeveless_spaghetti_straps_bandeau.1001005.3.upper_garment_sleeve_length_sleeveless_spaghetti_straps_bandeau.namecn": "Sleeve Length - Sleeveless/Spaghetti/Pleated", + "resource.label.1001005.upper_garment_sleeve_length_uncertain.1001005.4.upper_garment_sleeve_length_uncertain.namecn": "Sleeve Length - Uncertain", + "resource.label.1001007.name": "ReID Features", + "resource.label.1001007.pedestrianrecognition.1001007.0.pedestrianrecognition.namecn": "Pedestrian Features", + "resource.label.1001008.name": "Pedestrian Quality", + "resource.label.1001008.quality0.1001008.0.quality0.namecn": "Pedestrian Quality 0", + "resource.label.1001008.quality1.1001008.1.quality1.namecn": "Pedestrian Quality 1", + "resource.label.1001008.quality2.1001008.2.quality2.namecn": "Pedestrian Quality 2", + "resource.label.1001008.quality3.1001008.3.quality3.namecn": "Pedestrian Quality 3", + "resource.label.1001008.quality4.1001008.4.quality4.namecn": "Pedestrian Quality 4", + "resource.label.1001008.quality5.1001008.5.quality5.namecn": "Pedestrian Quality 5", + "resource.label.1001010.name": "Sleeping on Duty", + "resource.label.1001010.pedsleepliedown.1001010.0.pedsleepliedown.namecn": "Sleeping Posture - Lying Down", + "resource.label.1001010.pedsleepstomach.1001010.1.pedsleepstomach.namecn": "Sleeping Posture - Face Down", + "resource.label.2000001.name": "Vehicle Detection", + "resource.label.2000001.nonmotorvehicle.2000001.0.nonmotorvehicle.namecn": "Non-motor Vehicle", + "resource.label.2000001.pedestrian.2000001.1.pedestrian.namecn": "Pedestrian", + "resource.label.2000001.vehicle.2000001.2.vehicle.namecn": "Vehicle", + "resource.label.2000011.back.2000011.23.back.namecn": "Back", + "resource.label.2000011.black.2000011.11.black.namecn": "Black", + "resource.label.2000011.blue.2000011.12.blue.namecn": "Blue", + "resource.label.2000011.brown.2000011.13.brown.namecn": "Brown", + "resource.label.2000011.color_poorquality.2000011.22.color_poorquality.namecn": "Color - Poor Quality", + "resource.label.2000011.direction_poorquality.2000011.26.direction_poorquality.namecn": "Orientation - Poor Quality", + "resource.label.2000011.front.2000011.24.front.namecn": "Front", + "resource.label.2000011.green.2000011.19.green.namecn": "Green", + "resource.label.2000011.mixcolor.2000011.20.mixcolor.namecn": "Mixed Color", + "resource.label.2000011.motorcycle.2000011.2.motorcycle.namecn": "Motorcycle", + "resource.label.2000011.name": "Vehicle Attributes", + "resource.label.2000011.orange.2000011.17.orange.namecn": "Orange", + "resource.label.2000011.othercar.2000011.4.othercar.namecn": "Other Vehicle", + "resource.label.2000011.purple.2000011.15.purple.namecn": "Purple", + "resource.label.2000011.red.2000011.16.red.namecn": "Red", + "resource.label.2000011.side.2000011.25.side.namecn": "Side", + "resource.label.2000011.silver.2000011.21.silver.namecn": "Silver", + "resource.label.2000011.type_poorquality.2000011.8.type_poorquality.namecn": "Poor Quality", + "resource.label.2000011.white.2000011.14.white.namecn": "White", + "resource.label.2000011.yellow.2000011.18.yellow.namecn": "Yellow", + "resource.label.2000020.name": "E-bike in Elevator Classification", + "resource.label.2001002.hatless.2001002.0.hatless.namecn": "No Helmet", + "resource.label.2001002.name": "Head-shoulder Safety Helmet Detection", + "resource.label.2001002.normalhat.2001002.1.normalhat.namecn": "Regular Hat", + "resource.label.2001002.pedhelmet.2001002.2.pedhelmet.namecn": "Helmet", + "resource.label.2001002.pedsafehelmet.2001002.3.pedsafehelmet.namecn": "Safety Helmet", + "resource.label.2001002.unsure.2001002.4.unsure.namecn": "Uncertain", + "resource.label.2001003.fire.2001003.0.fire.namecn": "Flame", + "resource.label.2001003.name": "Flame & Smoke Detection", + "resource.label.2001003.smog.2001003.1.smog.namecn": "Smoke", + "resource.label.2001008.name": "Garbage Pile Detection", + "resource.label.2001008.rubbishdump.2001008.0.rubbishdump.namecn": "Garbage Pile", + "resource.label.2001036.hatless.2001036.0.hatless.namecn": "No Helmet", + "resource.label.2001036.name": "Pedestrian Safety Helmet Detection", + "resource.label.2001036.normalhat.2001036.1.normalhat.namecn": "Regular Hat", + "resource.label.2001036.pedhelmet.2001036.2.pedhelmet.namecn": "Helmet", + "resource.label.2001036.pedsafehelmet.2001036.3.pedsafehelmet.namecn": "Safety Helmet", + "resource.label.2001036.unsure.2001036.4.unsure.namecn": "Uncertain", + "resource.label.2002008.name": "Falling", + "resource.label.2002008.normal.2002008.0.normal.namecn": "Normal", + "resource.label.2002008.pedfalldown.2002008.1.pedfalldown.namecn": "Falling", + "resource.label.2002011.name": "Phone Call, Phone Usage & Smoking Detection", + "resource.label.2002011.obanswer.2002011.4.obanswer.namecn": "Subtle Phone Call (Not Recommended)", + "resource.label.2002011.obplay.2002011.5.obplay.namecn": "Subtle Phone Usage (Not Recommended)", + "resource.label.2002011.obsmoke.2002011.6.obsmoke.namecn": "Subtle Smoking (Not Recommended)", + "resource.label.2002011.passenger.2002011.3.passenger.namecn": "Pedestrian (Not Recommended)", + "resource.label.2002011.pedphoneanswer.2002011.0.pedphoneanswer.namecn": "Phone Call", + "resource.label.2002011.pedphoneplay.2002011.1.pedphoneplay.namecn": "Phone Usage", + "resource.label.2002011.pedsmoking.2002011.2.pedsmoking.namecn": "Smoking", + "resource.label.2180145.description": "YOLOv8 Detection Model", + "resource.label.3000003.mouse.3000003.0.mouse.namecn": "Kitchen Rat", + "resource.label.3000003.name": "Kitchen Creature Detection (Focus: Rats)", + "resource.label.9183416.description": "GroundingDINO Detection Foundation Model", + "resource.label.9233591.description": "SAM2 Segmentation Foundation Model", + "resource.model.4000001.yolo26_det.name": "YOLO26 Detection", + "resource.model.4000001.yolov11_det.name": "YOLOv8 Detection", + "resource.model.4000001.yolov12_det.name": "YOLOv8 Detection", + "resource.model.4000001.yolov8_det.name": "YOLOv8 Detection", + "resource.model.4000001.yolov9_det.name": "YOLOv8 Detection", + "resource.model.4000002.classify.name": "YOLOv8 Classification", + "resource.option.10.10.aiparam_fire_detpostion.0.options_name": "Bottom", + "resource.option.10.10.aiparam_fire_detpostion.1.options_name": "Center", + "resource.option.10.10.aiparam_fire_detpostion.2.options_name": "Top", + "resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.0.options_name": "Bottom", + "resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.1.options_name": "Center", + "resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.2.options_name": "Top", + "resource.option.11.11.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.11.11.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.11.11.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.12.12.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.12.12.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.12.12.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.13.13.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.13.13.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.13.13.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.13.13.param_areacalcdurationtimetype.1.options_name": "Milliseconds", + "resource.option.13.13.param_areacalcdurationtimetype.1000.options_name": "Seconds", + "resource.option.13.13.param_areacalcdurationtimetype.3600000.options_name": "Hours", + "resource.option.13.13.param_areacalcdurationtimetype.60000.options_name": "Minutes", + "resource.option.13.13.param_targetcalctype.0.options_name": "Instantaneous (Area People Counting)", + "resource.option.13.13.param_targetcalctype.1.options_name": "Periodic Total Count (People Flow)", + "resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.1.options_name": "Milliseconds", + "resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.1000.options_name": "Seconds", + "resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.3600000.options_name": "Hours", + "resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.60000.options_name": "Minutes", + "resource.option.13.ba_00005.97085574.param_targetcalctype.0.options_name": "Instantaneous (Area People Counting)", + "resource.option.13.ba_00005.97085574.param_targetcalctype.1.options_name": "Periodic Total Count (People Flow)", + "resource.option.15.15.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.15.15.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.15.15.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.16.16.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.16.16.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.16.16.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.16.16.param_arealimitdurationtimetype.1.options_name": "Milliseconds", + "resource.option.16.16.param_arealimitdurationtimetype.1000.options_name": "Seconds", + "resource.option.16.16.param_arealimitdurationtimetype.3600000.options_name": "Hours", + "resource.option.16.16.param_arealimitdurationtimetype.60000.options_name": "Minutes", + "resource.option.16.16.param_arealimittargettype.0.options_name": "Alarm when below target count", + "resource.option.16.16.param_arealimittargettype.1.options_name": "Alarm when above target count", + "resource.option.16.16.param_arealimittargettype.2.options_name": "Alarm when at or below target count", + "resource.option.16.16.param_arealimittargettype.3.options_name": "Alarm when at or above target count", + "resource.option.16.16.param_arealimittargettype.4.options_name": "Alarm when equal to target count", + "resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.1.options_name": "Milliseconds", + "resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.1000.options_name": "Seconds", + "resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.3600000.options_name": "Hours", + "resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.60000.options_name": "Minutes", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.0.options_name": "Alarm when below target count", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.1.options_name": "Alarm when above target count", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.2.options_name": "Alarm when at or below target count", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.3.options_name": "Alarm when at or above target count", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.4.options_name": "Alarm when equal to target count", + "resource.option.1917.1917.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.1917.1917.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.1917.1917.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.2.2.aiparam_face_detpostion.0.options_name": "Bottom", + "resource.option.2.2.aiparam_face_detpostion.1.options_name": "Center", + "resource.option.2.2.aiparam_face_detpostion.2.options_name": "Top", + "resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.0.options_name": "Bottom", + "resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.1.options_name": "Center", + "resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.2.options_name": "Top", + "resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.22.22.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.22.22.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.22.22.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.28862.28862.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.28862.28862.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.28862.28862.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.3.3.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.3.3.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.3.3.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.3.3.param_areadurationtimetype.1.options_name": "Milliseconds", + "resource.option.3.3.param_areadurationtimetype.1000.options_name": "Seconds", + "resource.option.3.3.param_areadurationtimetype.3600000.options_name": "Hours", + "resource.option.3.3.param_areadurationtimetype.60000.options_name": "Minutes", + "resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.1.options_name": "Milliseconds", + "resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.1000.options_name": "Seconds", + "resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.3600000.options_name": "Hours", + "resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.60000.options_name": "Minutes", + "resource.option.32.32.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.32.32.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.32.32.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.38873.38873.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.38873.38873.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.38873.38873.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.0.options_name": "Bottom", + "resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.1.options_name": "Center", + "resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.2.options_name": "Top", + "resource.option.5.5.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.5.5.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.5.5.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.5.5.param_arealimitdurationtimetype.1.options_name": "Milliseconds", + "resource.option.5.5.param_arealimitdurationtimetype.1000.options_name": "Seconds", + "resource.option.5.5.param_arealimitdurationtimetype.3600000.options_name": "Hours", + "resource.option.5.5.param_arealimitdurationtimetype.60000.options_name": "Minutes", + "resource.option.5.5.param_arealimittargettype.0.options_name": "Alarm when below target count", + "resource.option.5.5.param_arealimittargettype.1.options_name": "Alarm when above target count", + "resource.option.5.5.param_arealimittargettype.2.options_name": "Alarm when at or below target count", + "resource.option.5.5.param_arealimittargettype.3.options_name": "Alarm when at or above target count", + "resource.option.5.5.param_arealimittargettype.4.options_name": "Alarm when equal to target count", + "resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.1.options_name": "Milliseconds", + "resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.1000.options_name": "Seconds", + "resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.3600000.options_name": "Hours", + "resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.60000.options_name": "Minutes", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.0.options_name": "Alarm when below target count", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.1.options_name": "Alarm when above target count", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.2.options_name": "Alarm when at or below target count", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.3.options_name": "Alarm when at or above target count", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.4.options_name": "Alarm when equal to target count", + "resource.option.50813.50813.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.50813.50813.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.50813.50813.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.51.51.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.51.51.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.51.51.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.51.51.param_areacalcdurationtimetype.1.options_name": "Milliseconds", + "resource.option.51.51.param_areacalcdurationtimetype.1000.options_name": "Seconds", + "resource.option.51.51.param_areacalcdurationtimetype.3600000.options_name": "Hours", + "resource.option.51.51.param_areacalcdurationtimetype.60000.options_name": "Minutes", + "resource.option.51.51.param_targetcalctype.0.options_name": "Instantaneous (Area People Counting)", + "resource.option.51.51.param_targetcalctype.1.options_name": "Periodic Total Count (People Flow)", + "resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.1.options_name": "Milliseconds", + "resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.1000.options_name": "Seconds", + "resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.3600000.options_name": "Hours", + "resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.60000.options_name": "Minutes", + "resource.option.51.ba_00005.667e48b6.param_targetcalctype.0.options_name": "Instantaneous (Area People Counting)", + "resource.option.51.ba_00005.667e48b6.param_targetcalctype.1.options_name": "Periodic Total Count (People Flow)", + "resource.option.57.57.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.57.57.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.57.57.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.57.57.param_trippingwiretype.1.options_name": "Single Line", + "resource.option.57.57.param_trippingwiretype.2.options_name": "Double Line", + "resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.57.ba_00005.f7750059.param_trippingwiretype.1.options_name": "Single Line", + "resource.option.57.ba_00005.f7750059.param_trippingwiretype.2.options_name": "Double Line", + "resource.option.58.58.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.58.58.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.58.58.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.6.6.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.6.6.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.6.6.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.65.65.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.65.65.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.65.65.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.7.7.aiparam_nonmotorvehicle_detpostion.0.options_name": "Bottom", + "resource.option.7.7.aiparam_nonmotorvehicle_detpostion.1.options_name": "Center", + "resource.option.7.7.aiparam_nonmotorvehicle_detpostion.2.options_name": "Top", + "resource.option.7.7.aiparam_vehicle_detpostion.0.options_name": "Bottom", + "resource.option.7.7.aiparam_vehicle_detpostion.1.options_name": "Center", + "resource.option.7.7.aiparam_vehicle_detpostion.2.options_name": "Top", + "resource.option.7.7.param_areadurationtimetype.1.options_name": "Milliseconds", + "resource.option.7.7.param_areadurationtimetype.1000.options_name": "Seconds", + "resource.option.7.7.param_areadurationtimetype.3600000.options_name": "Hours", + "resource.option.7.7.param_areadurationtimetype.60000.options_name": "Minutes", + "resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.0.options_name": "Bottom", + "resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.1.options_name": "Center", + "resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.2.options_name": "Top", + "resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.0.options_name": "Bottom", + "resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.1.options_name": "Center", + "resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.2.options_name": "Top", + "resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.1.options_name": "Milliseconds", + "resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.1000.options_name": "Seconds", + "resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.3600000.options_name": "Hours", + "resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.60000.options_name": "Minutes", + "resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.0.options_name": "Bottom", + "resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.1.options_name": "Center", + "resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.2.options_name": "Top", + "resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.0.options_name": "Bottom", + "resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.1.options_name": "Center", + "resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.2.options_name": "Top", + "resource.option.83708.83708.aiparam_category0_detpostion.0.options_name": "Bottom", + "resource.option.83708.83708.aiparam_category0_detpostion.1.options_name": "Center", + "resource.option.83708.83708.aiparam_category0_detpostion.2.options_name": "Top", + "resource.option.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.0.options_name": "Bottom", + "resource.option.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.1.options_name": "Center", + "resource.option.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.2.options_name": "Top", + "resource.option.9.9.aiparam_smog_detpostion.0.options_name": "Bottom", + "resource.option.9.9.aiparam_smog_detpostion.1.options_name": "Center", + "resource.option.9.9.aiparam_smog_detpostion.2.options_name": "Top", + "resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.0.options_name": "Bottom", + "resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.1.options_name": "Center", + "resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.2.options_name": "Top", + "resource.option.aa_00003.motionstatus.0.options_name": "Off", + "resource.option.aa_00003.motionstatus.1.options_name": "Moving", + "resource.option.aa_00003.motionstatus.2.options_name": "Stationary", + "resource.option.aa_00003.shapechangestatus.0.options_name": "Not Required", + "resource.option.aa_00003.shapechangestatus.1.options_name": "Shape Change Required", + "resource.option.aa_00003.shapechangestatus.2.options_name": "Shape Unchanged Required", + "resource.option.aa_00005.featureinput.0.options_name": "Face Feature Extraction (No Comparison)", + "resource.option.aa_00005.featureinput.1.options_name": "Uniform Feature Extraction (Comparison Required)", + "resource.option.aa_00005.featureinput.2.options_name": "Object Feature Extraction (Comparison Required)", + "resource.option.aa_00005.featureinput.3.options_name": "Body Feature Extraction (No Comparison)", + "resource.option.aa_00005.matchflag.0.options_name": "Unmatched Alarm", + "resource.option.aa_00005.matchflag.1.options_name": "Matched Alarm", + "resource.option.ba_00003.detectiontimetype.1.options_name": "Seconds", + "resource.option.ba_00003.detectiontimetype.2.options_name": "Milliseconds", + "resource.option.ba_00004.alarmproperty.0.options_name": "Normal Alarm (No Attributes)", + "resource.option.ba_00004.alarmproperty.1.options_name": "Face Detection/Comparison (Feature Attributes)", + "resource.option.ba_00004.alarmproperty.10.options_name": "Body Feature Reporting", + "resource.option.ba_00004.alarmproperty.11.options_name": "Uniform Comparison Result", + "resource.option.ba_00004.alarmproperty.3.options_name": "Vehicle Attributes", + "resource.option.ba_00004.alarmproperty.5.options_name": "Object-class Special Detection Attributes (e.g., filter state/comparison result)", + "resource.option.ba_00004.alarmproperty.6.options_name": "People Flow Counting Attributes", + "resource.option.ba_00004.alarmproperty.7.options_name": "Vehicle Flow Counting Attributes", + "resource.option.ba_00004.alarmproperty.8.options_name": "Crowd Count", + "resource.option.ba_00004.alarmproperty.9.options_name": "People Counting Attributes (Area Count)", + "resource.option.ba_00004.custparam_alarmtype.1.options_name": "Without Target Tracking", + "resource.option.ba_00004.custparam_alarmtype.2.options_name": "With Target Tracking", + "resource.option.ba_00004.custparam_alarmtype.3.options_name": "No Suppression", + "resource.option.ba_00005.areaalarmtype.0.options_name": "Count Limit (for Off-post/Gathering)", + "resource.option.ba_00005.areaalarmtype.1.options_name": "Flow Counting & Area Count Statistics", + "resource.option.ba_00005.areaalarmtype.2.options_name": "Line Crossing (for Tripwire)", + "resource.option.ba_00005.areaalarmtype.3.options_name": "Target Direction Alarm (for Wrong-way)", + "resource.option.ba_00005.areaalarmtype.4.options_name": "Target in Region for Duration (for Intrusion)", + "resource.option.ba_00005.areaalarmtype.5.options_name": "Detection-class (for Body Detection)", + "resource.option.ba_00005.areaalarmtype.6.options_name": "Multi-instance Count Limit (multiple instances in one flow)", + "resource.option.ba_00005.areadurationtimetype.1.options_name": "Milliseconds", + "resource.option.ba_00005.areadurationtimetype.1000.options_name": "Seconds", + "resource.option.ba_00005.areadurationtimetype.3600000.options_name": "Hours", + "resource.option.ba_00005.areadurationtimetype.60000.options_name": "Minutes", + "resource.option.ba_00005.arealimittargettype.0.options_name": "Alarm when below target count", + "resource.option.ba_00005.arealimittargettype.1.options_name": "Alarm when above target count", + "resource.option.ba_00005.arealimittargettype.2.options_name": "Alarm when at or below target count", + "resource.option.ba_00005.arealimittargettype.3.options_name": "Alarm when at or above target count", + "resource.option.ba_00005.arealimittargettype.4.options_name": "Alarm when equal to target count", + "resource.option.ba_00005.breakareatype.101.options_name": "Forward Line Crossing", + "resource.option.ba_00005.countbreakareatype.0.options_name": "Alarm within Region", + "resource.option.ba_00005.countbreakareatype.103.options_name": "Bidirectional Line Crossing Statistics", + "resource.option.ba_00005.detectbreakareatype.0.options_name": "Alarm within Region", + "resource.option.ba_00005.durationbreakareatype.0.options_name": "Alarm within Region", + "resource.option.ba_00005.durationbreakareatype.2.options_name": "Outside to Inside", + "resource.option.ba_00005.inputareatype.1.options_name": "Primary Region", + "resource.option.ba_00005.inputareatype.2.options_name": "Associated Region", + "resource.option.ba_00005.param_areacalcdurationtimetype.1.options_name": "Milliseconds", + "resource.option.ba_00005.param_areacalcdurationtimetype.1000.options_name": "Seconds", + "resource.option.ba_00005.param_areacalcdurationtimetype.3600000.options_name": "Hours", + "resource.option.ba_00005.param_areacalcdurationtimetype.60000.options_name": "Minutes", + "resource.option.ba_00005.param_areadurationtimetype.1.options_name": "Milliseconds", + "resource.option.ba_00005.param_areadurationtimetype.1000.options_name": "Seconds", + "resource.option.ba_00005.param_areadurationtimetype.3600000.options_name": "Hours", + "resource.option.ba_00005.param_areadurationtimetype.60000.options_name": "Minutes", + "resource.option.ba_00005.param_arealimitdurationtimetype.1.options_name": "Milliseconds", + "resource.option.ba_00005.param_arealimitdurationtimetype.1000.options_name": "Seconds", + "resource.option.ba_00005.param_arealimitdurationtimetype.3600000.options_name": "Hours", + "resource.option.ba_00005.param_arealimitdurationtimetype.60000.options_name": "Minutes", + "resource.option.ba_00005.param_arealimittargettype.0.options_name": "Alarm when below target count", + "resource.option.ba_00005.param_arealimittargettype.1.options_name": "Alarm when above target count", + "resource.option.ba_00005.param_arealimittargettype.2.options_name": "Alarm when at or below target count", + "resource.option.ba_00005.param_arealimittargettype.3.options_name": "Alarm when at or above target count", + "resource.option.ba_00005.param_arealimittargettype.4.options_name": "Alarm when equal to target count", + "resource.option.ba_00005.param_retrodirect.0.options_name": "Bottom to Top", + "resource.option.ba_00005.param_retrodirect.1.options_name": "Top to Bottom", + "resource.option.ba_00005.param_targetcalctype.0.options_name": "Instantaneous (Area People Counting)", + "resource.option.ba_00005.param_targetcalctype.1.options_name": "Periodic Total Count (People Flow)", + "resource.option.ba_00005.param_trippingwiretype.1.options_name": "Single Line", + "resource.option.ba_00005.param_trippingwiretype.2.options_name": "Double Line", + "resource.option.da_00002.inputtype.box.options_name": "Box", + "resource.option.da_00002.inputtype.point.options_name": "Point", + "resource.option.da_00003.generationstyle.creative.options_name": "Creative", + "resource.option.da_00003.generationstyle.custom.options_name": "Custom", + "resource.option.da_00003.generationstyle.standard.options_name": "Standard", + "resource.option.da_00003.generationstyle.strict.options_name": "Precise", + "resource.option.ip0001.data_type.0.options_name": "Float32", + "resource.option.ip0001.data_type.1.options_name": "Int32", + "resource.option.ip0001.data_type.2.options_name": "Float16 (Half)", + "resource.option.ip0001.data_type.3.options_name": "Float16", + "resource.option.ip0001.data_type.4.options_name": "Uint8", + "resource.option.ip0001.data_type.5.options_name": "Int8", + "resource.option.la_audiodevice_code.operation.1.options_label": "Audio Playback", + "resource.option.la_audiodevice_code.operation.2.options_label": "Text-to-Speech", + "resource.option.la_audiodevice_code.tone.1.options_label": "Male Voice", + "resource.option.la_audiodevice_code.tone.2.options_label": "Female Voice", + "resource.option.on0001.data_type.0.options_name": "Float32", + "resource.option.on0001.data_type.1.options_name": "Int32", + "resource.option.on0001.data_type.2.options_name": "Float16 (Half)", + "resource.option.on0001.data_type.3.options_name": "Float16", + "resource.option.on0001.data_type.4.options_name": "Uint8", + "resource.option.on0001.data_type.5.options_name": "Int8", + "resource.option.pa_00005.featureinput.0.options_name": "Face Feature Extraction (Not Supported)", + "resource.option.pa_00005.featureinput.1.options_name": "Uniform Feature Extraction", + "resource.option.pa_00005.featureinput.2.options_name": "Object Feature Extraction", + "resource.option.pa_00005.featureinput.3.options_name": "Body Feature Extraction (Not Supported)", + "resource.option.pa_00005.matchflag.0.options_name": "Unmatched Alarm", + "resource.option.pa_00005.matchflag.1.options_name": "Matched Alarm", + "resource.option.pda_00002.inputtype.box.options_name": "Box", + "resource.option.pda_00002.inputtype.point.options_name": "Point", + "resource.option.pda_00003.generationstyle.creative.options_name": "Creative", + "resource.option.pda_00003.generationstyle.custom.options_name": "Custom", + "resource.option.pda_00003.generationstyle.standard.options_name": "Standard", + "resource.option.pda_00003.generationstyle.strict.options_name": "Precise", + "resource.option.pr0001.gravity.0.options_name": "Direct Resize", + "resource.option.pr0001.gravity.1.options_name": "Aspect Ratio Resize with Center Padding", + "resource.option.pr0001.gravity.2.options_name": "Aspect Ratio Resize with Top-left Alignment", + "resource.option.pr0005.normmode.0.options_name": "Mode 0", + "resource.option.pr0005.normmode.1.options_name": "Mode 1", + "resource.option.pr0005.normmode.2.options_name": "Mode 2", + "resource.option.pt0001.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.option.pt0002.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.option.pt0003.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.option.pt0004.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.option.pt0005.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.option.pt0006.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.option.pt0007.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.option.pt0008.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.option.pt0009.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess (YOLO26, etc.)", + "resource.param.10.10.0.name": "Default", + "resource.param.10.10.aiparam_2001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.10.10.aiparam_2001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.10.10.aiparam_2001003_trackdynamicmatch.name": "Flame & Smoke Detection Tracking Radius", + "resource.param.10.10.aiparam_fire_confidence.description": "Flame confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.10.10.aiparam_fire_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.10.10.aiparam_fire_confidence.name": "Flame Confidence", + "resource.param.10.10.aiparam_fire_confidenceconfig.description": "Flame confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.10.10.aiparam_fire_confidenceconfig.name": "Flame Confidence Offset", + "resource.param.10.10.aiparam_fire_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.10.10.aiparam_fire_detpostion.failedtip": "Please select a valid value", + "resource.param.10.10.aiparam_fire_detpostion.name": "Flame Detection Method", + "resource.param.10.10.filter_fire_side_min.description": "Min flame size: minimum image size for captured flame photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.10.10.filter_fire_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.10.10.filter_fire_side_min.name": "Min Flame Size", + "resource.param.10.10.name.description": "Region name: required, max 32 characters", + "resource.param.10.10.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.10.10.name.name": "Region Name", + "resource.param.10.10.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.10.10.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.10.10.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.10.10.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.10.10.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.10.10.param_detectionduration.name": "Detection Time (sec)", + "resource.param.10.10.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.10.10.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.10.10.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.10.10.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.10.10.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.10.10.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.10.10.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.10.10.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.10.10.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.10.10.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.10.10.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.10.10.param_sensitivity.name": "Sensitivity", + "resource.param.10.10.param_videoreadfps.description": "For offline videos with abnormal frame rates, this parameter forces a specific frame rate. <0: no forcing, >=0: forced frame rate, default: -1 (full frame).", + "resource.param.10.10.param_videoreadfps.failedtip": "Please enter a valid value", + "resource.param.10.10.param_videoreadfps.name": "Offline Video Frame Rate", + "resource.param.10.10.param_videorepeatcount.description": "Offline video loop count. <0: infinite, 0: once, >1: specified count", + "resource.param.10.10.param_videorepeatcount.failedtip": "Please enter an integer from 1 to 100", + "resource.param.10.10.param_videorepeatcount.name": "Offline Video Play Count", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.description": "Fire confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.name": "Fire Confidence", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidenceconfig.description": "Fire confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidenceconfig.name": "Fire Confidence Offset", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.failedtip": "Please select a valid value", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.name": "Fire Detection Method", + "resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.name": "Flame & Smoke Detection Tracking Radius", + "resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.description": "Min flame size: minimum image size for captured flame photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.name": "Min Flame Size", + "resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.description": "Detection time: range 1–3600, default 2.", + "resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.name": "Detection Time (sec)", + "resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.description": "Sensitivity: range 1–10, default: 5. Higher values make alarms easier to trigger.", + "resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.name": "Sensitivity", + "resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.10.ba_00004.1478c130.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.10.ba_00004.1478c130.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.10.ba_00004.1478c130.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.10.ba_00004.1478c130.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.10.ba_00004.1478c130.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.10.ba_00004.1478c130.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.10.ba_00004.1478c130.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.10.ba_00004.1478c130.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.10.ba_00004.1478c130.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.11.11.0.name": "Default", + "resource.param.11.11.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.11.11.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.11.11.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.11.11.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.11.11.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.11.11.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.11.11.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.11.11.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.11.11.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.11.11.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.11.11.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.11.11.aiparam_pedsmoking_confidence.description": "Smoking confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.11.11.aiparam_pedsmoking_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.11.11.aiparam_pedsmoking_confidence.name": "Smoking Confidence", + "resource.param.11.11.aiparam_pedsmoking_confidenceconfig.description": "Smoking confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.11.11.aiparam_pedsmoking_confidenceconfig.name": "Smoking Confidence Offset", + "resource.param.11.11.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.11.11.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.11.11.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.11.11.name.description": "Region name: required, max 32 characters", + "resource.param.11.11.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.11.11.name.name": "Region Name", + "resource.param.11.11.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.11.11.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.11.11.param_detectionduration.name": "Detection Time (sec)", + "resource.param.11.11.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.11.11.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.11.11.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.11.11.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.11.11.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.11.11.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.11.11.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.11.11.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.11.11.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.11.11.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.11.11.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.11.11.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.11.11.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.11.11.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.11.11.param_sensitivity.name": "Sensitivity", + "resource.param.11.11.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.11.11.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.11.11.param_targetalarmcount.name": "Alarm Count", + "resource.param.11.11.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.11.11.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.11.11.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.description": "Smoking (pedSmoking) confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.name": "Smoking (pedSmoking) Confidence", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidenceconfig.description": "Smoking (pedSmoking) confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidenceconfig.name": "Smoking (pedSmoking) Confidence Offset", + "resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.description": "Detection time: range 1–3600, default 2.", + "resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.name": "Detection Time (sec)", + "resource.param.11.ba_00003.b90c6769.param_sensitivity.description": "Sensitivity: range 1–10, default: 5. Higher values make alarms easier to trigger.", + "resource.param.11.ba_00003.b90c6769.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.11.ba_00003.b90c6769.param_sensitivity.name": "Sensitivity", + "resource.param.11.ba_00004.0f53b331.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.11.ba_00004.0f53b331.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.11.ba_00004.0f53b331.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name": "Overlay Trajectory on Panorama", + "resource.param.11.ba_00004.0f53b331.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.11.ba_00004.0f53b331.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.11.ba_00004.0f53b331.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.11.ba_00004.0f53b331.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.11.ba_00004.0f53b331.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.11.ba_00004.0f53b331.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip": "Please enter an integer from 0 to 100", + "resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name": "Alarm Count", + "resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name": "Alarm Interval (sec)", + "resource.param.12.12.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.12.12.2002011.0.pedphoneanswer.namecn": "Phone Call", + "resource.param.12.12.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.12.12.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.12.12.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.12.12.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.12.12.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.12.12.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.12.12.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.12.12.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.12.12.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.12.12.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.12.12.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.12.12.aiparam_pedphoneanswer_confidence.description": "Phone call confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.12.12.aiparam_pedphoneanswer_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.12.12.aiparam_pedphoneanswer_confidence.name": "Phone Call Confidence", + "resource.param.12.12.aiparam_pedphoneanswer_confidenceconfig.description": "Phone call confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.12.12.aiparam_pedphoneanswer_confidenceconfig.name": "Phone Call Confidence Offset", + "resource.param.12.12.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.12.12.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.12.12.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.12.12.name.description": "Region name: required, max 32 characters", + "resource.param.12.12.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.12.12.name.name": "Region Name", + "resource.param.12.12.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.12.12.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.12.12.param_detectionduration.name": "Detection Time (sec)", + "resource.param.12.12.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.12.12.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.12.12.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.12.12.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.12.12.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.12.12.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.12.12.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.12.12.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.12.12.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.12.12.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.12.12.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.12.12.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.12.12.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.12.12.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.12.12.param_sensitivity.name": "Sensitivity", + "resource.param.12.12.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.12.12.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.12.12.param_targetalarmcount.name": "Alarm Count", + "resource.param.12.12.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.12.12.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.12.12.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.12.aa_00001.487c1cf0.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.12.aa_00002.c37b8e34.2002011.0.pedphoneanswer.namecn": "Phone Call", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.description": "Phone call confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.name": "Phone Call Confidence", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidenceconfig.description": "Phone call confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidenceconfig.name": "Phone Call Confidence Offset", + "resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.12.ba_00003.0d015957.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.12.ba_00003.0d015957.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.12.ba_00003.0d015957.param_detectionduration.name": "Detection Time (sec)", + "resource.param.12.ba_00003.0d015957.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.12.ba_00003.0d015957.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.12.ba_00003.0d015957.param_sensitivity.name": "Sensitivity", + "resource.param.12.ba_00004.0f53b331.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.12.ba_00004.0f53b331.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.12.ba_00004.0f53b331.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.12.ba_00004.0f53b331.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.12.ba_00004.0f53b331.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.12.ba_00004.0f53b331.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.12.ba_00004.0f53b331.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.12.ba_00004.0f53b331.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.12.ba_00004.0f53b331.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.12.ba_00004.0f53b331.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.12.ba_00004.0f53b331.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.12.ba_00004.0f53b331.param_targetalarmcount.name": "Alarm Count", + "resource.param.12.ba_00004.0f53b331.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.12.ba_00004.0f53b331.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.12.ba_00004.0f53b331.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.13.13.0.name": "People Flow Line", + "resource.param.13.13.1.name": "Region", + "resource.param.13.13.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.13.13.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.13.13.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.13.13.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.13.13.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.13.13.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.13.13.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.13.13.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.13.13.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.13.13.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.13.13.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.13.13.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.13.13.name.description": "Region name: required, max 32 characters", + "resource.param.13.13.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.13.13.name.name": "Region Name", + "resource.param.13.13.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.13.13.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.13.13.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.13.13.param_areacalcduration.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.13.13.param_areacalcduration.failedtip": "Please enter a valid number", + "resource.param.13.13.param_areacalcduration.name": "People Count Report Interval", + "resource.param.13.13.param_areacalcdurationtimetype.description": "Detection Time Unit", + "resource.param.13.13.param_areacalcdurationtimetype.failedtip": "Please select a valid number", + "resource.param.13.13.param_areacalcdurationtimetype.name": "Detection Time Unit", + "resource.param.13.13.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.13.13.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.13.13.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.13.13.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.13.13.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.13.13.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.13.13.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.13.13.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.13.13.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.13.13.param_targetcalctype.description": "Target Counting Method", + "resource.param.13.13.param_targetcalctype.failedtip": "Please select a valid value", + "resource.param.13.13.param_targetcalctype.name": "Target Counting Method", + "resource.param.13.aa_00001.e9173765.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.13.ba_00004.a5c23881.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.13.ba_00004.a5c23881.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.13.ba_00004.a5c23881.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.13.ba_00004.a5c23881.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.13.ba_00004.a5c23881.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.13.ba_00004.a5c23881.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.13.ba_00004.a5c23881.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.13.ba_00004.a5c23881.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.13.ba_00004.a5c23881.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.13.ba_00004.a5c23881.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.13.ba_00004.a5c23881.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.13.ba_00004.a5c23881.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.13.ba_00005.97085574.param_areacalcduration.description": "Count report interval: range 1–3600000, note the time unit", + "resource.param.13.ba_00005.97085574.param_areacalcduration.failedtip": "Please enter a valid number", + "resource.param.13.ba_00005.97085574.param_areacalcduration.name": "Count Report Interval", + "resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.description": "Count Report Interval Time Unit", + "resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.failedtip": "Please select a valid unit", + "resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.name": "Count Report Interval Time Unit", + "resource.param.13.ba_00005.97085574.param_targetcalctype.description": "Target Counting Method", + "resource.param.13.ba_00005.97085574.param_targetcalctype.failedtip": "Please select a valid value", + "resource.param.13.ba_00005.97085574.param_targetcalctype.name": "Target Counting Method", + "resource.param.15.15.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.15.15.2001036.0.pedhelmet.namecn": "Helmet", + "resource.param.15.15.2001036.1.pedsafehelmet.namecn": "Safety Helmet", + "resource.param.15.15.2001036.3.hatless.namecn": "No Helmet", + "resource.param.15.15.2001036.4.unsure.namecn": "Uncertain", + "resource.param.15.15.aiparam_1001003_frames.description": "Tracking history frame count. Range: 2–100", + "resource.param.15.15.aiparam_1001003_frames.failedtip": "Please enter an integer from 2 to 100", + "resource.param.15.15.aiparam_1001003_frames.name": "Pedestrian Detection Tracking History Frames", + "resource.param.15.15.aiparam_1001003_motion.description": "Stationary threshold. Range: 1–99, e.g., 80.0", + "resource.param.15.15.aiparam_1001003_motion.failedtip": "Please enter a value from 1 to 99 with 1 decimal place", + "resource.param.15.15.aiparam_1001003_motion.name": "Pedestrian Detection Stationary Threshold", + "resource.param.15.15.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.15.15.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.15.15.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.15.15.aiparam_hatless_confidence.description": "Hatless confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.15.aiparam_hatless_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.15.aiparam_hatless_confidence.name": "Hatless Confidence", + "resource.param.15.15.aiparam_hatless_confidenceconfig.description": "Hatless confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.15.aiparam_hatless_confidenceconfig.name": "Hatless Confidence Offset", + "resource.param.15.15.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.15.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.15.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.15.15.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.15.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.15.15.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.15.15.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.15.15.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.15.15.aiparam_pedhelmet_confidence.description": "Helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.15.aiparam_pedhelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.15.aiparam_pedhelmet_confidence.name": "Helmet Confidence", + "resource.param.15.15.aiparam_pedhelmet_confidenceconfig.description": "Helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.15.aiparam_pedhelmet_confidenceconfig.name": "Helmet Confidence Offset", + "resource.param.15.15.aiparam_pedsafehelmet_confidence.description": "Safety helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.15.aiparam_pedsafehelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.15.aiparam_pedsafehelmet_confidence.name": "Safety Helmet Confidence", + "resource.param.15.15.aiparam_pedsafehelmet_confidenceconfig.description": "Safety helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.15.aiparam_pedsafehelmet_confidenceconfig.name": "Safety Helmet Confidence Offset", + "resource.param.15.15.aiparam_unsure_confidence.description": "Uncertain confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.15.aiparam_unsure_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.15.aiparam_unsure_confidence.name": "Uncertain Confidence", + "resource.param.15.15.aiparam_unsure_confidenceconfig.description": "Uncertain confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.15.aiparam_unsure_confidenceconfig.name": "Uncertain Confidence Offset", + "resource.param.15.15.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.15.15.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.15.15.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.15.15.name.description": "Region name: required, max 32 characters", + "resource.param.15.15.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.15.15.name.name": "Region Name", + "resource.param.15.15.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.15.15.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.15.15.param_detectionduration.name": "Detection Time (sec)", + "resource.param.15.15.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.15.15.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.15.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.15.15.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.15.15.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.15.15.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.15.15.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.15.15.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.15.15.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.15.15.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.15.15.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.15.15.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.15.15.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.15.15.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.15.15.param_sensitivity.name": "Sensitivity", + "resource.param.15.15.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.15.15.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.15.15.param_targetalarmcount.name": "Alarm Count", + "resource.param.15.15.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.15.15.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.15.15.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.15.aa_00001.83b4eb95.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.15.aa_00002.a0333a67.2001036.0.pedhelmet.namecn": "Helmet", + "resource.param.15.aa_00002.a0333a67.2001036.1.pedsafehelmet.namecn": "Safety Helmet", + "resource.param.15.aa_00002.a0333a67.2001036.3.hatless.namecn": "No Helmet", + "resource.param.15.aa_00002.a0333a67.2001036.4.unsure.namecn": "Uncertain", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.description": "Hatless confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.name": "Hatless Confidence", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidenceconfig.description": "Hatless confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidenceconfig.name": "Hatless Confidence Offset", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.description": "Helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.name": "Helmet Confidence", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidenceconfig.description": "Helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidenceconfig.name": "Helmet Confidence Offset", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.description": "Safety helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.name": "Safety Helmet Confidence", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidenceconfig.description": "Safety helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidenceconfig.name": "Safety Helmet Confidence Offset", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.description": "Uncertain confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.name": "Uncertain Confidence", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidenceconfig.description": "Uncertain confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidenceconfig.name": "Uncertain Confidence Offset", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.description": "Tracking history frame count. Range: 2–100", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.failedtip": "Please enter an integer from 2 to 100", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.name": "Pedestrian Detection Tracking History Frames", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.description": "Stationary threshold. Range: 1–99, e.g., 80.0", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.failedtip": "Please enter a value from 1 to 99 with 1 decimal place", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.name": "Pedestrian Detection Stationary Threshold", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.15.ba_00003.b4b02c33.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.15.ba_00003.b4b02c33.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.15.ba_00003.b4b02c33.param_detectionduration.name": "Detection Time (sec)", + "resource.param.15.ba_00003.b4b02c33.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.15.ba_00003.b4b02c33.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.15.ba_00003.b4b02c33.param_sensitivity.name": "Sensitivity", + "resource.param.15.ba_00004.4fb8d95e.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.15.ba_00004.4fb8d95e.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15.ba_00004.4fb8d95e.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.15.ba_00004.4fb8d95e.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.15.ba_00004.4fb8d95e.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.15.ba_00004.4fb8d95e.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.name": "Alarm Count", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.15760.15760.0.name": "Default", + "resource.param.15760.15760.name.description": "Region name: required, max 32 characters", + "resource.param.15760.15760.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.15760.15760.name.name": "Region Name", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.16.16.0.name": "Default", + "resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.name": "Pedestrian Confidence", + "resource.param.16.16.aiparam_pedestrian_confidenceconfig.custom_detection.0.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.16.16.aiparam_pedestrian_confidenceconfig.custom_detection.0.name": "Pedestrian Confidence Offset", + "resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.failedtip": "Please select a valid value", + "resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.name": "Pedestrian Detection Method", + "resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.name": "Min Pedestrian Size", + "resource.param.16.16.name.description": "Region name: required, max 32 characters", + "resource.param.16.16.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.16.16.name.name": "Region Name", + "resource.param.16.16.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.16.16.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.16.16.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.16.16.param_arealimitduration.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.16.16.param_arealimitduration.failedtip": "Please enter a valid number", + "resource.param.16.16.param_arealimitduration.name": "Detection Time", + "resource.param.16.16.param_arealimitdurationtimetype.description": "Detection Time Unit", + "resource.param.16.16.param_arealimitdurationtimetype.failedtip": "Please select a valid number", + "resource.param.16.16.param_arealimitdurationtimetype.name": "Detection Time Unit", + "resource.param.16.16.param_arealimittargetcount.description": "Target Count in Region", + "resource.param.16.16.param_arealimittargetcount.failedtip": "Please enter an integer from 0 to 3600", + "resource.param.16.16.param_arealimittargetcount.name": "Target Count in Region", + "resource.param.16.16.param_arealimittargettype.description": "Region Target Count Limit Type", + "resource.param.16.16.param_arealimittargettype.failedtip": "Please select a valid value", + "resource.param.16.16.param_arealimittargettype.name": "Region Target Count Limit Type", + "resource.param.16.16.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.16.16.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.16.16.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.16.16.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.16.16.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.16.16.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.16.16.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.16.16.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.16.16.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.16.ba_00004.f0c9e210.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.16.ba_00004.f0c9e210.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.16.ba_00004.f0c9e210.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.16.ba_00004.f0c9e210.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.16.ba_00004.f0c9e210.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.16.ba_00004.f0c9e210.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.16.ba_00004.f0c9e210.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.16.ba_00004.f0c9e210.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.16.ba_00004.f0c9e210.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.failedtip": "Please enter a valid number", + "resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.name": "Detection Time", + "resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.description": "Detection Time Unit", + "resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.failedtip": "Please select a valid number", + "resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.name": "Detection Time Unit", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.description": "Threshold used to compare with the actual valid target count in the region", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.failedtip": "Please enter an integer from 0 to 3600", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.name": "Target Count Threshold", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.description": "Region Target Count Limit Type", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.failedtip": "Please select a valid value", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.name": "Trigger Condition", + "resource.param.1917.1917.0.name": "Default", + "resource.param.1917.1917.1.name": "Default", + "resource.param.1917.1917.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.1917.1917.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.1917.1917.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.1917.1917.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.1917.1917.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.1917.1917.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.1917.1917.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.1917.1917.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.1917.1917.name.description": "Region name: required, max 32 characters", + "resource.param.1917.1917.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.1917.1917.name.name": "Region Name", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.2.2.0.name": "Default", + "resource.param.2.2.aiparam_1000001_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.2.2.aiparam_1000001_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.2.2.aiparam_1000001_trackdynamicmatch.name": "Face RGB Detection Tracking Radius", + "resource.param.2.2.aiparam_face_confidence.description": "Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.2.aiparam_face_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.2.aiparam_face_confidence.name": "Face Confidence", + "resource.param.2.2.aiparam_face_confidenceconfig.description": "Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.2.aiparam_face_confidenceconfig.name": "Face Confidence Offset", + "resource.param.2.2.aiparam_face_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.2.2.aiparam_face_detpostion.failedtip": "Please select a valid value", + "resource.param.2.2.aiparam_face_detpostion.name": "Face Detection Method", + "resource.param.2.2.aiparam_faceblur0_confidence.description": "Face Blur 0 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.2.aiparam_faceblur0_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.2.aiparam_faceblur0_confidence.name": "Face Blur 0 Confidence", + "resource.param.2.2.aiparam_faceblur0_confidenceconfig.description": "Face Blur 0 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.2.aiparam_faceblur0_confidenceconfig.name": "Face Blur 0 Confidence Offset", + "resource.param.2.2.aiparam_faceblur1_confidence.description": "Face Blur 1 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.2.aiparam_faceblur1_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.2.aiparam_faceblur1_confidence.name": "Face Blur 1 Confidence", + "resource.param.2.2.aiparam_faceblur1_confidenceconfig.description": "Face Blur 1 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.2.aiparam_faceblur1_confidenceconfig.name": "Face Blur 1 Confidence Offset", + "resource.param.2.2.aiparam_faceblur2_confidence.description": "Face Blur 2 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.2.aiparam_faceblur2_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.2.aiparam_faceblur2_confidence.name": "Face Blur 2 Confidence", + "resource.param.2.2.aiparam_faceblur2_confidenceconfig.description": "Face Blur 2 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.2.aiparam_faceblur2_confidenceconfig.name": "Face Blur 2 Confidence Offset", + "resource.param.2.2.aiparam_frontface_confidence.description": "Frontal Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.2.aiparam_frontface_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.2.aiparam_frontface_confidence.name": "Frontal Face Confidence", + "resource.param.2.2.aiparam_frontface_confidenceconfig.description": "Frontal Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.2.aiparam_frontface_confidenceconfig.name": "Frontal Face Confidence Offset", + "resource.param.2.2.aiparam_fullface_confidence.description": "Full Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.2.aiparam_fullface_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.2.aiparam_fullface_confidence.name": "Full Face Confidence", + "resource.param.2.2.aiparam_fullface_confidenceconfig.description": "Full Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.2.aiparam_fullface_confidenceconfig.name": "Full Face Confidence Offset", + "resource.param.2.2.aiparam_slantedface_confidence.description": "Slanted Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.2.aiparam_slantedface_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.2.aiparam_slantedface_confidence.name": "Slanted Face Confidence", + "resource.param.2.2.aiparam_slantedface_confidenceconfig.description": "Slanted Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.2.aiparam_slantedface_confidenceconfig.name": "Slanted Face Confidence Offset", + "resource.param.2.2.filter_face_side_min.description": "Min face size: minimum image size for captured face photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.2.2.filter_face_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.2.2.filter_face_side_min.name": "Min Face Size", + "resource.param.2.2.name.description": "Region name: required, max 32 characters", + "resource.param.2.2.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.2.2.name.name": "Region Name", + "resource.param.2.2.param_faceset.description": "Select face library group for comparison", + "resource.param.2.2.param_faceset.failedtip": "Please select a valid value", + "resource.param.2.2.param_faceset.name": "Bind Face Group", + "resource.param.2.2.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.2.2.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.2.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.2.2.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.2.2.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.2.2.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.2.2.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.2.2.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.2.2.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.2.2.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.2.2.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.2.2.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.2.2.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.2.2.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.2.2.param_targetalarmcount.name": "Alarm Count", + "resource.param.2.2.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.2.2.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.2.2.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.description": "Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.name": "Face Confidence", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidenceconfig.description": "Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidenceconfig.name": "Face Confidence Offset", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.failedtip": "Please select a valid value", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.name": "Face Detection Method", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.description": "Face Blur 0 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.name": "Face Blur 0 Confidence", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidenceconfig.description": "Face Blur 0 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidenceconfig.name": "Face Blur 0 Confidence Offset", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.description": "Face Blur 1 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.name": "Face Blur 1 Confidence", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidenceconfig.description": "Face Blur 1 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidenceconfig.name": "Face Blur 1 Confidence Offset", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.description": "Face Blur 2 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.name": "Face Blur 2 Confidence", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidenceconfig.description": "Face Blur 2 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidenceconfig.name": "Face Blur 2 Confidence Offset", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.description": "Frontal Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.name": "Frontal Face Confidence", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidenceconfig.description": "Frontal Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidenceconfig.name": "Frontal Face Confidence Offset", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.description": "Full Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.name": "Full Face Confidence", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidenceconfig.description": "Full Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidenceconfig.name": "Full Face Confidence Offset", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.description": "Slanted Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.name": "Slanted Face Confidence", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidenceconfig.description": "Slanted Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidenceconfig.name": "Slanted Face Confidence Offset", + "resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.name": "Face RGB Detection Tracking Radius", + "resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.description": "Select face library group for comparison", + "resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.failedtip": "Please select a valid value", + "resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.name": "Bind Face Group", + "resource.param.2.ba_00002.5c3ea492.filter_face_side_min.description": "Min face size: minimum image size for captured face photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.2.ba_00002.5c3ea492.filter_face_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.2.ba_00002.5c3ea492.filter_face_side_min.name": "Min Face Size", + "resource.param.2.ba_00004.bdf891b9.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.2.ba_00004.bdf891b9.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.2.ba_00004.bdf891b9.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.name": "Overlay Trajectory on Panorama", + "resource.param.2.ba_00004.bdf891b9.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.2.ba_00004.bdf891b9.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.2.ba_00004.bdf891b9.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.2.ba_00004.bdf891b9.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.2.ba_00004.bdf891b9.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.2.ba_00004.bdf891b9.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.failedtip": "Please enter an integer from 0 to 100", + "resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.name": "Alarm Count", + "resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.name": "Alarm Interval (sec)", + "resource.param.21283.21283.0.name": "Default", + "resource.param.21283.21283.name.description": "Region name: required, max 32 characters", + "resource.param.21283.21283.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.21283.21283.name.name": "Region Name", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.21283.ba_00004.fd4e2090.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.21283.ba_00004.fd4e2090.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.21283.ba_00004.fd4e2090.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.21283.ba_00004.fd4e2090.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.21283.ba_00004.fd4e2090.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.21283.ba_00004.fd4e2090.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.22.22.0.name": "Default", + "resource.param.22.22.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.22.22.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.22.22.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.22.22.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.22.22.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.22.22.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.22.22.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.22.22.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.22.22.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.22.22.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.22.22.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.22.22.aiparam_pedphoneplay_confidence.description": "Phone usage confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.22.22.aiparam_pedphoneplay_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.22.22.aiparam_pedphoneplay_confidence.name": "Phone Usage Confidence", + "resource.param.22.22.aiparam_pedphoneplay_confidenceconfig.description": "Phone usage confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.22.22.aiparam_pedphoneplay_confidenceconfig.name": "Phone Usage Confidence Offset", + "resource.param.22.22.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.22.22.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.22.22.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.22.22.name.description": "Region name: required, max 32 characters", + "resource.param.22.22.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.22.22.name.name": "Region Name", + "resource.param.22.22.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.22.22.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.22.22.param_detectionduration.name": "Detection Time (sec)", + "resource.param.22.22.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.22.22.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.22.22.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.22.22.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.22.22.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.22.22.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.22.22.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.22.22.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.22.22.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.22.22.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.22.22.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.22.22.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.22.22.param_sensitivity.description": "Sensitivity: range 1–10, default: 5. Higher values make alarms easier to trigger.", + "resource.param.22.22.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.22.22.param_sensitivity.name": "Sensitivity", + "resource.param.22.22.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.22.22.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.22.22.param_targetalarmcount.name": "Alarm Count", + "resource.param.22.22.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.22.22.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.22.22.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.description": "Phone usage confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.name": "Phone Usage Confidence", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidenceconfig.description": "Phone usage confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidenceconfig.name": "Phone Usage Confidence Offset", + "resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.description": "Detection time: range 1–3600, default 2.", + "resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.name": "Detection Time (sec)", + "resource.param.22.ba_00003.181f8b5a.param_sensitivity.description": "Sensitivity: range 1–10, default: 5. Higher values make alarms easier to trigger.", + "resource.param.22.ba_00003.181f8b5a.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.22.ba_00003.181f8b5a.param_sensitivity.name": "Sensitivity", + "resource.param.22.ba_00004.0f53b331.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.22.ba_00004.0f53b331.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.22.ba_00004.0f53b331.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name": "Overlay Trajectory on Panorama", + "resource.param.22.ba_00004.0f53b331.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.22.ba_00004.0f53b331.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.22.ba_00004.0f53b331.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.22.ba_00004.0f53b331.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.22.ba_00004.0f53b331.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.22.ba_00004.0f53b331.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip": "Please enter an integer from 0 to 100", + "resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name": "Alarm Count", + "resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name": "Alarm Interval (sec)", + "resource.param.28862.28862.0.name": "Default", + "resource.param.28862.28862.1.name": "Default", + "resource.param.28862.28862.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.28862.28862.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.28862.28862.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.28862.28862.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.28862.28862.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.28862.28862.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.28862.28862.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.28862.28862.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.28862.28862.name.description": "Region name: required, max 32 characters", + "resource.param.28862.28862.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.28862.28862.name.name": "Region Name", + "resource.param.28862.28862.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.28862.28862.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.28862.28862.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.28862.28862.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.28862.28862.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.28862.28862.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.28862.28862.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.28862.28862.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.28862.28862.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.28862.28862.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.28862.28862.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.28862.28862.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.28862.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.28862.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.28862.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.28862.ba_00004.fd4e2090.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.28862.ba_00004.fd4e2090.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.28862.ba_00004.fd4e2090.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.28862.ba_00004.fd4e2090.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.28862.ba_00004.fd4e2090.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.28862.ba_00004.fd4e2090.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.28862.ba_00004.fd4e2090.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.28862.ba_00004.fd4e2090.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.28862.ba_00004.fd4e2090.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.2935.2935.0.name": "Default", + "resource.param.2935.2935.name.description": "Region name: required, max 32 characters", + "resource.param.2935.2935.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.2935.2935.name.name": "Region Name", + "resource.param.3.3.0.name": "Default", + "resource.param.3.3.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.3.3.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.3.3.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.3.3.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.3.3.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.3.3.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.3.3.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.3.3.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.3.3.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.3.3.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.3.3.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.3.3.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.3.3.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.3.3.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.3.3.name.description": "Region name: required, max 32 characters", + "resource.param.3.3.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.3.3.name.name": "Region Name", + "resource.param.3.3.param_areaduration.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.3.3.param_areaduration.failedtip": "Please enter a valid number", + "resource.param.3.3.param_areaduration.name": "Detection Time", + "resource.param.3.3.param_areadurationtimetype.description": "Detection Time Unit", + "resource.param.3.3.param_areadurationtimetype.failedtip": "Please select a valid number", + "resource.param.3.3.param_areadurationtimetype.name": "Detection Time Unit", + "resource.param.3.3.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.3.3.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.3.3.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.3.3.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.3.3.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.3.3.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.3.3.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.3.3.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.3.3.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.3.3.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.3.3.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.3.3.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.3.3.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.3.3.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.3.3.param_targetalarmcount.name": "Alarm Count", + "resource.param.3.3.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.3.3.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.3.3.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.3.ba_00004.a5c23881.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.3.ba_00004.a5c23881.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.3.ba_00004.a5c23881.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.name": "Overlay Trajectory on Panorama", + "resource.param.3.ba_00004.a5c23881.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.3.ba_00004.a5c23881.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.3.ba_00004.a5c23881.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.3.ba_00004.a5c23881.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.3.ba_00004.a5c23881.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.3.ba_00004.a5c23881.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.failedtip": "Please enter an integer from 0 to 100", + "resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.name": "Alarm Count", + "resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.name": "Alarm Interval (sec)", + "resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.failedtip": "Please enter a valid number", + "resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.name": "Detection Time", + "resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.description": "Detection Time Unit", + "resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.failedtip": "Please select a valid number", + "resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.name": "Detection Time Unit", + "resource.param.32.32.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.32.32.1001008.0.quality0.namecn": "Pedestrian Quality 0", + "resource.param.32.32.aiparam_1001003_frames.description": "Tracking history frame count. Range: 2–100", + "resource.param.32.32.aiparam_1001003_frames.failedtip": "Please enter an integer from 2 to 100", + "resource.param.32.32.aiparam_1001003_frames.name": "Pedestrian Detection Tracking History Frames", + "resource.param.32.32.aiparam_1001003_motion.description": "Stationary threshold. Range: 1–99, e.g., 80.0", + "resource.param.32.32.aiparam_1001003_motion.failedtip": "Please enter a value from 1 to 99 with 1 decimal place", + "resource.param.32.32.aiparam_1001003_motion.name": "Pedestrian Detection Stationary Threshold", + "resource.param.32.32.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.32.32.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.32.32.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.32.32.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.32.32.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.32.32.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.32.32.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.32.32.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.32.32.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.32.32.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.32.32.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.32.32.aiparam_quality0_confidence.description": "Pedestrian quality 0 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.32.32.aiparam_quality0_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.32.32.aiparam_quality0_confidence.name": "Pedestrian Quality 0 Confidence", + "resource.param.32.32.aiparam_quality0_confidenceconfig.description": "Pedestrian quality 0 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.32.32.aiparam_quality0_confidenceconfig.name": "Pedestrian Quality 0 Confidence Offset", + "resource.param.32.32.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.32.32.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.32.32.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.32.32.name.description": "Region name: required, max 32 characters", + "resource.param.32.32.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.32.32.name.name": "Region Name", + "resource.param.32.32.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.32.32.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.32.32.param_detectionduration.name": "Detection Time (sec)", + "resource.param.32.32.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.32.32.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.32.32.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.32.32.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.32.32.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.32.32.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.32.32.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.32.32.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.32.32.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.32.32.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.32.32.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.32.32.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.32.32.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.32.32.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.32.32.param_sensitivity.name": "Sensitivity", + "resource.param.32.32.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.32.32.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.32.32.param_targetalarmcount.name": "Alarm Count", + "resource.param.32.32.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.32.32.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.32.32.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.32.32.param_videoreadfps.description": "For offline videos with abnormal frame rates, this parameter forces a specific frame rate. <0: no forcing, >=0: forced frame rate, default: -1 (full frame).", + "resource.param.32.32.param_videoreadfps.failedtip": "Please enter a valid value", + "resource.param.32.32.param_videoreadfps.name": "Offline Video Frame Rate", + "resource.param.32.32.param_videorepeatcount.description": "Offline video loop count. <0: infinite, 0: once, >1: specified count", + "resource.param.32.32.param_videorepeatcount.failedtip": "Please enter an integer from 1 to 100", + "resource.param.32.32.param_videorepeatcount.name": "Offline Video Play Count", + "resource.param.32.32.param_workclothesset.description": "Select work uniform group for comparison", + "resource.param.32.32.param_workclothesset.failedtip": "Please select a valid value", + "resource.param.32.32.param_workclothesset.name": "Bind Work Uniform Group", + "resource.param.32.aa_00001.1ffc7361.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.32.aa_00002.40a88def.1001008.0.quality0.namecn": "Pedestrian Quality 0", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.description": "Pedestrian quality 0 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.name": "Pedestrian Quality 0 Confidence", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidenceconfig.description": "Pedestrian quality 0 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidenceconfig.name": "Pedestrian Quality 0 Confidence Offset", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.description": "Tracking history frame count. Range: 2–100", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.failedtip": "Please enter an integer from 2 to 100", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.name": "Pedestrian Detection Tracking History Frames", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.description": "Stationary threshold. Range: 1–99, e.g., 80.0", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.failedtip": "Please enter a value from 1 to 99 with 1 decimal place", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.name": "Pedestrian Detection Stationary Threshold", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.32.aa_00005.247f620f.param_workclothesset.description": "Select work uniform group for comparison", + "resource.param.32.aa_00005.247f620f.param_workclothesset.failedtip": "Please select a valid value", + "resource.param.32.aa_00005.247f620f.param_workclothesset.name": "Bind Work Uniform Group", + "resource.param.32.ba_00001.551596af.param_videoreadfps.description": "For offline videos with abnormal frame rates, this parameter forces a specific frame rate. <0: no forcing, >=0: forced frame rate, default: -1 (full frame).", + "resource.param.32.ba_00001.551596af.param_videoreadfps.failedtip": "Please enter a valid value", + "resource.param.32.ba_00001.551596af.param_videoreadfps.name": "Offline Video Frame Rate", + "resource.param.32.ba_00001.551596af.param_videorepeatcount.description": "Offline video loop count. <0: infinite, 0: once, >1: specified count", + "resource.param.32.ba_00001.551596af.param_videorepeatcount.failedtip": "Please enter an integer from 1 to 100", + "resource.param.32.ba_00001.551596af.param_videorepeatcount.name": "Offline Video Play Count", + "resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.32.ba_00003.22705515.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.32.ba_00003.22705515.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.32.ba_00003.22705515.param_detectionduration.name": "Detection Time (sec)", + "resource.param.32.ba_00003.22705515.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.32.ba_00003.22705515.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.32.ba_00003.22705515.param_sensitivity.name": "Sensitivity", + "resource.param.32.ba_00004.da078adb.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.32.ba_00004.da078adb.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.32.ba_00004.da078adb.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.32.ba_00004.da078adb.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.32.ba_00004.da078adb.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.32.ba_00004.da078adb.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.32.ba_00004.da078adb.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.32.ba_00004.da078adb.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.32.ba_00004.da078adb.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.32.ba_00004.da078adb.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.32.ba_00004.da078adb.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.32.ba_00004.da078adb.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.32.ba_00004.da078adb.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.32.ba_00004.da078adb.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.32.ba_00004.da078adb.param_targetalarmcount.name": "Alarm Count", + "resource.param.32.ba_00004.da078adb.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.32.ba_00004.da078adb.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.32.ba_00004.da078adb.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.34707.34707.0.name": "Default", + "resource.param.34707.34707.name.description": "Region name: required, max 32 characters", + "resource.param.34707.34707.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.34707.34707.name.name": "Region Name", + "resource.param.34707.34707.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.34707.34707.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.34707.34707.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.34707.34707.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.34707.34707.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.34707.34707.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.34707.34707.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.34707.34707.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.34707.34707.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.34707.34707.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.34707.34707.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.34707.34707.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.34707.ba_00004.7ec477cd.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.34707.ba_00004.7ec477cd.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.34707.ba_00004.7ec477cd.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.34707.ba_00004.7ec477cd.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.34707.ba_00004.7ec477cd.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.34707.ba_00004.7ec477cd.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.38873.38873.0.name": "Default", + "resource.param.38873.38873.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.38873.38873.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.38873.38873.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.38873.38873.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.38873.38873.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.38873.38873.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.38873.38873.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.38873.38873.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.38873.38873.name.description": "Region name: required, max 32 characters", + "resource.param.38873.38873.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.38873.38873.name.name": "Region Name", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.description": "Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.name": "Face Confidence", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidenceconfig.description": "Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidenceconfig.name": "Face Confidence Offset", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.failedtip": "Please select a valid value", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.name": "Face Detection Method", + "resource.param.5.5.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.5.5.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.5.5.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.5.5.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.5.5.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.5.5.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.5.5.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.5.5.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.5.5.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.5.5.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.5.5.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.5.5.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.5.5.name.description": "Region name: required, max 32 characters", + "resource.param.5.5.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.5.5.name.name": "Region Name", + "resource.param.5.5.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.5.5.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.5.5.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.5.5.param_arealimitduration.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.5.5.param_arealimitduration.failedtip": "Please enter a valid number", + "resource.param.5.5.param_arealimitduration.name": "Detection Time", + "resource.param.5.5.param_arealimitdurationtimetype.description": "Detection Time Unit", + "resource.param.5.5.param_arealimitdurationtimetype.failedtip": "Please select a valid number", + "resource.param.5.5.param_arealimitdurationtimetype.name": "Detection Time Unit", + "resource.param.5.5.param_arealimittargetcount.description": "Target Count in Region", + "resource.param.5.5.param_arealimittargetcount.failedtip": "Please enter an integer from 0 to 3600", + "resource.param.5.5.param_arealimittargetcount.name": "Target Count in Region", + "resource.param.5.5.param_arealimittargettype.description": "Region Target Count Limit Type", + "resource.param.5.5.param_arealimittargettype.failedtip": "Please select a valid value", + "resource.param.5.5.param_arealimittargettype.name": "Region Target Count Limit Type", + "resource.param.5.5.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.5.5.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.5.5.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.5.5.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.5.5.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.5.5.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.5.5.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.5.5.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.5.5.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.5.aa_00001.bc4f4b27.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.5.ba_00004.f0c9e210.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.5.ba_00004.f0c9e210.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.5.ba_00004.f0c9e210.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.5.ba_00004.f0c9e210.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.5.ba_00004.f0c9e210.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.5.ba_00004.f0c9e210.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.5.ba_00004.f0c9e210.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.5.ba_00004.f0c9e210.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.5.ba_00004.f0c9e210.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.5.ba_00004.f0c9e210.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.5.ba_00004.f0c9e210.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.5.ba_00004.f0c9e210.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.5.ba_00005.ab935f8a.param_arealimitduration.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.5.ba_00005.ab935f8a.param_arealimitduration.failedtip": "Please enter a valid number", + "resource.param.5.ba_00005.ab935f8a.param_arealimitduration.name": "Detection Time", + "resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.description": "Detection Time Unit", + "resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.failedtip": "Please select a valid number", + "resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.name": "Detection Time Unit", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.description": "Threshold used to compare with the actual valid target count in the region", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.failedtip": "Please enter an integer from 0 to 3600", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.name": "Target Count Threshold", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.description": "Region Target Count Limit Type", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.failedtip": "Please select a valid value", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.name": "Trigger Condition", + "resource.param.50813.50813.0.name": "Default", + "resource.param.50813.50813.1.name": "Default", + "resource.param.50813.50813.aiparam_hatless_confidence.description": "Hatless confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.50813.aiparam_hatless_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.50813.aiparam_hatless_confidence.name": "Hatless Confidence", + "resource.param.50813.50813.aiparam_hatless_confidenceconfig.description": "Hatless confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.50813.aiparam_hatless_confidenceconfig.name": "Hatless Confidence Offset", + "resource.param.50813.50813.aiparam_normalhat_confidence.description": "Normal Hat confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.50813.aiparam_normalhat_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.50813.aiparam_normalhat_confidence.name": "Normal Hat Confidence", + "resource.param.50813.50813.aiparam_normalhat_confidenceconfig.description": "Normal Hat confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.50813.aiparam_normalhat_confidenceconfig.name": "Normal Hat Confidence Offset", + "resource.param.50813.50813.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.50813.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.50813.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.50813.50813.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.50813.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.50813.50813.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.50813.50813.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.50813.50813.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.50813.50813.aiparam_pedhelmet_confidence.description": "Pedestrian Helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.50813.aiparam_pedhelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.50813.aiparam_pedhelmet_confidence.name": "Pedestrian Helmet Confidence", + "resource.param.50813.50813.aiparam_pedhelmet_confidenceconfig.description": "Pedestrian Helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.50813.aiparam_pedhelmet_confidenceconfig.name": "Pedestrian Helmet Confidence Offset", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidence.description": "Pedestrian Safety Helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidence.name": "Pedestrian Safety Helmet Confidence", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidenceconfig.description": "Pedestrian Safety Helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidenceconfig.name": "Pedestrian Safety Helmet Confidence Offset", + "resource.param.50813.50813.aiparam_unsure_confidence.description": "Unsure confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.50813.aiparam_unsure_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.50813.aiparam_unsure_confidence.name": "Unsure Confidence", + "resource.param.50813.50813.aiparam_unsure_confidenceconfig.description": "Unsure confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.50813.aiparam_unsure_confidenceconfig.name": "Unsure Confidence Offset", + "resource.param.50813.50813.name.description": "Region name: required, max 32 characters", + "resource.param.50813.50813.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.50813.50813.name.name": "Region Name", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidence.description": "Hatless confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidence.name": "Hatless Confidence", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.description": "Hatless confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.name": "Hatless Confidence Offset", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidence.description": "Normal Hat confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidence.name": "Normal Hat Confidence", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.description": "Normal Hat confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.name": "Normal Hat Confidence Offset", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.description": "Pedestrian Helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.name": "Pedestrian Helmet Confidence", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.description": "Pedestrian Helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.name": "Pedestrian Helmet Confidence Offset", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.description": "Pedestrian Safety Helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.name": "Pedestrian Safety Helmet Confidence", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.description": "Pedestrian Safety Helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.name": "Pedestrian Safety Helmet Confidence Offset", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidence.description": "Unsure confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidence.name": "Unsure Confidence", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.description": "Unsure confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.name": "Unsure Confidence Offset", + "resource.param.51.51.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.51.51.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.51.51.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.51.51.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.51.51.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.51.51.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.51.51.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.51.51.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.51.51.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.51.51.name.description": "Region name: required, max 32 characters", + "resource.param.51.51.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.51.51.name.name": "Region Name", + "resource.param.51.51.param_areacalcduration.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.51.51.param_areacalcduration.failedtip": "Please enter a valid number", + "resource.param.51.51.param_areacalcduration.name": "Area People Count Report Interval", + "resource.param.51.51.param_areacalcdurationtimetype.description": "Detection Time Unit", + "resource.param.51.51.param_areacalcdurationtimetype.failedtip": "Please select a valid number", + "resource.param.51.51.param_areacalcdurationtimetype.name": "Detection Time Unit", + "resource.param.51.51.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.51.51.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.51.51.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.51.51.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.51.51.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.51.51.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.51.51.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.51.51.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.51.51.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.51.51.param_targetcalctype.description": "Target Counting Method", + "resource.param.51.51.param_targetcalctype.failedtip": "Please select a valid value", + "resource.param.51.51.param_targetcalctype.name": "Target Counting Method", + "resource.param.51.51.param_videoreadfps.description": "For offline videos with abnormal frame rates, this parameter forces a specific frame rate. <0: no forcing, >=0: forced frame rate, default: -1 (full frame).", + "resource.param.51.51.param_videoreadfps.failedtip": "Please enter a valid value", + "resource.param.51.51.param_videoreadfps.name": "Offline Video Frame Rate", + "resource.param.51.51.param_videorepeatcount.description": "Offline video loop count. <0: infinite, 0: once, >1: specified count", + "resource.param.51.51.param_videorepeatcount.failedtip": "Please enter an integer from 1 to 100", + "resource.param.51.51.param_videorepeatcount.name": "Offline Video Play Count", + "resource.param.51.aa_00001.e9173765.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.51.ba_00001.4053a96d.param_videoreadfps.description": "For offline videos with abnormal frame rates, this parameter forces a specific frame rate. <0: no forcing, >=0: forced frame rate, default: -1 (full frame).", + "resource.param.51.ba_00001.4053a96d.param_videoreadfps.failedtip": "Please enter a valid value", + "resource.param.51.ba_00001.4053a96d.param_videoreadfps.name": "Offline Video Frame Rate", + "resource.param.51.ba_00001.4053a96d.param_videorepeatcount.description": "Offline video loop count. <0: infinite, 0: once, >1: specified count", + "resource.param.51.ba_00001.4053a96d.param_videorepeatcount.failedtip": "Please enter an integer from 1 to 100", + "resource.param.51.ba_00001.4053a96d.param_videorepeatcount.name": "Offline Video Play Count", + "resource.param.51.ba_00004.9de4af16.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.51.ba_00004.9de4af16.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.51.ba_00004.9de4af16.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.51.ba_00004.9de4af16.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.51.ba_00004.9de4af16.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.51.ba_00004.9de4af16.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.51.ba_00004.9de4af16.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.51.ba_00004.9de4af16.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.51.ba_00004.9de4af16.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.51.ba_00005.667e48b6.param_areacalcduration.description": "Count report interval: range 1–3600000, note the time unit", + "resource.param.51.ba_00005.667e48b6.param_areacalcduration.failedtip": "Please enter a valid number", + "resource.param.51.ba_00005.667e48b6.param_areacalcduration.name": "Count Report Interval", + "resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.description": "Count Report Interval Time Unit", + "resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.failedtip": "Please select a valid unit", + "resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.name": "Count Report Interval Time Unit", + "resource.param.51.ba_00005.667e48b6.param_targetcalctype.description": "Target Counting Method", + "resource.param.51.ba_00005.667e48b6.param_targetcalctype.failedtip": "Please select a valid value", + "resource.param.51.ba_00005.667e48b6.param_targetcalctype.name": "Target Counting Method", + "resource.param.57.57.0.name": "Default", + "resource.param.57.57.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.57.57.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.57.57.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.57.57.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.57.57.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.57.57.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.57.57.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.57.57.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.57.57.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.57.57.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.57.57.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.57.57.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.57.57.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.57.57.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.57.57.name.description": "Region name: required, max 32 characters", + "resource.param.57.57.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.57.57.name.name": "Region Name", + "resource.param.57.57.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.57.57.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.57.57.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.57.57.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.57.57.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.57.57.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.57.57.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.57.57.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.57.57.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.57.57.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.57.57.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.57.57.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.57.57.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.57.57.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.57.57.param_targetalarmcount.name": "Alarm Count", + "resource.param.57.57.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.57.57.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.57.57.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.57.57.param_trippingwiretype.description": "Alarm condition: number of targets crossing the line", + "resource.param.57.57.param_trippingwiretype.failedtip": "Please select a valid value", + "resource.param.57.57.param_trippingwiretype.name": "Tripwire Type", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.57.ba_00004.a5c23881.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.57.ba_00004.a5c23881.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.57.ba_00004.a5c23881.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.name": "Overlay Trajectory on Panorama", + "resource.param.57.ba_00004.a5c23881.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.57.ba_00004.a5c23881.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.57.ba_00004.a5c23881.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.57.ba_00004.a5c23881.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.57.ba_00004.a5c23881.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.57.ba_00004.a5c23881.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.failedtip": "Please enter an integer from 0 to 100", + "resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.name": "Alarm Count", + "resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.name": "Alarm Interval (sec)", + "resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.description": "Alarm condition: number of targets crossing the line", + "resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.failedtip": "Please select a valid value", + "resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.name": "Tripwire Type", + "resource.param.58.58.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.58.58.1001008.0.quality0.namecn": "Pedestrian Quality 0", + "resource.param.58.58.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.58.58.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.58.58.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.58.58.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.58.58.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.58.58.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.58.58.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.58.58.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.58.58.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.58.58.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.58.58.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.58.58.aiparam_quality0_confidence.description": "Pedestrian quality 0 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.58.58.aiparam_quality0_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.58.58.aiparam_quality0_confidence.name": "Pedestrian Quality 0 Confidence", + "resource.param.58.58.aiparam_quality0_confidenceconfig.description": "Pedestrian quality 0 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.58.58.aiparam_quality0_confidenceconfig.name": "Pedestrian Quality 0 Confidence Offset", + "resource.param.58.58.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.58.58.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.58.58.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.58.58.name.description": "Region name: required, max 32 characters", + "resource.param.58.58.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.58.58.name.name": "Region Name", + "resource.param.58.58.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.58.58.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.58.58.param_detectionduration.name": "Detection Time (sec)", + "resource.param.58.58.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.58.58.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.58.58.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.58.58.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.58.58.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.58.58.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.58.58.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.58.58.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.58.58.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.58.58.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.58.58.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.58.58.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.58.58.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.58.58.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.58.58.param_sensitivity.name": "Sensitivity", + "resource.param.58.58.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.58.58.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.58.58.param_targetalarmcount.name": "Alarm Count", + "resource.param.58.58.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.58.58.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.58.58.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.58.58.param_workclothesset.description": "Select work uniform group for comparison", + "resource.param.58.58.param_workclothesset.failedtip": "Please select a valid value", + "resource.param.58.58.param_workclothesset.name": "Bind Work Uniform Group", + "resource.param.58.aa_00001.1ffc7361.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.58.aa_00002.40a88def.1001008.0.quality0.namecn": "Pedestrian Quality 0", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.description": "Pedestrian quality 0 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.name": "Pedestrian Quality 0 Confidence", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidenceconfig.description": "Pedestrian quality 0 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidenceconfig.name": "Pedestrian Quality 0 Confidence Offset", + "resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.58.aa_00005.247f620f.param_workclothesset.description": "Select work uniform group for comparison", + "resource.param.58.aa_00005.247f620f.param_workclothesset.failedtip": "Please select a valid value", + "resource.param.58.aa_00005.247f620f.param_workclothesset.name": "Bind Work Uniform Group", + "resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.58.ba_00003.bc6d90f2.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.58.ba_00003.bc6d90f2.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.58.ba_00003.bc6d90f2.param_detectionduration.name": "Detection Time (sec)", + "resource.param.58.ba_00003.bc6d90f2.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.58.ba_00003.bc6d90f2.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.58.ba_00003.bc6d90f2.param_sensitivity.name": "Sensitivity", + "resource.param.58.ba_00004.da078adb.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.58.ba_00004.da078adb.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.58.ba_00004.da078adb.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.58.ba_00004.da078adb.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.58.ba_00004.da078adb.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.58.ba_00004.da078adb.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.58.ba_00004.da078adb.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.58.ba_00004.da078adb.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.58.ba_00004.da078adb.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.58.ba_00004.da078adb.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.58.ba_00004.da078adb.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.58.ba_00004.da078adb.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.58.ba_00004.da078adb.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.58.ba_00004.da078adb.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.58.ba_00004.da078adb.param_targetalarmcount.name": "Alarm Count", + "resource.param.58.ba_00004.da078adb.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.58.ba_00004.da078adb.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.58.ba_00004.da078adb.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.6.6.0.name": "Default", + "resource.param.6.6.aiparam_1001003_frames.description": "Tracking history frame count. Range: 2–100", + "resource.param.6.6.aiparam_1001003_frames.failedtip": "Please enter an integer from 2 to 100", + "resource.param.6.6.aiparam_1001003_frames.name": "Pedestrian Detection Tracking History Frames", + "resource.param.6.6.aiparam_1001003_motion.description": "Stationary threshold. Range: 1–99, e.g., 80.0", + "resource.param.6.6.aiparam_1001003_motion.failedtip": "Please enter a value from 1 to 99 with 1 decimal place", + "resource.param.6.6.aiparam_1001003_motion.name": "Pedestrian Detection Stationary Threshold", + "resource.param.6.6.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.6.6.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.6.6.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.6.6.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.6.6.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.6.6.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.6.6.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.6.6.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.6.6.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.6.6.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.6.6.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.6.6.aiparam_pedfalldown_confidence.description": "Fall confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.6.6.aiparam_pedfalldown_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.6.6.aiparam_pedfalldown_confidence.name": "Fall Confidence", + "resource.param.6.6.aiparam_pedfalldown_confidenceconfig.description": "Fall confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.6.6.aiparam_pedfalldown_confidenceconfig.name": "Fall Confidence Offset", + "resource.param.6.6.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.6.6.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.6.6.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.6.6.name.description": "Region name: required, max 32 characters", + "resource.param.6.6.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.6.6.name.name": "Region Name", + "resource.param.6.6.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.6.6.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.6.6.param_detectionduration.name": "Detection Time (sec)", + "resource.param.6.6.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.6.6.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.6.6.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.6.6.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.6.6.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.6.6.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.6.6.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.6.6.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.6.6.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.6.6.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.6.6.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.6.6.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.6.6.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.6.6.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.6.6.param_sensitivity.name": "Sensitivity", + "resource.param.6.6.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.6.6.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.6.6.param_targetalarmcount.name": "Alarm Count", + "resource.param.6.6.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.6.6.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.6.6.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.description": "Fall detection confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.name": "Fall Detection Confidence", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidenceconfig.description": "Fall detection confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidenceconfig.name": "Fall Detection Confidence Offset", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.description": "Tracking history frame count. Range: 2–100", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.failedtip": "Please enter an integer from 2 to 100", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.name": "Pedestrian Detection Tracking History Frames", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.description": "Stationary threshold. Range: 1–99, e.g., 80.0", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.failedtip": "Please enter a value from 1 to 99 with 1 decimal place", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.name": "Pedestrian Detection Stationary Threshold", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.description": "Detection time: range 1–3600, default 2.", + "resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.name": "Detection Time (sec)", + "resource.param.6.ba_00003.6dbede3b.param_sensitivity.description": "Sensitivity: range 1–10, default: 5. Higher values make alarms easier to trigger.", + "resource.param.6.ba_00003.6dbede3b.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.6.ba_00003.6dbede3b.param_sensitivity.name": "Sensitivity", + "resource.param.6.ba_00004.0f53b331.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.6.ba_00004.0f53b331.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.6.ba_00004.0f53b331.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name": "Overlay Trajectory on Panorama", + "resource.param.6.ba_00004.0f53b331.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.6.ba_00004.0f53b331.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.6.ba_00004.0f53b331.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.6.ba_00004.0f53b331.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.6.ba_00004.0f53b331.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.6.ba_00004.0f53b331.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip": "Please enter an integer from 0 to 100", + "resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name": "Alarm Count", + "resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name": "Alarm Interval (sec)", + "resource.param.60460.60460.0.name": "Default", + "resource.param.60460.60460.1.name": "Default", + "resource.param.60460.60460.name.description": "Region name: required, max 32 characters", + "resource.param.60460.60460.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.60460.60460.name.name": "Region Name", + "resource.param.65.65.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.65.65.1001010.0.pedsleepstomach.namecn": "Sleeping Posture - Face Down", + "resource.param.65.65.1001010.5.pedsleepliedown.namecn": "Sleeping Posture - Lying Down", + "resource.param.65.65.aiparam_1001003_frames.description": "Tracking history frame count. Range: 2–100", + "resource.param.65.65.aiparam_1001003_frames.failedtip": "Please enter an integer from 2 to 100", + "resource.param.65.65.aiparam_1001003_frames.name": "Pedestrian Detection Tracking History Frames", + "resource.param.65.65.aiparam_1001003_motion.description": "Stationary threshold. Range: 1–99, e.g., 80.0", + "resource.param.65.65.aiparam_1001003_motion.failedtip": "Please enter a value from 1 to 99 with 1 decimal place", + "resource.param.65.65.aiparam_1001003_motion.name": "Pedestrian Detection Stationary Threshold", + "resource.param.65.65.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.65.65.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.65.65.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.65.65.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.65.65.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.65.65.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.65.65.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.65.65.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.65.65.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.65.65.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.65.65.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.65.65.aiparam_pedsleepliedown_confidence.description": "Sleeping Lying Down confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.65.65.aiparam_pedsleepliedown_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.65.65.aiparam_pedsleepliedown_confidence.name": "Sleeping Lying Down Confidence", + "resource.param.65.65.aiparam_pedsleepliedown_confidenceconfig.description": "Sleeping Lying Down confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.65.65.aiparam_pedsleepliedown_confidenceconfig.name": "Sleeping Lying Down Confidence Offset", + "resource.param.65.65.aiparam_pedsleepstomach_confidence.description": "Sleeping Face Down confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.65.65.aiparam_pedsleepstomach_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.65.65.aiparam_pedsleepstomach_confidence.name": "Sleeping Face Down Confidence", + "resource.param.65.65.aiparam_pedsleepstomach_confidenceconfig.description": "Sleeping Face Down confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.65.65.aiparam_pedsleepstomach_confidenceconfig.name": "Sleeping Face Down Confidence Offset", + "resource.param.65.65.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.65.65.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.65.65.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.65.65.name.description": "Region name: required, max 32 characters", + "resource.param.65.65.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.65.65.name.name": "Region Name", + "resource.param.65.65.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.65.65.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.65.65.param_detectionduration.name": "Detection Time (sec)", + "resource.param.65.65.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.65.65.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.65.65.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.65.65.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.65.65.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.65.65.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.65.65.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.65.65.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.65.65.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.65.65.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.65.65.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.65.65.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.65.65.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.65.65.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.65.65.param_sensitivity.name": "Sensitivity", + "resource.param.65.65.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.65.65.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.65.65.param_targetalarmcount.name": "Alarm Count", + "resource.param.65.65.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.65.65.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.65.65.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.65.aa_00001.487c1cf0.1001003.0.pedestrian.namecn": "Pedestrian", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.65.aa_00002.c37b8e34.1001010.0.pedsleepstomach.namecn": "Sleeping Posture - Face Down", + "resource.param.65.aa_00002.c37b8e34.1001010.5.pedsleepliedown.namecn": "Sleeping Posture - Lying Down", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.description": "Sleeping Lying Down confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.name": "Sleeping Lying Down Confidence", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidenceconfig.description": "Sleeping Lying Down confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidenceconfig.name": "Sleeping Lying Down Confidence Offset", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.description": "Sleeping Face Down confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.name": "Sleeping Face Down Confidence", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidenceconfig.description": "Sleeping Face Down confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidenceconfig.name": "Sleeping Face Down Confidence Offset", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.description": "Tracking history frame count. Range: 2–100", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.failedtip": "Please enter an integer from 2 to 100", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.name": "Pedestrian Detection Tracking History Frames", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.description": "Stationary threshold. Range: 1–99, e.g., 80.0", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.failedtip": "Please enter a value from 1 to 99 with 1 decimal place", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.name": "Pedestrian Detection Stationary Threshold", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "Pedestrian Detection Tracking Radius", + "resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.description": "Min pedestrian size: minimum image size for captured pedestrian photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.name": "Min Pedestrian Size", + "resource.param.65.ba_00003.b00198a1.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.65.ba_00003.b00198a1.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.65.ba_00003.b00198a1.param_detectionduration.name": "Detection Time (sec)", + "resource.param.65.ba_00003.b00198a1.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.65.ba_00003.b00198a1.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.65.ba_00003.b00198a1.param_sensitivity.name": "Sensitivity", + "resource.param.65.ba_00004.0f53b331.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.65.ba_00004.0f53b331.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.65.ba_00004.0f53b331.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.65.ba_00004.0f53b331.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.65.ba_00004.0f53b331.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.65.ba_00004.0f53b331.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.65.ba_00004.0f53b331.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.65.ba_00004.0f53b331.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.65.ba_00004.0f53b331.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.65.ba_00004.0f53b331.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.65.ba_00004.0f53b331.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.65.ba_00004.0f53b331.param_targetalarmcount.name": "Alarm Count", + "resource.param.65.ba_00004.0f53b331.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.65.ba_00004.0f53b331.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.65.ba_00004.0f53b331.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.67093.67093.0.name": "Default", + "resource.param.67093.67093.1.name": "Default", + "resource.param.67093.67093.name.description": "Region name: required, max 32 characters", + "resource.param.67093.67093.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.67093.67093.name.name": "Region Name", + "resource.param.67093.67093.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.67093.67093.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.67093.67093.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.67093.67093.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.67093.67093.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.67093.67093.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.67093.67093.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.67093.67093.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.67093.67093.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.67093.67093.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.67093.67093.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.67093.67093.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.67093.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.67093.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.67093.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.67093.ba_00004.7ec477cd.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.67093.ba_00004.7ec477cd.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.67093.ba_00004.7ec477cd.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.67093.ba_00004.7ec477cd.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.67093.ba_00004.7ec477cd.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.67093.ba_00004.7ec477cd.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.67093.ba_00004.7ec477cd.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.67093.ba_00004.7ec477cd.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.67093.ba_00004.7ec477cd.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.7.7.2000001.1.nonmotorvehicle.namecn": "Non-motor Vehicle", + "resource.param.7.7.2000001.2.vehicle.namecn": "Vehicle", + "resource.param.7.7.aiparam_2000001_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.7.7.aiparam_2000001_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.7.7.aiparam_2000001_trackdynamicmatch.name": "Vehicle Detection Tracking Radius", + "resource.param.7.7.aiparam_nonmotorvehicle_confidence.description": "Non-motor vehicle confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.7.7.aiparam_nonmotorvehicle_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7.7.aiparam_nonmotorvehicle_confidence.name": "Non-motor Vehicle Confidence", + "resource.param.7.7.aiparam_nonmotorvehicle_confidenceconfig.description": "Non-motor vehicle confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.7.7.aiparam_nonmotorvehicle_confidenceconfig.name": "Non-motor Vehicle Confidence Offset", + "resource.param.7.7.aiparam_nonmotorvehicle_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.7.7.aiparam_nonmotorvehicle_detpostion.failedtip": "Please select a valid value", + "resource.param.7.7.aiparam_nonmotorvehicle_detpostion.name": "Non-motor Vehicle Detection Method", + "resource.param.7.7.aiparam_vehicle_confidence.description": "Vehicle confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.7.7.aiparam_vehicle_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7.7.aiparam_vehicle_confidence.name": "Vehicle Confidence", + "resource.param.7.7.aiparam_vehicle_confidenceconfig.description": "Vehicle confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.7.7.aiparam_vehicle_confidenceconfig.name": "Vehicle Confidence Offset", + "resource.param.7.7.aiparam_vehicle_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.7.7.aiparam_vehicle_detpostion.failedtip": "Please select a valid value", + "resource.param.7.7.aiparam_vehicle_detpostion.name": "Vehicle Detection Method", + "resource.param.7.7.filter_nonmotorvehicle_side_min.description": "Min non-motor vehicle size: minimum image size for captured non-motor vehicle photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.7.7.filter_nonmotorvehicle_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.7.7.filter_nonmotorvehicle_side_min.name": "Min Non-motor Vehicle Size", + "resource.param.7.7.filter_vehicle_side_min.description": "Min vehicle size: minimum image size for captured vehicle photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.7.7.filter_vehicle_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.7.7.filter_vehicle_side_min.name": "Min Vehicle Size", + "resource.param.7.7.name.description": "Region name: required, max 32 characters", + "resource.param.7.7.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.7.7.name.name": "Region Name", + "resource.param.7.7.param_areaduration.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.7.7.param_areaduration.failedtip": "Please enter a valid number", + "resource.param.7.7.param_areaduration.name": "Detection Time", + "resource.param.7.7.param_areadurationtimetype.description": "Detection Time Unit", + "resource.param.7.7.param_areadurationtimetype.failedtip": "Please select a valid number", + "resource.param.7.7.param_areadurationtimetype.name": "Detection Time Unit", + "resource.param.7.7.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.7.7.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7.7.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.7.7.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.7.7.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.7.7.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.7.7.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.7.7.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.7.7.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.7.7.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.7.7.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.7.7.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.7.7.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.7.7.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.7.7.param_targetalarmcount.name": "Alarm Count", + "resource.param.7.7.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.7.7.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.7.7.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.7.7.param_videoreadfps.description": "For offline videos with abnormal frame rates, this parameter forces a specific frame rate. <0: no forcing, >=0: forced frame rate, default: -1 (full frame).", + "resource.param.7.7.param_videoreadfps.failedtip": "Please enter a valid value", + "resource.param.7.7.param_videoreadfps.name": "Offline Video Frame Rate", + "resource.param.7.7.param_videorepeatcount.description": "Offline video loop count. <0: infinite, 0: once, >1: specified count", + "resource.param.7.7.param_videorepeatcount.failedtip": "Please enter an integer from 1 to 100", + "resource.param.7.7.param_videorepeatcount.name": "Offline Video Play Count", + "resource.param.7.aa_00001.ddd59411.2000001.1.nonmotorvehicle.namecn": "Non-motor Vehicle", + "resource.param.7.aa_00001.ddd59411.2000001.2.vehicle.namecn": "Vehicle", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.description": "Non-motor vehicle confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.name": "Non-motor Vehicle Confidence", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidenceconfig.description": "Non-motor vehicle confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidenceconfig.name": "Non-motor Vehicle Confidence Offset", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.failedtip": "Please select a valid value", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.name": "Non-motor Vehicle Detection Method", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.description": "Vehicle confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.name": "Vehicle Confidence", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidenceconfig.description": "Vehicle confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidenceconfig.name": "Vehicle Confidence Offset", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.failedtip": "Please select a valid value", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.name": "Vehicle Detection Method", + "resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.description": "Tracking radius, also related to tracking frame count. Range: 0–100, e.g., 2.3", + "resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.failedtip": "Please enter a value from 0 to 100 with up to 2 decimal places", + "resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.name": "Vehicle Detection Tracking Radius", + "resource.param.7.ba_00001.20a13b0a.param_videoreadfps.description": "For offline videos with abnormal frame rates, this parameter forces a specific frame rate. <0: no forcing, >=0: forced frame rate, default: -1 (full frame).", + "resource.param.7.ba_00001.20a13b0a.param_videoreadfps.failedtip": "Please enter a valid value", + "resource.param.7.ba_00001.20a13b0a.param_videoreadfps.name": "Offline Video Frame Rate", + "resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.description": "Offline video loop count. <0: infinite, 0: once, >1: specified count", + "resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.failedtip": "Please enter an integer from 1 to 100", + "resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.name": "Offline Video Play Count", + "resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.description": "Min non-motor vehicle size: minimum image size for captured non-motor vehicle photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.name": "Min Non-motor Vehicle Size", + "resource.param.7.ba_00002.498141de.filter_vehicle_side_min.description": "Min vehicle size: minimum image size for captured vehicle photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.7.ba_00002.498141de.filter_vehicle_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.7.ba_00002.498141de.filter_vehicle_side_min.name": "Min Vehicle Size", + "resource.param.7.ba_00004.2add29ef.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.7.ba_00004.2add29ef.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7.ba_00004.2add29ef.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.name": "Overlay Trajectory on Panorama", + "resource.param.7.ba_00004.2add29ef.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.7.ba_00004.2add29ef.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.7.ba_00004.2add29ef.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.7.ba_00004.2add29ef.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.7.ba_00004.2add29ef.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.7.ba_00004.2add29ef.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.7.ba_00004.2add29ef.param_targetalarmcount.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.7.ba_00004.2add29ef.param_targetalarmcount.failedtip": "Please enter an integer from 0 to 100", + "resource.param.7.ba_00004.2add29ef.param_targetalarmcount.name": "Alarm Count", + "resource.param.7.ba_00004.2add29ef.param_targetalarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.7.ba_00004.2add29ef.param_targetalarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.7.ba_00004.2add29ef.param_targetalarminterval.name": "Alarm Interval (sec)", + "resource.param.7.ba_00005.7d7b0fa3.param_areaduration.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.7.ba_00005.7d7b0fa3.param_areaduration.failedtip": "Please enter a valid number", + "resource.param.7.ba_00005.7d7b0fa3.param_areaduration.name": "Detection Time", + "resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.description": "Detection Time Unit", + "resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.failedtip": "Please select a valid number", + "resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.name": "Detection Time Unit", + "resource.param.7602.7602.0.name": "Default", + "resource.param.7602.7602.name.description": "Region name: required, max 32 characters", + "resource.param.7602.7602.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.7602.7602.name.name": "Region Name", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.description": "Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.name": "Face Confidence", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidenceconfig.description": "Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidenceconfig.name": "Face Confidence Offset", + "resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.failedtip": "Please select a valid value", + "resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.name": "Face Detection Method", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.description": "Frontal Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.name": "Frontal Face Confidence", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidenceconfig.description": "Frontal Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidenceconfig.name": "Frontal Face Confidence Offset", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.description": "Full Face confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.name": "Full Face Confidence", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidenceconfig.description": "Full Face confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidenceconfig.name": "Full Face Confidence Offset", + "resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.description": "Select face library group for comparison", + "resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.failedtip": "Please select a valid value", + "resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.name": "Bind Face Group", + "resource.param.77380.77380.0.name": "Default", + "resource.param.77380.77380.name.description": "Region name: required, max 32 characters", + "resource.param.77380.77380.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.77380.77380.name.name": "Region Name", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.description": "Pedestrian confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.name": "Pedestrian Confidence", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.description": "Pedestrian confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.name": "Pedestrian Confidence Offset", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.failedtip": "Please select a valid value", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.name": "Pedestrian Detection Method", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.description": "Hatless confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.name": "Hatless Confidence", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.description": "Hatless confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.name": "Hatless Confidence Offset", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.description": "Normal Hat confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.name": "Normal Hat Confidence", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.description": "Normal Hat confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.name": "Normal Hat Confidence Offset", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.description": "Pedestrian Helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.name": "Pedestrian Helmet Confidence", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.description": "Pedestrian Helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.name": "Pedestrian Helmet Confidence Offset", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.description": "Pedestrian Safety Helmet confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.name": "Pedestrian Safety Helmet Confidence", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.description": "Pedestrian Safety Helmet confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.name": "Pedestrian Safety Helmet Confidence Offset", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.description": "Unsure confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.name": "Unsure Confidence", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.description": "Unsure confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.name": "Unsure Confidence Offset", + "resource.param.80498.80498.0.name": "Default", + "resource.param.80498.80498.1.name": "Default", + "resource.param.80498.80498.name.description": "Region name: required, max 32 characters", + "resource.param.80498.80498.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.80498.80498.name.name": "Region Name", + "resource.param.80498.80498.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.80498.80498.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.80498.80498.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.80498.80498.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.80498.80498.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.80498.80498.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.80498.80498.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.80498.80498.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.80498.80498.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.80498.80498.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.80498.80498.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.80498.80498.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.80498.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.80498.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.80498.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.80498.ba_00004.051ea786.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.80498.ba_00004.051ea786.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.80498.ba_00004.051ea786.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.80498.ba_00004.051ea786.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.80498.ba_00004.051ea786.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.80498.ba_00004.051ea786.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.80498.ba_00004.051ea786.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.80498.ba_00004.051ea786.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.80498.ba_00004.051ea786.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.82819.82819.0.name": "Default", + "resource.param.82819.82819.name.description": "Region name: required, max 32 characters", + "resource.param.82819.82819.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.82819.82819.name.name": "Region Name", + "resource.param.83708.83708.0.name": "Default", + "resource.param.83708.83708.1.name": "Default", + "resource.param.83708.83708.aiparam_category0_confidence.description": "Category 0 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.83708.83708.aiparam_category0_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.83708.83708.aiparam_category0_confidence.name": "Category 0 Confidence", + "resource.param.83708.83708.aiparam_category0_confidenceconfig.description": "Category 0 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.83708.83708.aiparam_category0_confidenceconfig.name": "Category 0 Confidence Offset", + "resource.param.83708.83708.aiparam_category0_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.83708.83708.aiparam_category0_detpostion.failedtip": "Please select a valid value", + "resource.param.83708.83708.aiparam_category0_detpostion.name": "Category 0 Detection Method", + "resource.param.83708.83708.name.description": "Region name: required, max 32 characters", + "resource.param.83708.83708.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.83708.83708.name.name": "Region Name", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidence.description": "Category 0 confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidence.name": "Category 0 Confidence", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidenceconfig.description": "Category 0 confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidenceconfig.name": "Category 0 Confidence Offset", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.failedtip": "Please select a valid value", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.name": "Category 0 Detection Method", + "resource.param.8533.8533.0.name": "Default", + "resource.param.8533.8533.name.description": "Region name: required, max 32 characters", + "resource.param.8533.8533.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.8533.8533.name.name": "Region Name", + "resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.8533.ba_00004.051ea786.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.8533.ba_00004.051ea786.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.8533.ba_00004.051ea786.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.8533.ba_00004.051ea786.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.8533.ba_00004.051ea786.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.8533.ba_00004.051ea786.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.8533.ba_00004.051ea786.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.8533.ba_00004.051ea786.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.8533.ba_00004.051ea786.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.89336.89336.0.name": "Default", + "resource.param.89336.89336.name.description": "Region name: required, max 32 characters", + "resource.param.89336.89336.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.89336.89336.name.name": "Region Name", + "resource.param.9.9.0.name": "Default", + "resource.param.9.9.aiparam_smog_confidence.description": "Smoke confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.9.9.aiparam_smog_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.9.9.aiparam_smog_confidence.name": "Smoke Confidence", + "resource.param.9.9.aiparam_smog_confidenceconfig.description": "Smoke confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.9.9.aiparam_smog_confidenceconfig.name": "Smoke Confidence Offset", + "resource.param.9.9.aiparam_smog_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.9.9.aiparam_smog_detpostion.failedtip": "Please select a valid value", + "resource.param.9.9.aiparam_smog_detpostion.name": "Smoke Detection Method", + "resource.param.9.9.filter_smog_side_min.description": "Min smoke size: minimum image size for captured smoke photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.9.9.filter_smog_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.9.9.filter_smog_side_min.name": "Min Smoke Size", + "resource.param.9.9.name.description": "Region name: required, max 32 characters", + "resource.param.9.9.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.9.9.name.name": "Region Name", + "resource.param.9.9.param_alarminterval.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 60 sec.", + "resource.param.9.9.param_alarminterval.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.9.9.param_alarminterval.name": "Alarm Interval (sec)", + "resource.param.9.9.param_detectionduration.description": "Detection time: range 1–3600, default 2.", + "resource.param.9.9.param_detectionduration.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.9.9.param_detectionduration.name": "Detection Time (sec)", + "resource.param.9.9.param_overlaprate.param_restrainswitch.1.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.9.9.param_overlaprate.param_restrainswitch.1.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.9.9.param_overlaprate.param_restrainswitch.1.name": "Stationary Target Overlap Rate", + "resource.param.9.9.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.9.9.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.9.9.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.9.9.param_restraintime.param_restrainswitch.1.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.9.9.param_restraintime.param_restrainswitch.1.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.9.9.param_restraintime.param_restrainswitch.1.name": "Stationary Target Dedup Time (hr)", + "resource.param.9.9.param_sensitivity.description": "Sensitivity: used to calculate hit count within the total count range. For example, if total is 10 and frame rate is 3, it takes ≥10/3 seconds to potentially trigger an alarm.", + "resource.param.9.9.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.9.9.param_sensitivity.name": "Sensitivity", + "resource.param.9.9.param_videoreadfps.description": "For offline videos with abnormal frame rates, this parameter forces a specific frame rate. <0: no forcing, >=0: forced frame rate, default: -1 (full frame).", + "resource.param.9.9.param_videoreadfps.failedtip": "Please enter a valid value", + "resource.param.9.9.param_videoreadfps.name": "Offline Video Frame Rate", + "resource.param.9.9.param_videorepeatcount.description": "Offline video loop count. <0: infinite, 0: once, >1: specified count", + "resource.param.9.9.param_videorepeatcount.failedtip": "Please enter an integer from 1 to 100", + "resource.param.9.9.param_videorepeatcount.name": "Offline Video Play Count", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.description": "Smog confidence, range: 0.0–1.0, up to 3 decimal places.", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.name": "Smog Confidence", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidenceconfig.description": "Smog confidence offset, default: strict threshold. Options: strict threshold, recommended threshold.", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidenceconfig.name": "Smog Confidence Offset", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.description": "Detection method: defines the center point position of the detection box. Default: bottom. Options: top, bottom, center.", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.failedtip": "Please select a valid value", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.name": "Smog Detection Method", + "resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.description": "Min smoke size: minimum image size for captured smoke photos. If set to 100, the minimum size is 100×100 pixels. Range: 10–1000 px, default: 100 px.", + "resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.failedtip": "Please enter an integer from 0 to 10000", + "resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.name": "Min Smoke Size", + "resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.description": "Detection time: range 1–3600, default 2.", + "resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.name": "Detection Time (sec)", + "resource.param.9.ba_00003.e37ea9c1.param_sensitivity.description": "Sensitivity: range 1–10, default: 5. Higher values make alarms easier to trigger.", + "resource.param.9.ba_00003.e37ea9c1.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.9.ba_00003.e37ea9c1.param_sensitivity.name": "Sensitivity", + "resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.9.ba_00004.1478c130.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.9.ba_00004.1478c130.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.9.ba_00004.1478c130.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.9.ba_00004.1478c130.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.9.ba_00004.1478c130.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.9.ba_00004.1478c130.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.9.ba_00004.1478c130.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.9.ba_00004.1478c130.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.9.ba_00004.1478c130.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.91435.91435.0.name": "Default", + "resource.param.91435.91435.1.name": "Default", + "resource.param.91435.91435.name.description": "Region name: required, max 32 characters", + "resource.param.91435.91435.name.failedtip": "Please enter a string of less than 32 characters without spaces", + "resource.param.91435.91435.name.name": "Region Name", + "resource.param.aa_00001.atomiccode.description": "Select Atomic Model", + "resource.param.aa_00001.atomiccode.failedtip": "Please select", + "resource.param.aa_00001.atomiccode.name": "Select Atomic Model", + "resource.param.aa_00001.enableftp.description": "Custom frame rate: enabled by default. When disabled, uses full frame rate.", + "resource.param.aa_00001.enableftp.failedtip": "Please select", + "resource.param.aa_00001.enableftp.name": "Custom Frame Rate", + "resource.param.aa_00001.fps.enableftp.1.description": "Custom frame rate, should not exceed upstream frame rate. Range: 0.01–1000, default: -1 (full frame).", + "resource.param.aa_00001.fps.enableftp.1.failedtip": "Please enter a valid value", + "resource.param.aa_00001.fps.enableftp.1.name": "Frame Rate", + "resource.param.aa_00002.atomiccode.description": "Select Atomic Model", + "resource.param.aa_00002.atomiccode.failedtip": "Please select", + "resource.param.aa_00002.atomiccode.name": "Select Atomic Model", + "resource.param.aa_00002.enableftp.description": "Custom frame rate: enabled by default. When disabled, uses the preceding action's frame rate.", + "resource.param.aa_00002.enableftp.failedtip": "Please select", + "resource.param.aa_00002.enableftp.name": "Custom Frame Rate", + "resource.param.aa_00002.fps.enableftp.1.description": "Frame rate needed for active mode. Leave empty to inherit previous method. Range: 0.01–1000.0, default: -1 (full frame).", + "resource.param.aa_00002.fps.enableftp.1.failedtip": "Please enter a valid value", + "resource.param.aa_00002.fps.enableftp.1.name": "Frame Capture Rate", + "resource.param.aa_00003.motionstatus.description": "State Evaluation", + "resource.param.aa_00003.motionstatus.failedtip": "Please select a valid value", + "resource.param.aa_00003.motionstatus.name": "State Evaluation", + "resource.param.aa_00003.shapechangestatus.description": "Shape Change State Evaluation", + "resource.param.aa_00003.shapechangestatus.failedtip": "Please select a valid value", + "resource.param.aa_00003.shapechangestatus.name": "Shape Change State Evaluation", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.description": "Shape is considered changed when this threshold is reached. Range: 0.0–1.0", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.failedtip": "Please enter a valid number", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.name": "Shape Change Threshold", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.description": "Target is considered stationary when below this threshold. Range: 0.0–1.0", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.failedtip": "Please enter a valid number", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.name": "Shape Change Threshold", + "resource.param.aa_00003.trackselect.failedtip": "Please select", + "resource.param.aa_00003.trackselect.name": "Label Filter Parameters", + "resource.param.aa_00004.atomiccode.description": "Select Atomic Model", + "resource.param.aa_00004.atomiccode.failedtip": "Please select", + "resource.param.aa_00004.atomiccode.name": "Select Face Landmark Model", + "resource.param.aa_00005.atomiccode.description": "Select Atomic Model", + "resource.param.aa_00005.atomiccode.failedtip": "Please select", + "resource.param.aa_00005.atomiccode.name": "Select Atomic Model", + "resource.param.aa_00005.featureinput.description": "Feature Input Type", + "resource.param.aa_00005.featureinput.failedtip": "Please select a valid value", + "resource.param.aa_00005.featureinput.name": "Feature Input Type", + "resource.param.aa_00005.fps.description": "Frame rate needed for active mode. Leave empty to inherit previous method. Range: 0.01–1000.0, default: -1 (full frame).", + "resource.param.aa_00005.fps.failedtip": "Please enter a valid value", + "resource.param.aa_00005.fps.name": "Frame Capture Rate", + "resource.param.aa_00005.matchflag.featureinput.1.description": "Match Flag", + "resource.param.aa_00005.matchflag.featureinput.1.failedtip": "Please select a valid value", + "resource.param.aa_00005.matchflag.featureinput.1.name": "Match Flag", + "resource.param.aa_00005.matchflag.featureinput.2.description": "Match Flag", + "resource.param.aa_00005.matchflag.featureinput.2.failedtip": "Please select a valid value", + "resource.param.aa_00005.matchflag.featureinput.2.name": "Match Flag", + "resource.param.aa_00005.param_commodityset.featureinput.2.description": "Select object group for comparison", + "resource.param.aa_00005.param_commodityset.featureinput.2.failedtip": "Please select a valid value", + "resource.param.aa_00005.param_commodityset.featureinput.2.name": "Bind Object Group", + "resource.param.aa_00005.param_faceset.featureinput.0.description": "Select face library group for comparison", + "resource.param.aa_00005.param_faceset.featureinput.0.failedtip": "Please select a valid value", + "resource.param.aa_00005.param_faceset.featureinput.0.name": "Bind Face Group", + "resource.param.aa_00005.param_workclothesset.featureinput.1.description": "Select work uniform group for comparison", + "resource.param.aa_00005.param_workclothesset.featureinput.1.failedtip": "Please select a valid value", + "resource.param.aa_00005.param_workclothesset.featureinput.1.name": "Bind Work Uniform Group", + "resource.param.ba_00002.0.failedtip": "Please select", + "resource.param.ba_00002.0.name": "Label Parameters", + "resource.param.ba_00003.detectiontimetype.description": "Detection Time Type", + "resource.param.ba_00003.detectiontimetype.failedtip": "Please select a valid value", + "resource.param.ba_00003.detectiontimetype.name": "Detection Time Unit Type", + "resource.param.ba_00003.param_detectionduration.detectiontimetype.1.description": "Detection time: range 1–3600, default 2.", + "resource.param.ba_00003.param_detectionduration.detectiontimetype.1.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.ba_00003.param_detectionduration.detectiontimetype.1.name": "Detection Time (sec)", + "resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.description": "Detection time: range 1–3600000, default 2000.", + "resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.failedtip": "Please enter an integer from 1 to 3600000", + "resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.name": "Detection Time (ms)", + "resource.param.ba_00003.param_sensitivity.description": "Sensitivity: range 1–10, default: 5. Higher values make alarms easier to trigger.", + "resource.param.ba_00003.param_sensitivity.failedtip": "Please enter an integer from 1 to 10", + "resource.param.ba_00003.param_sensitivity.name": "Sensitivity", + "resource.param.ba_00004.alarmproperty.description": "Some special events in reported data require additional parameters", + "resource.param.ba_00004.alarmproperty.failedtip": "Please select a valid value", + "resource.param.ba_00004.alarmproperty.name": "Event Extended Properties", + "resource.param.ba_00004.custparam_alarmtype.description": "Whether target has tracking, selects different alarm suppression methods", + "resource.param.ba_00004.custparam_alarmtype.failedtip": "Please select a valid value", + "resource.param.ba_00004.custparam_alarmtype.name": "Target with Tracking", + "resource.param.ba_00004.enablellmreview.description": "When enabled, alarm events will be reviewed by Qwen3VL Vision-Language Model before reporting to filter false positives. Only applies to trigger-type events.", + "resource.param.ba_00004.enablellmreview.failedtip": "Please select", + "resource.param.ba_00004.enablellmreview.name": "Foundation Model Review", + "resource.param.ba_00004.llmatomiccode.enablellmreview.1.description": "Select a Qwen3VL vision-language model for alarm review", + "resource.param.ba_00004.llmatomiccode.enablellmreview.1.failedtip": "Please select a review model", + "resource.param.ba_00004.llmatomiccode.enablellmreview.1.name": "Review Model", + "resource.param.ba_00004.llmreviewcontent.enablellmreview.1.description": "Content description for review, e.g., flames, people without safety helmets, smoke. Leave empty to use algorithm name automatically.", + "resource.param.ba_00004.llmreviewcontent.enablellmreview.1.name": "Review Content", + "resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.name": "Alarm Interval (sec)", + "resource.param.ba_00004.param_overlaprate.description": "Stationary target overlap rate, range: 0.0–1.0, up to 3 decimal places, default: 0.2.", + "resource.param.ba_00004.param_overlaprate.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.ba_00004.param_overlaprate.name": "Stationary Target Overlap Rate", + "resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.description": "When enabled, overlays target motion trajectory on the panoramic image", + "resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "Please select whether to enable trajectory overlay", + "resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.name": "Overlay Trajectory on Panorama", + "resource.param.ba_00004.param_restrainswitch.description": "Stationary target deduplication: when enabled, detects whether alarm targets are stationary. Stationary targets will not trigger repeated alarms.", + "resource.param.ba_00004.param_restrainswitch.failedtip": "Please select whether to enable alarm suppression", + "resource.param.ba_00004.param_restrainswitch.name": "Stationary Target Deduplication", + "resource.param.ba_00004.param_restraintime.description": "Stationary target dedup time, range: 1–24 hours, default: 6 hours.", + "resource.param.ba_00004.param_restraintime.failedtip": "Please enter an integer from 0 to 24.", + "resource.param.ba_00004.param_restraintime.name": "Stationary Target Dedup Time (hr)", + "resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.description": "Alarm count: range 0–100, default 1. 0 means unlimited.", + "resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.failedtip": "Please enter an integer from 0 to 100", + "resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.name": "Alarm Count", + "resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.description": "Alarm interval: time between two alarm events. Range: 1–36000 sec, default: 3 sec.", + "resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.failedtip": "Please enter an integer from 1 to 36000", + "resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.name": "Alarm Interval (sec)", + "resource.param.ba_00004.realtimeeventrecordtype.description": "Whether timed events need video clips", + "resource.param.ba_00004.realtimeeventrecordtype.failedtip": "Please select", + "resource.param.ba_00004.realtimeeventrecordtype.name": "Whether timed events need video clips", + "resource.param.ba_00004.triggereventrecordtype.description": "Whether trigger events need video clips", + "resource.param.ba_00004.triggereventrecordtype.failedtip": "Please select", + "resource.param.ba_00004.triggereventrecordtype.name": "Whether trigger events need video clips", + "resource.param.ba_00005.areaalarmtype.description": "Region Alarm Statistics Method", + "resource.param.ba_00005.areaalarmtype.failedtip": "Please select a valid value", + "resource.param.ba_00005.areaalarmtype.name": "Region Alarm Statistics Method", + "resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.description": "Detection Time Unit", + "resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.failedtip": "Please select a valid number", + "resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.name": "Detection Time Unit", + "resource.param.ba_00005.arealimitduration.areaalarmtype.6.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.ba_00005.arealimitduration.areaalarmtype.6.failedtip": "Please enter a valid number", + "resource.param.ba_00005.arealimitduration.areaalarmtype.6.name": "Detection Time", + "resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.description": "Target Count in Region", + "resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.failedtip": "Please enter an integer from 0 to 3600", + "resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.name": "Target Count in Region", + "resource.param.ba_00005.arealimittargettype.areaalarmtype.6.description": "Region Target Count Limit Type", + "resource.param.ba_00005.arealimittargettype.areaalarmtype.6.failedtip": "Please select a valid value", + "resource.param.ba_00005.arealimittargettype.areaalarmtype.6.name": "Region Target Count Limit Type", + "resource.param.ba_00005.breakareatype.areaalarmtype.2.description": "Entry/Exit Line Method", + "resource.param.ba_00005.breakareatype.areaalarmtype.2.failedtip": "Please select a valid value", + "resource.param.ba_00005.breakareatype.areaalarmtype.2.name": "Entry/Exit Line Method", + "resource.param.ba_00005.countbreakareatype.areaalarmtype.1.description": "Counting Line Direction Method", + "resource.param.ba_00005.countbreakareatype.areaalarmtype.1.failedtip": "Please select a valid value", + "resource.param.ba_00005.countbreakareatype.areaalarmtype.1.name": "Counting Line Direction Method", + "resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.description": "Counting Line Direction Method", + "resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.failedtip": "Please select a valid value", + "resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.name": "Counting Line Direction Method", + "resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.description": "Counting Line Direction Method", + "resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.failedtip": "Please select a valid value", + "resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.name": "Counting Line Direction Method", + "resource.param.ba_00005.inputareatype.description": "Input Region Type", + "resource.param.ba_00005.inputareatype.failedtip": "Please select a valid value", + "resource.param.ba_00005.inputareatype.name": "Input Region Type", + "resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.description": "Count report interval: range 1–3600000, note the time unit", + "resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.failedtip": "Please enter a valid number", + "resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.name": "Count Report Interval", + "resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.description": "Count Report Interval Time Unit", + "resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.failedtip": "Please select a valid unit", + "resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.name": "Count Report Interval Time Unit", + "resource.param.ba_00005.param_areaduration.areaalarmtype.4.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.ba_00005.param_areaduration.areaalarmtype.4.failedtip": "Please enter a valid number", + "resource.param.ba_00005.param_areaduration.areaalarmtype.4.name": "Detection Time", + "resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.description": "Detection Time Unit", + "resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.failedtip": "Please select a valid number", + "resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.name": "Detection Time Unit", + "resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.description": "Detection time: range 1–3600000, note the time unit", + "resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.failedtip": "Please enter a valid number", + "resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.name": "Detection Time", + "resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.description": "Detection Time Unit", + "resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.failedtip": "Please select a valid number", + "resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.name": "Detection Time Unit", + "resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.description": "Threshold used to compare with the actual valid target count in the region", + "resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.failedtip": "Please enter an integer from 0 to 3600", + "resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.name": "Target Count Threshold", + "resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.description": "Region Target Count Limit Type", + "resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.failedtip": "Please select a valid value", + "resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.name": "Trigger Condition", + "resource.param.ba_00005.param_retrodirect.areaalarmtype.3.description": "Target Wrong-way Alarm Direction", + "resource.param.ba_00005.param_retrodirect.areaalarmtype.3.failedtip": "Please select a valid value", + "resource.param.ba_00005.param_retrodirect.areaalarmtype.3.name": "Target Wrong-way Alarm Direction", + "resource.param.ba_00005.param_retrodistance.areaalarmtype.3.description": "Wrong-way distance: Y-axis movement (relative), range: 0.00–1.0, default: 0.05.", + "resource.param.ba_00005.param_retrodistance.areaalarmtype.3.failedtip": "Please enter a valid value", + "resource.param.ba_00005.param_retrodistance.areaalarmtype.3.name": "Wrong-way Distance: Y-axis Movement (relative)", + "resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.description": "Target Counting Method", + "resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.failedtip": "Please select a valid value", + "resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.name": "Target Counting Method", + "resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.description": "Alarm condition: number of targets crossing the line", + "resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.failedtip": "Please select a valid value", + "resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.name": "Tripwire Type", + "resource.param.ba_00005.targetcountchange.areaalarmtype.1.description": "When enabled, reports immediately when target count changes, even if the time interval condition is not met", + "resource.param.ba_00005.targetcountchange.areaalarmtype.1.failedtip": "Please select", + "resource.param.ba_00005.targetcountchange.areaalarmtype.1.name": "Target Count Change Status", + "resource.param.ba_10003.param_senhitcount.description": "Sensitivity hit count, range: 1 to total count.", + "resource.param.ba_10003.param_senhitcount.failedtip": "Please enter an integer from 1 to 3600", + "resource.param.ba_10003.param_senhitcount.name": "Sensitivity Hit Count", + "resource.param.ba_10003.param_sentotalcount.description": "Sensitivity Total Count", + "resource.param.ba_10003.param_sentotalcount.failedtip": "Please enter an integer from 1 to 3600000", + "resource.param.ba_10003.param_sentotalcount.name": "Sensitivity Total Count", + "resource.param.ba_90001.condition.description": "Configure conditions to evaluate as true and execute the actions below", + "resource.param.ba_90001.condition.failedtip": "Please select", + "resource.param.ba_90001.condition.name": "Condition Configuration", + "resource.param.da_00001.aiparam_box_confidence.description": "Target confidence, range: 0.0–1.0, up to 3 decimal places", + "resource.param.da_00001.aiparam_box_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.da_00001.aiparam_box_confidence.name": "Target Confidence", + "resource.param.da_00001.aiparam_text_confidence.description": "Text confidence, range: 0.0–1.0, up to 3 decimal places", + "resource.param.da_00001.aiparam_text_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.da_00001.aiparam_text_confidence.name": "Text Confidence", + "resource.param.da_00001.atomiccode.description": "Select Atomic Model", + "resource.param.da_00001.atomiccode.failedtip": "Please select", + "resource.param.da_00001.atomiccode.name": "Select Atomic Model", + "resource.param.da_00001.fps.description": "Custom frame rate, should not exceed upstream frame rate. Range: 0.01–1000, default: 1.", + "resource.param.da_00001.fps.failedtip": "Please enter a valid value", + "resource.param.da_00001.fps.name": "Frame Rate", + "resource.param.da_00001.keywords.description": "Multiple prompts can be separated by periods", + "resource.param.da_00001.keywords.failedtip": "Please enter in English", + "resource.param.da_00001.keywords.name": "Prompt", + "resource.param.da_00002.atomiccode.description": "Select Atomic Model", + "resource.param.da_00002.atomiccode.failedtip": "Please select", + "resource.param.da_00002.atomiccode.name": "Select Atomic Model", + "resource.param.da_00002.fps.description": "Custom frame rate, should not exceed upstream frame rate. Range: 0.01–1000, default: 1.", + "resource.param.da_00002.fps.failedtip": "Please enter a valid value", + "resource.param.da_00002.fps.name": "Frame Rate", + "resource.param.da_00002.inputtype.description": "Input Type", + "resource.param.da_00002.inputtype.failedtip": "Please select a valid value", + "resource.param.da_00002.inputtype.name": "Input Type", + "resource.param.da_00003.advanced_mode.description": "Advanced mode allows full customization of the prompt prefix. When disabled (e.g., input: safety helmet), the actual prompt is \"Determine if [safety helmet] exists in the image...\"; when enabled, the input is used directly.", + "resource.param.da_00003.advanced_mode.failedtip": "Please select", + "resource.param.da_00003.advanced_mode.name": "Advanced Prompt Mode", + "resource.param.da_00003.atomiccode.description": "Select Atomic Model", + "resource.param.da_00003.atomiccode.failedtip": "Please select", + "resource.param.da_00003.atomiccode.name": "Select Atomic Model", + "resource.param.da_00003.dosample.generationstyle.custom.description": "Enable Random Sampling", + "resource.param.da_00003.dosample.generationstyle.custom.failedtip": "Please select", + "resource.param.da_00003.fps.description": "Custom frame rate, should not exceed upstream frame rate. Range: 0.01–1000, default: 1.", + "resource.param.da_00003.fps.failedtip": "Please enter a valid value", + "resource.param.da_00003.fps.name": "Frame Rate", + "resource.param.da_00003.generationstyle.description": "Generation Style", + "resource.param.da_00003.generationstyle.failedtip": "Please select a valid value", + "resource.param.da_00003.generationstyle.name": "Generation Style", + "resource.param.da_00003.keywords.description": "Input Prompt", + "resource.param.da_00003.keywords.failedtip": "Please enter a prompt", + "resource.param.da_00003.keywords.name": "Prompt", + "resource.param.da_00003.temperature.generationstyle.custom.description": "Response temperature. Lower values produce more precise and stable responses. Range: 0.0–2.0, default: 0.7", + "resource.param.da_00003.temperature.generationstyle.custom.failedtip": "Please enter a value from 0.0 to 2.0", + "resource.param.da_00003.topk.generationstyle.custom.description": "Top-K sampling: selects from the K most probable tokens at each step. Range: 1–100, default: 20", + "resource.param.da_00003.topk.generationstyle.custom.failedtip": "Please enter an integer from 1 to 100", + "resource.param.da_00003.topp.generationstyle.custom.description": "Top-P sampling: samples from tokens with cumulative probability ≤ top_p. Range: 0.1–1.0, default: 0.8", + "resource.param.da_00003.topp.generationstyle.custom.failedtip": "Please enter a value from 0.1 to 1.0", + "resource.param.ip0001.data_type.description": "Data Type Selection", + "resource.param.ip0001.data_type.name": "Data Type", + "resource.param.ip0001.input_node.description": "Model Input Node Name", + "resource.param.ip0001.input_node.name": "Input Node Name", + "resource.param.ip0001.shape.description": "Input tensor shape, format: [batch, channel, height, width]", + "resource.param.ip0001.shape.name": "Input Shape", + "resource.param.la_alarmdata_code.algs.failedtip": "Please select", + "resource.param.la_audiodevice_code.audiodeviceid.description": "Select Network Audio Column", + "resource.param.la_audiodevice_code.audiodeviceid.failedtip": "Select Network Audio Column", + "resource.param.la_audiodevice_code.audiodeviceid.name": "Select Network Audio Column", + "resource.param.la_audiodevice_code.data.operation.1.description": "Select the corresponding alarm audio file.", + "resource.param.la_audiodevice_code.data.operation.1.failedtip": "Select the corresponding alarm audio file.", + "resource.param.la_audiodevice_code.data.operation.1.name": "Audio File", + "resource.param.la_audiodevice_code.duration.description": "Play Duration (sec)", + "resource.param.la_audiodevice_code.duration.failedtip": "Please enter an integer", + "resource.param.la_audiodevice_code.duration.name": "Play Duration (sec)", + "resource.param.la_audiodevice_code.gap.description": "Play Interval (sec)", + "resource.param.la_audiodevice_code.gap.failedtip": "Please enter an integer", + "resource.param.la_audiodevice_code.gap.name": "Play Interval (sec)", + "resource.param.la_audiodevice_code.operation.description": "Play Mode", + "resource.param.la_audiodevice_code.operation.failedtip": "Please select a valid value", + "resource.param.la_audiodevice_code.operation.name": "Play Mode", + "resource.param.la_audiodevice_code.speed.operation.2.description": "Speech Speed", + "resource.param.la_audiodevice_code.speed.operation.2.failedtip": "Please enter an integer", + "resource.param.la_audiodevice_code.speed.operation.2.name": "Speech Speed", + "resource.param.la_audiodevice_code.text.operation.2.description": "Playback text: max 32 characters.", + "resource.param.la_audiodevice_code.text.operation.2.failedtip": "Please enter up to 32 characters", + "resource.param.la_audiodevice_code.text.operation.2.name": "Playback Text", + "resource.param.la_audiodevice_code.times.description": "Play Count", + "resource.param.la_audiodevice_code.times.failedtip": "Please enter an integer", + "resource.param.la_audiodevice_code.times.name": "Play Count", + "resource.param.la_audiodevice_code.tone.operation.2.description": "Voice type: options are male voice, female voice. Default: male voice.", + "resource.param.la_audiodevice_code.tone.operation.2.failedtip": "Please select", + "resource.param.la_audiodevice_code.tone.operation.2.name": "Voice Type", + "resource.param.la_audiodevice_code.volume.description": "Volume", + "resource.param.la_audiodevice_code.volume.failedtip": "Please enter an integer", + "resource.param.la_audiodevice_code.volume.name": "Volume", + "resource.param.lb0001.categories.description": "Class info configuration (JSON format)", + "resource.param.lb0001.categories.name": "Class Info", + "resource.param.lb0001.output_info.description": "Output label info configuration (JSON format)", + "resource.param.lb0001.output_info.name": "Output Info", + "resource.param.lb0001.output_node.description": "Configure the output node name", + "resource.param.lb0001.output_node.name": "Output Node Name", + "resource.param.lb0001.shape.description": "Output Tensor Shape", + "resource.param.lb0001.shape.name": "Output Shape", + "resource.param.on0001.data_type.description": "Data Type Selection", + "resource.param.on0001.data_type.name": "Data Type", + "resource.param.on0001.output_node.description": "Model Output Node Name", + "resource.param.on0001.output_node.name": "Output Node Name", + "resource.param.on0001.shape.description": "Output Tensor Shape", + "resource.param.on0001.shape.name": "Output Shape", + "resource.param.pa_00001.atomiccode.description": "Select Atomic Model", + "resource.param.pa_00001.atomiccode.failedtip": "Please select", + "resource.param.pa_00001.atomiccode.name": "Select Atomic Model", + "resource.param.pa_00002.atomiccode.description": "Select Atomic Model", + "resource.param.pa_00002.atomiccode.failedtip": "Please select", + "resource.param.pa_00002.atomiccode.name": "Select Atomic Model", + "resource.param.pa_00005.atomiccode.description": "Select Atomic Model", + "resource.param.pa_00005.atomiccode.failedtip": "Please select", + "resource.param.pa_00005.atomiccode.name": "Select Atomic Model", + "resource.param.pa_00005.featureinput.description": "Feature Input Type", + "resource.param.pa_00005.featureinput.failedtip": "Please select a valid value", + "resource.param.pa_00005.featureinput.name": "Feature Input Type", + "resource.param.pa_00005.matchflag.featureinput.1.description": "Match Flag", + "resource.param.pa_00005.matchflag.featureinput.1.failedtip": "Please select a valid value", + "resource.param.pa_00005.matchflag.featureinput.1.name": "Match Flag", + "resource.param.pa_00005.matchflag.featureinput.2.description": "Match Flag", + "resource.param.pa_00005.matchflag.featureinput.2.failedtip": "Please select a valid value", + "resource.param.pa_00005.matchflag.featureinput.2.name": "Match Flag", + "resource.param.pa_00005.param_commodityset.featureinput.2.description": "Select object group for comparison", + "resource.param.pa_00005.param_commodityset.featureinput.2.failedtip": "Please select a valid value", + "resource.param.pa_00005.param_commodityset.featureinput.2.name": "Bind Object Group", + "resource.param.pa_00005.param_faceset.featureinput.0.description": "Select face library group for comparison", + "resource.param.pa_00005.param_faceset.featureinput.0.failedtip": "Please select a valid value", + "resource.param.pa_00005.param_faceset.featureinput.0.name": "Bind Face Group", + "resource.param.pa_00005.param_workclothesset.featureinput.1.description": "Select work uniform group for comparison", + "resource.param.pa_00005.param_workclothesset.featureinput.1.failedtip": "Please select a valid value", + "resource.param.pa_00005.param_workclothesset.featureinput.1.name": "Bind Work Uniform Group", + "resource.param.pb_90001.condition.description": "Configure conditions to evaluate as true and execute the actions below", + "resource.param.pb_90001.condition.failedtip": "Please select", + "resource.param.pb_90001.condition.name": "Condition Configuration", + "resource.param.pda_00001.aiparam_box_confidence.description": "Target confidence, range: 0.0–1.0, up to 3 decimal places", + "resource.param.pda_00001.aiparam_box_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.pda_00001.aiparam_box_confidence.name": "Target Confidence", + "resource.param.pda_00001.aiparam_text_confidence.description": "Text confidence, range: 0.0–1.0, up to 3 decimal places", + "resource.param.pda_00001.aiparam_text_confidence.failedtip": "Please enter a value from 0 to 1 with up to 3 decimal places.", + "resource.param.pda_00001.aiparam_text_confidence.name": "Text Confidence", + "resource.param.pda_00001.atomiccode.description": "Select Atomic Model", + "resource.param.pda_00001.atomiccode.failedtip": "Please select", + "resource.param.pda_00001.atomiccode.name": "Select Atomic Model", + "resource.param.pda_00001.keywords.description": "Multiple prompts can be separated by periods", + "resource.param.pda_00001.keywords.failedtip": "Please enter in English", + "resource.param.pda_00001.keywords.name": "Prompt", + "resource.param.pda_00002.atomiccode.description": "Select Atomic Model", + "resource.param.pda_00002.atomiccode.failedtip": "Please select", + "resource.param.pda_00002.atomiccode.name": "Select Atomic Model", + "resource.param.pda_00002.inputtype.description": "Input Type", + "resource.param.pda_00002.inputtype.failedtip": "Please select a valid value", + "resource.param.pda_00002.inputtype.name": "Input Type", + "resource.param.pda_00003.advanced_mode.description": "Advanced mode allows full customization of the prompt prefix. When disabled (e.g., input: safety helmet), the actual prompt is \"Determine if [safety helmet] exists in the image...\"; when enabled, the input is used directly.", + "resource.param.pda_00003.advanced_mode.failedtip": "Please select", + "resource.param.pda_00003.advanced_mode.name": "Advanced Prompt Mode", + "resource.param.pda_00003.atomiccode.description": "Select Atomic Model", + "resource.param.pda_00003.atomiccode.failedtip": "Please select", + "resource.param.pda_00003.atomiccode.name": "Select Atomic Model", + "resource.param.pda_00003.dosample.generationstyle.custom.description": "Enable Random Sampling", + "resource.param.pda_00003.dosample.generationstyle.custom.failedtip": "Please select", + "resource.param.pda_00003.generationstyle.description": "Generation Style", + "resource.param.pda_00003.generationstyle.failedtip": "Please select a valid value", + "resource.param.pda_00003.generationstyle.name": "Generation Style", + "resource.param.pda_00003.keywords.description": "Input Prompt", + "resource.param.pda_00003.keywords.failedtip": "Please enter a prompt", + "resource.param.pda_00003.keywords.name": "Prompt", + "resource.param.pda_00003.temperature.generationstyle.custom.description": "Response temperature. Lower values produce more precise and stable responses. Range: 0.0–2.0, default: 0.7", + "resource.param.pda_00003.temperature.generationstyle.custom.failedtip": "Please enter a value from 0.0 to 2.0", + "resource.param.pda_00003.topk.generationstyle.custom.description": "Top-K sampling: selects from the K most probable tokens at each step. Range: 1–100, default: 20", + "resource.param.pda_00003.topk.generationstyle.custom.failedtip": "Please enter an integer from 1 to 100", + "resource.param.pda_00003.topp.generationstyle.custom.description": "Top-P sampling: samples from tokens with cumulative probability ≤ top_p. Range: 0.1–1.0, default: 0.8", + "resource.param.pda_00003.topp.generationstyle.custom.failedtip": "Please enter a value from 0.1 to 1.0", + "resource.param.pr0001.color.description": "Fill color [R, G, B] (effective when gravity ≠ 0)", + "resource.param.pr0001.color.name": "Fill Color", + "resource.param.pr0001.dsize.description": "Resized image dimensions [height, width]", + "resource.param.pr0001.dsize.name": "Target Size", + "resource.param.pr0001.gravity.description": "Resize strategy: 0 - direct resize, 1 - aspect ratio resize with center padding, 2 - aspect ratio resize with top-left alignment (compatible with cwnn_sophon)", + "resource.param.pr0001.gravity.name": "Resize Strategy", + "resource.param.pr0001.op.description": "Pre-processing Operation Type", + "resource.param.pr0001.op.name": "Pre-processing Operation Type", + "resource.param.pr0002.is_bgr.description": "Whether BGR format", + "resource.param.pr0002.is_bgr.name": "BGR Format", + "resource.param.pr0002.mean.description": "Normalization Mean [R, G, B]", + "resource.param.pr0002.mean.name": "Mean", + "resource.param.pr0002.op.description": "Pre-processing Operation Type", + "resource.param.pr0002.op.name": "Pre-processing Operation Type", + "resource.param.pr0002.scale.description": "Normalization Scale Factor", + "resource.param.pr0002.scale.name": "Scale Factor", + "resource.param.pr0002.std.description": "Normalization std [R, G, B], optional. If provided, uses 1/std; otherwise uses scale", + "resource.param.pr0002.std.name": "Std Dev", + "resource.param.pr0003.h_bottom_crop.description": "-1 to 1: negative or 0 = crop, positive = expand", + "resource.param.pr0003.h_bottom_crop.name": "Bottom", + "resource.param.pr0003.h_top_crop.description": "Range -1 to 1: negative or 0 means crop (e.g., -0.1 crops 10%), positive means expand (e.g., 0.1 expands 10%)", + "resource.param.pr0003.h_top_crop.name": "Top", + "resource.param.pr0003.op.description": "Pre-processing Operation Type", + "resource.param.pr0003.op.name": "Pre-processing Operation Type", + "resource.param.pr0003.skip.description": "Whether to skip this operation", + "resource.param.pr0003.skip.name": "Skip Operation", + "resource.param.pr0003.square_mode.description": "Square mode: 0-max, 1-min, 2-avg", + "resource.param.pr0003.square_mode.name": "Square Mode", + "resource.param.pr0003.square.description": "Whether to force square", + "resource.param.pr0003.square.name": "Force Square", + "resource.param.pr0003.w_left_crop.description": "-1 to 1: negative or 0 = crop, positive = expand", + "resource.param.pr0003.w_left_crop.name": "Left", + "resource.param.pr0003.w_right_crop.description": "-1 to 1: negative or 0 = crop, positive = expand", + "resource.param.pr0003.w_right_crop.name": "Right", + "resource.param.pr0004.h_bottom_crop.description": "-1 to 1: negative or 0 = crop, positive = expand", + "resource.param.pr0004.h_bottom_crop.name": "Bottom", + "resource.param.pr0004.h_top_crop.description": "-1 to 1: negative or 0 = crop, positive = expand (e.g., 0.1 expands 10%)", + "resource.param.pr0004.h_top_crop.name": "Top", + "resource.param.pr0004.op.description": "Shares -1 to 1 semantics with crop: negative or 0 = crop, positive = expand. Expand typically uses positive values", + "resource.param.pr0004.op.name": "Pre-processing Operation Type", + "resource.param.pr0004.skip.description": "Whether to skip this operation", + "resource.param.pr0004.skip.name": "Skip Operation", + "resource.param.pr0004.square_mode.description": "Square mode: 0-max, 1-min, 2-avg", + "resource.param.pr0004.square_mode.name": "Square Mode", + "resource.param.pr0004.square.description": "Whether to force square", + "resource.param.pr0004.square.name": "Force Square", + "resource.param.pr0004.w_left_crop.description": "-1 to 1: negative or 0 = crop, positive = expand", + "resource.param.pr0004.w_left_crop.name": "Left", + "resource.param.pr0004.w_right_crop.description": "-1 to 1: negative or 0 = crop, positive = expand", + "resource.param.pr0004.w_right_crop.name": "Right", + "resource.param.pr0005.center_index.description": "Optional, determines center point calculation method, e.g., [0, 1, 3, 4]", + "resource.param.pr0005.center_index.name": "Center Point Indices", + "resource.param.pr0005.norm_ratio.description": "Normalization Ratio", + "resource.param.pr0005.norm_ratio.name": "Normalization Ratio", + "resource.param.pr0005.normmode.description": "Normalization Mode: 0/1/2", + "resource.param.pr0005.normmode.name": "Normalization Mode", + "resource.param.pr0005.op.description": "Pre-processing Operation Type", + "resource.param.pr0005.op.name": "Pre-processing Operation Type", + "resource.param.pr0005.output_hw.description": "Output Size [height, width]", + "resource.param.pr0005.output_hw.name": "Output Size", + "resource.param.pr0006.dsize.description": "Target Size [height, width]", + "resource.param.pr0006.dsize.name": "Target Size", + "resource.param.pr0006.is_bgr.description": "Whether BGR format", + "resource.param.pr0006.is_bgr.name": "BGR Format", + "resource.param.pr0006.op.description": "Pre-processing Operation Type", + "resource.param.pr0006.op.name": "Pre-processing Operation Type", + "resource.param.pr0006.scale.description": "Scale Factor", + "resource.param.pr0006.scale.name": "Scale", + "resource.param.pr0006.size.description": "Sequence Length", + "resource.param.pr0006.size.name": "Sequence Length", + "resource.param.pr0007.count.description": "Image Count", + "resource.param.pr0007.count.name": "Image Count", + "resource.param.pr0007.dst_height.description": "Target Height", + "resource.param.pr0007.dst_height.name": "Target Height", + "resource.param.pr0007.dst_width.description": "Target Width", + "resource.param.pr0007.dst_width.name": "Target Width", + "resource.param.pr0007.op.description": "Pre-processing Operation Type", + "resource.param.pr0007.op.name": "Pre-processing Operation Type", + "resource.param.pr0008.dst_height.description": "Target Height", + "resource.param.pr0008.dst_height.name": "Target Height", + "resource.param.pr0008.dst_width.description": "Target Width", + "resource.param.pr0008.dst_width.name": "Target Width", + "resource.param.pr0008.is_bgr.description": "Whether BGR format", + "resource.param.pr0008.is_bgr.name": "BGR Format", + "resource.param.pr0008.mean.description": "Normalization Mean [R, G, B]", + "resource.param.pr0008.mean.name": "Mean", + "resource.param.pr0008.op.description": "Pre-processing Operation Type", + "resource.param.pr0008.op.name": "Pre-processing Operation Type", + "resource.param.pr0008.std.description": "Normalization Std [R, G, B]", + "resource.param.pr0008.std.name": "Std Dev", + "resource.param.pt0001.nms_detection_conf.description": "NMS Detection Confidence", + "resource.param.pt0001.nms_detection_conf.name": "Detection Confidence", + "resource.param.pt0001.nms_threshold.description": "NMS Threshold", + "resource.param.pt0001.nms_threshold.name": "NMS Threshold", + "resource.param.pt0001.op.description": "Post-processing Operation Type", + "resource.param.pt0001.op.name": "Post-processing Operation Type", + "resource.param.pt0001.top_k.description": "Keep Top-K Detection Results", + "resource.param.pt0002.anchors.description": "YOLO Anchor Configuration", + "resource.param.pt0002.anchors.name": "Anchors", + "resource.param.pt0002.nms_detection_conf.description": "NMS Detection Confidence", + "resource.param.pt0002.nms_detection_conf.name": "Detection Confidence", + "resource.param.pt0002.nms_threshold.description": "NMS Threshold", + "resource.param.pt0002.nms_threshold.name": "NMS Threshold", + "resource.param.pt0002.op.description": "Post-processing Operation Type", + "resource.param.pt0002.op.name": "Post-processing Operation Type", + "resource.param.pt0002.stride.description": "YOLO Stride", + "resource.param.pt0002.stride.name": "Stride", + "resource.param.pt0002.top_k.description": "Keep Top-K Detection Results", + "resource.param.pt0003.nms_detection_conf.description": "NMS Detection Confidence", + "resource.param.pt0003.nms_detection_conf.name": "Detection Confidence", + "resource.param.pt0003.nms_threshold.description": "NMS Threshold", + "resource.param.pt0003.nms_threshold.name": "NMS Threshold", + "resource.param.pt0003.op.description": "Post-processing Operation Type", + "resource.param.pt0003.op.name": "Post-processing Operation Type", + "resource.param.pt0003.top_k.description": "Keep Top-K Detection Results", + "resource.param.pt0004.op.description": "Post-processing Operation Type", + "resource.param.pt0004.op.name": "Post-processing Operation Type", + "resource.param.pt0005.axis.description": "Argmax along specified axis", + "resource.param.pt0005.axis.name": "Axis", + "resource.param.pt0005.op.description": "Post-processing Operation Type", + "resource.param.pt0005.op.name": "Post-processing Operation Type", + "resource.param.pt0006.axis.description": "Current implementation requires 1", + "resource.param.pt0006.axis.name": "Axis", + "resource.param.pt0006.op.description": "Post-processing Operation Type", + "resource.param.pt0006.op.name": "Post-processing Operation Type", + "resource.param.pt0006.split.description": "Sum of segment widths must equal the dimension length", + "resource.param.pt0006.split.name": "Split Configuration", + "resource.param.pt0007.op.description": "Post-processing Operation Type", + "resource.param.pt0007.op.name": "Post-processing Operation Type", + "resource.param.pt0007.split.description": "Split Configuration Array", + "resource.param.pt0007.split.name": "Split Configuration", + "resource.param.pt0008.box_threshold.description": "Box Threshold", + "resource.param.pt0008.box_threshold.name": "Box Threshold", + "resource.param.pt0008.op.description": "Post-processing Operation Type", + "resource.param.pt0008.op.name": "Post-processing Operation Type", + "resource.param.pt0008.text_threshold.description": "Text Threshold", + "resource.param.pt0008.text_threshold.name": "Text Threshold", + "resource.param.pt0009.nms_detection_conf.description": "Detection confidence threshold (no NMS)", + "resource.param.pt0009.nms_detection_conf.name": "Confidence Threshold", + "resource.param.pt0009.op.description": "End-to-end detection (NMS built-in, e.g., YOLO26)", + "resource.param.pt0009.op.name": "Post-processing Operation Type", + "resource.param.pt0009.top_k.description": "Keep Top-K Detection Results", + "resource.param.da_00003.vlmprovider.name": "Inference Mode", + "resource.param.da_00003.vlmprovider.description": "Choose local atomic model or OpenAI-compatible API", + "resource.param.da_00003.vlmprovider.failedtip": "Please select a valid value", + "resource.option.da_00003.vlmprovider.local_model.options_name": "Local Atomic Model", + "resource.option.da_00003.vlmprovider.openai_vlm.options_name": "OpenAI API", + "resource.param.da_00003.openai_base_url.vlmprovider.openai_vlm.description": "OpenAI-compatible API base URL, for example http://127.0.0.1:8000/v1", + "resource.param.da_00003.openai_base_url.vlmprovider.openai_vlm.failedtip": "Please enter API base URL", + "resource.param.da_00003.openai_api_key.vlmprovider.openai_vlm.description": "OpenAI API key; leave empty when local vLLM authentication is disabled", + "resource.param.da_00003.openai_api_key.vlmprovider.openai_vlm.failedtip": "Please enter API key", + "resource.param.da_00003.openai_model.vlmprovider.openai_vlm.description": "OpenAI API model name", + "resource.param.da_00003.openai_model.vlmprovider.openai_vlm.failedtip": "Please enter model name", + "resource.param.da_00003.openai_endpoint.vlmprovider.openai_vlm.description": "OpenAI-compatible API path, default /chat/completions", + "resource.param.da_00003.openai_endpoint.vlmprovider.openai_vlm.failedtip": "Please enter API path", + "resource.param.da_00003.openai_timeout_ms.vlmprovider.openai_vlm.description": "Request timeout in milliseconds", + "resource.param.da_00003.openai_timeout_ms.vlmprovider.openai_vlm.failedtip": "Please enter timeout", + "resource.param.da_00003.openai_max_tokens.vlmprovider.openai_vlm.description": "Maximum output token count", + "resource.param.da_00003.openai_max_tokens.vlmprovider.openai_vlm.failedtip": "Please enter maximum output token count", + "resource.param.pda_00003.vlmprovider.name": "Inference Mode", + "resource.param.pda_00003.vlmprovider.description": "Choose local atomic model or OpenAI-compatible API", + "resource.param.pda_00003.vlmprovider.failedtip": "Please select a valid value", + "resource.option.pda_00003.vlmprovider.local_model.options_name": "Local Atomic Model", + "resource.option.pda_00003.vlmprovider.openai_vlm.options_name": "OpenAI API", + "resource.param.pda_00003.openai_base_url.vlmprovider.openai_vlm.description": "OpenAI-compatible API base URL, for example http://127.0.0.1:8000/v1", + "resource.param.pda_00003.openai_base_url.vlmprovider.openai_vlm.failedtip": "Please enter API base URL", + "resource.param.pda_00003.openai_api_key.vlmprovider.openai_vlm.description": "OpenAI API key; leave empty when local vLLM authentication is disabled", + "resource.param.pda_00003.openai_api_key.vlmprovider.openai_vlm.failedtip": "Please enter API key", + "resource.param.pda_00003.openai_model.vlmprovider.openai_vlm.description": "OpenAI API model name", + "resource.param.pda_00003.openai_model.vlmprovider.openai_vlm.failedtip": "Please enter model name", + "resource.param.pda_00003.openai_endpoint.vlmprovider.openai_vlm.description": "OpenAI-compatible API path, default /chat/completions", + "resource.param.pda_00003.openai_endpoint.vlmprovider.openai_vlm.failedtip": "Please enter API path", + "resource.param.pda_00003.openai_timeout_ms.vlmprovider.openai_vlm.description": "Request timeout in milliseconds", + "resource.param.pda_00003.openai_timeout_ms.vlmprovider.openai_vlm.failedtip": "Please enter timeout", + "resource.param.pda_00003.openai_max_tokens.vlmprovider.openai_vlm.description": "Maximum output token count", + "resource.param.pda_00003.openai_max_tokens.vlmprovider.openai_vlm.failedtip": "Please enter maximum output token count", + "resource.param.ba_00004.llmprovider.enablellmreview.1.name": "Review Inference Mode", + "resource.param.ba_00004.llmprovider.enablellmreview.1.description": "Choose local review model or OpenAI-compatible API", + "resource.param.ba_00004.llmprovider.enablellmreview.1.failedtip": "Please select a valid value", + "resource.option.ba_00004.llmprovider.local_model.options_name": "Local Atomic Model", + "resource.option.ba_00004.llmprovider.openai_vlm.options_name": "OpenAI API", + "resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.description": "OpenAI-compatible API base URL, for example http://127.0.0.1:8000/v1", + "resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.failedtip": "Please enter API base URL", + "resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.description": "OpenAI API key; leave empty when local vLLM authentication is disabled", + "resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.failedtip": "Please enter API key", + "resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.description": "OpenAI API model name", + "resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.failedtip": "Please enter model name", + "resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.description": "OpenAI-compatible API path, default /chat/completions", + "resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.failedtip": "Please enter API path", + "resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.description": "Request timeout in milliseconds", + "resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.failedtip": "Please enter timeout", + "resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.description": "Maximum output token count", + "resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.failedtip": "Please enter maximum output token count" +} diff --git a/data/resource/aiboxresource_cv186x/i18n/resource.zh-CN.json b/data/resource/aiboxresource_cv186x/i18n/resource.zh-CN.json new file mode 100644 index 000000000..fe2c32f47 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/i18n/resource.zh-CN.json @@ -0,0 +1,3589 @@ +{ + "resource.action.10.aa_00001.ba9c7d80.actionname": "目标检测算法", + "resource.action.10.aa_00001.ba9c7d80.remark": "检测算法,需要选择算法模型", + "resource.action.10.aa_00003.674483de.actionname": "追踪算法", + "resource.action.10.aa_00003.674483de.remark": "需要人体追踪时放在检测算法后", + "resource.action.10.ba_00001.b62ab911.actionname": "视频解码", + "resource.action.10.ba_00001.b62ab911.remark": "视频解码", + "resource.action.10.ba_00002.a59e0a7e.actionname": "类别过滤", + "resource.action.10.ba_00002.a59e0a7e.remark": "对目标进行过滤", + "resource.action.10.ba_00003.2c1f8a2b.actionname": "灵敏度计算-计时", + "resource.action.10.ba_00003.2c1f8a2b.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.10.ba_00004.1478c130.actionname": "事件上报", + "resource.action.10.ba_00004.1478c130.remark": "事件上报", + "resource.action.11.aa_00001.487c1cf0.actionname": "目标检测算法", + "resource.action.11.aa_00001.487c1cf0.remark": "检测算法,需要选择算法模型", + "resource.action.11.aa_00002.c37b8e34.actionname": "目标分类算法", + "resource.action.11.aa_00002.c37b8e34.remark": "分类算法,需要选择一个分类模型", + "resource.action.11.aa_00003.c232a753.actionname": "追踪算法", + "resource.action.11.aa_00003.c232a753.remark": "需要人体追踪时放在检测算法后", + "resource.action.11.ba_00001.01fc708c.actionname": "视频解码", + "resource.action.11.ba_00001.01fc708c.remark": "视频解码", + "resource.action.11.ba_00002.5a2f08ca.actionname": "类别过滤", + "resource.action.11.ba_00002.5a2f08ca.remark": "对目标进行过滤", + "resource.action.11.ba_00003.b90c6769.actionname": "灵敏度计算-计时", + "resource.action.11.ba_00003.b90c6769.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.11.ba_00004.0f53b331.actionname": "事件上报", + "resource.action.11.ba_00004.0f53b331.remark": "事件上报", + "resource.action.11.ba_90001.e02bf44c.actionname": "目标判断", + "resource.action.11.ba_90001.e02bf44c.remark": "目标判断", + "resource.action.12.aa_00001.487c1cf0.actionname": "目标检测算法", + "resource.action.12.aa_00001.487c1cf0.remark": "检测算法,需要选择算法模型", + "resource.action.12.aa_00002.c37b8e34.actionname": "目标分类算法", + "resource.action.12.aa_00002.c37b8e34.remark": "分类算法,需要选择一个分类模型", + "resource.action.12.aa_00003.c232a753.actionname": "追踪算法", + "resource.action.12.aa_00003.c232a753.remark": "需要人体追踪时放在检测算法后", + "resource.action.12.ba_00001.94b4ca49.actionname": "视频解码", + "resource.action.12.ba_00001.94b4ca49.remark": "视频解码", + "resource.action.12.ba_00002.ccc378e3.actionname": "类别过滤", + "resource.action.12.ba_00002.ccc378e3.remark": "对目标进行过滤", + "resource.action.12.ba_00003.0d015957.actionname": "灵敏度计算-计时", + "resource.action.12.ba_00003.0d015957.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.12.ba_00004.0f53b331.actionname": "事件上报", + "resource.action.12.ba_00004.0f53b331.remark": "事件上报", + "resource.action.12.ba_90001.e02bf44c.actionname": "目标判断", + "resource.action.12.ba_90001.e02bf44c.remark": "目标判断", + "resource.action.13.aa_00001.e9173765.actionname": "目标检测算法", + "resource.action.13.aa_00001.e9173765.remark": "检测算法,需要选择算法模型", + "resource.action.13.aa_00003.9253e062.actionname": "追踪算法", + "resource.action.13.aa_00003.9253e062.remark": "需要人体追踪时放在检测算法后", + "resource.action.13.ba_00001.cc54dbba.actionname": "视频解码", + "resource.action.13.ba_00001.cc54dbba.remark": "视频解码", + "resource.action.13.ba_00004.a5c23881.actionname": "事件上报", + "resource.action.13.ba_00004.a5c23881.remark": "事件上报", + "resource.action.13.ba_00005.97085574.actionname": "区域告警判断", + "resource.action.13.ba_00005.97085574.remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "resource.action.15.aa_00001.83b4eb95.actionname": "目标检测算法", + "resource.action.15.aa_00001.83b4eb95.remark": "检测算法,需要选择算法模型", + "resource.action.15.aa_00002.a0333a67.actionname": "目标分类算法", + "resource.action.15.aa_00002.a0333a67.remark": "检测目标送分类算法,需要选择一个分类模型", + "resource.action.15.aa_00003.e1a418ab.actionname": "追踪算法", + "resource.action.15.aa_00003.e1a418ab.remark": "需要人体追踪时放在检测算法后", + "resource.action.15.ba_00001.3b63e86f.actionname": "视频解码", + "resource.action.15.ba_00001.3b63e86f.remark": "视频解码", + "resource.action.15.ba_00002.66fe69a4.actionname": "类别过滤", + "resource.action.15.ba_00002.66fe69a4.remark": "对目标进行过滤", + "resource.action.15.ba_00003.b4b02c33.actionname": "灵敏度计算-计时", + "resource.action.15.ba_00003.b4b02c33.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.15.ba_00004.4fb8d95e.actionname": "事件上报", + "resource.action.15.ba_00004.4fb8d95e.remark": "事件上报", + "resource.action.15.ba_90001.0d105731.actionname": "目标判断", + "resource.action.15.ba_90001.0d105731.remark": "目标判断", + "resource.action.15760.pa_00001.b7fe1598.actionname": "目标检测算法", + "resource.action.15760.pda_00002.ea49228d.actionname": "分割视觉大模型", + "resource.action.16.aa_00001.bc4f4b27.actionname": "目标检测算法", + "resource.action.16.aa_00001.bc4f4b27.remark": "检测算法,需要选择算法模型", + "resource.action.16.ba_00001.fdc4d661.actionname": "视频解码", + "resource.action.16.ba_00001.fdc4d661.remark": "视频解码", + "resource.action.16.ba_00002.72ec426d.actionname": "类别过滤", + "resource.action.16.ba_00002.72ec426d.remark": "对目标进行过滤", + "resource.action.16.ba_00004.f0c9e210.actionname": "事件上报", + "resource.action.16.ba_00004.f0c9e210.remark": "事件上报", + "resource.action.16.ba_00005.ab935f8a.actionname": "区域告警判断", + "resource.action.16.ba_00005.ab935f8a.remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "resource.action.1917.pa_00001.b7fe1598.actionname": "目标检测算法", + "resource.action.1917.pda_00002.ea49228d.actionname": "分割视觉大模型", + "resource.action.2.aa_00001.aaa71a68.actionname": "目标检测算法", + "resource.action.2.aa_00002.12564ac1.actionname": "目标分类算法", + "resource.action.2.aa_00003.6f833257.actionname": "追踪算法", + "resource.action.2.aa_00004.f225eab6.actionname": "关键点算法", + "resource.action.2.aa_00005.061f82a7.actionname": "特征提取算法", + "resource.action.2.ba_00001.4874a700.actionname": "视频解码", + "resource.action.2.ba_00002.5c3ea492.actionname": "类别筛选", + "resource.action.2.ba_00004.bdf891b9.actionname": "事件上报", + "resource.action.21283.aa_00001.4f8ba85c.actionname": "目标检测算法", + "resource.action.21283.ba_00001.f865585c.actionname": "视频解码", + "resource.action.21283.ba_00004.fd4e2090.actionname": "事件上报", + "resource.action.21283.ba_00005.308335b0.actionname": "区域告警判断", + "resource.action.21283.da_00002.e9ee0bc1.actionname": "分割视觉大模型", + "resource.action.22.aa_00001.487c1cf0.actionname": "目标检测算法", + "resource.action.22.aa_00001.487c1cf0.remark": "检测算法,需要选择算法模型", + "resource.action.22.aa_00002.c37b8e34.actionname": "目标分类算法", + "resource.action.22.aa_00002.c37b8e34.remark": "分类算法,需要选择一个分类模型", + "resource.action.22.aa_00003.c232a753.actionname": "追踪算法", + "resource.action.22.aa_00003.c232a753.remark": "需要人体追踪时放在检测算法后", + "resource.action.22.ba_00001.df5884a8.actionname": "视频解码", + "resource.action.22.ba_00001.df5884a8.remark": "视频解码", + "resource.action.22.ba_00002.ffac0ae1.actionname": "类别过滤", + "resource.action.22.ba_00002.ffac0ae1.remark": "对目标进行过滤", + "resource.action.22.ba_00003.181f8b5a.actionname": "灵敏度计算-计时", + "resource.action.22.ba_00003.181f8b5a.remark": "灵敏度计算", + "resource.action.22.ba_00004.0f53b331.actionname": "事件上报", + "resource.action.22.ba_00004.0f53b331.remark": "事件上报", + "resource.action.22.ba_90001.e02bf44c.actionname": "目标判断", + "resource.action.22.ba_90001.e02bf44c.remark": "目标判断", + "resource.action.28862.aa_00001.4f8ba85c.actionname": "目标检测算法", + "resource.action.28862.ba_00001.f865585c.actionname": "视频解码", + "resource.action.28862.ba_00004.fd4e2090.actionname": "事件上报", + "resource.action.28862.ba_00005.308335b0.actionname": "区域告警判断", + "resource.action.28862.da_00002.e9ee0bc1.actionname": "分割视觉大模型", + "resource.action.2935.pda_00001.0c349519.actionname": "检测视觉大模型", + "resource.action.3.aa_00001.e9173765.actionname": "目标检测算法", + "resource.action.3.aa_00001.e9173765.remark": "检测算法,需要选择算法模型", + "resource.action.3.aa_00003.9253e062.actionname": "追踪算法", + "resource.action.3.aa_00003.9253e062.remark": "需要人体追踪时放在检测算法后", + "resource.action.3.ba_00001.8d29063d.actionname": "视频解码", + "resource.action.3.ba_00001.8d29063d.remark": "视频解码", + "resource.action.3.ba_00002.fdd2a4cd.actionname": "类别过滤", + "resource.action.3.ba_00002.fdd2a4cd.remark": "对目标进行过滤", + "resource.action.3.ba_00004.a5c23881.actionname": "事件上报", + "resource.action.3.ba_00004.a5c23881.remark": "事件上报", + "resource.action.3.ba_00005.f21131a5.actionname": "区域告警判断", + "resource.action.3.ba_00005.f21131a5.remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "resource.action.32.aa_00001.1ffc7361.actionname": "目标检测算法", + "resource.action.32.aa_00001.1ffc7361.remark": "检测算法,需要选择算法模型", + "resource.action.32.aa_00002.40a88def.actionname": "目标分类算法", + "resource.action.32.aa_00002.40a88def.remark": "分类算法,需要选择一个分类模型", + "resource.action.32.aa_00003.0ca3cfc7.actionname": "追踪算法", + "resource.action.32.aa_00003.0ca3cfc7.remark": "需要人体追踪时放在检测算法后", + "resource.action.32.aa_00005.247f620f.actionname": "特征提取算法", + "resource.action.32.aa_00005.247f620f.remark": "支持人脸、人体、机物提取特征", + "resource.action.32.ba_00001.551596af.actionname": "视频解码", + "resource.action.32.ba_00001.551596af.remark": "视频解码", + "resource.action.32.ba_00002.6cdfc847.actionname": "类别过滤", + "resource.action.32.ba_00002.6cdfc847.remark": "对目标进行过滤", + "resource.action.32.ba_00003.22705515.actionname": "灵敏度计算-计时", + "resource.action.32.ba_00003.22705515.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.32.ba_00004.da078adb.actionname": "事件上报", + "resource.action.32.ba_00004.da078adb.remark": "事件上报", + "resource.action.34707.ba_00001.3c61bba4.actionname": "视频解码", + "resource.action.34707.ba_00004.7ec477cd.actionname": "事件上报", + "resource.action.34707.da_00003.4a05a806.actionname": "语言视觉大模型", + "resource.action.38873.pa_00001.0fa44adc.actionname": "目标检测算法", + "resource.action.5.aa_00001.bc4f4b27.actionname": "目标检测算法", + "resource.action.5.aa_00001.bc4f4b27.remark": "检测算法,需要选择算法模型", + "resource.action.5.ba_00001.991da170.actionname": "视频解码", + "resource.action.5.ba_00001.991da170.remark": "视频解码", + "resource.action.5.ba_00002.72ec426d.actionname": "类别过滤", + "resource.action.5.ba_00002.72ec426d.remark": "对目标进行过滤", + "resource.action.5.ba_00004.f0c9e210.actionname": "事件上报", + "resource.action.5.ba_00004.f0c9e210.remark": "事件上报", + "resource.action.5.ba_00005.ab935f8a.actionname": "区域告警判断", + "resource.action.5.ba_00005.ab935f8a.remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "resource.action.50813.pa_00001.27f515bd.actionname": "目标检测算法", + "resource.action.50813.pa_00002.27e33c9b.actionname": "目标分类算法", + "resource.action.51.aa_00001.e9173765.actionname": "目标检测算法", + "resource.action.51.aa_00001.e9173765.remark": "检测算法,需要选择算法模型", + "resource.action.51.ba_00001.4053a96d.actionname": "视频解码", + "resource.action.51.ba_00001.4053a96d.remark": "视频解码", + "resource.action.51.ba_00004.9de4af16.actionname": "事件上报", + "resource.action.51.ba_00004.9de4af16.remark": "事件上报", + "resource.action.51.ba_00005.667e48b6.actionname": "区域告警判断", + "resource.action.51.ba_00005.667e48b6.remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "resource.action.57.aa_00001.e9173765.actionname": "目标检测算法", + "resource.action.57.aa_00001.e9173765.remark": "检测算法,需要选择算法模型", + "resource.action.57.aa_00003.9253e062.actionname": "追踪算法", + "resource.action.57.aa_00003.9253e062.remark": "需要人体追踪时放在检测算法后", + "resource.action.57.ba_00001.251d0f78.actionname": "视频解码", + "resource.action.57.ba_00001.251d0f78.remark": "视频解码", + "resource.action.57.ba_00002.fdd2a4cd.actionname": "类别过滤", + "resource.action.57.ba_00002.fdd2a4cd.remark": "对目标进行过滤", + "resource.action.57.ba_00004.a5c23881.actionname": "事件上报", + "resource.action.57.ba_00004.a5c23881.remark": "事件上报", + "resource.action.57.ba_00005.f7750059.actionname": "区域告警判断", + "resource.action.57.ba_00005.f7750059.remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "resource.action.58.aa_00001.1ffc7361.actionname": "目标检测算法", + "resource.action.58.aa_00001.1ffc7361.remark": "检测算法,需要选择算法模型", + "resource.action.58.aa_00002.40a88def.actionname": "目标分类算法", + "resource.action.58.aa_00002.40a88def.remark": "分类算法,需要选择一个分类模型", + "resource.action.58.aa_00003.0ca3cfc7.actionname": "追踪算法", + "resource.action.58.aa_00003.0ca3cfc7.remark": "需要人体追踪时放在检测算法后", + "resource.action.58.aa_00005.247f620f.actionname": "特征提取算法", + "resource.action.58.aa_00005.247f620f.remark": "支持人脸、人体、机物提取特征", + "resource.action.58.ba_00001.03ef5862.actionname": "视频解码", + "resource.action.58.ba_00001.03ef5862.remark": "视频解码", + "resource.action.58.ba_00002.6cdfc847.actionname": "类别过滤", + "resource.action.58.ba_00002.6cdfc847.remark": "对目标进行过滤", + "resource.action.58.ba_00003.bc6d90f2.actionname": "灵敏度计算-计时", + "resource.action.58.ba_00003.bc6d90f2.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.58.ba_00004.da078adb.actionname": "事件上报", + "resource.action.58.ba_00004.da078adb.remark": "事件上报", + "resource.action.6.aa_00001.487c1cf0.actionname": "目标检测算法", + "resource.action.6.aa_00001.487c1cf0.remark": "检测算法,需要选择算法模型", + "resource.action.6.aa_00002.c37b8e34.actionname": "目标分类算法", + "resource.action.6.aa_00002.c37b8e34.remark": "分类算法,需要选择一个分类模型", + "resource.action.6.aa_00003.c232a753.actionname": "追踪算法", + "resource.action.6.aa_00003.c232a753.remark": "需要人体追踪时放在检测算法后", + "resource.action.6.ba_00001.e7eadb5a.actionname": "视频解码", + "resource.action.6.ba_00001.e7eadb5a.remark": "视频解码", + "resource.action.6.ba_00002.d56fc47d.actionname": "类别过滤", + "resource.action.6.ba_00002.d56fc47d.remark": "对目标进行过滤", + "resource.action.6.ba_00003.6dbede3b.actionname": "灵敏度计算-计时", + "resource.action.6.ba_00003.6dbede3b.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.6.ba_00004.0f53b331.actionname": "事件上报", + "resource.action.6.ba_00004.0f53b331.remark": "事件上报", + "resource.action.6.ba_90001.e02bf44c.actionname": "目标判断", + "resource.action.6.ba_90001.e02bf44c.remark": "目标判断", + "resource.action.60460.pda_00003.da2e695d.actionname": "语言视觉大模型", + "resource.action.65.aa_00001.487c1cf0.actionname": "目标检测算法", + "resource.action.65.aa_00001.487c1cf0.remark": "检测算法,需要选择算法模型", + "resource.action.65.aa_00002.c37b8e34.actionname": "目标分类算法", + "resource.action.65.aa_00002.c37b8e34.remark": "分类算法,需要选择一个分类模型", + "resource.action.65.aa_00003.c232a753.actionname": "追踪算法", + "resource.action.65.aa_00003.c232a753.remark": "需要人体追踪时放在检测算法后", + "resource.action.65.ba_00001.55e37370.actionname": "视频解码", + "resource.action.65.ba_00001.55e37370.remark": "视频解码", + "resource.action.65.ba_00002.d56fc47d.actionname": "类别过滤", + "resource.action.65.ba_00002.d56fc47d.remark": "对目标进行过滤", + "resource.action.65.ba_00003.b00198a1.actionname": "灵敏度计算-计时", + "resource.action.65.ba_00003.b00198a1.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.65.ba_00004.0f53b331.actionname": "事件上报", + "resource.action.65.ba_00004.0f53b331.remark": "事件上报", + "resource.action.65.ba_90001.e02bf44c.actionname": "目标判断", + "resource.action.65.ba_90001.e02bf44c.remark": "目标判断", + "resource.action.67093.ba_00001.3c61bba4.actionname": "视频解码", + "resource.action.67093.ba_00004.7ec477cd.actionname": "事件上报", + "resource.action.67093.da_00003.4a05a806.actionname": "语言视觉大模型", + "resource.action.7.aa_00001.ddd59411.actionname": "目标检测算法", + "resource.action.7.aa_00001.ddd59411.remark": "检测算法,需要选择算法模型", + "resource.action.7.aa_00003.10a89d8c.actionname": "追踪算法", + "resource.action.7.aa_00003.10a89d8c.remark": "需要人体追踪时放在检测算法后", + "resource.action.7.ba_00001.20a13b0a.actionname": "视频解码", + "resource.action.7.ba_00001.20a13b0a.remark": "视频解码", + "resource.action.7.ba_00002.498141de.actionname": "类别过滤", + "resource.action.7.ba_00002.498141de.remark": "对目标进行过滤", + "resource.action.7.ba_00004.2add29ef.actionname": "事件上报", + "resource.action.7.ba_00004.2add29ef.remark": "事件上报", + "resource.action.7.ba_00005.7d7b0fa3.actionname": "区域告警判断", + "resource.action.7.ba_00005.7d7b0fa3.remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "resource.action.7602.pa_00001.d8241567.actionname": "目标检测算法", + "resource.action.7602.pa_00002.2337df82.actionname": "目标分类算法", + "resource.action.7602.pa_00004.34499952.actionname": "关键点算法", + "resource.action.7602.pa_00005.c0d31881.actionname": "特征提取算法", + "resource.action.77380.pa_00001.27f515bd.actionname": "目标检测算法", + "resource.action.77380.pa_00002.27e33c9b.actionname": "目标分类算法", + "resource.action.80498.ba_00001.7d004992.actionname": "视频解码", + "resource.action.80498.ba_00004.051ea786.actionname": "事件上报", + "resource.action.80498.ba_00005.f53ea7bb.actionname": "区域告警判断", + "resource.action.80498.da_00001.9599adc7.actionname": "检测视觉大模型", + "resource.action.82819.pda_00001.f15b0a07.actionname": "检测视觉大模型", + "resource.action.82819.pda_00002.ff07761f.actionname": "分割视觉大模型", + "resource.action.83708.pa_00001.0fa44adc.actionname": "目标检测算法", + "resource.action.8533.ba_00001.7d004992.actionname": "视频解码", + "resource.action.8533.ba_00004.051ea786.actionname": "事件上报", + "resource.action.8533.ba_00005.f53ea7bb.actionname": "区域告警判断", + "resource.action.8533.da_00001.9599adc7.actionname": "检测视觉大模型", + "resource.action.89336.pda_00003.da2e695d.actionname": "语言视觉大模型", + "resource.action.9.aa_00001.ba9c7d80.actionname": "目标检测算法", + "resource.action.9.aa_00001.ba9c7d80.remark": "检测算法,需要选择算法模型", + "resource.action.9.ba_00001.eaf547cb.actionname": "视频解码", + "resource.action.9.ba_00001.eaf547cb.remark": "视频解码", + "resource.action.9.ba_00002.a59e0a7e.actionname": "类别过滤", + "resource.action.9.ba_00002.a59e0a7e.remark": "对目标进行过滤", + "resource.action.9.ba_00003.e37ea9c1.actionname": "灵敏度计算-计时", + "resource.action.9.ba_00003.e37ea9c1.remark": "用于计算检测时间内的命中数,如检测时间为3秒,取帧频率为3,灵敏度为5,当命中数≥3*3*(11-5)/10,则产生告警。有可能出现早于检测时间告警的情况。范围1-10,默认:5", + "resource.action.9.ba_00004.1478c130.actionname": "事件上报", + "resource.action.9.ba_00004.1478c130.remark": "事件上报", + "resource.action.91435.pda_00001.0c349519.actionname": "检测视觉大模型", + "resource.action.aa_00001.actionname": "目标检测算法", + "resource.action.aa_00001.remark": "检测算法,需要选择算法模型", + "resource.action.aa_00002.actionname": "目标分类算法", + "resource.action.aa_00002.remark": "检测目标送分类算法,需要选择一个分类模型", + "resource.action.aa_00003.actionname": "追踪算法", + "resource.action.aa_00003.remark": "需要人体追踪时放在检测算法后", + "resource.action.aa_00004.actionname": "关键点算法", + "resource.action.aa_00004.remark": "人脸landmark", + "resource.action.aa_00005.actionname": "特征提取算法", + "resource.action.aa_00005.remark": "支持人脸、人体、机物提取特征", + "resource.action.aa_00011.actionname": "文字识别", + "resource.action.aa_00011.remark": "识别关键点定位后的车牌文字,需要选择 OCR 模型", + "resource.action.ba_00001.actionname": "视频解码", + "resource.action.ba_00001.remark": "视频解码", + "resource.action.ba_00002.actionname": "类别筛选", + "resource.action.ba_00002.remark": "对目标进行筛选", + "resource.action.ba_00003.actionname": "灵敏度计算-计时", + "resource.action.ba_00003.remark": "灵敏度计算", + "resource.action.ba_00004.actionname": "事件上报", + "resource.action.ba_00004.remark": "事件上报", + "resource.action.ba_00005.actionname": "区域告警判断", + "resource.action.ba_00005.remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "resource.action.ba_10003.actionname": "灵敏度计算-计数", + "resource.action.ba_10003.remark": "灵敏度计算", + "resource.action.ba_90001.actionname": "目标判断", + "resource.action.ba_90001.remark": "目标判断", + "resource.action.da_00001.actionname": "检测视觉大模型", + "resource.action.da_00001.remark": "检测视觉大模型", + "resource.action.da_00002.actionname": "分割视觉大模型", + "resource.action.da_00002.remark": "分割视觉大模型", + "resource.action.da_00003.actionname": "语言视觉大模型", + "resource.action.da_00003.remark": "语言视觉大模型", + "resource.action.ip0001.componentname": "输入节点组件", + "resource.action.la_alarmdata_code.actionname": "算法告警数据", + "resource.action.la_alarmdata_code.remark": "配置通道中的算法告警数据,用于触发联动流程", + "resource.action.la_audiodevice_code.actionname": "网络音柱联动", + "resource.action.la_audiodevice_code.remark": "配置IP音设备进行告警播报", + "resource.action.lb0001.componentname": "配置组件", + "resource.action.on0001.componentname": "输出节点组件", + "resource.action.pa_00001.actionname": "目标检测算法", + "resource.action.pa_00001.remark": "检测算法,需要选择算法模型", + "resource.action.pa_00002.actionname": "目标分类算法", + "resource.action.pa_00002.remark": "检测目标送分类算法,需要选择一个分类模型", + "resource.action.pa_00005.actionname": "特征提取算法", + "resource.action.pa_00005.remark": "支持人脸、人体、机物提取特征", + "resource.action.pb_90001.actionname": "目标判断", + "resource.action.pb_90001.remark": "目标判断", + "resource.action.pda_00001.actionname": "检测视觉大模型", + "resource.action.pda_00001.remark": "检测视觉大模型(图片)", + "resource.action.pda_00002.actionname": "分割视觉大模型", + "resource.action.pda_00002.remark": "分割视觉大模型(图片)", + "resource.action.pda_00003.actionname": "语言视觉大模型", + "resource.action.pda_00003.remark": "语言视觉大模型(图片)", + "resource.action.pr0001.componentname": "resize组件", + "resource.action.pr0002.componentname": "normalize组件", + "resource.action.pr0003.componentname": "crop组件", + "resource.action.pr0004.componentname": "expand组件", + "resource.action.pr0005.componentname": "affine_crop组件", + "resource.action.pr0006.componentname": "sequence组件", + "resource.action.pr0007.componentname": "combine_image组件", + "resource.action.pr0008.componentname": "dino_encode组件", + "resource.action.pt0001.componentname": "yolo_postprocess组件", + "resource.action.pt0002.componentname": "yolo_npu_postprocess组件", + "resource.action.pt0003.componentname": "yolov8_postprocess组件", + "resource.action.pt0004.componentname": "sum组件", + "resource.action.pt0005.componentname": "arg_max组件", + "resource.action.pt0006.componentname": "split组件", + "resource.action.pt0007.componentname": "split_arg_max组件", + "resource.action.pt0008.componentname": "dino_decode组件", + "resource.action.pt0009.componentname": "yolo_e2e_postprocess组件", + "resource.algorithm.10.algorithmname": "火焰检测", + "resource.algorithm.10.remark": "应用火焰检测算法,对检测区域内的火焰超过阈值时间的事件进行告警。\n仅支持白天场景,摄像机转红外图像后,将自动停止分析。", + "resource.algorithm.11.algorithmname": "吸烟检测", + "resource.algorithm.11.remark": "应用行人检测跟踪算法、吸烟分类算法,对进入检测区域的行人进行吸烟检测,对超过阈值的行人进行吸烟告警。吸烟算法,对吸烟姿态、烟进行同时分析。", + "resource.algorithm.12.algorithmname": "打电话检测", + "resource.algorithm.12.remark": "应用行人检测跟踪算法、打电话分类算法,对进入检测区域的行人进行打电话检测,对超过阈值时间的行人进行打电话告警。打电话算法,对打电话姿态、电话进行同时分析。", + "resource.algorithm.13.algorithmname": "人流量统计", + "resource.algorithm.13.remark": "应用头肩检测算法,对经过规则线的进出人数进行统计,并按时间粒度保存。(最小时间粒度小时)", + "resource.algorithm.15.algorithmname": "未戴安全帽", + "resource.algorithm.15.remark": "应用头肩检测、跟踪算法、安全帽分类算法,进行人员是否带安全帽的检测,并进行未带安全帽的预警。安全帽颜色有:红、蓝、黄、白、黑。", + "resource.algorithm.15760.algorithmname": "分割大模型", + "resource.algorithm.16.algorithmname": "离岗检测", + "resource.algorithm.16.remark": "应用头肩检测或人体检测算法,对区域内人员数量进行计数,如少于相应的人数且时间超过设定的阈值,则进行告警。", + "resource.algorithm.1917.algorithmname": "图片分割大模型", + "resource.algorithm.1917.remark": "图片分割大模型", + "resource.algorithm.2.algorithmname": "人脸比对", + "resource.algorithm.2.remark": "人脸1比N比对,主要用于重点关注人员布控、陌生人提醒、人员久居未出、久出未归分析。", + "resource.algorithm.21283.algorithmname": "视觉分割大模型分析", + "resource.algorithm.22.algorithmname": "玩手机检测", + "resource.algorithm.22.remark": "应用行人检测跟踪算法、玩手机分类算法,对进入检测区域的行人进行玩手机检测,对超过阈值时间的行人进行玩手机告警。玩手机算法,对玩手机姿态、电话进行同时分析。", + "resource.algorithm.28862.algorithmname": "视觉分割大模型", + "resource.algorithm.28862.remark": "视觉分割大模型", + "resource.algorithm.2935.algorithmname": "检测大模型", + "resource.algorithm.029.algorithmname": "车牌识别", + "resource.algorithm.029.process.aa_00001.remark": "检测视频中的车牌目标。", + "resource.algorithm.029.process.aa_00004.remark": "定位车牌左上、左下、右下、右上四个关键点。", + "resource.algorithm.029.process.ba_00004.remark": "以车辆属性格式上报车牌识别事件。", + "resource.algorithm.029.remark": "检测视频中的车牌,提取四点关键点并进行文字识别,以车辆属性格式上报告警。", + "resource.param.029.029.aiparam_car_plate_confidence.description": "车牌置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.029.029.aiparam_car_plate_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.029.029.aiparam_car_plate_confidence.name": "车牌置信度", + "resource.param.029.029.alarmproperty.name": "车辆属性", + "resource.param.029.029.name.description": "区域名称:必填,限制32字符。", + "resource.param.029.029.name.failedtip": "请输入长度小于32位且不包含空格的字符串。", + "resource.param.029.029.name.name": "区域名称", + "resource.param.029.029.param_alarminterval.description": "两次车牌告警的最小间隔,范围:1~36000秒。", + "resource.param.029.029.param_alarminterval.failedtip": "请输入1-36000的整数。", + "resource.param.029.029.param_alarminterval.name": "告警时间间隔(秒)", + "resource.algorithm.3.algorithmname": "区域入侵", + "resource.algorithm.3.remark": "在视频中设定检测区域,对行人进入该区域超过一定时间的事件进行检测。行人由检测框外到内的过程进行检测、跟踪。", + "resource.algorithm.32.algorithmname": "未穿反光衣", + "resource.algorithm.32.remark": "工地检测人员是否穿戴反光衣,对于未穿人员进行告警提醒", + "resource.algorithm.34707.algorithmname": "视觉语言大模型分析", + "resource.algorithm.38873.algorithmname": "检测类算法", + "resource.algorithm.5.algorithmname": "人员聚集", + "resource.algorithm.5.remark": "应用头肩或人体检测算法,对进入检测区域的行人进行计数,对超过阈值人数的事件进行告警。", + "resource.algorithm.50813.algorithmname": "图片检测分类任务", + "resource.algorithm.50813.remark": "图片检测分类任务", + "resource.algorithm.51.algorithmname": "区域人数统计", + "resource.algorithm.51.remark": "应用头肩检测算法,对检测框内的人数进行统计实时统计。", + "resource.algorithm.57.algorithmname": "绊线检测", + "resource.algorithm.57.remark": "应用行人跟踪算法对人员绊线行为进行告警。可设置单向、双向绊线检测。", + "resource.algorithm.58.algorithmname": "未穿工服", + "resource.algorithm.58.remark": "应用人体识别算法对工服库内未命中的人体进行报警。可基于客户场景进行工服库的自定义。支持多种工服样式、颜色的检测。", + "resource.algorithm.6.algorithmname": "人员跌倒", + "resource.algorithm.6.remark": "应用行人检测、跟踪算法,对进入检测区域的行人进行跌倒检测,对超过阈值的行人进行跌倒告警", + "resource.algorithm.60460.algorithmname": "图片语言视觉大模型", + "resource.algorithm.60460.remark": "图片语言视觉大模型", + "resource.algorithm.65.algorithmname": "睡岗检测", + "resource.algorithm.65.remark": "应用人体检测、跟踪、睡岗分类算法,对人员的睡岗行为进行告警。支持卧睡、趴睡2种睡岗行为", + "resource.algorithm.67093.algorithmname": "视觉语言大模型", + "resource.algorithm.67093.remark": "视觉语言大模型", + "resource.algorithm.7.algorithmname": "车辆违停", + "resource.algorithm.7.remark": "应用机动车检测、跟踪算法,对进入检测区域的机动车进行检测,对超过阈值时间的机动车进行告警。\n机动车:支持三轮电动车、摩托车(带排气管)、轿车、SUV、卡车。\n应用非机动车检测算法,对进入检测区域的非机动车进行检测,对超过阈值时间的非机动车进行告警。\n非机动车:支持两轮电动车、自行车、人力三轮车", + "resource.algorithm.7602.algorithmname": "人脸识别算法", + "resource.algorithm.7602.remark": "人脸特征值提取", + "resource.algorithm.77380.algorithmname": "检测后分类算法", + "resource.algorithm.80498.algorithmname": "视觉检测大模型", + "resource.algorithm.80498.remark": "视觉检测大模型", + "resource.algorithm.82819.algorithmname": "检测后分割算法", + "resource.algorithm.83708.algorithmname": "图片检测任务", + "resource.algorithm.83708.remark": "图片类检测任务", + "resource.algorithm.8533.algorithmname": "视觉检测大模型分析", + "resource.algorithm.89336.algorithmname": "视觉语言大模型", + "resource.algorithm.9.algorithmname": "烟雾检测", + "resource.algorithm.9.remark": "应用烟雾检测算法,对检测区域内的烟雾超过阈值时间的事件进行告警。\n仅支持白天场景,摄像机转红外图像后,将自动停止分析。", + "resource.algorithm.91435.algorithmname": "图片检测大模型", + "resource.algorithm.91435.remark": "图片检测大模型", + "resource.label.1000001.face.1000001.0.face.namecn": "人脸", + "resource.label.1000001.name": "RGB人脸检测", + "resource.label.1000005.name": "RGB人脸识别", + "resource.label.1000010.mask.1000010.0.mask.namecn": "戴口罩", + "resource.label.1000010.name": "口罩属性识别", + "resource.label.1000010.normal.1000010.1.normal.namecn": "未戴口罩", + "resource.label.1000012.faceblur0.1000012.0.faceblur0.namecn": "人脸模糊1", + "resource.label.1000012.faceblur1.1000012.1.faceblur1.namecn": "人脸模糊2", + "resource.label.1000012.faceblur2.1000012.2.faceblur2.namecn": "人脸模糊3", + "resource.label.1000012.frontface.1000012.3.frontface.namecn": "正面人脸", + "resource.label.1000012.fullface.1000012.4.fullface.namecn": "完整人脸", + "resource.label.1000012.name": "人脸质量评估", + "resource.label.1000012.slantedface.1000012.5.slantedface.namecn": "部分倾斜人脸", + "resource.label.1000016.name": "人脸关键点", + "resource.label.1001001.headshoulder.1001001.0.headshoulder.namecn": "头部肩部", + "resource.label.1001001.name": "头肩检测", + "resource.label.1001003.description": "人体检测", + "resource.label.1001003.name": "行人检测", + "resource.label.1001003.pedestrian.1001003.0.pedestrian.namecn": "行人", + "resource.label.1001005.apron_long.1001005.62.apron_long.namecn": "长围裙", + "resource.label.1001005.apron_none.1001005.63.apron_none.namecn": "无围裙", + "resource.label.1001005.apron_short.1001005.64.apron_short.namecn": "短围裙", + "resource.label.1001005.apron_uncertain.1001005.65.apron_uncertain.namecn": "不确定有围裙", + "resource.label.1001005.bag_handling_carried_suitcase.1001005.44.bag_handling_carried_suitcase.namecn": "包的处理-拎手提箱", + "resource.label.1001005.bag_handling_crossbody_bag.1001005.45.bag_handling_crossbody_bag.namecn": "包的处理-斜挎包", + "resource.label.1001005.bag_handling_double_shoulder_backpack.1001005.46.bag_handling_double_shoulder_backpack.namecn": "包的处理-双肩背包", + "resource.label.1001005.bag_handling_luggage.1001005.47.bag_handling_luggage.namecn": "包的处理-行李箱", + "resource.label.1001005.bag_handling_none.1001005.48.bag_handling_none.namecn": "包的处理-无", + "resource.label.1001005.bag_handling_plastic_bag_shopping_bag.1001005.49.bag_handling_plastic_bag_shopping_bag.namecn": "包的处理-塑料袋/购物袋", + "resource.label.1001005.bag_handling_shopping_cart.1001005.50.bag_handling_shopping_cart.namecn": "包的处理-购物车", + "resource.label.1001005.bag_handling_single_shoulder_backpack.1001005.51.bag_handling_single_shoulder_backpack.namecn": "包的处理-单肩背包", + "resource.label.1001005.bag_handling_stroller_carrying_a_child.1001005.52.bag_handling_stroller_carrying_a_child.namecn": "包的处理-推婴儿车/抱小孩", + "resource.label.1001005.bag_handling_umbrella.1001005.53.bag_handling_umbrella.namecn": "包的处理-伞", + "resource.label.1001005.bag_handling_uncertain.1001005.54.bag_handling_uncertain.namecn": "包的处理-不确定", + "resource.label.1001005.bag_handling_waist_pack.1001005.55.bag_handling_waist_pack.namecn": "包的处理-腰包", + "resource.label.1001005.bottom_color_black.1001005.21.bottom_color_black.namecn": "下装颜色-黑色", + "resource.label.1001005.bottom_color_blue.1001005.22.bottom_color_blue.namecn": "下装颜色-蓝色", + "resource.label.1001005.bottom_color_brown_camel.1001005.23.bottom_color_brown_camel.namecn": "下装颜色-棕色/骆驼色", + "resource.label.1001005.bottom_color_floral.1001005.24.bottom_color_floral.namecn": "下装颜色-花色", + "resource.label.1001005.bottom_color_gray.1001005.25.bottom_color_gray.namecn": "下装颜色-灰色", + "resource.label.1001005.bottom_color_green.1001005.26.bottom_color_green.namecn": "下装颜色-绿色", + "resource.label.1001005.bottom_color_nude_flesh.1001005.27.bottom_color_nude_flesh.namecn": "下装颜色-裸色/肤色", + "resource.label.1001005.bottom_color_orange.1001005.28.bottom_color_orange.namecn": "下装颜色-橙色", + "resource.label.1001005.bottom_color_pink.1001005.29.bottom_color_pink.namecn": "下装颜色-粉色", + "resource.label.1001005.bottom_color_polka_dot.1001005.30.bottom_color_polka_dot.namecn": "下装颜色-波点", + "resource.label.1001005.bottom_color_purple.1001005.31.bottom_color_purple.namecn": "下装颜色-紫色", + "resource.label.1001005.bottom_color_red.1001005.32.bottom_color_red.namecn": "下装颜色-红色", + "resource.label.1001005.bottom_color_striped.1001005.33.bottom_color_striped.namecn": "下装颜色-条纹", + "resource.label.1001005.bottom_color_uncertain.1001005.34.bottom_color_uncertain.namecn": "下装颜色-不确定", + "resource.label.1001005.bottom_color_white.1001005.35.bottom_color_white.namecn": "下装颜色-白色", + "resource.label.1001005.bottom_color_yellow.1001005.36.bottom_color_yellow.namecn": "下装颜色-黄色", + "resource.label.1001005.cycling.1001005.56.cycling.namecn": "骑车_", + "resource.label.1001005.hat_none.1001005.57.hat_none.namecn": "无帽子", + "resource.label.1001005.hat_uncertain.1001005.58.hat_uncertain.namecn": "不确定有帽子", + "resource.label.1001005.helmet.1001005.59.helmet.namecn": "头盔", + "resource.label.1001005.lower_garment_length_long_pants.1001005.37.lower_garment_length_long_pants.namecn": "下装长度-长裤", + "resource.label.1001005.lower_garment_length_long_skirt.1001005.38.lower_garment_length_long_skirt.namecn": "下装长度-长裙", + "resource.label.1001005.lower_garment_length_mid_length_pants.1001005.39.lower_garment_length_mid_length_pants.namecn": "下装长度-中长裤", + "resource.label.1001005.lower_garment_length_mid_length_skirt.1001005.40.lower_garment_length_mid_length_skirt.namecn": "下装长度-中长裙", + "resource.label.1001005.lower_garment_length_short_skirt.1001005.41.lower_garment_length_short_skirt.namecn": "下装长度-短裙", + "resource.label.1001005.lower_garment_length_shorts.1001005.42.lower_garment_length_shorts.namecn": "下装长度-短裤", + "resource.label.1001005.lower_garment_length_uncertain.1001005.43.lower_garment_length_uncertain.namecn": "下装长度-不确定", + "resource.label.1001005.name": "行人属性识别、厨师衣帽检测", + "resource.label.1001005.ordinary_hat.1001005.60.ordinary_hat.namecn": "普通帽子", + "resource.label.1001005.safety_helmet.1001005.61.safety_helmet.namecn": "安全帽", + "resource.label.1001005.top_color_black.1001005.5.top_color_black.namecn": "上装颜色-黑色", + "resource.label.1001005.top_color_blue.1001005.6.top_color_blue.namecn": "上装颜色-蓝色", + "resource.label.1001005.top_color_brown_camel.1001005.7.top_color_brown_camel.namecn": "上装颜色-棕色/骆驼色", + "resource.label.1001005.top_color_floral.1001005.8.top_color_floral.namecn": "上装颜色-花色", + "resource.label.1001005.top_color_gray.1001005.9.top_color_gray.namecn": "上装颜色-灰色", + "resource.label.1001005.top_color_green.1001005.10.top_color_green.namecn": "上装颜色-绿色", + "resource.label.1001005.top_color_nude_flesh.1001005.11.top_color_nude_flesh.namecn": "上装颜色-裸色/肤色", + "resource.label.1001005.top_color_orange.1001005.12.top_color_orange.namecn": "上装颜色-橙色", + "resource.label.1001005.top_color_pink.1001005.13.top_color_pink.namecn": "上装颜色-粉色", + "resource.label.1001005.top_color_polka_dot.1001005.14.top_color_polka_dot.namecn": "上装颜色-波点", + "resource.label.1001005.top_color_purple.1001005.15.top_color_purple.namecn": "上装颜色-紫色", + "resource.label.1001005.top_color_red.1001005.16.top_color_red.namecn": "上装颜色-红色", + "resource.label.1001005.top_color_striped.1001005.17.top_color_striped.namecn": "上装颜色-条纹", + "resource.label.1001005.top_color_uncertain.1001005.18.top_color_uncertain.namecn": "上装颜色-不确定", + "resource.label.1001005.top_color_white.1001005.19.top_color_white.namecn": "上装颜色-白色", + "resource.label.1001005.top_color_yellow.1001005.20.top_color_yellow.namecn": "上装颜色-黄色", + "resource.label.1001005.upper_garment_sleeve_length_long_sleeves.1001005.0.upper_garment_sleeve_length_long_sleeves.namecn": "上装袖长-长袖", + "resource.label.1001005.upper_garment_sleeve_length_mid_length_sleeves.1001005.1.upper_garment_sleeve_length_mid_length_sleeves.namecn": "上装袖长-中长袖", + "resource.label.1001005.upper_garment_sleeve_length_short_sleeves.1001005.2.upper_garment_sleeve_length_short_sleeves.namecn": "上装袖长-短袖", + "resource.label.1001005.upper_garment_sleeve_length_sleeveless_spaghetti_straps_bandeau.1001005.3.upper_garment_sleeve_length_sleeveless_spaghetti_straps_bandeau.namecn": "上装袖长-无袖/吊带/百褶裙", + "resource.label.1001005.upper_garment_sleeve_length_uncertain.1001005.4.upper_garment_sleeve_length_uncertain.namecn": "上装袖长-不确定", + "resource.label.1001007.name": "ReID特征", + "resource.label.1001007.pedestrianrecognition.1001007.0.pedestrianrecognition.namecn": "行人特征", + "resource.label.1001008.name": "行人质量", + "resource.label.1001008.quality0.1001008.0.quality0.namecn": "行人质量0", + "resource.label.1001008.quality1.1001008.1.quality1.namecn": "行人质量1", + "resource.label.1001008.quality2.1001008.2.quality2.namecn": "行人质量2", + "resource.label.1001008.quality3.1001008.3.quality3.namecn": "行人质量3", + "resource.label.1001008.quality4.1001008.4.quality4.namecn": "行人质量4", + "resource.label.1001008.quality5.1001008.5.quality5.namecn": "行人质量5", + "resource.label.1001010.name": "睡岗", + "resource.label.1001010.pedsleepliedown.1001010.0.pedsleepliedown.namecn": "行人睡姿-躺着睡", + "resource.label.1001010.pedsleepstomach.1001010.1.pedsleepstomach.namecn": "行人睡姿-趴睡", + "resource.label.2000001.name": "车辆检测", + "resource.label.2000001.nonmotorvehicle.2000001.0.nonmotorvehicle.namecn": "非机动车", + "resource.label.2000001.pedestrian.2000001.1.pedestrian.namecn": "行人", + "resource.label.2000001.vehicle.2000001.2.vehicle.namecn": "车辆", + "resource.label.2000011.back.2000011.23.back.namecn": "背面", + "resource.label.2000011.black.2000011.11.black.namecn": "黑色", + "resource.label.2000011.blue.2000011.12.blue.namecn": "蓝色", + "resource.label.2000011.brown.2000011.13.brown.namecn": "褐色", + "resource.label.2000011.color_poorquality.2000011.22.color_poorquality.namecn": "颜色_质量不好", + "resource.label.2000011.direction_poorquality.2000011.26.direction_poorquality.namecn": "朝向_质量不好", + "resource.label.2000011.front.2000011.24.front.namecn": "前面", + "resource.label.2000011.green.2000011.19.green.namecn": "绿色", + "resource.label.2000011.mixcolor.2000011.20.mixcolor.namecn": "混色", + "resource.label.2000011.motorcycle.2000011.2.motorcycle.namecn": "摩托车", + "resource.label.2000011.name": "车辆属性", + "resource.label.2000011.orange.2000011.17.orange.namecn": "橘色", + "resource.label.2000011.othercar.2000011.4.othercar.namecn": "其他车辆", + "resource.label.2000011.purple.2000011.15.purple.namecn": "紫色", + "resource.label.2000011.red.2000011.16.red.namecn": "红色", + "resource.label.2000011.side.2000011.25.side.namecn": "侧面", + "resource.label.2000011.silver.2000011.21.silver.namecn": "银色", + "resource.label.2000011.type_poorquality.2000011.8.type_poorquality.namecn": "质量不好", + "resource.label.2000011.white.2000011.14.white.namecn": "白色", + "resource.label.2000011.yellow.2000011.18.yellow.namecn": "黄色", + "resource.label.2000020.name": "电动车进电梯分类", + "resource.label.2001002.hatless.2001002.0.hatless.namecn": "无帽", + "resource.label.2001002.name": "头肩安全帽检测", + "resource.label.2001002.normalhat.2001002.1.normalhat.namecn": "普通帽子", + "resource.label.2001002.pedhelmet.2001002.2.pedhelmet.namecn": "头盔", + "resource.label.2001002.pedsafehelmet.2001002.3.pedsafehelmet.namecn": "安全帽", + "resource.label.2001002.unsure.2001002.4.unsure.namecn": "不确定", + "resource.label.2001003.fire.2001003.0.fire.namecn": "火焰", + "resource.label.2001003.name": "火焰、烟雾检测", + "resource.label.2001003.smog.2001003.1.smog.namecn": "烟雾", + "resource.label.2001008.name": "垃圾堆检测", + "resource.label.2001008.rubbishdump.2001008.0.rubbishdump.namecn": "垃圾堆", + "resource.label.2001036.hatless.2001036.0.hatless.namecn": "无帽", + "resource.label.2001036.name": "行人安全帽检测", + "resource.label.2001036.normalhat.2001036.1.normalhat.namecn": "普通帽子", + "resource.label.2001036.pedhelmet.2001036.2.pedhelmet.namecn": "头盔", + "resource.label.2001036.pedsafehelmet.2001036.3.pedsafehelmet.namecn": "安全帽", + "resource.label.2001036.unsure.2001036.4.unsure.namecn": "不确定", + "resource.label.2002008.name": "跌倒", + "resource.label.2002008.normal.2002008.0.normal.namecn": "正常", + "resource.label.2002008.pedfalldown.2002008.1.pedfalldown.namecn": "跌倒", + "resource.label.2002011.name": "打电话、玩手机和吸烟检测", + "resource.label.2002011.obanswer.2002011.4.obanswer.namecn": "不明显接电话(不建议使用)", + "resource.label.2002011.obplay.2002011.5.obplay.namecn": "不明显玩手机(不建议使用)", + "resource.label.2002011.obsmoke.2002011.6.obsmoke.namecn": "不明显吸烟(不建议使用)", + "resource.label.2002011.passenger.2002011.3.passenger.namecn": "行人(不建议使用)", + "resource.label.2002011.pedphoneanswer.2002011.0.pedphoneanswer.namecn": "打电话", + "resource.label.2002011.pedphoneplay.2002011.1.pedphoneplay.namecn": "玩手机", + "resource.label.2002011.pedsmoking.2002011.2.pedsmoking.namecn": "抽烟", + "resource.label.2180145.description": "yolov8检测模型", + "resource.label.3000003.mouse.3000003.0.mouse.namecn": "厨房老鼠", + "resource.label.3000003.name": "厨房活体检测(重点老鼠)", + "resource.label.9183416.description": "GrounddingDIno检测大模型", + "resource.label.9233591.description": "SAM2分割大模型", + "resource.model.4000001.yolo26_det.name": "yolo26检测", + "resource.model.4000001.yolov11_det.name": "yolov8检测", + "resource.model.4000001.yolov12_det.name": "yolov8检测", + "resource.model.4000001.yolov8_det.name": "yolov8检测", + "resource.model.4000001.yolov9_det.name": "yolov8检测", + "resource.model.4000002.classify.name": "yolov8分类", + "resource.option.10.10.aiparam_fire_detpostion.0.options_name": "底部", + "resource.option.10.10.aiparam_fire_detpostion.1.options_name": "中心", + "resource.option.10.10.aiparam_fire_detpostion.2.options_name": "顶部", + "resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.0.options_name": "底部", + "resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.1.options_name": "中心", + "resource.option.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.2.options_name": "顶部", + "resource.option.11.11.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.11.11.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.11.11.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.12.12.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.12.12.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.12.12.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.13.13.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.13.13.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.13.13.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.13.13.param_areacalcdurationtimetype.1.options_name": "毫秒", + "resource.option.13.13.param_areacalcdurationtimetype.1000.options_name": "秒", + "resource.option.13.13.param_areacalcdurationtimetype.3600000.options_name": "小时", + "resource.option.13.13.param_areacalcdurationtimetype.60000.options_name": "分钟", + "resource.option.13.13.param_targetcalctype.0.options_name": "瞬时(区域人数统计)", + "resource.option.13.13.param_targetcalctype.1.options_name": "周期总人数 (人流量)", + "resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.1.options_name": "毫秒", + "resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.1000.options_name": "秒", + "resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.3600000.options_name": "小时", + "resource.option.13.ba_00005.97085574.param_areacalcdurationtimetype.60000.options_name": "分钟", + "resource.option.13.ba_00005.97085574.param_targetcalctype.0.options_name": "瞬时(区域人数统计)", + "resource.option.13.ba_00005.97085574.param_targetcalctype.1.options_name": "周期总人数 (人流量)", + "resource.option.15.15.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.15.15.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.15.15.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.16.16.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.16.16.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.16.16.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.16.16.param_arealimitdurationtimetype.1.options_name": "毫秒", + "resource.option.16.16.param_arealimitdurationtimetype.1000.options_name": "秒", + "resource.option.16.16.param_arealimitdurationtimetype.3600000.options_name": "小时", + "resource.option.16.16.param_arealimitdurationtimetype.60000.options_name": "分钟", + "resource.option.16.16.param_arealimittargettype.0.options_name": "小于目标数告警", + "resource.option.16.16.param_arealimittargettype.1.options_name": "大于目标数告警", + "resource.option.16.16.param_arealimittargettype.2.options_name": "小于等于目标数告警", + "resource.option.16.16.param_arealimittargettype.3.options_name": "大于等于目标数告警", + "resource.option.16.16.param_arealimittargettype.4.options_name": "等于目标数告警", + "resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.1.options_name": "毫秒", + "resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.1000.options_name": "秒", + "resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.3600000.options_name": "小时", + "resource.option.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.60000.options_name": "分钟", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.0.options_name": "小于目标数告警", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.1.options_name": "大于目标数告警", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.2.options_name": "小于等于目标数告警", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.3.options_name": "大于等于目标数告警", + "resource.option.16.ba_00005.ab935f8a.param_arealimittargettype.4.options_name": "等于目标数告警", + "resource.option.1917.1917.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.1917.1917.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.1917.1917.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.2.2.aiparam_face_detpostion.0.options_name": "底部", + "resource.option.2.2.aiparam_face_detpostion.1.options_name": "中心", + "resource.option.2.2.aiparam_face_detpostion.2.options_name": "顶部", + "resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.0.options_name": "底部", + "resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.1.options_name": "中心", + "resource.option.2.aa_00001.aaa71a68.aiparam_face_detpostion.2.options_name": "顶部", + "resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.22.22.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.22.22.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.22.22.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.28862.28862.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.28862.28862.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.28862.28862.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.3.3.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.3.3.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.3.3.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.3.3.param_areadurationtimetype.1.options_name": "毫秒", + "resource.option.3.3.param_areadurationtimetype.1000.options_name": "秒", + "resource.option.3.3.param_areadurationtimetype.3600000.options_name": "小时", + "resource.option.3.3.param_areadurationtimetype.60000.options_name": "分钟", + "resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.1.options_name": "毫秒", + "resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.1000.options_name": "秒", + "resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.3600000.options_name": "小时", + "resource.option.3.ba_00005.f21131a5.param_areadurationtimetype.60000.options_name": "分钟", + "resource.option.32.32.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.32.32.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.32.32.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.38873.38873.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.38873.38873.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.38873.38873.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.0.options_name": "底部", + "resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.1.options_name": "中心", + "resource.option.38873.pa_00001.0fa44adc.aiparam_face_detpostion.2.options_name": "顶部", + "resource.option.5.5.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.5.5.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.5.5.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.5.5.param_arealimitdurationtimetype.1.options_name": "毫秒", + "resource.option.5.5.param_arealimitdurationtimetype.1000.options_name": "秒", + "resource.option.5.5.param_arealimitdurationtimetype.3600000.options_name": "小时", + "resource.option.5.5.param_arealimitdurationtimetype.60000.options_name": "分钟", + "resource.option.5.5.param_arealimittargettype.0.options_name": "小于目标数告警", + "resource.option.5.5.param_arealimittargettype.1.options_name": "大于目标数告警", + "resource.option.5.5.param_arealimittargettype.2.options_name": "小于等于目标数告警", + "resource.option.5.5.param_arealimittargettype.3.options_name": "大于等于目标数告警", + "resource.option.5.5.param_arealimittargettype.4.options_name": "等于目标数告警", + "resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.1.options_name": "毫秒", + "resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.1000.options_name": "秒", + "resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.3600000.options_name": "小时", + "resource.option.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.60000.options_name": "分钟", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.0.options_name": "小于目标数告警", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.1.options_name": "大于目标数告警", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.2.options_name": "小于等于目标数告警", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.3.options_name": "大于等于目标数告警", + "resource.option.5.ba_00005.ab935f8a.param_arealimittargettype.4.options_name": "等于目标数告警", + "resource.option.50813.50813.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.50813.50813.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.50813.50813.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.51.51.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.51.51.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.51.51.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.51.51.param_areacalcdurationtimetype.1.options_name": "毫秒", + "resource.option.51.51.param_areacalcdurationtimetype.1000.options_name": "秒", + "resource.option.51.51.param_areacalcdurationtimetype.3600000.options_name": "小时", + "resource.option.51.51.param_areacalcdurationtimetype.60000.options_name": "分钟", + "resource.option.51.51.param_targetcalctype.0.options_name": "瞬时(区域人数统计)", + "resource.option.51.51.param_targetcalctype.1.options_name": "周期总人数 (人流量)", + "resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.1.options_name": "毫秒", + "resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.1000.options_name": "秒", + "resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.3600000.options_name": "小时", + "resource.option.51.ba_00005.667e48b6.param_areacalcdurationtimetype.60000.options_name": "分钟", + "resource.option.51.ba_00005.667e48b6.param_targetcalctype.0.options_name": "瞬时(区域人数统计)", + "resource.option.51.ba_00005.667e48b6.param_targetcalctype.1.options_name": "周期总人数 (人流量)", + "resource.option.57.57.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.57.57.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.57.57.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.57.57.param_trippingwiretype.1.options_name": "单线", + "resource.option.57.57.param_trippingwiretype.2.options_name": "双线", + "resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.57.ba_00005.f7750059.param_trippingwiretype.1.options_name": "单线", + "resource.option.57.ba_00005.f7750059.param_trippingwiretype.2.options_name": "双线", + "resource.option.58.58.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.58.58.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.58.58.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.6.6.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.6.6.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.6.6.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.65.65.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.65.65.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.65.65.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.7.7.aiparam_nonmotorvehicle_detpostion.0.options_name": "底部", + "resource.option.7.7.aiparam_nonmotorvehicle_detpostion.1.options_name": "中心", + "resource.option.7.7.aiparam_nonmotorvehicle_detpostion.2.options_name": "顶部", + "resource.option.7.7.aiparam_vehicle_detpostion.0.options_name": "底部", + "resource.option.7.7.aiparam_vehicle_detpostion.1.options_name": "中心", + "resource.option.7.7.aiparam_vehicle_detpostion.2.options_name": "顶部", + "resource.option.7.7.param_areadurationtimetype.1.options_name": "毫秒", + "resource.option.7.7.param_areadurationtimetype.1000.options_name": "秒", + "resource.option.7.7.param_areadurationtimetype.3600000.options_name": "小时", + "resource.option.7.7.param_areadurationtimetype.60000.options_name": "分钟", + "resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.0.options_name": "底部", + "resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.1.options_name": "中心", + "resource.option.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.2.options_name": "顶部", + "resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.0.options_name": "底部", + "resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.1.options_name": "中心", + "resource.option.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.2.options_name": "顶部", + "resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.1.options_name": "毫秒", + "resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.1000.options_name": "秒", + "resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.3600000.options_name": "小时", + "resource.option.7.ba_00005.7d7b0fa3.param_areadurationtimetype.60000.options_name": "分钟", + "resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.0.options_name": "底部", + "resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.1.options_name": "中心", + "resource.option.7602.pa_00001.d8241567.aiparam_face_detpostion.2.options_name": "顶部", + "resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.0.options_name": "底部", + "resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.1.options_name": "中心", + "resource.option.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.2.options_name": "顶部", + "resource.option.83708.83708.aiparam_category0_detpostion.0.options_name": "底部", + "resource.option.83708.83708.aiparam_category0_detpostion.1.options_name": "中心", + "resource.option.83708.83708.aiparam_category0_detpostion.2.options_name": "顶部", + "resource.option.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.0.options_name": "底部", + "resource.option.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.1.options_name": "中心", + "resource.option.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.2.options_name": "顶部", + "resource.option.9.9.aiparam_smog_detpostion.0.options_name": "底部", + "resource.option.9.9.aiparam_smog_detpostion.1.options_name": "中心", + "resource.option.9.9.aiparam_smog_detpostion.2.options_name": "顶部", + "resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.0.options_name": "底部", + "resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.1.options_name": "中心", + "resource.option.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.2.options_name": "顶部", + "resource.option.aa_00003.motionstatus.0.options_name": "关闭", + "resource.option.aa_00003.motionstatus.1.options_name": "运动状态", + "resource.option.aa_00003.motionstatus.2.options_name": "静止状态", + "resource.option.aa_00003.shapechangestatus.0.options_name": "不需要", + "resource.option.aa_00003.shapechangestatus.1.options_name": "需要形状发生变化的", + "resource.option.aa_00003.shapechangestatus.2.options_name": "需要形状不发生变的", + "resource.option.aa_00005.featureinput.0.options_name": "人脸特征提取(无需比对)", + "resource.option.aa_00005.featureinput.1.options_name": "工服特征提取(需要比对)", + "resource.option.aa_00005.featureinput.2.options_name": "机物特征提取(需要比对)", + "resource.option.aa_00005.featureinput.3.options_name": "人体特征提取(无需比对)", + "resource.option.aa_00005.matchflag.0.options_name": "未命中告警", + "resource.option.aa_00005.matchflag.1.options_name": "命中告警", + "resource.option.ba_00003.detectiontimetype.1.options_name": "秒", + "resource.option.ba_00003.detectiontimetype.2.options_name": "毫秒", + "resource.option.ba_00004.alarmproperty.0.options_name": "普通告警(无属性)", + "resource.option.ba_00004.alarmproperty.1.options_name": "人脸检测/比对(特征属性)", + "resource.option.ba_00004.alarmproperty.10.options_name": "人体特征上报", + "resource.option.ba_00004.alarmproperty.11.options_name": "工服比对结果", + "resource.option.ba_00004.alarmproperty.3.options_name": "车辆属性", + "resource.option.ba_00004.alarmproperty.5.options_name": "机物类特殊检测属性(如滤波状态开关/机物比对结果)", + "resource.option.ba_00004.alarmproperty.6.options_name": "人流量统计属性", + "resource.option.ba_00004.alarmproperty.7.options_name": "车流量统计属性", + "resource.option.ba_00004.alarmproperty.8.options_name": "聚集人数", + "resource.option.ba_00004.alarmproperty.9.options_name": "人数统计属性(区域人数)", + "resource.option.ba_00004.custparam_alarmtype.1.options_name": "不带目标跟踪", + "resource.option.ba_00004.custparam_alarmtype.2.options_name": "带目标跟踪", + "resource.option.ba_00004.custparam_alarmtype.3.options_name": "不需要抑制", + "resource.option.ba_00005.areaalarmtype.0.options_name": "数量限制(用于离岗/聚集)", + "resource.option.ba_00005.areaalarmtype.1.options_name": "流量统计和区域数量统计", + "resource.option.ba_00005.areaalarmtype.2.options_name": "过线(用于绊线)", + "resource.option.ba_00005.areaalarmtype.3.options_name": "目标方向告警(用于逆行)", + "resource.option.ba_00005.areaalarmtype.4.options_name": "目标进入区域一段时间(用于入侵)", + "resource.option.ba_00005.areaalarmtype.5.options_name": "侦测类(用于人体侦测)", + "resource.option.ba_00005.areaalarmtype.6.options_name": "多实例的数量限制(一个流程中有多个实例)", + "resource.option.ba_00005.areadurationtimetype.1.options_name": "毫秒", + "resource.option.ba_00005.areadurationtimetype.1000.options_name": "秒", + "resource.option.ba_00005.areadurationtimetype.3600000.options_name": "小时", + "resource.option.ba_00005.areadurationtimetype.60000.options_name": "分钟", + "resource.option.ba_00005.arealimittargettype.0.options_name": "小于目标数告警", + "resource.option.ba_00005.arealimittargettype.1.options_name": "大于目标数告警", + "resource.option.ba_00005.arealimittargettype.2.options_name": "小于等于目标数告警", + "resource.option.ba_00005.arealimittargettype.3.options_name": "大于等于目标数告警", + "resource.option.ba_00005.arealimittargettype.4.options_name": "等于目标数告警", + "resource.option.ba_00005.breakareatype.101.options_name": "正向过线", + "resource.option.ba_00005.countbreakareatype.0.options_name": "在区域内告警", + "resource.option.ba_00005.countbreakareatype.103.options_name": "双向过线统计", + "resource.option.ba_00005.detectbreakareatype.0.options_name": "在区域内告警", + "resource.option.ba_00005.durationbreakareatype.0.options_name": "在区域内告警", + "resource.option.ba_00005.durationbreakareatype.2.options_name": "从外到内", + "resource.option.ba_00005.inputareatype.1.options_name": "主区域", + "resource.option.ba_00005.inputareatype.2.options_name": "关联区域", + "resource.option.ba_00005.param_areacalcdurationtimetype.1.options_name": "毫秒", + "resource.option.ba_00005.param_areacalcdurationtimetype.1000.options_name": "秒", + "resource.option.ba_00005.param_areacalcdurationtimetype.3600000.options_name": "小时", + "resource.option.ba_00005.param_areacalcdurationtimetype.60000.options_name": "分钟", + "resource.option.ba_00005.param_areadurationtimetype.1.options_name": "毫秒", + "resource.option.ba_00005.param_areadurationtimetype.1000.options_name": "秒", + "resource.option.ba_00005.param_areadurationtimetype.3600000.options_name": "小时", + "resource.option.ba_00005.param_areadurationtimetype.60000.options_name": "分钟", + "resource.option.ba_00005.param_arealimitdurationtimetype.1.options_name": "毫秒", + "resource.option.ba_00005.param_arealimitdurationtimetype.1000.options_name": "秒", + "resource.option.ba_00005.param_arealimitdurationtimetype.3600000.options_name": "小时", + "resource.option.ba_00005.param_arealimitdurationtimetype.60000.options_name": "分钟", + "resource.option.ba_00005.param_arealimittargettype.0.options_name": "小于目标数告警", + "resource.option.ba_00005.param_arealimittargettype.1.options_name": "大于目标数告警", + "resource.option.ba_00005.param_arealimittargettype.2.options_name": "小于等于目标数告警", + "resource.option.ba_00005.param_arealimittargettype.3.options_name": "大于等于目标数告警", + "resource.option.ba_00005.param_arealimittargettype.4.options_name": "等于目标数告警", + "resource.option.ba_00005.param_retrodirect.0.options_name": "从下往上", + "resource.option.ba_00005.param_retrodirect.1.options_name": "从上往下", + "resource.option.ba_00005.param_targetcalctype.0.options_name": "瞬时(区域人数统计)", + "resource.option.ba_00005.param_targetcalctype.1.options_name": "周期总人数 (人流量)", + "resource.option.ba_00005.param_trippingwiretype.1.options_name": "单线", + "resource.option.ba_00005.param_trippingwiretype.2.options_name": "双线", + "resource.option.da_00002.inputtype.box.options_name": "框", + "resource.option.da_00002.inputtype.point.options_name": "点", + "resource.option.da_00003.generationstyle.creative.options_name": "发散", + "resource.option.da_00003.generationstyle.custom.options_name": "自定义", + "resource.option.da_00003.generationstyle.standard.options_name": "标准", + "resource.option.da_00003.generationstyle.strict.options_name": "严谨", + "resource.option.ip0001.data_type.0.options_name": "32位浮点数", + "resource.option.ip0001.data_type.1.options_name": "32位有符号整数", + "resource.option.ip0001.data_type.2.options_name": "16位半精度浮点数", + "resource.option.ip0001.data_type.3.options_name": "16位浮点数", + "resource.option.ip0001.data_type.4.options_name": "8位无符号整数", + "resource.option.ip0001.data_type.5.options_name": "8位有符号整数", + "resource.option.la_audiodevice_code.operation.1.options_label": "音频播放", + "resource.option.la_audiodevice_code.operation.2.options_label": "文字播放", + "resource.option.la_audiodevice_code.tone.1.options_label": "男声", + "resource.option.la_audiodevice_code.tone.2.options_label": "女声", + "resource.option.on0001.data_type.0.options_name": "32位浮点数", + "resource.option.on0001.data_type.1.options_name": "32位有符号整数", + "resource.option.on0001.data_type.2.options_name": "16位半精度浮点数", + "resource.option.on0001.data_type.3.options_name": "16位浮点数", + "resource.option.on0001.data_type.4.options_name": "8位无符号整数", + "resource.option.on0001.data_type.5.options_name": "8位有符号整数", + "resource.option.pa_00005.featureinput.0.options_name": "人脸特征提取(暂不支持)", + "resource.option.pa_00005.featureinput.1.options_name": "工服特征提取", + "resource.option.pa_00005.featureinput.2.options_name": "机物特征提取", + "resource.option.pa_00005.featureinput.3.options_name": "人体特征提取(暂不支持)", + "resource.option.pa_00005.matchflag.0.options_name": "未命中告警", + "resource.option.pa_00005.matchflag.1.options_name": "命中告警", + "resource.option.pda_00002.inputtype.box.options_name": "框", + "resource.option.pda_00002.inputtype.point.options_name": "点", + "resource.option.pda_00003.generationstyle.creative.options_name": "发散", + "resource.option.pda_00003.generationstyle.custom.options_name": "自定义", + "resource.option.pda_00003.generationstyle.standard.options_name": "标准", + "resource.option.pda_00003.generationstyle.strict.options_name": "严谨", + "resource.option.pr0001.gravity.0.options_name": "直接缩放", + "resource.option.pr0001.gravity.1.options_name": "等比缩放后居中填充", + "resource.option.pr0001.gravity.2.options_name": "等比缩放顶左对齐", + "resource.option.pr0005.normmode.0.options_name": "模式0", + "resource.option.pr0005.normmode.1.options_name": "模式1", + "resource.option.pr0005.normmode.2.options_name": "模式2", + "resource.option.pt0001.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.option.pt0002.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.option.pt0003.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.option.pt0004.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.option.pt0005.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.option.pt0006.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.option.pt0007.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.option.pt0008.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.option.pt0009.op.yolo_e2e_postprocess.options_name": "yolo_e2e_postprocess(YOLO26等)", + "resource.param.10.10.0.name": "默认", + "resource.param.10.10.aiparam_2001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.10.10.aiparam_2001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.10.10.aiparam_2001003_trackdynamicmatch.name": "火焰、烟雾检测追踪半径", + "resource.param.10.10.aiparam_fire_confidence.description": "火焰置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.10.10.aiparam_fire_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.10.10.aiparam_fire_confidence.name": "火焰置信度", + "resource.param.10.10.aiparam_fire_confidenceconfig.description": "火焰置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.10.10.aiparam_fire_confidenceconfig.name": "火焰置信度偏移", + "resource.param.10.10.aiparam_fire_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.10.10.aiparam_fire_detpostion.failedtip": "请选择正确的值", + "resource.param.10.10.aiparam_fire_detpostion.name": "火焰检测方式", + "resource.param.10.10.filter_fire_side_min.description": "最小火焰尺寸:火焰抓拍照片的最小图像尺寸。如输入值为100,则最小火焰尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.10.10.filter_fire_side_min.failedtip": "请输入0-10000的整数", + "resource.param.10.10.filter_fire_side_min.name": "最小火焰尺寸", + "resource.param.10.10.name.description": "区域名称:必填,限制32字符", + "resource.param.10.10.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.10.10.name.name": "区域名称", + "resource.param.10.10.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.10.10.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.10.10.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.10.10.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.10.10.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.10.10.param_detectionduration.name": "检测时间(秒)", + "resource.param.10.10.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.10.10.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.10.10.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.10.10.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.10.10.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.10.10.param_restrainswitch.name": "静止目标去重", + "resource.param.10.10.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.10.10.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.10.10.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.10.10.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.10.10.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.10.10.param_sensitivity.name": "灵敏度", + "resource.param.10.10.param_videoreadfps.description": "离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。", + "resource.param.10.10.param_videoreadfps.failedtip": "请输入正确的值", + "resource.param.10.10.param_videoreadfps.name": "离线视频播放取帧帧率", + "resource.param.10.10.param_videorepeatcount.description": "离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次", + "resource.param.10.10.param_videorepeatcount.failedtip": "请输入1-100的整数", + "resource.param.10.10.param_videorepeatcount.name": "离线视频播放次数", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.description": "fire置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidence.name": "fire置信度", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidenceconfig.description": "fire置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_confidenceconfig.name": "fire置信度偏移", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.failedtip": "请选择正确的值", + "resource.param.10.aa_00001.ba9c7d80.aiparam_fire_detpostion.name": "fire检测方式", + "resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.10.aa_00003.674483de.aiparam_2001003_trackdynamicmatch.name": "火焰、烟雾检测追踪半径", + "resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.description": "最小火焰尺寸:火焰抓拍照片的最小图像尺寸。如输入值为100,则最小火焰尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.failedtip": "请输入0-10000的整数", + "resource.param.10.ba_00002.a59e0a7e.filter_fire_side_min.name": "最小火焰尺寸", + "resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.description": "检测时间:范围:1-3600。默认2。", + "resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.failedtip": "请输入1-3600的整数", + "resource.param.10.ba_00003.2c1f8a2b.param_detectionduration.detectiontimetype.1.name": "检测时间(秒)", + "resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.description": "灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。", + "resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.10.ba_00003.2c1f8a2b.param_sensitivity.name": "灵敏度", + "resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.10.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.10.ba_00004.1478c130.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.10.ba_00004.1478c130.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.10.ba_00004.1478c130.param_overlaprate.name": "静止目标重叠率", + "resource.param.10.ba_00004.1478c130.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.10.ba_00004.1478c130.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.10.ba_00004.1478c130.param_restrainswitch.name": "静止目标去重", + "resource.param.10.ba_00004.1478c130.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.10.ba_00004.1478c130.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.10.ba_00004.1478c130.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.11.11.0.name": "默认", + "resource.param.11.11.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.11.11.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.11.11.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.11.11.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.11.11.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.11.11.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.11.11.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.11.11.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.11.11.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.11.11.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.11.11.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.11.11.aiparam_pedsmoking_confidence.description": "抽烟置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.11.11.aiparam_pedsmoking_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.11.11.aiparam_pedsmoking_confidence.name": "抽烟置信度", + "resource.param.11.11.aiparam_pedsmoking_confidenceconfig.description": "抽烟置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.11.11.aiparam_pedsmoking_confidenceconfig.name": "抽烟置信度偏移", + "resource.param.11.11.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.11.11.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.11.11.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.11.11.name.description": "区域名称:必填,限制32字符", + "resource.param.11.11.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.11.11.name.name": "区域名称", + "resource.param.11.11.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.11.11.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.11.11.param_detectionduration.name": "检测时间(秒)", + "resource.param.11.11.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.11.11.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.11.11.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.11.11.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.11.11.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.11.11.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.11.11.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.11.11.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.11.11.param_restrainswitch.name": "静止目标去重", + "resource.param.11.11.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.11.11.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.11.11.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.11.11.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.11.11.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.11.11.param_sensitivity.name": "灵敏度", + "resource.param.11.11.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.11.11.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.11.11.param_targetalarmcount.name": "告警次数", + "resource.param.11.11.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.11.11.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.11.11.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.11.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.description": "pedSmoking置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidence.name": "pedSmoking置信度", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidenceconfig.description": "pedSmoking置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.11.aa_00002.c37b8e34.aiparam_pedsmoking_confidenceconfig.name": "pedSmoking置信度偏移", + "resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.11.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "PedestrianDetection追踪半径", + "resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.11.ba_00002.5a2f08ca.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.description": "检测时间:范围:1-3600。默认2。", + "resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.failedtip": "请输入1-3600的整数", + "resource.param.11.ba_00003.b90c6769.param_detectionduration.detectiontimetype.1.name": "检测时间(秒)", + "resource.param.11.ba_00003.b90c6769.param_sensitivity.description": "灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。", + "resource.param.11.ba_00003.b90c6769.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.11.ba_00003.b90c6769.param_sensitivity.name": "灵敏度", + "resource.param.11.ba_00004.0f53b331.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.11.ba_00004.0f53b331.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.11.ba_00004.0f53b331.param_overlaprate.name": "静止目标重叠率", + "resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "请选择是否打开叠加轨迹", + "resource.param.11.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name": "全景图叠加轨迹", + "resource.param.11.ba_00004.0f53b331.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.11.ba_00004.0f53b331.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.11.ba_00004.0f53b331.param_restrainswitch.name": "静止目标去重", + "resource.param.11.ba_00004.0f53b331.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.11.ba_00004.0f53b331.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.11.ba_00004.0f53b331.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip": "请输入0-100的整数", + "resource.param.11.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name": "告警次数", + "resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip": "请输入1-36000的整数", + "resource.param.11.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name": "告警时间间隔(秒)", + "resource.param.12.12.1001003.0.pedestrian.namecn": "行人", + "resource.param.12.12.2002011.0.pedphoneanswer.namecn": "打电话", + "resource.param.12.12.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.12.12.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.12.12.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.12.12.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.12.12.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.12.12.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.12.12.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.12.12.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.12.12.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.12.12.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.12.12.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.12.12.aiparam_pedphoneanswer_confidence.description": "打电话置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.12.12.aiparam_pedphoneanswer_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.12.12.aiparam_pedphoneanswer_confidence.name": "打电话置信度", + "resource.param.12.12.aiparam_pedphoneanswer_confidenceconfig.description": "打电话置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.12.12.aiparam_pedphoneanswer_confidenceconfig.name": "打电话置信度偏移", + "resource.param.12.12.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.12.12.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.12.12.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.12.12.name.description": "区域名称:必填,限制32字符", + "resource.param.12.12.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.12.12.name.name": "区域名称", + "resource.param.12.12.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.12.12.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.12.12.param_detectionduration.name": "检测时间(秒)", + "resource.param.12.12.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.12.12.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.12.12.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.12.12.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.12.12.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.12.12.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.12.12.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.12.12.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.12.12.param_restrainswitch.name": "静止目标去重", + "resource.param.12.12.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.12.12.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.12.12.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.12.12.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.12.12.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.12.12.param_sensitivity.name": "灵敏度", + "resource.param.12.12.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.12.12.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.12.12.param_targetalarmcount.name": "告警次数", + "resource.param.12.12.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.12.12.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.12.12.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.12.aa_00001.487c1cf0.1001003.0.pedestrian.namecn": "行人", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.12.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.12.aa_00002.c37b8e34.2002011.0.pedphoneanswer.namecn": "打电话", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.description": "打电话置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidence.name": "打电话置信度", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidenceconfig.description": "打电话置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.12.aa_00002.c37b8e34.aiparam_pedphoneanswer_confidenceconfig.name": "打电话置信度偏移", + "resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.12.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.12.ba_00002.ccc378e3.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.12.ba_00003.0d015957.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.12.ba_00003.0d015957.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.12.ba_00003.0d015957.param_detectionduration.name": "检测时间(秒)", + "resource.param.12.ba_00003.0d015957.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.12.ba_00003.0d015957.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.12.ba_00003.0d015957.param_sensitivity.name": "灵敏度", + "resource.param.12.ba_00004.0f53b331.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.12.ba_00004.0f53b331.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.12.ba_00004.0f53b331.param_overlaprate.name": "静止目标重叠率", + "resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.12.ba_00004.0f53b331.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.12.ba_00004.0f53b331.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.12.ba_00004.0f53b331.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.12.ba_00004.0f53b331.param_restrainswitch.name": "静止目标去重", + "resource.param.12.ba_00004.0f53b331.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.12.ba_00004.0f53b331.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.12.ba_00004.0f53b331.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.12.ba_00004.0f53b331.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.12.ba_00004.0f53b331.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.12.ba_00004.0f53b331.param_targetalarmcount.name": "告警次数", + "resource.param.12.ba_00004.0f53b331.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.12.ba_00004.0f53b331.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.12.ba_00004.0f53b331.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.13.13.0.name": "人流线", + "resource.param.13.13.1.name": "区域", + "resource.param.13.13.1001003.0.pedestrian.namecn": "行人", + "resource.param.13.13.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.13.13.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.13.13.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.13.13.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.13.13.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.13.13.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.13.13.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.13.13.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.13.13.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.13.13.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.13.13.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.13.13.name.description": "区域名称:必填,限制32字符", + "resource.param.13.13.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.13.13.name.name": "区域名称", + "resource.param.13.13.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.13.13.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.13.13.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.13.13.param_areacalcduration.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.13.13.param_areacalcduration.failedtip": "请输入正确的数值", + "resource.param.13.13.param_areacalcduration.name": "人数上报间隔", + "resource.param.13.13.param_areacalcdurationtimetype.description": "检测时间单位", + "resource.param.13.13.param_areacalcdurationtimetype.failedtip": "请选择正确的数值", + "resource.param.13.13.param_areacalcdurationtimetype.name": "检测时间单位", + "resource.param.13.13.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.13.13.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.13.13.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.13.13.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.13.13.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.13.13.param_restrainswitch.name": "静止目标去重", + "resource.param.13.13.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.13.13.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.13.13.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.13.13.param_targetcalctype.description": "目标统计方式", + "resource.param.13.13.param_targetcalctype.failedtip": "请选择正确的值", + "resource.param.13.13.param_targetcalctype.name": "目标统计方式", + "resource.param.13.aa_00001.e9173765.1001003.0.pedestrian.namecn": "行人", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.13.aa_00001.e9173765.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.13.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.13.ba_00004.a5c23881.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.13.ba_00004.a5c23881.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.13.ba_00004.a5c23881.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.13.ba_00004.a5c23881.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.13.ba_00004.a5c23881.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.13.ba_00004.a5c23881.param_overlaprate.name": "静止目标重叠率", + "resource.param.13.ba_00004.a5c23881.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.13.ba_00004.a5c23881.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.13.ba_00004.a5c23881.param_restrainswitch.name": "静止目标去重", + "resource.param.13.ba_00004.a5c23881.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.13.ba_00004.a5c23881.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.13.ba_00004.a5c23881.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.13.ba_00005.97085574.param_areacalcduration.description": "数量上报间隔:范围:1-3600000,注意时间单位", + "resource.param.13.ba_00005.97085574.param_areacalcduration.failedtip": "请输入正确的数值", + "resource.param.13.ba_00005.97085574.param_areacalcduration.name": "数量上报间隔", + "resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.description": "数量上报间隔时间单位", + "resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.failedtip": "请选择正确的单位", + "resource.param.13.ba_00005.97085574.param_areacalcdurationtimetype.name": "数量上报间隔时间单位", + "resource.param.13.ba_00005.97085574.param_targetcalctype.description": "目标统计方式", + "resource.param.13.ba_00005.97085574.param_targetcalctype.failedtip": "请选择正确的值", + "resource.param.13.ba_00005.97085574.param_targetcalctype.name": "目标统计方式", + "resource.param.15.15.1001003.0.pedestrian.namecn": "行人", + "resource.param.15.15.2001036.0.pedhelmet.namecn": "头盔", + "resource.param.15.15.2001036.1.pedsafehelmet.namecn": "安全帽", + "resource.param.15.15.2001036.3.hatless.namecn": "无帽", + "resource.param.15.15.2001036.4.unsure.namecn": "不确定", + "resource.param.15.15.aiparam_1001003_frames.description": "追踪历史帧数。范围:2~100", + "resource.param.15.15.aiparam_1001003_frames.failedtip": "请输入2-100的整数", + "resource.param.15.15.aiparam_1001003_frames.name": "行人检测追踪历史帧数", + "resource.param.15.15.aiparam_1001003_motion.description": "静止阈值。范围:1~99,例如:80.0", + "resource.param.15.15.aiparam_1001003_motion.failedtip": "请输入1-99的一位小数", + "resource.param.15.15.aiparam_1001003_motion.name": "行人检测静止阈值", + "resource.param.15.15.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.15.15.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.15.15.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.15.15.aiparam_hatless_confidence.description": "无帽置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.15.aiparam_hatless_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.15.aiparam_hatless_confidence.name": "无帽置信度", + "resource.param.15.15.aiparam_hatless_confidenceconfig.description": "无帽置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.15.aiparam_hatless_confidenceconfig.name": "无帽置信度偏移", + "resource.param.15.15.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.15.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.15.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.15.15.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.15.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.15.15.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.15.15.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.15.15.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.15.15.aiparam_pedhelmet_confidence.description": "头盔置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.15.aiparam_pedhelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.15.aiparam_pedhelmet_confidence.name": "头盔置信度", + "resource.param.15.15.aiparam_pedhelmet_confidenceconfig.description": "头盔置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.15.aiparam_pedhelmet_confidenceconfig.name": "头盔置信度偏移", + "resource.param.15.15.aiparam_pedsafehelmet_confidence.description": "安全帽置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.15.aiparam_pedsafehelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.15.aiparam_pedsafehelmet_confidence.name": "安全帽置信度", + "resource.param.15.15.aiparam_pedsafehelmet_confidenceconfig.description": "安全帽置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.15.aiparam_pedsafehelmet_confidenceconfig.name": "安全帽置信度偏移", + "resource.param.15.15.aiparam_unsure_confidence.description": "不确定置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.15.aiparam_unsure_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.15.aiparam_unsure_confidence.name": "不确定置信度", + "resource.param.15.15.aiparam_unsure_confidenceconfig.description": "不确定置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.15.aiparam_unsure_confidenceconfig.name": "不确定置信度偏移", + "resource.param.15.15.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.15.15.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.15.15.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.15.15.name.description": "区域名称:必填,限制32字符", + "resource.param.15.15.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.15.15.name.name": "区域名称", + "resource.param.15.15.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.15.15.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.15.15.param_detectionduration.name": "检测时间(秒)", + "resource.param.15.15.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.15.15.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.15.15.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.15.15.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.15.15.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.15.15.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.15.15.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.15.15.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.15.15.param_restrainswitch.name": "静止目标去重", + "resource.param.15.15.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.15.15.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.15.15.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.15.15.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.15.15.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.15.15.param_sensitivity.name": "灵敏度", + "resource.param.15.15.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.15.15.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.15.15.param_targetalarmcount.name": "告警次数", + "resource.param.15.15.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.15.15.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.15.15.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.15.aa_00001.83b4eb95.1001003.0.pedestrian.namecn": "行人", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.15.aa_00001.83b4eb95.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.15.aa_00002.a0333a67.2001036.0.pedhelmet.namecn": "头盔", + "resource.param.15.aa_00002.a0333a67.2001036.1.pedsafehelmet.namecn": "安全帽", + "resource.param.15.aa_00002.a0333a67.2001036.3.hatless.namecn": "无帽", + "resource.param.15.aa_00002.a0333a67.2001036.4.unsure.namecn": "不确定", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.description": "无帽置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidence.name": "无帽置信度", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidenceconfig.description": "无帽置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.aa_00002.a0333a67.aiparam_hatless_confidenceconfig.name": "无帽置信度偏移", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.description": "头盔置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidence.name": "头盔置信度", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidenceconfig.description": "头盔置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.aa_00002.a0333a67.aiparam_pedhelmet_confidenceconfig.name": "头盔置信度偏移", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.description": "安全帽置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidence.name": "安全帽置信度", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidenceconfig.description": "安全帽置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.aa_00002.a0333a67.aiparam_pedsafehelmet_confidenceconfig.name": "安全帽置信度偏移", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.description": "不确定置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidence.name": "不确定置信度", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidenceconfig.description": "不确定置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15.aa_00002.a0333a67.aiparam_unsure_confidenceconfig.name": "不确定置信度偏移", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.description": "追踪历史帧数。范围:2~100", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.failedtip": "请输入2-100的整数", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_frames.name": "行人检测追踪历史帧数", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.description": "静止阈值。范围:1~99,例如:80.0", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.failedtip": "请输入1-99的一位小数", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_motion.name": "行人检测静止阈值", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.15.aa_00003.e1a418ab.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.15.ba_00002.66fe69a4.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.15.ba_00003.b4b02c33.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.15.ba_00003.b4b02c33.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.15.ba_00003.b4b02c33.param_detectionduration.name": "检测时间(秒)", + "resource.param.15.ba_00003.b4b02c33.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.15.ba_00003.b4b02c33.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.15.ba_00003.b4b02c33.param_sensitivity.name": "灵敏度", + "resource.param.15.ba_00004.4fb8d95e.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.15.ba_00004.4fb8d95e.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.15.ba_00004.4fb8d95e.param_overlaprate.name": "静止目标重叠率", + "resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.15.ba_00004.4fb8d95e.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.15.ba_00004.4fb8d95e.param_restrainswitch.name": "静止目标去重", + "resource.param.15.ba_00004.4fb8d95e.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.15.ba_00004.4fb8d95e.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.15.ba_00004.4fb8d95e.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarmcount.name": "告警次数", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.15.ba_00004.4fb8d95e.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.15760.15760.0.name": "默认", + "resource.param.15760.15760.name.description": "区域名称:必填,限制32字符", + "resource.param.15760.15760.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.15760.15760.name.name": "区域名称", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.15760.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.16.16.0.name": "默认", + "resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.failedtip": "请输入0-1的三位小数。", + "resource.param.16.16.aiparam_pedestrian_confidence.custom_detection.0.name": "行人置信度", + "resource.param.16.16.aiparam_pedestrian_confidenceconfig.custom_detection.0.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.16.16.aiparam_pedestrian_confidenceconfig.custom_detection.0.name": "行人置信度偏移", + "resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.failedtip": "请选择正确的值", + "resource.param.16.16.aiparam_pedestrian_detpostion.custom_detection.0.name": "行人检测方式", + "resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.failedtip": "请输入0-10000的整数", + "resource.param.16.16.filter_pedestrian_side_min.custom_detection.0.name": "最小行人尺寸", + "resource.param.16.16.name.description": "区域名称:必填,限制32字符", + "resource.param.16.16.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.16.16.name.name": "区域名称", + "resource.param.16.16.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.16.16.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.16.16.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.16.16.param_arealimitduration.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.16.16.param_arealimitduration.failedtip": "请输入正确的数值", + "resource.param.16.16.param_arealimitduration.name": "检测时间", + "resource.param.16.16.param_arealimitdurationtimetype.description": "检测时间单位", + "resource.param.16.16.param_arealimitdurationtimetype.failedtip": "请选择正确的数值", + "resource.param.16.16.param_arealimitdurationtimetype.name": "检测时间单位", + "resource.param.16.16.param_arealimittargetcount.description": "区域中的目标数", + "resource.param.16.16.param_arealimittargetcount.failedtip": "请输入0-3600的整数", + "resource.param.16.16.param_arealimittargetcount.name": "区域中的目标数", + "resource.param.16.16.param_arealimittargettype.description": "区域中目标数限制类型", + "resource.param.16.16.param_arealimittargettype.failedtip": "请选择正确的值", + "resource.param.16.16.param_arealimittargettype.name": "区域中目标数限制类型", + "resource.param.16.16.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.16.16.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.16.16.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.16.16.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.16.16.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.16.16.param_restrainswitch.name": "静止目标去重", + "resource.param.16.16.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.16.16.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.16.16.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.16.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.16.ba_00002.72ec426d.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.16.ba_00004.f0c9e210.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.16.ba_00004.f0c9e210.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.16.ba_00004.f0c9e210.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.16.ba_00004.f0c9e210.param_overlaprate.name": "静止目标重叠率", + "resource.param.16.ba_00004.f0c9e210.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.16.ba_00004.f0c9e210.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.16.ba_00004.f0c9e210.param_restrainswitch.name": "静止目标去重", + "resource.param.16.ba_00004.f0c9e210.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.16.ba_00004.f0c9e210.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.16.ba_00004.f0c9e210.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.failedtip": "请输入正确的数值", + "resource.param.16.ba_00005.ab935f8a.param_arealimitduration.areaalarmtype.0.name": "检测时间", + "resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.description": "检测时间单位", + "resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.failedtip": "请选择正确的数值", + "resource.param.16.ba_00005.ab935f8a.param_arealimitdurationtimetype.areaalarmtype.0.name": "检测时间单位", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.description": "用于和区域内实际有效目标数量进行比较的阈值", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.failedtip": "请输入0-3600的整数", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargetcount.areaalarmtype.0.name": "目标数量阈值", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.description": "区域中目标数限制类型", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.failedtip": "请选择正确的值", + "resource.param.16.ba_00005.ab935f8a.param_arealimittargettype.areaalarmtype.0.name": "触发条件", + "resource.param.1917.1917.0.name": "默认", + "resource.param.1917.1917.1.name": "默认", + "resource.param.1917.1917.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.1917.1917.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.1917.1917.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.1917.1917.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.1917.1917.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.1917.1917.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.1917.1917.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.1917.1917.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.1917.1917.name.description": "区域名称:必填,限制32字符", + "resource.param.1917.1917.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.1917.1917.name.name": "区域名称", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.1917.pa_00001.b7fe1598.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.2.2.0.name": "默认", + "resource.param.2.2.aiparam_1000001_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.2.2.aiparam_1000001_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.2.2.aiparam_1000001_trackdynamicmatch.name": "FaceRGBDetection追踪半径", + "resource.param.2.2.aiparam_face_confidence.description": "face置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.2.aiparam_face_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.2.aiparam_face_confidence.name": "face置信度", + "resource.param.2.2.aiparam_face_confidenceconfig.description": "face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.2.aiparam_face_confidenceconfig.name": "face置信度偏移", + "resource.param.2.2.aiparam_face_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.2.2.aiparam_face_detpostion.failedtip": "请选择正确的值", + "resource.param.2.2.aiparam_face_detpostion.name": "face检测方式", + "resource.param.2.2.aiparam_faceblur0_confidence.description": "faceBlur0置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.2.aiparam_faceblur0_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.2.aiparam_faceblur0_confidence.name": "faceBlur0置信度", + "resource.param.2.2.aiparam_faceblur0_confidenceconfig.description": "faceBlur0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.2.aiparam_faceblur0_confidenceconfig.name": "faceBlur0置信度偏移", + "resource.param.2.2.aiparam_faceblur1_confidence.description": "faceBlur1置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.2.aiparam_faceblur1_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.2.aiparam_faceblur1_confidence.name": "faceBlur1置信度", + "resource.param.2.2.aiparam_faceblur1_confidenceconfig.description": "faceBlur1置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.2.aiparam_faceblur1_confidenceconfig.name": "faceBlur1置信度偏移", + "resource.param.2.2.aiparam_faceblur2_confidence.description": "faceBlur2置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.2.aiparam_faceblur2_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.2.aiparam_faceblur2_confidence.name": "faceBlur2置信度", + "resource.param.2.2.aiparam_faceblur2_confidenceconfig.description": "faceBlur2置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.2.aiparam_faceblur2_confidenceconfig.name": "faceBlur2置信度偏移", + "resource.param.2.2.aiparam_frontface_confidence.description": "frontFace置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.2.aiparam_frontface_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.2.aiparam_frontface_confidence.name": "frontFace置信度", + "resource.param.2.2.aiparam_frontface_confidenceconfig.description": "frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.2.aiparam_frontface_confidenceconfig.name": "frontFace置信度偏移", + "resource.param.2.2.aiparam_fullface_confidence.description": "fullFace置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.2.aiparam_fullface_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.2.aiparam_fullface_confidence.name": "fullFace置信度", + "resource.param.2.2.aiparam_fullface_confidenceconfig.description": "fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.2.aiparam_fullface_confidenceconfig.name": "fullFace置信度偏移", + "resource.param.2.2.aiparam_slantedface_confidence.description": "slantedFace置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.2.aiparam_slantedface_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.2.aiparam_slantedface_confidence.name": "slantedFace置信度", + "resource.param.2.2.aiparam_slantedface_confidenceconfig.description": "slantedFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.2.aiparam_slantedface_confidenceconfig.name": "slantedFace置信度偏移", + "resource.param.2.2.filter_face_side_min.description": "最小face尺寸:face抓拍照片的最小图像尺寸。如输入值为100,则最小face尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.2.2.filter_face_side_min.failedtip": "请输入0-10000的整数", + "resource.param.2.2.filter_face_side_min.name": "最小face尺寸", + "resource.param.2.2.name.description": "区域名称:必填,限制32字符", + "resource.param.2.2.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.2.2.name.name": "区域名称", + "resource.param.2.2.param_faceset.description": "选择需要比对的脸库分组", + "resource.param.2.2.param_faceset.failedtip": "请选择正确的值", + "resource.param.2.2.param_faceset.name": "绑定人脸分组", + "resource.param.2.2.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.2.2.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.2.2.param_overlaprate.name": "静止目标重叠率", + "resource.param.2.2.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.2.2.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.2.2.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.2.2.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.2.2.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.2.2.param_restrainswitch.name": "静止目标去重", + "resource.param.2.2.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.2.2.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.2.2.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.2.2.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.2.2.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.2.2.param_targetalarmcount.name": "告警次数", + "resource.param.2.2.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.2.2.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.2.2.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.description": "face置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidence.name": "face置信度", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidenceconfig.description": "face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_confidenceconfig.name": "face置信度偏移", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.failedtip": "请选择正确的值", + "resource.param.2.aa_00001.aaa71a68.aiparam_face_detpostion.name": "face检测方式", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.description": "faceBlur0置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidence.name": "faceBlur0置信度", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidenceconfig.description": "faceBlur0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur0_confidenceconfig.name": "faceBlur0置信度偏移", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.description": "faceBlur1置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidence.name": "faceBlur1置信度", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidenceconfig.description": "faceBlur1置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur1_confidenceconfig.name": "faceBlur1置信度偏移", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.description": "faceBlur2置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidence.name": "faceBlur2置信度", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidenceconfig.description": "faceBlur2置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.aa_00002.12564ac1.aiparam_faceblur2_confidenceconfig.name": "faceBlur2置信度偏移", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.description": "frontFace置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidence.name": "frontFace置信度", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidenceconfig.description": "frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.aa_00002.12564ac1.aiparam_frontface_confidenceconfig.name": "frontFace置信度偏移", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.description": "fullFace置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidence.name": "fullFace置信度", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidenceconfig.description": "fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.aa_00002.12564ac1.aiparam_fullface_confidenceconfig.name": "fullFace置信度偏移", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.description": "slantedFace置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidence.name": "slantedFace置信度", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidenceconfig.description": "slantedFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.2.aa_00002.12564ac1.aiparam_slantedface_confidenceconfig.name": "slantedFace置信度偏移", + "resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.2.aa_00003.6f833257.aiparam_1000001_trackdynamicmatch.name": "FaceRGBDetection追踪半径", + "resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.description": "选择需要比对的脸库分组", + "resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.failedtip": "请选择正确的值", + "resource.param.2.aa_00005.061f82a7.param_faceset.featureinput.0.name": "绑定人脸分组", + "resource.param.2.ba_00002.5c3ea492.filter_face_side_min.description": "最小face尺寸:face抓拍照片的最小图像尺寸。如输入值为100,则最小face尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.2.ba_00002.5c3ea492.filter_face_side_min.failedtip": "请输入0-10000的整数", + "resource.param.2.ba_00002.5c3ea492.filter_face_side_min.name": "最小face尺寸", + "resource.param.2.ba_00004.bdf891b9.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.2.ba_00004.bdf891b9.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.2.ba_00004.bdf891b9.param_overlaprate.name": "静止目标重叠率", + "resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "请选择是否打开叠加轨迹", + "resource.param.2.ba_00004.bdf891b9.param_overlaytrajectory.custparam_alarmtype.2.name": "全景图叠加轨迹", + "resource.param.2.ba_00004.bdf891b9.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.2.ba_00004.bdf891b9.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.2.ba_00004.bdf891b9.param_restrainswitch.name": "静止目标去重", + "resource.param.2.ba_00004.bdf891b9.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.2.ba_00004.bdf891b9.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.2.ba_00004.bdf891b9.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.failedtip": "请输入0-100的整数", + "resource.param.2.ba_00004.bdf891b9.param_targetalarmcount.custparam_alarmtype.2.name": "告警次数", + "resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.failedtip": "请输入1-36000的整数", + "resource.param.2.ba_00004.bdf891b9.param_targetalarminterval.custparam_alarmtype.2.name": "告警时间间隔(秒)", + "resource.param.21283.21283.0.name": "默认", + "resource.param.21283.21283.name.description": "区域名称:必填,限制32字符", + "resource.param.21283.21283.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.21283.21283.name.name": "区域名称", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.21283.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.21283.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.21283.ba_00004.fd4e2090.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.21283.ba_00004.fd4e2090.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.21283.ba_00004.fd4e2090.param_overlaprate.name": "静止目标重叠率", + "resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.21283.ba_00004.fd4e2090.param_restrainswitch.name": "静止目标去重", + "resource.param.21283.ba_00004.fd4e2090.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.21283.ba_00004.fd4e2090.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.21283.ba_00004.fd4e2090.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.22.22.0.name": "默认", + "resource.param.22.22.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.22.22.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.22.22.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.22.22.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.22.22.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.22.22.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.22.22.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.22.22.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.22.22.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.22.22.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.22.22.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.22.22.aiparam_pedphoneplay_confidence.description": "玩手机置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.22.22.aiparam_pedphoneplay_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.22.22.aiparam_pedphoneplay_confidence.name": "玩手机置信度", + "resource.param.22.22.aiparam_pedphoneplay_confidenceconfig.description": "玩手机置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.22.22.aiparam_pedphoneplay_confidenceconfig.name": "玩手机置信度偏移", + "resource.param.22.22.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.22.22.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.22.22.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.22.22.name.description": "区域名称:必填,限制32字符", + "resource.param.22.22.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.22.22.name.name": "区域名称", + "resource.param.22.22.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.22.22.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.22.22.param_detectionduration.name": "检测时间(秒)", + "resource.param.22.22.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.22.22.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.22.22.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.22.22.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.22.22.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.22.22.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.22.22.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.22.22.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.22.22.param_restrainswitch.name": "静止目标去重", + "resource.param.22.22.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.22.22.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.22.22.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.22.22.param_sensitivity.description": "灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。", + "resource.param.22.22.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.22.22.param_sensitivity.name": "灵敏度", + "resource.param.22.22.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.22.22.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.22.22.param_targetalarmcount.name": "告警次数", + "resource.param.22.22.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.22.22.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.22.22.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.22.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.description": "pedPhonePlay置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidence.name": "pedPhonePlay置信度", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidenceconfig.description": "pedPhonePlay置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.22.aa_00002.c37b8e34.aiparam_pedphoneplay_confidenceconfig.name": "pedPhonePlay置信度偏移", + "resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.22.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.22.ba_00002.ffac0ae1.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.description": "检测时间:范围:1-3600。默认2。", + "resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.failedtip": "请输入1-3600的整数", + "resource.param.22.ba_00003.181f8b5a.param_detectionduration.detectiontimetype.1.name": "检测时间(秒)", + "resource.param.22.ba_00003.181f8b5a.param_sensitivity.description": "灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。", + "resource.param.22.ba_00003.181f8b5a.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.22.ba_00003.181f8b5a.param_sensitivity.name": "灵敏度", + "resource.param.22.ba_00004.0f53b331.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.22.ba_00004.0f53b331.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.22.ba_00004.0f53b331.param_overlaprate.name": "静止目标重叠率", + "resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "请选择是否打开叠加轨迹", + "resource.param.22.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name": "全景图叠加轨迹", + "resource.param.22.ba_00004.0f53b331.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.22.ba_00004.0f53b331.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.22.ba_00004.0f53b331.param_restrainswitch.name": "静止目标去重", + "resource.param.22.ba_00004.0f53b331.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.22.ba_00004.0f53b331.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.22.ba_00004.0f53b331.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip": "请输入0-100的整数", + "resource.param.22.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name": "告警次数", + "resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip": "请输入1-36000的整数", + "resource.param.22.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name": "告警时间间隔(秒)", + "resource.param.28862.28862.0.name": "默认", + "resource.param.28862.28862.1.name": "默认", + "resource.param.28862.28862.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.28862.28862.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.28862.28862.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.28862.28862.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.28862.28862.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.28862.28862.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.28862.28862.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.28862.28862.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.28862.28862.name.description": "区域名称:必填,限制32字符", + "resource.param.28862.28862.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.28862.28862.name.name": "区域名称", + "resource.param.28862.28862.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.28862.28862.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.28862.28862.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.28862.28862.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.28862.28862.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.28862.28862.param_overlaprate.name": "静止目标重叠率", + "resource.param.28862.28862.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.28862.28862.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.28862.28862.param_restrainswitch.name": "静止目标去重", + "resource.param.28862.28862.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.28862.28862.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.28862.28862.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.28862.aa_00001.4f8ba85c.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.28862.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.28862.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.28862.ba_00004.fd4e2090.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.28862.ba_00004.fd4e2090.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.28862.ba_00004.fd4e2090.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.28862.ba_00004.fd4e2090.param_overlaprate.name": "静止目标重叠率", + "resource.param.28862.ba_00004.fd4e2090.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.28862.ba_00004.fd4e2090.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.28862.ba_00004.fd4e2090.param_restrainswitch.name": "静止目标去重", + "resource.param.28862.ba_00004.fd4e2090.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.28862.ba_00004.fd4e2090.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.28862.ba_00004.fd4e2090.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.2935.2935.0.name": "默认", + "resource.param.2935.2935.name.description": "区域名称:必填,限制32字符", + "resource.param.2935.2935.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.2935.2935.name.name": "区域名称", + "resource.param.3.3.0.name": "默认", + "resource.param.3.3.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.3.3.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.3.3.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.3.3.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.3.3.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.3.3.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.3.3.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.3.3.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.3.3.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.3.3.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.3.3.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.3.3.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.3.3.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.3.3.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.3.3.name.description": "区域名称:必填,限制32字符", + "resource.param.3.3.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.3.3.name.name": "区域名称", + "resource.param.3.3.param_areaduration.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.3.3.param_areaduration.failedtip": "请输入正确的数值", + "resource.param.3.3.param_areaduration.name": "检测时间", + "resource.param.3.3.param_areadurationtimetype.description": "检测时间单位", + "resource.param.3.3.param_areadurationtimetype.failedtip": "请选择正确的数值", + "resource.param.3.3.param_areadurationtimetype.name": "检测时间单位", + "resource.param.3.3.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.3.3.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.3.3.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.3.3.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.3.3.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.3.3.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.3.3.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.3.3.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.3.3.param_restrainswitch.name": "静止目标去重", + "resource.param.3.3.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.3.3.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.3.3.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.3.3.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.3.3.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.3.3.param_targetalarmcount.name": "告警次数", + "resource.param.3.3.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.3.3.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.3.3.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.3.aa_00001.e9173765.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.3.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.3.ba_00002.fdd2a4cd.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.3.ba_00004.a5c23881.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.3.ba_00004.a5c23881.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.3.ba_00004.a5c23881.param_overlaprate.name": "静止目标重叠率", + "resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "请选择是否打开叠加轨迹", + "resource.param.3.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.name": "全景图叠加轨迹", + "resource.param.3.ba_00004.a5c23881.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.3.ba_00004.a5c23881.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.3.ba_00004.a5c23881.param_restrainswitch.name": "静止目标去重", + "resource.param.3.ba_00004.a5c23881.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.3.ba_00004.a5c23881.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.3.ba_00004.a5c23881.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.failedtip": "请输入0-100的整数", + "resource.param.3.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.name": "告警次数", + "resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.failedtip": "请输入1-36000的整数", + "resource.param.3.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.name": "告警时间间隔(秒)", + "resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.failedtip": "请输入正确的数值", + "resource.param.3.ba_00005.f21131a5.param_areaduration.areaalarmtype.4.name": "检测时间", + "resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.description": "检测时间单位", + "resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.failedtip": "请选择正确的数值", + "resource.param.3.ba_00005.f21131a5.param_areadurationtimetype.areaalarmtype.4.name": "检测时间单位", + "resource.param.32.32.1001003.0.pedestrian.namecn": "行人", + "resource.param.32.32.1001008.0.quality0.namecn": "行人质量0", + "resource.param.32.32.aiparam_1001003_frames.description": "追踪历史帧数。范围:2~100", + "resource.param.32.32.aiparam_1001003_frames.failedtip": "请输入2-100的整数", + "resource.param.32.32.aiparam_1001003_frames.name": "行人检测追踪历史帧数", + "resource.param.32.32.aiparam_1001003_motion.description": "静止阈值。范围:1~99,例如:80.0", + "resource.param.32.32.aiparam_1001003_motion.failedtip": "请输入1-99的一位小数", + "resource.param.32.32.aiparam_1001003_motion.name": "行人检测静止阈值", + "resource.param.32.32.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.32.32.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.32.32.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.32.32.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.32.32.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.32.32.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.32.32.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.32.32.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.32.32.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.32.32.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.32.32.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.32.32.aiparam_quality0_confidence.description": "行人质量0置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.32.32.aiparam_quality0_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.32.32.aiparam_quality0_confidence.name": "行人质量0置信度", + "resource.param.32.32.aiparam_quality0_confidenceconfig.description": "行人质量0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.32.32.aiparam_quality0_confidenceconfig.name": "行人质量0置信度偏移", + "resource.param.32.32.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.32.32.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.32.32.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.32.32.name.description": "区域名称:必填,限制32字符", + "resource.param.32.32.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.32.32.name.name": "区域名称", + "resource.param.32.32.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.32.32.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.32.32.param_detectionduration.name": "检测时间(秒)", + "resource.param.32.32.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.32.32.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.32.32.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.32.32.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.32.32.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.32.32.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.32.32.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.32.32.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.32.32.param_restrainswitch.name": "静止目标去重", + "resource.param.32.32.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.32.32.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.32.32.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.32.32.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.32.32.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.32.32.param_sensitivity.name": "灵敏度", + "resource.param.32.32.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.32.32.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.32.32.param_targetalarmcount.name": "告警次数", + "resource.param.32.32.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.32.32.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.32.32.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.32.32.param_videoreadfps.description": "离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。", + "resource.param.32.32.param_videoreadfps.failedtip": "请输入正确的值", + "resource.param.32.32.param_videoreadfps.name": "离线视频播放取帧帧率", + "resource.param.32.32.param_videorepeatcount.description": "离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次", + "resource.param.32.32.param_videorepeatcount.failedtip": "请输入1-100的整数", + "resource.param.32.32.param_videorepeatcount.name": "离线视频播放次数", + "resource.param.32.32.param_workclothesset.description": "选择需要比对的工服分组", + "resource.param.32.32.param_workclothesset.failedtip": "请选择正确的值", + "resource.param.32.32.param_workclothesset.name": "绑定工服分组", + "resource.param.32.aa_00001.1ffc7361.1001003.0.pedestrian.namecn": "行人", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.32.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.32.aa_00002.40a88def.1001008.0.quality0.namecn": "行人质量0", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.description": "行人质量0置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidence.name": "行人质量0置信度", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidenceconfig.description": "行人质量0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.32.aa_00002.40a88def.aiparam_quality0_confidenceconfig.name": "行人质量0置信度偏移", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.description": "追踪历史帧数。范围:2~100", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.failedtip": "请输入2-100的整数", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_frames.name": "行人检测追踪历史帧数", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.description": "静止阈值。范围:1~99,例如:80.0", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.failedtip": "请输入1-99的一位小数", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_motion.name": "行人检测静止阈值", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.32.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.32.aa_00005.247f620f.param_workclothesset.description": "选择需要比对的工服分组", + "resource.param.32.aa_00005.247f620f.param_workclothesset.failedtip": "请选择正确的值", + "resource.param.32.aa_00005.247f620f.param_workclothesset.name": "绑定工服分组", + "resource.param.32.ba_00001.551596af.param_videoreadfps.description": "离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。", + "resource.param.32.ba_00001.551596af.param_videoreadfps.failedtip": "请输入正确的值", + "resource.param.32.ba_00001.551596af.param_videoreadfps.name": "离线视频播放取帧帧率", + "resource.param.32.ba_00001.551596af.param_videorepeatcount.description": "离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次", + "resource.param.32.ba_00001.551596af.param_videorepeatcount.failedtip": "请输入1-100的整数", + "resource.param.32.ba_00001.551596af.param_videorepeatcount.name": "离线视频播放次数", + "resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.32.ba_00002.6cdfc847.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.32.ba_00003.22705515.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.32.ba_00003.22705515.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.32.ba_00003.22705515.param_detectionduration.name": "检测时间(秒)", + "resource.param.32.ba_00003.22705515.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.32.ba_00003.22705515.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.32.ba_00003.22705515.param_sensitivity.name": "灵敏度", + "resource.param.32.ba_00004.da078adb.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.32.ba_00004.da078adb.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.32.ba_00004.da078adb.param_overlaprate.name": "静止目标重叠率", + "resource.param.32.ba_00004.da078adb.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.32.ba_00004.da078adb.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.32.ba_00004.da078adb.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.32.ba_00004.da078adb.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.32.ba_00004.da078adb.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.32.ba_00004.da078adb.param_restrainswitch.name": "静止目标去重", + "resource.param.32.ba_00004.da078adb.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.32.ba_00004.da078adb.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.32.ba_00004.da078adb.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.32.ba_00004.da078adb.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.32.ba_00004.da078adb.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.32.ba_00004.da078adb.param_targetalarmcount.name": "告警次数", + "resource.param.32.ba_00004.da078adb.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.32.ba_00004.da078adb.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.32.ba_00004.da078adb.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.34707.34707.0.name": "默认", + "resource.param.34707.34707.name.description": "区域名称:必填,限制32字符", + "resource.param.34707.34707.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.34707.34707.name.name": "区域名称", + "resource.param.34707.34707.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.34707.34707.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.34707.34707.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.34707.34707.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.34707.34707.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.34707.34707.param_overlaprate.name": "静止目标重叠率", + "resource.param.34707.34707.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.34707.34707.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.34707.34707.param_restrainswitch.name": "静止目标去重", + "resource.param.34707.34707.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.34707.34707.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.34707.34707.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.34707.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.34707.ba_00004.7ec477cd.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.34707.ba_00004.7ec477cd.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.34707.ba_00004.7ec477cd.param_overlaprate.name": "静止目标重叠率", + "resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.34707.ba_00004.7ec477cd.param_restrainswitch.name": "静止目标去重", + "resource.param.34707.ba_00004.7ec477cd.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.34707.ba_00004.7ec477cd.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.34707.ba_00004.7ec477cd.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.38873.38873.0.name": "默认", + "resource.param.38873.38873.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.38873.38873.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.38873.38873.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.38873.38873.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.38873.38873.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.38873.38873.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.38873.38873.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.38873.38873.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.38873.38873.name.description": "区域名称:必填,限制32字符", + "resource.param.38873.38873.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.38873.38873.name.name": "区域名称", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.description": "face置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidence.name": "face置信度", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidenceconfig.description": "face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_confidenceconfig.name": "face置信度偏移", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.failedtip": "请选择正确的值", + "resource.param.38873.pa_00001.0fa44adc.aiparam_face_detpostion.name": "face检测方式", + "resource.param.5.5.1001003.0.pedestrian.namecn": "行人", + "resource.param.5.5.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.5.5.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.5.5.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.5.5.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.5.5.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.5.5.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.5.5.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.5.5.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.5.5.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.5.5.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.5.5.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.5.5.name.description": "区域名称:必填,限制32字符", + "resource.param.5.5.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.5.5.name.name": "区域名称", + "resource.param.5.5.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.5.5.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.5.5.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.5.5.param_arealimitduration.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.5.5.param_arealimitduration.failedtip": "请输入正确的数值", + "resource.param.5.5.param_arealimitduration.name": "检测时间", + "resource.param.5.5.param_arealimitdurationtimetype.description": "检测时间单位", + "resource.param.5.5.param_arealimitdurationtimetype.failedtip": "请选择正确的数值", + "resource.param.5.5.param_arealimitdurationtimetype.name": "检测时间单位", + "resource.param.5.5.param_arealimittargetcount.description": "区域中的目标数", + "resource.param.5.5.param_arealimittargetcount.failedtip": "请输入0-3600的整数", + "resource.param.5.5.param_arealimittargetcount.name": "区域中的目标数", + "resource.param.5.5.param_arealimittargettype.description": "区域中目标数限制类型", + "resource.param.5.5.param_arealimittargettype.failedtip": "请选择正确的值", + "resource.param.5.5.param_arealimittargettype.name": "区域中目标数限制类型", + "resource.param.5.5.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.5.5.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.5.5.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.5.5.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.5.5.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.5.5.param_restrainswitch.name": "静止目标去重", + "resource.param.5.5.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.5.5.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.5.5.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.5.aa_00001.bc4f4b27.1001003.0.pedestrian.namecn": "行人", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.5.aa_00001.bc4f4b27.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.5.ba_00002.72ec426d.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.5.ba_00004.f0c9e210.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.5.ba_00004.f0c9e210.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.5.ba_00004.f0c9e210.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.5.ba_00004.f0c9e210.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.5.ba_00004.f0c9e210.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.5.ba_00004.f0c9e210.param_overlaprate.name": "静止目标重叠率", + "resource.param.5.ba_00004.f0c9e210.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.5.ba_00004.f0c9e210.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.5.ba_00004.f0c9e210.param_restrainswitch.name": "静止目标去重", + "resource.param.5.ba_00004.f0c9e210.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.5.ba_00004.f0c9e210.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.5.ba_00004.f0c9e210.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.5.ba_00005.ab935f8a.param_arealimitduration.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.5.ba_00005.ab935f8a.param_arealimitduration.failedtip": "请输入正确的数值", + "resource.param.5.ba_00005.ab935f8a.param_arealimitduration.name": "检测时间", + "resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.description": "检测时间单位", + "resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.failedtip": "请选择正确的数值", + "resource.param.5.ba_00005.ab935f8a.param_arealimitdurationtimetype.name": "检测时间单位", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.description": "用于和区域内实际有效目标数量进行比较的阈值", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.failedtip": "请输入0-3600的整数", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargetcount.name": "目标数量阈值", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.description": "区域中目标数限制类型", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.failedtip": "请选择正确的值", + "resource.param.5.ba_00005.ab935f8a.param_arealimittargettype.name": "触发条件", + "resource.param.50813.50813.0.name": "默认", + "resource.param.50813.50813.1.name": "默认", + "resource.param.50813.50813.aiparam_hatless_confidence.description": "hatless置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.50813.aiparam_hatless_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.50813.aiparam_hatless_confidence.name": "hatless置信度", + "resource.param.50813.50813.aiparam_hatless_confidenceconfig.description": "hatless置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.50813.aiparam_hatless_confidenceconfig.name": "hatless置信度偏移", + "resource.param.50813.50813.aiparam_normalhat_confidence.description": "normalHat置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.50813.aiparam_normalhat_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.50813.aiparam_normalhat_confidence.name": "normalHat置信度", + "resource.param.50813.50813.aiparam_normalhat_confidenceconfig.description": "normalHat置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.50813.aiparam_normalhat_confidenceconfig.name": "normalHat置信度偏移", + "resource.param.50813.50813.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.50813.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.50813.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.50813.50813.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.50813.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.50813.50813.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.50813.50813.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.50813.50813.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.50813.50813.aiparam_pedhelmet_confidence.description": "pedHelmet置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.50813.aiparam_pedhelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.50813.aiparam_pedhelmet_confidence.name": "pedHelmet置信度", + "resource.param.50813.50813.aiparam_pedhelmet_confidenceconfig.description": "pedHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.50813.aiparam_pedhelmet_confidenceconfig.name": "pedHelmet置信度偏移", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidence.description": "pedSafeHelmet置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidence.name": "pedSafeHelmet置信度", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidenceconfig.description": "pedSafeHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.50813.aiparam_pedsafehelmet_confidenceconfig.name": "pedSafeHelmet置信度偏移", + "resource.param.50813.50813.aiparam_unsure_confidence.description": "unsure置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.50813.aiparam_unsure_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.50813.aiparam_unsure_confidence.name": "unsure置信度", + "resource.param.50813.50813.aiparam_unsure_confidenceconfig.description": "unsure置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.50813.aiparam_unsure_confidenceconfig.name": "unsure置信度偏移", + "resource.param.50813.50813.name.description": "区域名称:必填,限制32字符", + "resource.param.50813.50813.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.50813.50813.name.name": "区域名称", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.50813.pa_00001.27f515bd.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidence.description": "hatless置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidence.name": "hatless置信度", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.description": "hatless置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.name": "hatless置信度偏移", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidence.description": "normalHat置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidence.name": "normalHat置信度", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.description": "normalHat置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.name": "normalHat置信度偏移", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.description": "pedHelmet置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.name": "pedHelmet置信度", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.description": "pedHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.name": "pedHelmet置信度偏移", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.description": "pedSafeHelmet置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.name": "pedSafeHelmet置信度", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.description": "pedSafeHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.name": "pedSafeHelmet置信度偏移", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidence.description": "unsure置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidence.name": "unsure置信度", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.description": "unsure置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.50813.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.name": "unsure置信度偏移", + "resource.param.51.51.1001003.0.pedestrian.namecn": "行人", + "resource.param.51.51.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.51.51.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.51.51.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.51.51.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.51.51.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.51.51.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.51.51.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.51.51.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.51.51.name.description": "区域名称:必填,限制32字符", + "resource.param.51.51.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.51.51.name.name": "区域名称", + "resource.param.51.51.param_areacalcduration.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.51.51.param_areacalcduration.failedtip": "请输入正确的数值", + "resource.param.51.51.param_areacalcduration.name": "区域人数上报间隔", + "resource.param.51.51.param_areacalcdurationtimetype.description": "检测时间单位", + "resource.param.51.51.param_areacalcdurationtimetype.failedtip": "请选择正确的数值", + "resource.param.51.51.param_areacalcdurationtimetype.name": "检测时间单位", + "resource.param.51.51.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.51.51.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.51.51.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.51.51.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.51.51.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.51.51.param_restrainswitch.name": "静止目标去重", + "resource.param.51.51.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.51.51.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.51.51.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.51.51.param_targetcalctype.description": "目标统计方式", + "resource.param.51.51.param_targetcalctype.failedtip": "请选择正确的值", + "resource.param.51.51.param_targetcalctype.name": "目标统计方式", + "resource.param.51.51.param_videoreadfps.description": "离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。", + "resource.param.51.51.param_videoreadfps.failedtip": "请输入正确的值", + "resource.param.51.51.param_videoreadfps.name": "离线视频播放取帧帧率", + "resource.param.51.51.param_videorepeatcount.description": "离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次", + "resource.param.51.51.param_videorepeatcount.failedtip": "请输入1-100的整数", + "resource.param.51.51.param_videorepeatcount.name": "离线视频播放次数", + "resource.param.51.aa_00001.e9173765.1001003.0.pedestrian.namecn": "行人", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.51.aa_00001.e9173765.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.51.ba_00001.4053a96d.param_videoreadfps.description": "离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。", + "resource.param.51.ba_00001.4053a96d.param_videoreadfps.failedtip": "请输入正确的值", + "resource.param.51.ba_00001.4053a96d.param_videoreadfps.name": "离线视频播放取帧帧率", + "resource.param.51.ba_00001.4053a96d.param_videorepeatcount.description": "离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次", + "resource.param.51.ba_00001.4053a96d.param_videorepeatcount.failedtip": "请输入1-100的整数", + "resource.param.51.ba_00001.4053a96d.param_videorepeatcount.name": "离线视频播放次数", + "resource.param.51.ba_00004.9de4af16.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.51.ba_00004.9de4af16.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.51.ba_00004.9de4af16.param_overlaprate.name": "静止目标重叠率", + "resource.param.51.ba_00004.9de4af16.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.51.ba_00004.9de4af16.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.51.ba_00004.9de4af16.param_restrainswitch.name": "静止目标去重", + "resource.param.51.ba_00004.9de4af16.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.51.ba_00004.9de4af16.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.51.ba_00004.9de4af16.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.51.ba_00005.667e48b6.param_areacalcduration.description": "数量上报间隔:范围:1-3600000,注意时间单位", + "resource.param.51.ba_00005.667e48b6.param_areacalcduration.failedtip": "请输入正确的数值", + "resource.param.51.ba_00005.667e48b6.param_areacalcduration.name": "数量上报间隔", + "resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.description": "数量上报间隔时间单位", + "resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.failedtip": "请选择正确的单位", + "resource.param.51.ba_00005.667e48b6.param_areacalcdurationtimetype.name": "数量上报间隔时间单位", + "resource.param.51.ba_00005.667e48b6.param_targetcalctype.description": "目标统计方式", + "resource.param.51.ba_00005.667e48b6.param_targetcalctype.failedtip": "请选择正确的值", + "resource.param.51.ba_00005.667e48b6.param_targetcalctype.name": "目标统计方式", + "resource.param.57.57.0.name": "默认", + "resource.param.57.57.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.57.57.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.57.57.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.57.57.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.57.57.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.57.57.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.57.57.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.57.57.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.57.57.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.57.57.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.57.57.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.57.57.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.57.57.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.57.57.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.57.57.name.description": "区域名称:必填,限制32字符", + "resource.param.57.57.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.57.57.name.name": "区域名称", + "resource.param.57.57.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.57.57.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.57.57.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.57.57.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.57.57.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.57.57.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.57.57.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.57.57.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.57.57.param_restrainswitch.name": "静止目标去重", + "resource.param.57.57.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.57.57.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.57.57.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.57.57.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.57.57.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.57.57.param_targetalarmcount.name": "告警次数", + "resource.param.57.57.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.57.57.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.57.57.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.57.57.param_trippingwiretype.description": "告警条件:目标过线的数量", + "resource.param.57.57.param_trippingwiretype.failedtip": "请选择正确的值", + "resource.param.57.57.param_trippingwiretype.name": "绊线类型", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.57.aa_00001.e9173765.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.57.aa_00003.9253e062.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.57.ba_00002.fdd2a4cd.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.57.ba_00004.a5c23881.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.57.ba_00004.a5c23881.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.57.ba_00004.a5c23881.param_overlaprate.name": "静止目标重叠率", + "resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "请选择是否打开叠加轨迹", + "resource.param.57.ba_00004.a5c23881.param_overlaytrajectory.custparam_alarmtype.2.name": "全景图叠加轨迹", + "resource.param.57.ba_00004.a5c23881.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.57.ba_00004.a5c23881.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.57.ba_00004.a5c23881.param_restrainswitch.name": "静止目标去重", + "resource.param.57.ba_00004.a5c23881.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.57.ba_00004.a5c23881.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.57.ba_00004.a5c23881.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.failedtip": "请输入0-100的整数", + "resource.param.57.ba_00004.a5c23881.param_targetalarmcount.custparam_alarmtype.2.name": "告警次数", + "resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.failedtip": "请输入1-36000的整数", + "resource.param.57.ba_00004.a5c23881.param_targetalarminterval.custparam_alarmtype.2.name": "告警时间间隔(秒)", + "resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.description": "告警条件:目标过线的数量", + "resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.failedtip": "请选择正确的值", + "resource.param.57.ba_00005.f7750059.param_trippingwiretype.areaalarmtype.2.name": "绊线类型", + "resource.param.58.58.1001003.0.pedestrian.namecn": "行人", + "resource.param.58.58.1001008.0.quality0.namecn": "行人质量0", + "resource.param.58.58.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.58.58.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.58.58.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.58.58.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.58.58.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.58.58.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.58.58.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.58.58.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.58.58.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.58.58.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.58.58.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.58.58.aiparam_quality0_confidence.description": "行人质量0置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.58.58.aiparam_quality0_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.58.58.aiparam_quality0_confidence.name": "行人质量0置信度", + "resource.param.58.58.aiparam_quality0_confidenceconfig.description": "行人质量0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.58.58.aiparam_quality0_confidenceconfig.name": "行人质量0置信度偏移", + "resource.param.58.58.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.58.58.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.58.58.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.58.58.name.description": "区域名称:必填,限制32字符", + "resource.param.58.58.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.58.58.name.name": "区域名称", + "resource.param.58.58.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.58.58.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.58.58.param_detectionduration.name": "检测时间(秒)", + "resource.param.58.58.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.58.58.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.58.58.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.58.58.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.58.58.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.58.58.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.58.58.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.58.58.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.58.58.param_restrainswitch.name": "静止目标去重", + "resource.param.58.58.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.58.58.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.58.58.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.58.58.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.58.58.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.58.58.param_sensitivity.name": "灵敏度", + "resource.param.58.58.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.58.58.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.58.58.param_targetalarmcount.name": "告警次数", + "resource.param.58.58.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.58.58.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.58.58.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.58.58.param_workclothesset.description": "选择需要比对的工服分组", + "resource.param.58.58.param_workclothesset.failedtip": "请选择正确的值", + "resource.param.58.58.param_workclothesset.name": "绑定工服分组", + "resource.param.58.aa_00001.1ffc7361.1001003.0.pedestrian.namecn": "行人", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.58.aa_00001.1ffc7361.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.58.aa_00002.40a88def.1001008.0.quality0.namecn": "行人质量0", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.description": "行人质量0置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidence.name": "行人质量0置信度", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidenceconfig.description": "行人质量0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.58.aa_00002.40a88def.aiparam_quality0_confidenceconfig.name": "行人质量0置信度偏移", + "resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.58.aa_00003.0ca3cfc7.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.58.aa_00005.247f620f.param_workclothesset.description": "选择需要比对的工服分组", + "resource.param.58.aa_00005.247f620f.param_workclothesset.failedtip": "请选择正确的值", + "resource.param.58.aa_00005.247f620f.param_workclothesset.name": "绑定工服分组", + "resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.58.ba_00002.6cdfc847.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.58.ba_00003.bc6d90f2.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.58.ba_00003.bc6d90f2.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.58.ba_00003.bc6d90f2.param_detectionduration.name": "检测时间(秒)", + "resource.param.58.ba_00003.bc6d90f2.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.58.ba_00003.bc6d90f2.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.58.ba_00003.bc6d90f2.param_sensitivity.name": "灵敏度", + "resource.param.58.ba_00004.da078adb.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.58.ba_00004.da078adb.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.58.ba_00004.da078adb.param_overlaprate.name": "静止目标重叠率", + "resource.param.58.ba_00004.da078adb.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.58.ba_00004.da078adb.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.58.ba_00004.da078adb.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.58.ba_00004.da078adb.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.58.ba_00004.da078adb.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.58.ba_00004.da078adb.param_restrainswitch.name": "静止目标去重", + "resource.param.58.ba_00004.da078adb.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.58.ba_00004.da078adb.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.58.ba_00004.da078adb.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.58.ba_00004.da078adb.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.58.ba_00004.da078adb.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.58.ba_00004.da078adb.param_targetalarmcount.name": "告警次数", + "resource.param.58.ba_00004.da078adb.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.58.ba_00004.da078adb.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.58.ba_00004.da078adb.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.6.6.0.name": "默认", + "resource.param.6.6.aiparam_1001003_frames.description": "追踪历史帧数。范围:2~100", + "resource.param.6.6.aiparam_1001003_frames.failedtip": "请输入2-100的整数", + "resource.param.6.6.aiparam_1001003_frames.name": "行人检测追踪历史帧数", + "resource.param.6.6.aiparam_1001003_motion.description": "静止阈值。范围:1~99,例如:80.0", + "resource.param.6.6.aiparam_1001003_motion.failedtip": "请输入1-99的一位小数", + "resource.param.6.6.aiparam_1001003_motion.name": "行人检测静止阈值", + "resource.param.6.6.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.6.6.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.6.6.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.6.6.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.6.6.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.6.6.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.6.6.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.6.6.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.6.6.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.6.6.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.6.6.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.6.6.aiparam_pedfalldown_confidence.description": "跌倒置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.6.6.aiparam_pedfalldown_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.6.6.aiparam_pedfalldown_confidence.name": "跌倒置信度", + "resource.param.6.6.aiparam_pedfalldown_confidenceconfig.description": "跌倒置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.6.6.aiparam_pedfalldown_confidenceconfig.name": "跌倒置信度偏移", + "resource.param.6.6.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.6.6.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.6.6.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.6.6.name.description": "区域名称:必填,限制32字符", + "resource.param.6.6.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.6.6.name.name": "区域名称", + "resource.param.6.6.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.6.6.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.6.6.param_detectionduration.name": "检测时间(秒)", + "resource.param.6.6.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.6.6.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.6.6.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.6.6.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.6.6.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.6.6.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.6.6.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.6.6.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.6.6.param_restrainswitch.name": "静止目标去重", + "resource.param.6.6.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.6.6.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.6.6.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.6.6.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.6.6.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.6.6.param_sensitivity.name": "灵敏度", + "resource.param.6.6.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.6.6.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.6.6.param_targetalarmcount.name": "告警次数", + "resource.param.6.6.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.6.6.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.6.6.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.6.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.description": "pedfalldown置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidence.name": "pedfalldown置信度", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidenceconfig.description": "pedfalldown置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.6.aa_00002.c37b8e34.aiparam_pedfalldown_confidenceconfig.name": "pedfalldown置信度偏移", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.description": "追踪历史帧数。范围:2~100", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.failedtip": "请输入2-100的整数", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_frames.name": "行人检测追踪历史帧数", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.description": "静止阈值。范围:1~99,例如:80.0", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.failedtip": "请输入1-99的一位小数", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_motion.name": "行人检测静止阈值", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.6.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.6.ba_00002.d56fc47d.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.description": "检测时间:范围:1-3600。默认2。", + "resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.failedtip": "请输入1-3600的整数", + "resource.param.6.ba_00003.6dbede3b.param_detectionduration.detectiontimetype.1.name": "检测时间(秒)", + "resource.param.6.ba_00003.6dbede3b.param_sensitivity.description": "灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。", + "resource.param.6.ba_00003.6dbede3b.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.6.ba_00003.6dbede3b.param_sensitivity.name": "灵敏度", + "resource.param.6.ba_00004.0f53b331.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.6.ba_00004.0f53b331.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.6.ba_00004.0f53b331.param_overlaprate.name": "静止目标重叠率", + "resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "请选择是否打开叠加轨迹", + "resource.param.6.ba_00004.0f53b331.param_overlaytrajectory.custparam_alarmtype.2.name": "全景图叠加轨迹", + "resource.param.6.ba_00004.0f53b331.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.6.ba_00004.0f53b331.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.6.ba_00004.0f53b331.param_restrainswitch.name": "静止目标去重", + "resource.param.6.ba_00004.0f53b331.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.6.ba_00004.0f53b331.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.6.ba_00004.0f53b331.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.failedtip": "请输入0-100的整数", + "resource.param.6.ba_00004.0f53b331.param_targetalarmcount.custparam_alarmtype.2.name": "告警次数", + "resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.failedtip": "请输入1-36000的整数", + "resource.param.6.ba_00004.0f53b331.param_targetalarminterval.custparam_alarmtype.2.name": "告警时间间隔(秒)", + "resource.param.60460.60460.0.name": "默认", + "resource.param.60460.60460.1.name": "默认", + "resource.param.60460.60460.name.description": "区域名称:必填,限制32字符", + "resource.param.60460.60460.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.60460.60460.name.name": "区域名称", + "resource.param.65.65.1001003.0.pedestrian.namecn": "行人", + "resource.param.65.65.1001010.0.pedsleepstomach.namecn": "行人睡姿-趴睡", + "resource.param.65.65.1001010.5.pedsleepliedown.namecn": "行人睡姿-躺着睡", + "resource.param.65.65.aiparam_1001003_frames.description": "追踪历史帧数。范围:2~100", + "resource.param.65.65.aiparam_1001003_frames.failedtip": "请输入2-100的整数", + "resource.param.65.65.aiparam_1001003_frames.name": "行人检测追踪历史帧数", + "resource.param.65.65.aiparam_1001003_motion.description": "静止阈值。范围:1~99,例如:80.0", + "resource.param.65.65.aiparam_1001003_motion.failedtip": "请输入1-99的一位小数", + "resource.param.65.65.aiparam_1001003_motion.name": "行人检测静止阈值", + "resource.param.65.65.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.65.65.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.65.65.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.65.65.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.65.65.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.65.65.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.65.65.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.65.65.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.65.65.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.65.65.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.65.65.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.65.65.aiparam_pedsleepliedown_confidence.description": "行人睡姿-躺着睡置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.65.65.aiparam_pedsleepliedown_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.65.65.aiparam_pedsleepliedown_confidence.name": "行人睡姿-躺着睡置信度", + "resource.param.65.65.aiparam_pedsleepliedown_confidenceconfig.description": "行人睡姿-躺着睡置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.65.65.aiparam_pedsleepliedown_confidenceconfig.name": "行人睡姿-躺着睡置信度偏移", + "resource.param.65.65.aiparam_pedsleepstomach_confidence.description": "行人睡姿-趴睡置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.65.65.aiparam_pedsleepstomach_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.65.65.aiparam_pedsleepstomach_confidence.name": "行人睡姿-趴睡置信度", + "resource.param.65.65.aiparam_pedsleepstomach_confidenceconfig.description": "行人睡姿-趴睡置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.65.65.aiparam_pedsleepstomach_confidenceconfig.name": "行人睡姿-趴睡置信度偏移", + "resource.param.65.65.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.65.65.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.65.65.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.65.65.name.description": "区域名称:必填,限制32字符", + "resource.param.65.65.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.65.65.name.name": "区域名称", + "resource.param.65.65.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.65.65.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.65.65.param_detectionduration.name": "检测时间(秒)", + "resource.param.65.65.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.65.65.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.65.65.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.65.65.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.65.65.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.65.65.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.65.65.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.65.65.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.65.65.param_restrainswitch.name": "静止目标去重", + "resource.param.65.65.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.65.65.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.65.65.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.65.65.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.65.65.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.65.65.param_sensitivity.name": "灵敏度", + "resource.param.65.65.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.65.65.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.65.65.param_targetalarmcount.name": "告警次数", + "resource.param.65.65.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.65.65.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.65.65.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.65.aa_00001.487c1cf0.1001003.0.pedestrian.namecn": "行人", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.description": "行人置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidence.name": "行人置信度", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.description": "行人置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_confidenceconfig.name": "行人置信度偏移", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.65.aa_00001.487c1cf0.aiparam_pedestrian_detpostion.name": "行人检测方式", + "resource.param.65.aa_00002.c37b8e34.1001010.0.pedsleepstomach.namecn": "行人睡姿-趴睡", + "resource.param.65.aa_00002.c37b8e34.1001010.5.pedsleepliedown.namecn": "行人睡姿-躺着睡", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.description": "行人睡姿-躺着睡置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidence.name": "行人睡姿-躺着睡置信度", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidenceconfig.description": "行人睡姿-躺着睡置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepliedown_confidenceconfig.name": "行人睡姿-躺着睡置信度偏移", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.description": "行人睡姿-趴睡置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidence.name": "行人睡姿-趴睡置信度", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidenceconfig.description": "行人睡姿-趴睡置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.65.aa_00002.c37b8e34.aiparam_pedsleepstomach_confidenceconfig.name": "行人睡姿-趴睡置信度偏移", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.description": "追踪历史帧数。范围:2~100", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.failedtip": "请输入2-100的整数", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_frames.name": "行人检测追踪历史帧数", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.description": "静止阈值。范围:1~99,例如:80.0", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.failedtip": "请输入1-99的一位小数", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_motion.name": "行人检测静止阈值", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.65.aa_00003.c232a753.aiparam_1001003_trackdynamicmatch.name": "行人检测追踪半径", + "resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.description": "最小行人尺寸:行人抓拍照片的最小图像尺寸。如输入值为100,则最小行人尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.failedtip": "请输入0-10000的整数", + "resource.param.65.ba_00002.d56fc47d.filter_pedestrian_side_min.name": "最小行人尺寸", + "resource.param.65.ba_00003.b00198a1.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.65.ba_00003.b00198a1.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.65.ba_00003.b00198a1.param_detectionduration.name": "检测时间(秒)", + "resource.param.65.ba_00003.b00198a1.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.65.ba_00003.b00198a1.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.65.ba_00003.b00198a1.param_sensitivity.name": "灵敏度", + "resource.param.65.ba_00004.0f53b331.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.65.ba_00004.0f53b331.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.65.ba_00004.0f53b331.param_overlaprate.name": "静止目标重叠率", + "resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.65.ba_00004.0f53b331.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.65.ba_00004.0f53b331.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.65.ba_00004.0f53b331.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.65.ba_00004.0f53b331.param_restrainswitch.name": "静止目标去重", + "resource.param.65.ba_00004.0f53b331.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.65.ba_00004.0f53b331.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.65.ba_00004.0f53b331.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.65.ba_00004.0f53b331.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.65.ba_00004.0f53b331.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.65.ba_00004.0f53b331.param_targetalarmcount.name": "告警次数", + "resource.param.65.ba_00004.0f53b331.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.65.ba_00004.0f53b331.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.65.ba_00004.0f53b331.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.67093.67093.0.name": "默认", + "resource.param.67093.67093.1.name": "默认", + "resource.param.67093.67093.name.description": "区域名称:必填,限制32字符", + "resource.param.67093.67093.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.67093.67093.name.name": "区域名称", + "resource.param.67093.67093.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.67093.67093.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.67093.67093.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.67093.67093.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.67093.67093.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.67093.67093.param_overlaprate.name": "静止目标重叠率", + "resource.param.67093.67093.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.67093.67093.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.67093.67093.param_restrainswitch.name": "静止目标去重", + "resource.param.67093.67093.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.67093.67093.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.67093.67093.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.67093.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.67093.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.67093.ba_00004.7ec477cd.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.67093.ba_00004.7ec477cd.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.67093.ba_00004.7ec477cd.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.67093.ba_00004.7ec477cd.param_overlaprate.name": "静止目标重叠率", + "resource.param.67093.ba_00004.7ec477cd.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.67093.ba_00004.7ec477cd.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.67093.ba_00004.7ec477cd.param_restrainswitch.name": "静止目标去重", + "resource.param.67093.ba_00004.7ec477cd.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.67093.ba_00004.7ec477cd.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.67093.ba_00004.7ec477cd.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.7.7.2000001.1.nonmotorvehicle.namecn": "非机动车", + "resource.param.7.7.2000001.2.vehicle.namecn": "车辆", + "resource.param.7.7.aiparam_2000001_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.7.7.aiparam_2000001_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.7.7.aiparam_2000001_trackdynamicmatch.name": "车辆检测追踪半径", + "resource.param.7.7.aiparam_nonmotorvehicle_confidence.description": "非机动车置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.7.7.aiparam_nonmotorvehicle_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.7.7.aiparam_nonmotorvehicle_confidence.name": "非机动车置信度", + "resource.param.7.7.aiparam_nonmotorvehicle_confidenceconfig.description": "非机动车置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.7.7.aiparam_nonmotorvehicle_confidenceconfig.name": "非机动车置信度偏移", + "resource.param.7.7.aiparam_nonmotorvehicle_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.7.7.aiparam_nonmotorvehicle_detpostion.failedtip": "请选择正确的值", + "resource.param.7.7.aiparam_nonmotorvehicle_detpostion.name": "非机动车检测方式", + "resource.param.7.7.aiparam_vehicle_confidence.description": "车辆置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.7.7.aiparam_vehicle_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.7.7.aiparam_vehicle_confidence.name": "车辆置信度", + "resource.param.7.7.aiparam_vehicle_confidenceconfig.description": "车辆置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.7.7.aiparam_vehicle_confidenceconfig.name": "车辆置信度偏移", + "resource.param.7.7.aiparam_vehicle_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.7.7.aiparam_vehicle_detpostion.failedtip": "请选择正确的值", + "resource.param.7.7.aiparam_vehicle_detpostion.name": "车辆检测方式", + "resource.param.7.7.filter_nonmotorvehicle_side_min.description": "最小非机动车尺寸:非机动车抓拍照片的最小图像尺寸。如输入值为100,则最小非机动车尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.7.7.filter_nonmotorvehicle_side_min.failedtip": "请输入0-10000的整数", + "resource.param.7.7.filter_nonmotorvehicle_side_min.name": "最小非机动车尺寸", + "resource.param.7.7.filter_vehicle_side_min.description": "最小车辆尺寸:车辆抓拍照片的最小图像尺寸。如输入值为100,则最小车辆尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.7.7.filter_vehicle_side_min.failedtip": "请输入0-10000的整数", + "resource.param.7.7.filter_vehicle_side_min.name": "最小车辆尺寸", + "resource.param.7.7.name.description": "区域名称:必填,限制32字符", + "resource.param.7.7.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.7.7.name.name": "区域名称", + "resource.param.7.7.param_areaduration.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.7.7.param_areaduration.failedtip": "请输入正确的数值", + "resource.param.7.7.param_areaduration.name": "检测时间", + "resource.param.7.7.param_areadurationtimetype.description": "检测时间单位", + "resource.param.7.7.param_areadurationtimetype.failedtip": "请选择正确的数值", + "resource.param.7.7.param_areadurationtimetype.name": "检测时间单位", + "resource.param.7.7.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.7.7.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.7.7.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.7.7.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.7.7.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.7.7.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.7.7.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.7.7.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.7.7.param_restrainswitch.name": "静止目标去重", + "resource.param.7.7.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.7.7.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.7.7.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.7.7.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.7.7.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.7.7.param_targetalarmcount.name": "告警次数", + "resource.param.7.7.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.7.7.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.7.7.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.7.7.param_videoreadfps.description": "离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。", + "resource.param.7.7.param_videoreadfps.failedtip": "请输入正确的值", + "resource.param.7.7.param_videoreadfps.name": "离线视频播放取帧帧率", + "resource.param.7.7.param_videorepeatcount.description": "离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次", + "resource.param.7.7.param_videorepeatcount.failedtip": "请输入1-100的整数", + "resource.param.7.7.param_videorepeatcount.name": "离线视频播放次数", + "resource.param.7.aa_00001.ddd59411.2000001.1.nonmotorvehicle.namecn": "非机动车", + "resource.param.7.aa_00001.ddd59411.2000001.2.vehicle.namecn": "车辆", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.description": "非机动车置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidence.name": "非机动车置信度", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidenceconfig.description": "非机动车置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_confidenceconfig.name": "非机动车置信度偏移", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.failedtip": "请选择正确的值", + "resource.param.7.aa_00001.ddd59411.aiparam_nonmotorvehicle_detpostion.name": "非机动车检测方式", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.description": "车辆置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidence.name": "车辆置信度", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidenceconfig.description": "车辆置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_confidenceconfig.name": "车辆置信度偏移", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.failedtip": "请选择正确的值", + "resource.param.7.aa_00001.ddd59411.aiparam_vehicle_detpostion.name": "车辆检测方式", + "resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.description": "追踪半径,跟追踪帧数也有关系。范围:0~100,例如:2.3", + "resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.failedtip": "请输入0-100的两位小数", + "resource.param.7.aa_00003.10a89d8c.aiparam_2000001_trackdynamicmatch.name": "车辆检测追踪半径", + "resource.param.7.ba_00001.20a13b0a.param_videoreadfps.description": "离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。", + "resource.param.7.ba_00001.20a13b0a.param_videoreadfps.failedtip": "请输入正确的值", + "resource.param.7.ba_00001.20a13b0a.param_videoreadfps.name": "离线视频播放取帧帧率", + "resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.description": "离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次", + "resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.failedtip": "请输入1-100的整数", + "resource.param.7.ba_00001.20a13b0a.param_videorepeatcount.name": "离线视频播放次数", + "resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.description": "最小非机动车尺寸:非机动车抓拍照片的最小图像尺寸。如输入值为100,则最小非机动车尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.failedtip": "请输入0-10000的整数", + "resource.param.7.ba_00002.498141de.filter_nonmotorvehicle_side_min.name": "最小非机动车尺寸", + "resource.param.7.ba_00002.498141de.filter_vehicle_side_min.description": "最小车辆尺寸:车辆抓拍照片的最小图像尺寸。如输入值为100,则最小车辆尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.7.ba_00002.498141de.filter_vehicle_side_min.failedtip": "请输入0-10000的整数", + "resource.param.7.ba_00002.498141de.filter_vehicle_side_min.name": "最小车辆尺寸", + "resource.param.7.ba_00004.2add29ef.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.7.ba_00004.2add29ef.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.7.ba_00004.2add29ef.param_overlaprate.name": "静止目标重叠率", + "resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.failedtip": "请选择是否打开叠加轨迹", + "resource.param.7.ba_00004.2add29ef.param_overlaytrajectory.name": "全景图叠加轨迹", + "resource.param.7.ba_00004.2add29ef.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.7.ba_00004.2add29ef.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.7.ba_00004.2add29ef.param_restrainswitch.name": "静止目标去重", + "resource.param.7.ba_00004.2add29ef.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.7.ba_00004.2add29ef.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.7.ba_00004.2add29ef.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.7.ba_00004.2add29ef.param_targetalarmcount.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.7.ba_00004.2add29ef.param_targetalarmcount.failedtip": "请输入0-100的整数", + "resource.param.7.ba_00004.2add29ef.param_targetalarmcount.name": "告警次数", + "resource.param.7.ba_00004.2add29ef.param_targetalarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.7.ba_00004.2add29ef.param_targetalarminterval.failedtip": "请输入1-36000的整数", + "resource.param.7.ba_00004.2add29ef.param_targetalarminterval.name": "告警时间间隔(秒)", + "resource.param.7.ba_00005.7d7b0fa3.param_areaduration.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.7.ba_00005.7d7b0fa3.param_areaduration.failedtip": "请输入正确的数值", + "resource.param.7.ba_00005.7d7b0fa3.param_areaduration.name": "检测时间", + "resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.description": "检测时间单位", + "resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.failedtip": "请选择正确的数值", + "resource.param.7.ba_00005.7d7b0fa3.param_areadurationtimetype.name": "检测时间单位", + "resource.param.7602.7602.0.name": "默认", + "resource.param.7602.7602.name.description": "区域名称:必填,限制32字符", + "resource.param.7602.7602.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.7602.7602.name.name": "区域名称", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.description": "face置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidence.name": "face置信度", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidenceconfig.description": "face置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.7602.pa_00001.d8241567.aiparam_face_confidenceconfig.name": "face置信度偏移", + "resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.failedtip": "请选择正确的值", + "resource.param.7602.pa_00001.d8241567.aiparam_face_detpostion.name": "face检测方式", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.description": "frontFace置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidence.name": "frontFace置信度", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidenceconfig.description": "frontFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.7602.pa_00002.2337df82.aiparam_frontface_confidenceconfig.name": "frontFace置信度偏移", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.description": "fullFace置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidence.name": "fullFace置信度", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidenceconfig.description": "fullFace置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.7602.pa_00002.2337df82.aiparam_fullface_confidenceconfig.name": "fullFace置信度偏移", + "resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.description": "选择需要比对的脸库分组", + "resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.failedtip": "请选择正确的值", + "resource.param.7602.pa_00005.c0d31881.param_faceset.featureinput.0.name": "绑定人脸分组", + "resource.param.77380.77380.0.name": "默认", + "resource.param.77380.77380.name.description": "区域名称:必填,限制32字符", + "resource.param.77380.77380.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.77380.77380.name.name": "区域名称", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.description": "pedestrian置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidence.name": "pedestrian置信度", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.description": "pedestrian置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_confidenceconfig.name": "pedestrian置信度偏移", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.failedtip": "请选择正确的值", + "resource.param.77380.pa_00001.27f515bd.aiparam_pedestrian_detpostion.name": "pedestrian检测方式", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.description": "hatless置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidence.name": "hatless置信度", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.description": "hatless置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_hatless_confidenceconfig.name": "hatless置信度偏移", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.description": "normalHat置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidence.name": "normalHat置信度", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.description": "normalHat置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_normalhat_confidenceconfig.name": "normalHat置信度偏移", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.description": "pedHelmet置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidence.name": "pedHelmet置信度", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.description": "pedHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedhelmet_confidenceconfig.name": "pedHelmet置信度偏移", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.description": "pedSafeHelmet置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidence.name": "pedSafeHelmet置信度", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.description": "pedSafeHelmet置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_pedsafehelmet_confidenceconfig.name": "pedSafeHelmet置信度偏移", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.description": "unsure置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidence.name": "unsure置信度", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.description": "unsure置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.77380.pa_00002.27e33c9b.aiparam_unsure_confidenceconfig.name": "unsure置信度偏移", + "resource.param.80498.80498.0.name": "默认", + "resource.param.80498.80498.1.name": "默认", + "resource.param.80498.80498.name.description": "区域名称:必填,限制32字符", + "resource.param.80498.80498.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.80498.80498.name.name": "区域名称", + "resource.param.80498.80498.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.80498.80498.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.80498.80498.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.80498.80498.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.80498.80498.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.80498.80498.param_overlaprate.name": "静止目标重叠率", + "resource.param.80498.80498.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.80498.80498.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.80498.80498.param_restrainswitch.name": "静止目标去重", + "resource.param.80498.80498.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.80498.80498.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.80498.80498.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.80498.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.80498.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.80498.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.80498.ba_00004.051ea786.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.80498.ba_00004.051ea786.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.80498.ba_00004.051ea786.param_overlaprate.name": "静止目标重叠率", + "resource.param.80498.ba_00004.051ea786.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.80498.ba_00004.051ea786.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.80498.ba_00004.051ea786.param_restrainswitch.name": "静止目标去重", + "resource.param.80498.ba_00004.051ea786.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.80498.ba_00004.051ea786.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.80498.ba_00004.051ea786.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.82819.82819.0.name": "默认", + "resource.param.82819.82819.name.description": "区域名称:必填,限制32字符", + "resource.param.82819.82819.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.82819.82819.name.name": "区域名称", + "resource.param.83708.83708.0.name": "默认", + "resource.param.83708.83708.1.name": "默认", + "resource.param.83708.83708.aiparam_category0_confidence.description": "category0置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.83708.83708.aiparam_category0_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.83708.83708.aiparam_category0_confidence.name": "category0置信度", + "resource.param.83708.83708.aiparam_category0_confidenceconfig.description": "category0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.83708.83708.aiparam_category0_confidenceconfig.name": "category0置信度偏移", + "resource.param.83708.83708.aiparam_category0_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.83708.83708.aiparam_category0_detpostion.failedtip": "请选择正确的值", + "resource.param.83708.83708.aiparam_category0_detpostion.name": "category0检测方式", + "resource.param.83708.83708.name.description": "区域名称:必填,限制32字符", + "resource.param.83708.83708.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.83708.83708.name.name": "区域名称", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidence.description": "category0置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidence.name": "category0置信度", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidenceconfig.description": "category0置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_confidenceconfig.name": "category0置信度偏移", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.failedtip": "请选择正确的值", + "resource.param.83708.pa_00001.0fa44adc.aiparam_category0_detpostion.name": "category0检测方式", + "resource.param.8533.8533.0.name": "默认", + "resource.param.8533.8533.name.description": "区域名称:必填,限制32字符", + "resource.param.8533.8533.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.8533.8533.name.name": "区域名称", + "resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.8533.ba_00004.051ea786.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.8533.ba_00004.051ea786.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.8533.ba_00004.051ea786.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.8533.ba_00004.051ea786.param_overlaprate.name": "静止目标重叠率", + "resource.param.8533.ba_00004.051ea786.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.8533.ba_00004.051ea786.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.8533.ba_00004.051ea786.param_restrainswitch.name": "静止目标去重", + "resource.param.8533.ba_00004.051ea786.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.8533.ba_00004.051ea786.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.8533.ba_00004.051ea786.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.89336.89336.0.name": "默认", + "resource.param.89336.89336.name.description": "区域名称:必填,限制32字符", + "resource.param.89336.89336.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.89336.89336.name.name": "区域名称", + "resource.param.9.9.0.name": "默认", + "resource.param.9.9.aiparam_smog_confidence.description": "烟雾置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.9.9.aiparam_smog_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.9.9.aiparam_smog_confidence.name": "烟雾置信度", + "resource.param.9.9.aiparam_smog_confidenceconfig.description": "烟雾置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.9.9.aiparam_smog_confidenceconfig.name": "烟雾置信度偏移", + "resource.param.9.9.aiparam_smog_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.9.9.aiparam_smog_detpostion.failedtip": "请选择正确的值", + "resource.param.9.9.aiparam_smog_detpostion.name": "烟雾检测方式", + "resource.param.9.9.filter_smog_side_min.description": "最小烟雾尺寸:烟雾抓拍照片的最小图像尺寸。如输入值为100,则最小烟雾尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.9.9.filter_smog_side_min.failedtip": "请输入0-10000的整数", + "resource.param.9.9.filter_smog_side_min.name": "最小烟雾尺寸", + "resource.param.9.9.name.description": "区域名称:必填,限制32字符", + "resource.param.9.9.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.9.9.name.name": "区域名称", + "resource.param.9.9.param_alarminterval.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:60秒。", + "resource.param.9.9.param_alarminterval.failedtip": "请输入1-36000的整数", + "resource.param.9.9.param_alarminterval.name": "告警时间间隔(秒)", + "resource.param.9.9.param_detectionduration.description": "检测时间:范围:1-3600。默认2。", + "resource.param.9.9.param_detectionduration.failedtip": "请输入1-3600的整数", + "resource.param.9.9.param_detectionduration.name": "检测时间(秒)", + "resource.param.9.9.param_overlaprate.param_restrainswitch.1.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.9.9.param_overlaprate.param_restrainswitch.1.failedtip": "请输入0-1的三位小数。", + "resource.param.9.9.param_overlaprate.param_restrainswitch.1.name": "静止目标重叠率", + "resource.param.9.9.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.9.9.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.9.9.param_restrainswitch.name": "静止目标去重", + "resource.param.9.9.param_restraintime.param_restrainswitch.1.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.9.9.param_restraintime.param_restrainswitch.1.failedtip": "请输入0-24的整数。", + "resource.param.9.9.param_restraintime.param_restrainswitch.1.name": "静止目标去重时间(小时)", + "resource.param.9.9.param_sensitivity.description": "灵敏度:用于计算总数范围内的命中数。如总数为10,取帧频率为3,则需时间≥10/3秒,才有可能产生告警。", + "resource.param.9.9.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.9.9.param_sensitivity.name": "灵敏度", + "resource.param.9.9.param_videoreadfps.description": "离线视频有不正常帧速现象,指定该参数可以强制指定帧率。<0 不强制,>=0 视频取帧时强制帧率,默认:-1全帧。", + "resource.param.9.9.param_videoreadfps.failedtip": "请输入正确的值", + "resource.param.9.9.param_videoreadfps.name": "离线视频播放取帧帧率", + "resource.param.9.9.param_videorepeatcount.description": "离线视频循环播放次数,小于0代表无限次。0代表1次,大于1代表多少次", + "resource.param.9.9.param_videorepeatcount.failedtip": "请输入1-100的整数", + "resource.param.9.9.param_videorepeatcount.name": "离线视频播放次数", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.description": "smog置信度,范围:0.0~1.0,限小数点后3位。", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidence.name": "smog置信度", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidenceconfig.description": "smog置信度偏移,默认为严格阈值。可选严格阈值、推荐阈值。", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_confidenceconfig.name": "smog置信度偏移", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.description": "检测方式:定义检测框中心点的位置。默认在底部。可选顶部、底部、中心。", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.failedtip": "请选择正确的值", + "resource.param.9.aa_00001.ba9c7d80.aiparam_smog_detpostion.name": "smog检测方式", + "resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.description": "最小烟雾尺寸:烟雾抓拍照片的最小图像尺寸。如输入值为100,则最小烟雾尺寸为100*100像素。范围:10px~1000像素 默认:100像素。", + "resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.failedtip": "请输入0-10000的整数", + "resource.param.9.ba_00002.a59e0a7e.filter_smog_side_min.name": "最小烟雾尺寸", + "resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.description": "检测时间:范围:1-3600。默认2。", + "resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.failedtip": "请输入1-3600的整数", + "resource.param.9.ba_00003.e37ea9c1.param_detectionduration.detectiontimetype.1.name": "检测时间(秒)", + "resource.param.9.ba_00003.e37ea9c1.param_sensitivity.description": "灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。", + "resource.param.9.ba_00003.e37ea9c1.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.9.ba_00003.e37ea9c1.param_sensitivity.name": "灵敏度", + "resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.9.ba_00004.1478c130.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.9.ba_00004.1478c130.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.9.ba_00004.1478c130.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.9.ba_00004.1478c130.param_overlaprate.name": "静止目标重叠率", + "resource.param.9.ba_00004.1478c130.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.9.ba_00004.1478c130.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.9.ba_00004.1478c130.param_restrainswitch.name": "静止目标去重", + "resource.param.9.ba_00004.1478c130.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.9.ba_00004.1478c130.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.9.ba_00004.1478c130.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.91435.91435.0.name": "默认", + "resource.param.91435.91435.1.name": "默认", + "resource.param.91435.91435.name.description": "区域名称:必填,限制32字符", + "resource.param.91435.91435.name.failedtip": "请输入长度小于32位且不包含空格的字符串", + "resource.param.91435.91435.name.name": "区域名称", + "resource.param.aa_00001.atomiccode.description": "选择原子模型", + "resource.param.aa_00001.atomiccode.failedtip": "请选择", + "resource.param.aa_00001.atomiccode.name": "选择原子模型", + "resource.param.aa_00001.enableftp.description": "自定义取帧频率:默认开启,关闭按全帧取帧。", + "resource.param.aa_00001.enableftp.failedtip": "请选择", + "resource.param.aa_00001.enableftp.name": "自定义取帧频率", + "resource.param.aa_00001.fps.enableftp.1.description": "自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:-1全帧。", + "resource.param.aa_00001.fps.enableftp.1.failedtip": "请输入正确的值", + "resource.param.aa_00001.fps.enableftp.1.name": "取帧频率", + "resource.param.aa_00002.atomiccode.description": "选择原子模型", + "resource.param.aa_00002.atomiccode.failedtip": "请选择", + "resource.param.aa_00002.atomiccode.name": "选择原子模型", + "resource.param.aa_00002.enableftp.description": "自定义取帧频率:默认开启,关闭则按前面动作的取帧频率。", + "resource.param.aa_00002.enableftp.failedtip": "请选择", + "resource.param.aa_00002.enableftp.name": "自定义取帧频率", + "resource.param.aa_00002.fps.enableftp.1.description": "active需要的帧率,不填就继承之前的方法。范围:0.01-1000.0,默认:-1全帧。", + "resource.param.aa_00002.fps.enableftp.1.failedtip": "请输入正确的值", + "resource.param.aa_00002.fps.enableftp.1.name": "取帧帧率", + "resource.param.aa_00003.motionstatus.description": "状态判断", + "resource.param.aa_00003.motionstatus.failedtip": "请选择正确的值", + "resource.param.aa_00003.motionstatus.name": "状态判断", + "resource.param.aa_00003.shapechangestatus.description": "形变状态判断", + "resource.param.aa_00003.shapechangestatus.failedtip": "请选择正确的值", + "resource.param.aa_00003.shapechangestatus.name": "形变状态判断", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.description": "大于等于此阈值后认为目标形状发生了变化。取值范围:0.0-1.0", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.failedtip": "请输入正确的数值", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.name": "形变阈值", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.description": "小于此阈值后认为目标是静止不变的。取值范围:0.0-1.0", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.failedtip": "请输入正确的数值", + "resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.name": "形变阈值", + "resource.param.aa_00003.trackselect.failedtip": "请选择", + "resource.param.aa_00003.trackselect.name": "标签过滤参数", + "resource.param.aa_00004.atomiccode.description": "选择原子模型", + "resource.param.aa_00004.atomiccode.failedtip": "请选择", + "resource.param.aa_00004.atomiccode.name": "选择人脸关键点模型", + "resource.param.aa_00005.atomiccode.description": "选择原子模型", + "resource.param.aa_00005.atomiccode.failedtip": "请选择", + "resource.param.aa_00005.atomiccode.name": "选择原子模型", + "resource.param.aa_00005.featureinput.description": "特征输入类型", + "resource.param.aa_00005.featureinput.failedtip": "请选择正确的值", + "resource.param.aa_00005.featureinput.name": "特征输入类型", + "resource.param.aa_00005.fps.description": "active需要的帧率,不填就继承之前的方法。范围:0.01-1000.0,默认:-1全帧。", + "resource.param.aa_00005.fps.failedtip": "请输入正确的值", + "resource.param.aa_00005.fps.name": "取帧帧率", + "resource.param.aa_00005.matchflag.featureinput.1.description": "匹配标志", + "resource.param.aa_00005.matchflag.featureinput.1.failedtip": "请选择正确的值", + "resource.param.aa_00005.matchflag.featureinput.1.name": "匹配标志", + "resource.param.aa_00005.matchflag.featureinput.2.description": "匹配标志", + "resource.param.aa_00005.matchflag.featureinput.2.failedtip": "请选择正确的值", + "resource.param.aa_00005.matchflag.featureinput.2.name": "匹配标志", + "resource.param.aa_00005.param_commodityset.featureinput.2.description": "选择需要比对的机物分组", + "resource.param.aa_00005.param_commodityset.featureinput.2.failedtip": "请选择正确的值", + "resource.param.aa_00005.param_commodityset.featureinput.2.name": "绑定机物分组", + "resource.param.aa_00005.param_faceset.featureinput.0.description": "选择需要比对的脸库分组", + "resource.param.aa_00005.param_faceset.featureinput.0.failedtip": "请选择正确的值", + "resource.param.aa_00005.param_faceset.featureinput.0.name": "绑定人脸分组", + "resource.param.aa_00005.param_workclothesset.featureinput.1.description": "选择需要比对的工服分组", + "resource.param.aa_00005.param_workclothesset.featureinput.1.failedtip": "请选择正确的值", + "resource.param.aa_00005.param_workclothesset.featureinput.1.name": "绑定工服分组", + "resource.param.ba_00002.0.failedtip": "请选择", + "resource.param.ba_00002.0.name": "标签参数", + "resource.param.ba_00003.detectiontimetype.description": "检测时间类型", + "resource.param.ba_00003.detectiontimetype.failedtip": "请选择正确的值", + "resource.param.ba_00003.detectiontimetype.name": "检测时间单位类型", + "resource.param.ba_00003.param_detectionduration.detectiontimetype.1.description": "检测时间:范围:1-3600。默认2。", + "resource.param.ba_00003.param_detectionduration.detectiontimetype.1.failedtip": "请输入1-3600的整数", + "resource.param.ba_00003.param_detectionduration.detectiontimetype.1.name": "检测时间(秒)", + "resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.description": "检测时间:范围:1-3600000。默认2000。", + "resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.failedtip": "请输入1-3600000的整数", + "resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.name": "检测时间(毫秒)", + "resource.param.ba_00003.param_sensitivity.description": "灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。", + "resource.param.ba_00003.param_sensitivity.failedtip": "请输入1-10的整数", + "resource.param.ba_00003.param_sensitivity.name": "灵敏度", + "resource.param.ba_00004.alarmproperty.description": "上报数据中,部分特殊事件需要额外送参数", + "resource.param.ba_00004.alarmproperty.failedtip": "请选择正确的值", + "resource.param.ba_00004.alarmproperty.name": "事件扩展属性", + "resource.param.ba_00004.custparam_alarmtype.description": "目标是否带跟踪,选择不同的告警抑制方式", + "resource.param.ba_00004.custparam_alarmtype.failedtip": "请选择正确的值", + "resource.param.ba_00004.custparam_alarmtype.name": "目标是否带跟踪", + "resource.param.ba_00004.enablellmreview.description": "启用后,告警事件在上报前将由Qwen3VL大模型进行二次审核验证,过滤误报。仅对触发类事件生效。", + "resource.param.ba_00004.enablellmreview.failedtip": "请选择", + "resource.param.ba_00004.enablellmreview.name": "大模型审核", + "resource.param.ba_00004.llmatomiccode.enablellmreview.1.description": "选择用于告警审核的Qwen3VL语言视觉大模型", + "resource.param.ba_00004.llmatomiccode.enablellmreview.1.failedtip": "请选择审核模型", + "resource.param.ba_00004.llmatomiccode.enablellmreview.1.name": "审核模型", + "resource.param.ba_00004.llmreviewcontent.enablellmreview.1.description": "用于审核的内容描述,比如:火焰、未带安全帽的人、烟雾等。留空则自动使用算法名称。", + "resource.param.ba_00004.llmreviewcontent.enablellmreview.1.name": "审核内容", + "resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.failedtip": "请输入1-36000的整数", + "resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.name": "告警时间间隔(秒)", + "resource.param.ba_00004.param_overlaprate.description": "静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。", + "resource.param.ba_00004.param_overlaprate.failedtip": "请输入0-1的三位小数。", + "resource.param.ba_00004.param_overlaprate.name": "静止目标重叠率", + "resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.description": "打开后会在全景图上叠加目标运动轨迹", + "resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.failedtip": "请选择是否打开叠加轨迹", + "resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.name": "全景图叠加轨迹", + "resource.param.ba_00004.param_restrainswitch.description": "静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。", + "resource.param.ba_00004.param_restrainswitch.failedtip": "请选择是否打开告警抑制服务", + "resource.param.ba_00004.param_restrainswitch.name": "静止目标去重", + "resource.param.ba_00004.param_restraintime.description": "静止目标去重时间,范围:1~24小时,默认:6小时。", + "resource.param.ba_00004.param_restraintime.failedtip": "请输入0-24的整数。", + "resource.param.ba_00004.param_restraintime.name": "静止目标去重时间(小时)", + "resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.description": "告警次数:范围:0-100,默认为1。0表示不限次数。", + "resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.failedtip": "请输入0-100的整数", + "resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.name": "告警次数", + "resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.description": "告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。", + "resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.failedtip": "请输入1-36000的整数", + "resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.name": "告警时间间隔(秒)", + "resource.param.ba_00004.realtimeeventrecordtype.description": "定时上报事件是否需要视频片段", + "resource.param.ba_00004.realtimeeventrecordtype.failedtip": "请选择", + "resource.param.ba_00004.realtimeeventrecordtype.name": "定时上报事件是否需要视频片段", + "resource.param.ba_00004.triggereventrecordtype.description": "触发类上报事件是否需要视频片段", + "resource.param.ba_00004.triggereventrecordtype.failedtip": "请选择", + "resource.param.ba_00004.triggereventrecordtype.name": "触发类上报事件是否需要视频片段", + "resource.param.ba_00005.areaalarmtype.description": "区域告警统计方式", + "resource.param.ba_00005.areaalarmtype.failedtip": "请选择正确的值", + "resource.param.ba_00005.areaalarmtype.name": "区域告警统计方式", + "resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.description": "检测时间单位", + "resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.failedtip": "请选择正确的数值", + "resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.name": "检测时间单位", + "resource.param.ba_00005.arealimitduration.areaalarmtype.6.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.ba_00005.arealimitduration.areaalarmtype.6.failedtip": "请输入正确的数值", + "resource.param.ba_00005.arealimitduration.areaalarmtype.6.name": "检测时间", + "resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.description": "区域中的目标数", + "resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.failedtip": "请输入0-3600的整数", + "resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.name": "区域中的目标数", + "resource.param.ba_00005.arealimittargettype.areaalarmtype.6.description": "区域中目标数限制类型", + "resource.param.ba_00005.arealimittargettype.areaalarmtype.6.failedtip": "请选择正确的值", + "resource.param.ba_00005.arealimittargettype.areaalarmtype.6.name": "区域中目标数限制类型", + "resource.param.ba_00005.breakareatype.areaalarmtype.2.description": "进出区域线方式", + "resource.param.ba_00005.breakareatype.areaalarmtype.2.failedtip": "请选择正确的值", + "resource.param.ba_00005.breakareatype.areaalarmtype.2.name": "进出区域线方式", + "resource.param.ba_00005.countbreakareatype.areaalarmtype.1.description": "统计类进出区域线方式", + "resource.param.ba_00005.countbreakareatype.areaalarmtype.1.failedtip": "请选择正确的值", + "resource.param.ba_00005.countbreakareatype.areaalarmtype.1.name": "统计类进出区域线方式", + "resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.description": "统计类进出区域线方式", + "resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.failedtip": "请选择正确的值", + "resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.name": "统计类进出区域线方式", + "resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.description": "统计类进出区域线方式", + "resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.failedtip": "请选择正确的值", + "resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.name": "统计类进出区域线方式", + "resource.param.ba_00005.inputareatype.description": "输入区域类型", + "resource.param.ba_00005.inputareatype.failedtip": "请选择正确的值", + "resource.param.ba_00005.inputareatype.name": "输入区域类型", + "resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.description": "数量上报间隔:范围:1-3600000,注意时间单位", + "resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.failedtip": "请输入正确的数值", + "resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.name": "数量上报间隔", + "resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.description": "数量上报间隔时间单位", + "resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.failedtip": "请选择正确的单位", + "resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.name": "数量上报间隔时间单位", + "resource.param.ba_00005.param_areaduration.areaalarmtype.4.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.ba_00005.param_areaduration.areaalarmtype.4.failedtip": "请输入正确的数值", + "resource.param.ba_00005.param_areaduration.areaalarmtype.4.name": "检测时间", + "resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.description": "检测时间单位", + "resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.failedtip": "请选择正确的数值", + "resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.name": "检测时间单位", + "resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.description": "检测时间:范围:1-3600000,注意时间单位", + "resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.failedtip": "请输入正确的数值", + "resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.name": "检测时间", + "resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.description": "检测时间单位", + "resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.failedtip": "请选择正确的数值", + "resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.name": "检测时间单位", + "resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.description": "用于和区域内实际有效目标数量进行比较的阈值", + "resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.failedtip": "请输入0-3600的整数", + "resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.name": "目标数量阈值", + "resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.description": "区域中目标数限制类型", + "resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.failedtip": "请选择正确的值", + "resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.name": "触发条件", + "resource.param.ba_00005.param_retrodirect.areaalarmtype.3.description": "目标逆行告警方向", + "resource.param.ba_00005.param_retrodirect.areaalarmtype.3.failedtip": "请选择正确的值", + "resource.param.ba_00005.param_retrodirect.areaalarmtype.3.name": "目标逆行告警方向", + "resource.param.ba_00005.param_retrodistance.areaalarmtype.3.description": "逆行距离:Y轴移动距离(相对值) ,范围:0.00~1.0,默认:0.05。", + "resource.param.ba_00005.param_retrodistance.areaalarmtype.3.failedtip": "请输入正确的值", + "resource.param.ba_00005.param_retrodistance.areaalarmtype.3.name": "逆行距离: Y轴移动距离(相对值) ", + "resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.description": "目标统计方式", + "resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.failedtip": "请选择正确的值", + "resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.name": "目标统计方式", + "resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.description": "告警条件:目标过线的数量", + "resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.failedtip": "请选择正确的值", + "resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.name": "绊线类型", + "resource.param.ba_00005.targetcountchange.areaalarmtype.1.description": "打开后,目标数量变化时立即上报,即便没有满足时间间隔条件", + "resource.param.ba_00005.targetcountchange.areaalarmtype.1.failedtip": "请选择", + "resource.param.ba_00005.targetcountchange.areaalarmtype.1.name": "目标数量变化状态", + "resource.param.ba_10003.param_senhitcount.description": "灵敏度计算命中数,范围:1-总数。", + "resource.param.ba_10003.param_senhitcount.failedtip": "请输入1-3600的整数", + "resource.param.ba_10003.param_senhitcount.name": "灵敏度计算命中数", + "resource.param.ba_10003.param_sentotalcount.description": "灵敏度计算总数", + "resource.param.ba_10003.param_sentotalcount.failedtip": "请输入1-3600000的整数", + "resource.param.ba_10003.param_sentotalcount.name": "灵敏度计算总数", + "resource.param.ba_90001.condition.description": "配置条件使其结果为真,并运行下面的动作", + "resource.param.ba_90001.condition.failedtip": "请选择", + "resource.param.ba_90001.condition.name": "条件配置", + "resource.param.da_00001.aiparam_box_confidence.description": "目标置信度,范围:0.0~1.0,限小数点后3位", + "resource.param.da_00001.aiparam_box_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.da_00001.aiparam_box_confidence.name": "目标置信度", + "resource.param.da_00001.aiparam_text_confidence.description": "文字置信度,范围:0.0~1.0,限小数点后3位", + "resource.param.da_00001.aiparam_text_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.da_00001.aiparam_text_confidence.name": "文字置信度", + "resource.param.da_00001.atomiccode.description": "选择原子模型", + "resource.param.da_00001.atomiccode.failedtip": "请选择", + "resource.param.da_00001.atomiccode.name": "选择原子模型", + "resource.param.da_00001.fps.description": "自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:1。", + "resource.param.da_00001.fps.failedtip": "请输入正确的值", + "resource.param.da_00001.fps.name": "取帧频率", + "resource.param.da_00001.keywords.description": "多个提示词可以使用英文句号隔开", + "resource.param.da_00001.keywords.failedtip": "请输入英文", + "resource.param.da_00001.keywords.name": "提示词", + "resource.param.da_00002.atomiccode.description": "选择原子模型", + "resource.param.da_00002.atomiccode.failedtip": "请选择", + "resource.param.da_00002.atomiccode.name": "选择原子模型", + "resource.param.da_00002.fps.description": "自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:1。", + "resource.param.da_00002.fps.failedtip": "请输入正确的值", + "resource.param.da_00002.fps.name": "取帧频率", + "resource.param.da_00002.inputtype.description": "输入类型", + "resource.param.da_00002.inputtype.failedtip": "请选择正确的值", + "resource.param.da_00002.inputtype.name": "输入类型", + "resource.param.da_00003.advanced_mode.description": "开启高级模式可完整自定义前半段提示词。不开启(如输入:安全帽),实际为“判断图片中是否存在【安全帽】目标,回答...”;开启(如输入:判断画面有无安全帽),实际为“判断画面有无安全帽,回答...”", + "resource.param.da_00003.advanced_mode.failedtip": "请选择", + "resource.param.da_00003.advanced_mode.name": "高级提示词模式", + "resource.param.da_00003.atomiccode.description": "选择原子模型", + "resource.param.da_00003.atomiccode.failedtip": "请选择", + "resource.param.da_00003.atomiccode.name": "选择原子模型", + "resource.param.da_00003.dosample.generationstyle.custom.description": "启用随机采样", + "resource.param.da_00003.dosample.generationstyle.custom.failedtip": "请选择", + "resource.param.da_00003.fps.description": "自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:1。", + "resource.param.da_00003.fps.failedtip": "请输入正确的值", + "resource.param.da_00003.fps.name": "取帧频率", + "resource.param.da_00003.generationstyle.description": "生成风格", + "resource.param.da_00003.generationstyle.failedtip": "请选择正确的值", + "resource.param.da_00003.generationstyle.name": "生成风格", + "resource.param.da_00003.keywords.description": "输入提示词", + "resource.param.da_00003.keywords.failedtip": "请输入提示词", + "resource.param.da_00003.keywords.name": "提示词", + "resource.param.da_00003.temperature.generationstyle.custom.description": "回答发散度,数值越低,回答越严谨、越稳定,范围:0.0~2.0,默认:0.7", + "resource.param.da_00003.temperature.generationstyle.custom.failedtip": "请输入0.0-2.0的数值", + "resource.param.da_00003.topk.generationstyle.custom.description": "每一步只从概率最高的 K 个 token 里选,范围:1~100,默认:20", + "resource.param.da_00003.topk.generationstyle.custom.failedtip": "请输入1-100的整数", + "resource.param.da_00003.topp.generationstyle.custom.description": "只在累计概率 ≤ top_p 的 token 集合中采样,范围:0.1~1.0,默认:0.8", + "resource.param.da_00003.topp.generationstyle.custom.failedtip": "请输入0.1-1.0的数值", + "resource.param.ip0001.data_type.description": "数据类型选择", + "resource.param.ip0001.data_type.name": "数据类型", + "resource.param.ip0001.input_node.description": "模型输入节点名称", + "resource.param.ip0001.input_node.name": "输入节点名称", + "resource.param.ip0001.shape.description": "输入张量形状,格式:[batch, channel, height, width]", + "resource.param.ip0001.shape.name": "输入形状", + "resource.param.la_alarmdata_code.algs.failedtip": "请选择", + "resource.param.la_audiodevice_code.audiodeviceid.description": "选择网络音柱", + "resource.param.la_audiodevice_code.audiodeviceid.failedtip": "选择网络音柱", + "resource.param.la_audiodevice_code.audiodeviceid.name": "选择网络音柱", + "resource.param.la_audiodevice_code.data.operation.1.description": "选择对应的告警音频文件。", + "resource.param.la_audiodevice_code.data.operation.1.failedtip": "选择对应的告警音频文件.", + "resource.param.la_audiodevice_code.data.operation.1.name": "音频文件", + "resource.param.la_audiodevice_code.duration.description": "播放时长(秒)", + "resource.param.la_audiodevice_code.duration.failedtip": "请输入整数", + "resource.param.la_audiodevice_code.duration.name": "播放时长(秒)", + "resource.param.la_audiodevice_code.gap.description": "播放间隔(秒)", + "resource.param.la_audiodevice_code.gap.failedtip": "请输入整数", + "resource.param.la_audiodevice_code.gap.name": "播放间隔(秒)", + "resource.param.la_audiodevice_code.operation.description": "播放方式", + "resource.param.la_audiodevice_code.operation.failedtip": "请选择正确的值", + "resource.param.la_audiodevice_code.operation.name": "播放方式", + "resource.param.la_audiodevice_code.speed.operation.2.description": "音速", + "resource.param.la_audiodevice_code.speed.operation.2.failedtip": "请输入整数", + "resource.param.la_audiodevice_code.speed.operation.2.name": "音速", + "resource.param.la_audiodevice_code.text.operation.2.description": "播放文字:限制32字符。", + "resource.param.la_audiodevice_code.text.operation.2.failedtip": "请输入32字符以下", + "resource.param.la_audiodevice_code.text.operation.2.name": "播放文字", + "resource.param.la_audiodevice_code.times.description": "播放次数", + "resource.param.la_audiodevice_code.times.failedtip": "请输入整数", + "resource.param.la_audiodevice_code.times.name": "播放次数", + "resource.param.la_audiodevice_code.tone.operation.2.description": "音色:可选择男声、女声,默认男声。", + "resource.param.la_audiodevice_code.tone.operation.2.failedtip": "请选择", + "resource.param.la_audiodevice_code.tone.operation.2.name": "音色", + "resource.param.la_audiodevice_code.volume.description": "音量", + "resource.param.la_audiodevice_code.volume.failedtip": "请输入整数", + "resource.param.la_audiodevice_code.volume.name": "音量", + "resource.param.lb0001.categories.description": "类别信息配置(JSON格式)", + "resource.param.lb0001.categories.name": "类别信息", + "resource.param.lb0001.output_info.description": "输出标签信息配置(JSON格式)", + "resource.param.lb0001.output_info.name": "输出信息", + "resource.param.lb0001.output_node.description": "配置对应的输出节点名称", + "resource.param.lb0001.output_node.name": "输出节点名称", + "resource.param.lb0001.shape.description": "输出张量形状", + "resource.param.lb0001.shape.name": "输出形状", + "resource.param.on0001.data_type.description": "数据类型选择", + "resource.param.on0001.data_type.name": "数据类型", + "resource.param.on0001.output_node.description": "模型输出节点名称", + "resource.param.on0001.output_node.name": "输出节点名称", + "resource.param.on0001.shape.description": "输出张量形状", + "resource.param.on0001.shape.name": "输出形状", + "resource.param.pa_00001.atomiccode.description": "选择原子模型", + "resource.param.pa_00001.atomiccode.failedtip": "请选择", + "resource.param.pa_00001.atomiccode.name": "选择原子模型", + "resource.param.pa_00002.atomiccode.description": "选择原子模型", + "resource.param.pa_00002.atomiccode.failedtip": "请选择", + "resource.param.pa_00002.atomiccode.name": "选择原子模型", + "resource.param.pa_00005.atomiccode.description": "选择原子模型", + "resource.param.pa_00005.atomiccode.failedtip": "请选择", + "resource.param.pa_00005.atomiccode.name": "选择原子模型", + "resource.param.pa_00005.featureinput.description": "特征输入类型", + "resource.param.pa_00005.featureinput.failedtip": "请选择正确的值", + "resource.param.pa_00005.featureinput.name": "特征输入类型", + "resource.param.pa_00005.matchflag.featureinput.1.description": "匹配标志", + "resource.param.pa_00005.matchflag.featureinput.1.failedtip": "请选择正确的值", + "resource.param.pa_00005.matchflag.featureinput.1.name": "匹配标志", + "resource.param.pa_00005.matchflag.featureinput.2.description": "匹配标志", + "resource.param.pa_00005.matchflag.featureinput.2.failedtip": "请选择正确的值", + "resource.param.pa_00005.matchflag.featureinput.2.name": "匹配标志", + "resource.param.pa_00005.param_commodityset.featureinput.2.description": "选择需要比对的机物分组", + "resource.param.pa_00005.param_commodityset.featureinput.2.failedtip": "请选择正确的值", + "resource.param.pa_00005.param_commodityset.featureinput.2.name": "绑定机物分组", + "resource.param.pa_00005.param_faceset.featureinput.0.description": "选择需要比对的脸库分组", + "resource.param.pa_00005.param_faceset.featureinput.0.failedtip": "请选择正确的值", + "resource.param.pa_00005.param_faceset.featureinput.0.name": "绑定人脸分组", + "resource.param.pa_00005.param_workclothesset.featureinput.1.description": "选择需要比对的工服分组", + "resource.param.pa_00005.param_workclothesset.featureinput.1.failedtip": "请选择正确的值", + "resource.param.pa_00005.param_workclothesset.featureinput.1.name": "绑定工服分组", + "resource.param.pb_90001.condition.description": "配置条件使其结果为真,并运行下面的动作", + "resource.param.pb_90001.condition.failedtip": "请选择", + "resource.param.pb_90001.condition.name": "条件配置", + "resource.param.pda_00001.aiparam_box_confidence.description": "目标置信度,范围:0.0~1.0,限小数点后3位", + "resource.param.pda_00001.aiparam_box_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.pda_00001.aiparam_box_confidence.name": "目标置信度", + "resource.param.pda_00001.aiparam_text_confidence.description": "文字置信度,范围:0.0~1.0,限小数点后3位", + "resource.param.pda_00001.aiparam_text_confidence.failedtip": "请输入0-1的三位小数。", + "resource.param.pda_00001.aiparam_text_confidence.name": "文字置信度", + "resource.param.pda_00001.atomiccode.description": "选择原子模型", + "resource.param.pda_00001.atomiccode.failedtip": "请选择", + "resource.param.pda_00001.atomiccode.name": "选择原子模型", + "resource.param.pda_00001.keywords.description": "多个提示词可以使用英文句号隔开", + "resource.param.pda_00001.keywords.failedtip": "请输入英文", + "resource.param.pda_00001.keywords.name": "提示词", + "resource.param.pda_00002.atomiccode.description": "选择原子模型", + "resource.param.pda_00002.atomiccode.failedtip": "请选择", + "resource.param.pda_00002.atomiccode.name": "选择原子模型", + "resource.param.pda_00002.inputtype.description": "输入类型", + "resource.param.pda_00002.inputtype.failedtip": "请选择正确的值", + "resource.param.pda_00002.inputtype.name": "输入类型", + "resource.param.pda_00003.advanced_mode.description": "开启高级模式可完整自定义前半段提示词。不开启(如输入:安全帽),实际为“判断图片中是否存在【安全帽】目标,回答...”;开启(如输入:判断画面有无安全帽),实际为“判断画面有无安全帽,回答...”", + "resource.param.pda_00003.advanced_mode.failedtip": "请选择", + "resource.param.pda_00003.advanced_mode.name": "高级提示词模式", + "resource.param.pda_00003.atomiccode.description": "选择原子模型", + "resource.param.pda_00003.atomiccode.failedtip": "请选择", + "resource.param.pda_00003.atomiccode.name": "选择原子模型", + "resource.param.pda_00003.dosample.generationstyle.custom.description": "启用随机采样", + "resource.param.pda_00003.dosample.generationstyle.custom.failedtip": "请选择", + "resource.param.pda_00003.generationstyle.description": "生成风格", + "resource.param.pda_00003.generationstyle.failedtip": "请选择正确的值", + "resource.param.pda_00003.generationstyle.name": "生成风格", + "resource.param.pda_00003.keywords.description": "输入提示词", + "resource.param.pda_00003.keywords.failedtip": "请输入提示词", + "resource.param.pda_00003.keywords.name": "提示词", + "resource.param.pda_00003.temperature.generationstyle.custom.description": "回答发散度,数值越低,回答越严谨、越稳定,范围:0.0~2.0,默认:0.7", + "resource.param.pda_00003.temperature.generationstyle.custom.failedtip": "请输入0.0-2.0的数值", + "resource.param.pda_00003.topk.generationstyle.custom.description": "每一步只从概率最高的 K 个 token 里选,范围:1~100,默认:20", + "resource.param.pda_00003.topk.generationstyle.custom.failedtip": "请输入1-100的整数", + "resource.param.pda_00003.topp.generationstyle.custom.description": "只在累计概率 ≤ top_p 的 token 集合中采样,范围:0.1~1.0,默认:0.8", + "resource.param.pda_00003.topp.generationstyle.custom.failedtip": "请输入0.1-1.0的数值", + "resource.param.pr0001.color.description": "填充颜色 [R, G, B](gravity 非 0 时生效)", + "resource.param.pr0001.color.name": "填充颜色", + "resource.param.pr0001.dsize.description": "调整后的图像尺寸 [height, width]", + "resource.param.pr0001.dsize.name": "目标尺寸", + "resource.param.pr0001.gravity.description": "缩放策略:0-直接缩放,1-等比缩放后居中填充,2-等比缩放顶左对齐(与 cwnn_sophon 一致)", + "resource.param.pr0001.gravity.name": "缩放策略", + "resource.param.pr0001.op.description": "预处理操作类型", + "resource.param.pr0001.op.name": "预处理操作类型", + "resource.param.pr0002.is_bgr.description": "是否为BGR格式", + "resource.param.pr0002.is_bgr.name": "BGR格式", + "resource.param.pr0002.mean.description": "归一化均值 [R, G, B]", + "resource.param.pr0002.mean.name": "均值", + "resource.param.pr0002.op.description": "预处理操作类型", + "resource.param.pr0002.op.name": "预处理操作类型", + "resource.param.pr0002.scale.description": "归一化缩放因子", + "resource.param.pr0002.scale.name": "缩放因子", + "resource.param.pr0002.std.description": "归一化标准差 [R, G, B],可选,若提供则使用 1/std;若不提供,则按 scale 使用", + "resource.param.pr0002.std.name": "标准差", + "resource.param.pr0003.h_bottom_crop.description": "-1~1:负或 0=裁剪,正=扩展", + "resource.param.pr0003.h_bottom_crop.name": "底部", + "resource.param.pr0003.h_top_crop.description": "范围 -1~1:负值或 0 表示该边裁剪(如 -0.1 裁 10%),正值表示扩展(如 0.1 扩 10%)", + "resource.param.pr0003.h_top_crop.name": "顶部", + "resource.param.pr0003.op.description": "预处理操作类型", + "resource.param.pr0003.op.name": "预处理操作类型", + "resource.param.pr0003.skip.description": "是否跳过此操作", + "resource.param.pr0003.skip.name": "跳过操作", + "resource.param.pr0003.square_mode.description": "正方形模式:0-max, 1-min, 2-avg", + "resource.param.pr0003.square_mode.name": "正方形模式", + "resource.param.pr0003.square.description": "是否强制为正方形", + "resource.param.pr0003.square.name": "强制正方形", + "resource.param.pr0003.w_left_crop.description": "-1~1:负或 0=裁剪,正=扩展", + "resource.param.pr0003.w_left_crop.name": "左侧", + "resource.param.pr0003.w_right_crop.description": "-1~1:负或 0=裁剪,正=扩展", + "resource.param.pr0003.w_right_crop.name": "右侧", + "resource.param.pr0004.h_bottom_crop.description": "-1~1:负或 0=裁剪,正=扩展", + "resource.param.pr0004.h_bottom_crop.name": "底部", + "resource.param.pr0004.h_top_crop.description": "-1~1:负或 0=裁剪,正=扩展(如 0.1 扩 10%)", + "resource.param.pr0004.h_top_crop.name": "顶部", + "resource.param.pr0004.op.description": "与 crop 共用 -1~1 语义:负或 0=裁剪,正=扩展。expand 时常用正值", + "resource.param.pr0004.op.name": "预处理操作类型", + "resource.param.pr0004.skip.description": "是否跳过此操作", + "resource.param.pr0004.skip.name": "跳过操作", + "resource.param.pr0004.square_mode.description": "正方形模式:0-max, 1-min, 2-avg", + "resource.param.pr0004.square_mode.name": "正方形模式", + "resource.param.pr0004.square.description": "是否强制为正方形", + "resource.param.pr0004.square.name": "强制正方形", + "resource.param.pr0004.w_left_crop.description": "-1~1:负或 0=裁剪,正=扩展", + "resource.param.pr0004.w_left_crop.name": "左侧", + "resource.param.pr0004.w_right_crop.description": "-1~1:负或 0=裁剪,正=扩展", + "resource.param.pr0004.w_right_crop.name": "右侧", + "resource.param.pr0005.center_index.description": "可选,决定中心点计算方式,如: [0, 1, 3, 4]", + "resource.param.pr0005.center_index.name": "中心点索引", + "resource.param.pr0005.norm_ratio.description": "归一化比例", + "resource.param.pr0005.norm_ratio.name": "归一化比例", + "resource.param.pr0005.normmode.description": "归一化模式:0/1/2", + "resource.param.pr0005.normmode.name": "归一化模式", + "resource.param.pr0005.op.description": "预处理操作类型", + "resource.param.pr0005.op.name": "预处理操作类型", + "resource.param.pr0005.output_hw.description": "输出尺寸 [height, width]", + "resource.param.pr0005.output_hw.name": "输出尺寸", + "resource.param.pr0006.dsize.description": "目标尺寸 [height, width]", + "resource.param.pr0006.dsize.name": "目标尺寸", + "resource.param.pr0006.is_bgr.description": "是否为BGR格式", + "resource.param.pr0006.is_bgr.name": "BGR格式", + "resource.param.pr0006.op.description": "预处理操作类型", + "resource.param.pr0006.op.name": "预处理操作类型", + "resource.param.pr0006.scale.description": "缩放因子", + "resource.param.pr0006.scale.name": "缩放", + "resource.param.pr0006.size.description": "序列长度", + "resource.param.pr0006.size.name": "序列长度", + "resource.param.pr0007.count.description": "图像数量", + "resource.param.pr0007.count.name": "图像数量", + "resource.param.pr0007.dst_height.description": "目标高度", + "resource.param.pr0007.dst_height.name": "目标高度", + "resource.param.pr0007.dst_width.description": "目标宽度", + "resource.param.pr0007.dst_width.name": "目标宽度", + "resource.param.pr0007.op.description": "预处理操作类型", + "resource.param.pr0007.op.name": "预处理操作类型", + "resource.param.pr0008.dst_height.description": "目标高度", + "resource.param.pr0008.dst_height.name": "目标高度", + "resource.param.pr0008.dst_width.description": "目标宽度", + "resource.param.pr0008.dst_width.name": "目标宽度", + "resource.param.pr0008.is_bgr.description": "是否为BGR格式", + "resource.param.pr0008.is_bgr.name": "BGR格式", + "resource.param.pr0008.mean.description": "归一化均值 [R, G, B]", + "resource.param.pr0008.mean.name": "均值", + "resource.param.pr0008.op.description": "预处理操作类型", + "resource.param.pr0008.op.name": "预处理操作类型", + "resource.param.pr0008.std.description": "归一化标准差 [R, G, B]", + "resource.param.pr0008.std.name": "标准差", + "resource.param.pt0001.nms_detection_conf.description": "NMS检测置信度", + "resource.param.pt0001.nms_detection_conf.name": "检测置信度", + "resource.param.pt0001.nms_threshold.description": "NMS阈值", + "resource.param.pt0001.nms_threshold.name": "NMS阈值", + "resource.param.pt0001.op.description": "后处理操作类型", + "resource.param.pt0001.op.name": "后处理操作类型", + "resource.param.pt0001.top_k.description": "保留前K个检测结果", + "resource.param.pt0002.anchors.description": "YOLO锚点配置", + "resource.param.pt0002.anchors.name": "锚点", + "resource.param.pt0002.nms_detection_conf.description": "NMS检测置信度", + "resource.param.pt0002.nms_detection_conf.name": "检测置信度", + "resource.param.pt0002.nms_threshold.description": "NMS阈值", + "resource.param.pt0002.nms_threshold.name": "NMS阈值", + "resource.param.pt0002.op.description": "后处理操作类型", + "resource.param.pt0002.op.name": "后处理操作类型", + "resource.param.pt0002.stride.description": "YOLO步长", + "resource.param.pt0002.stride.name": "步长", + "resource.param.pt0002.top_k.description": "保留前K个检测结果", + "resource.param.pt0003.nms_detection_conf.description": "NMS检测置信度", + "resource.param.pt0003.nms_detection_conf.name": "检测置信度", + "resource.param.pt0003.nms_threshold.description": "NMS阈值", + "resource.param.pt0003.nms_threshold.name": "NMS阈值", + "resource.param.pt0003.op.description": "后处理操作类型", + "resource.param.pt0003.op.name": "后处理操作类型", + "resource.param.pt0003.top_k.description": "保留前K个检测结果", + "resource.param.pt0004.op.description": "后处理操作类型", + "resource.param.pt0004.op.name": "后处理操作类型", + "resource.param.pt0005.axis.description": "按指定轴做 argmax", + "resource.param.pt0005.axis.name": "轴", + "resource.param.pt0005.op.description": "后处理操作类型", + "resource.param.pt0005.op.name": "后处理操作类型", + "resource.param.pt0006.axis.description": "当前实现要求为 1", + "resource.param.pt0006.axis.name": "轴", + "resource.param.pt0006.op.description": "后处理操作类型", + "resource.param.pt0006.op.name": "后处理操作类型", + "resource.param.pt0006.split.description": "各段宽度之和需等于该维度长度", + "resource.param.pt0006.split.name": "分割配置", + "resource.param.pt0007.op.description": "后处理操作类型", + "resource.param.pt0007.op.name": "后处理操作类型", + "resource.param.pt0007.split.description": "分割配置数组", + "resource.param.pt0007.split.name": "分割配置", + "resource.param.pt0008.box_threshold.description": "框阈值", + "resource.param.pt0008.box_threshold.name": "框阈值", + "resource.param.pt0008.op.description": "后处理操作类型", + "resource.param.pt0008.op.name": "后处理操作类型", + "resource.param.pt0008.text_threshold.description": "文本阈值", + "resource.param.pt0008.text_threshold.name": "文本阈值", + "resource.param.pt0009.nms_detection_conf.description": "检测置信度阈值(无NMS)", + "resource.param.pt0009.nms_detection_conf.name": "置信度阈值", + "resource.param.pt0009.op.description": "端到端检测(NMS已内置,如YOLO26)", + "resource.param.pt0009.op.name": "后处理操作类型", + "resource.param.pt0009.top_k.description": "保留前K个检测结果", + "resource.param.da_00003.vlmprovider.name": "推理方式", + "resource.param.da_00003.vlmprovider.description": "选择本地原子模型或OpenAI兼容接口", + "resource.param.da_00003.vlmprovider.failedtip": "请选择正确的值", + "resource.option.da_00003.vlmprovider.local_model.options_name": "本地原子模型", + "resource.option.da_00003.vlmprovider.openai_vlm.options_name": "OpenAI接口", + "resource.param.da_00003.openai_base_url.vlmprovider.openai_vlm.description": "OpenAI兼容接口基础地址,例如 http://127.0.0.1:8000/v1", + "resource.param.da_00003.openai_base_url.vlmprovider.openai_vlm.failedtip": "请输入接口地址", + "resource.param.da_00003.openai_api_key.vlmprovider.openai_vlm.description": "OpenAI接口密钥;本地vLLM未启用鉴权时可为空", + "resource.param.da_00003.openai_api_key.vlmprovider.openai_vlm.failedtip": "请输入API Key", + "resource.param.da_00003.openai_model.vlmprovider.openai_vlm.description": "OpenAI接口模型名称", + "resource.param.da_00003.openai_model.vlmprovider.openai_vlm.failedtip": "请输入模型名称", + "resource.param.da_00003.openai_endpoint.vlmprovider.openai_vlm.description": "OpenAI兼容接口路径,默认 /chat/completions", + "resource.param.da_00003.openai_endpoint.vlmprovider.openai_vlm.failedtip": "请输入接口路径", + "resource.param.da_00003.openai_timeout_ms.vlmprovider.openai_vlm.description": "请求超时时间,单位毫秒", + "resource.param.da_00003.openai_timeout_ms.vlmprovider.openai_vlm.failedtip": "请输入超时时间", + "resource.param.da_00003.openai_max_tokens.vlmprovider.openai_vlm.description": "最大输出token数", + "resource.param.da_00003.openai_max_tokens.vlmprovider.openai_vlm.failedtip": "请输入最大输出token数", + "resource.param.pda_00003.vlmprovider.name": "推理方式", + "resource.param.pda_00003.vlmprovider.description": "选择本地原子模型或OpenAI兼容接口", + "resource.param.pda_00003.vlmprovider.failedtip": "请选择正确的值", + "resource.option.pda_00003.vlmprovider.local_model.options_name": "本地原子模型", + "resource.option.pda_00003.vlmprovider.openai_vlm.options_name": "OpenAI接口", + "resource.param.pda_00003.openai_base_url.vlmprovider.openai_vlm.description": "OpenAI兼容接口基础地址,例如 http://127.0.0.1:8000/v1", + "resource.param.pda_00003.openai_base_url.vlmprovider.openai_vlm.failedtip": "请输入接口地址", + "resource.param.pda_00003.openai_api_key.vlmprovider.openai_vlm.description": "OpenAI接口密钥;本地vLLM未启用鉴权时可为空", + "resource.param.pda_00003.openai_api_key.vlmprovider.openai_vlm.failedtip": "请输入API Key", + "resource.param.pda_00003.openai_model.vlmprovider.openai_vlm.description": "OpenAI接口模型名称", + "resource.param.pda_00003.openai_model.vlmprovider.openai_vlm.failedtip": "请输入模型名称", + "resource.param.pda_00003.openai_endpoint.vlmprovider.openai_vlm.description": "OpenAI兼容接口路径,默认 /chat/completions", + "resource.param.pda_00003.openai_endpoint.vlmprovider.openai_vlm.failedtip": "请输入接口路径", + "resource.param.pda_00003.openai_timeout_ms.vlmprovider.openai_vlm.description": "请求超时时间,单位毫秒", + "resource.param.pda_00003.openai_timeout_ms.vlmprovider.openai_vlm.failedtip": "请输入超时时间", + "resource.param.pda_00003.openai_max_tokens.vlmprovider.openai_vlm.description": "最大输出token数", + "resource.param.pda_00003.openai_max_tokens.vlmprovider.openai_vlm.failedtip": "请输入最大输出token数", + "resource.param.ba_00004.llmprovider.enablellmreview.1.name": "审核推理方式", + "resource.param.ba_00004.llmprovider.enablellmreview.1.description": "选择本地审核模型或OpenAI兼容接口", + "resource.param.ba_00004.llmprovider.enablellmreview.1.failedtip": "请选择正确的值", + "resource.option.ba_00004.llmprovider.local_model.options_name": "本地原子模型", + "resource.option.ba_00004.llmprovider.openai_vlm.options_name": "OpenAI接口", + "resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.description": "OpenAI兼容接口基础地址,例如 http://127.0.0.1:8000/v1", + "resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.failedtip": "请输入接口地址", + "resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.description": "OpenAI接口密钥;本地vLLM未启用鉴权时可为空", + "resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.failedtip": "请输入API Key", + "resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.description": "OpenAI接口模型名称", + "resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.failedtip": "请输入模型名称", + "resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.description": "OpenAI兼容接口路径,默认 /chat/completions", + "resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.failedtip": "请输入接口路径", + "resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.description": "请求超时时间,单位毫秒", + "resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.failedtip": "请输入超时时间", + "resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.description": "最大输出token数", + "resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.failedtip": "请输入最大输出token数" +} diff --git a/data/resource/aiboxresource_cv186x/layout/actions.json b/data/resource/aiboxresource_cv186x/layout/actions.json new file mode 100644 index 000000000..6b09fe860 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/layout/actions.json @@ -0,0 +1,255 @@ +[ + { + "id": "AA_00001", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "目标检测算法", + "inputParamConfig": "[{\"type\":\"modelSelect_detector\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00001.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.aa_00001.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.aa_00001.atomiccode.name\"},{\"type\":\"switch\",\"defaultValue\":\"0\",\"description\":\"自定义取帧频率:默认开启,关闭按全帧取帧。\",\"failedTip\":\"请选择\",\"key\":\"Enableftp\",\"name\":\"自定义取帧频率\",\"level\":\"1\",\"regexpr\":\"/^[0-1]$/\",\"descriptionI18nKey\":\"resource.param.aa_00001.enableftp.description\",\"failedTipI18nKey\":\"resource.param.aa_00001.enableftp.failedtip\",\"nameI18nKey\":\"resource.param.aa_00001.enableftp.name\"},{\"type\":\"text\",\"defaultValue\":\"-1\",\"description\":\"自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"fps\",\"name\":\"取帧频率\",\"dependsOn\":{\"key\":\"Enableftp\",\"value\":\"1\"},\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00001.fps.enableftp.1.description\",\"failedTipI18nKey\":\"resource.param.aa_00001.fps.enableftp.1.failedtip\",\"nameI18nKey\":\"resource.param.aa_00001.fps.enableftp.1.name\"}]", + "remark": "检测算法,需要选择算法模型", + "actionNameI18nKey": "resource.action.aa_00001.actionname", + "remarkI18nKey": "resource.action.aa_00001.remark" + }, + { + "id": "AA_00002", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "目标分类算法", + "inputParamConfig": "[{\"type\":\"modelSelect_classify\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00002.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.aa_00002.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.aa_00002.atomiccode.name\"},{\"type\":\"switch\",\"defaultValue\":\"0\",\"description\":\"自定义取帧频率:默认开启,关闭则按前面动作的取帧频率。\",\"failedTip\":\"请选择\",\"key\":\"Enableftp\",\"name\":\"自定义取帧频率\",\"level\":\"1\",\"regexpr\":\"/^[0-1]$/\",\"descriptionI18nKey\":\"resource.param.aa_00002.enableftp.description\",\"failedTipI18nKey\":\"resource.param.aa_00002.enableftp.failedtip\",\"nameI18nKey\":\"resource.param.aa_00002.enableftp.name\"},{\"type\":\"text\",\"defaultValue\":\"-1\",\"description\":\"active需要的帧率,不填就继承之前的方法。范围:0.01-1000.0,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"fps\",\"name\":\"取帧帧率\",\"dependsOn\":{\"key\":\"Enableftp\",\"value\":\"1\"},\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00002.fps.enableftp.1.description\",\"failedTipI18nKey\":\"resource.param.aa_00002.fps.enableftp.1.failedtip\",\"nameI18nKey\":\"resource.param.aa_00002.fps.enableftp.1.name\"}]", + "remark": "检测目标送分类算法,需要选择一个分类模型", + "actionNameI18nKey": "resource.action.aa_00002.actionname", + "remarkI18nKey": "resource.action.aa_00002.remark" + }, + { + "id": "AA_00003", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "追踪算法", + "inputParamConfig": "[{\"type\":\"trackSelect\",\"defaultValue\":\"\",\"description\":\"\",\"failedTip\":\"请选择\",\"key\":\"trackSelect\",\"name\":\"标签过滤参数\",\"level\":\"1\",\"regexpr\":\"\",\"failedTipI18nKey\":\"resource.param.aa_00003.trackselect.failedtip\",\"nameI18nKey\":\"resource.param.aa_00003.trackselect.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"状态判断\",\"failedTip\":\"请选择正确的值\",\"key\":\"motionStatus\",\"name\":\"状态判断\",\"options\":[{\"name\":\"关闭\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.aa_00003.motionstatus.0.options_name\"},{\"name\":\"运动状态\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.aa_00003.motionstatus.1.options_name\"},{\"name\":\"静止状态\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.aa_00003.motionstatus.2.options_name\"}],\"level\":\"1\",\"regexpr\":\"/^[0-2]$/\",\"descriptionI18nKey\":\"resource.param.aa_00003.motionstatus.description\",\"failedTipI18nKey\":\"resource.param.aa_00003.motionstatus.failedtip\",\"nameI18nKey\":\"resource.param.aa_00003.motionstatus.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"形变状态判断\",\"failedTip\":\"请选择正确的值\",\"key\":\"shapeChangeStatus\",\"name\":\"形变状态判断\",\"options\":[{\"name\":\"不需要\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.aa_00003.shapechangestatus.0.options_name\"},{\"name\":\"需要形状发生变化的\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.aa_00003.shapechangestatus.1.options_name\"},{\"name\":\"需要形状不发生变的\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.aa_00003.shapechangestatus.2.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00003.shapechangestatus.description\",\"failedTipI18nKey\":\"resource.param.aa_00003.shapechangestatus.failedtip\",\"nameI18nKey\":\"resource.param.aa_00003.shapechangestatus.name\"},{\"key\":\"shapeChangeThreshold\",\"name\":\"形变阈值\",\"defaultValue\":\"0.1\",\"description\":\"大于等于此阈值后认为目标形状发生了变化。取值范围:0.0-1.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"1\",\"dependsOn\":{\"key\":\"shapeChangeStatus\",\"value\":\"1\"},\"nameI18nKey\":\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.name\",\"descriptionI18nKey\":\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.description\",\"failedTipI18nKey\":\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.1.failedtip\"},{\"key\":\"shapeChangeThreshold\",\"name\":\"形变阈值\",\"defaultValue\":\"0.1\",\"description\":\"小于此阈值后认为目标是静止不变的。取值范围:0.0-1.0\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"1\",\"dependsOn\":{\"key\":\"shapeChangeStatus\",\"value\":\"2\"},\"nameI18nKey\":\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.name\",\"descriptionI18nKey\":\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.description\",\"failedTipI18nKey\":\"resource.param.aa_00003.shapechangethreshold.shapechangestatus.2.failedtip\"}]", + "remark": "需要人体追踪时放在检测算法后", + "actionNameI18nKey": "resource.action.aa_00003.actionname", + "remarkI18nKey": "resource.action.aa_00003.remark" + }, + { + "id": "AA_00004", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "关键点算法", + "inputParamConfig": "[{\"type\":\"modelSelect_keypoints\",\"defaultValue\":\"1000016\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择人脸关键点模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00004.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.aa_00004.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.aa_00004.atomiccode.name\"}]", + "remark": "人脸landmark", + "actionNameI18nKey": "resource.action.aa_00004.actionname", + "remarkI18nKey": "resource.action.aa_00004.remark" + }, + { + "id": "AA_00005", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "特征提取算法", + "inputParamConfig": "[{\"type\":\"modelSelect_feature\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00005.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.aa_00005.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.aa_00005.atomiccode.name\"},{\"type\":\"text\",\"defaultValue\":\"-1\",\"description\":\"active需要的帧率,不填就继承之前的方法。范围:0.01-1000.0,默认:-1全帧。\",\"failedTip\":\"请输入正确的值\",\"key\":\"fps\",\"name\":\"取帧帧率\",\"dependsOn\":null,\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00005.fps.description\",\"failedTipI18nKey\":\"resource.param.aa_00005.fps.failedtip\",\"nameI18nKey\":\"resource.param.aa_00005.fps.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"特征输入类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"featureInput\",\"name\":\"特征输入类型\",\"options\":[{\"name\":\"人脸特征提取(无需比对)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.aa_00005.featureinput.0.options_name\"},{\"name\":\"工服特征提取(需要比对)\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.aa_00005.featureinput.1.options_name\"},{\"name\":\"机物特征提取(需要比对)\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.aa_00005.featureinput.2.options_name\"},{\"name\":\"人体特征提取(无需比对)\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.aa_00005.featureinput.3.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00005.featureinput.description\",\"failedTipI18nKey\":\"resource.param.aa_00005.featureinput.failedtip\",\"nameI18nKey\":\"resource.param.aa_00005.featureinput.name\"},{\"type\":\"faceSet\",\"description\":\"选择需要比对的脸库分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.faceSet\",\"name\":\"绑定人脸分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"0\"},\"level\":\"2\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00005.param_faceset.featureinput.0.description\",\"failedTipI18nKey\":\"resource.param.aa_00005.param_faceset.featureinput.0.failedtip\",\"nameI18nKey\":\"resource.param.aa_00005.param_faceset.featureinput.0.name\"},{\"type\":\"workClothesSet\",\"description\":\"选择需要比对的工服分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.workClothesSet\",\"name\":\"绑定工服分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"1\"},\"level\":\"2\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00005.param_workclothesset.featureinput.1.description\",\"failedTipI18nKey\":\"resource.param.aa_00005.param_workclothesset.featureinput.1.failedtip\",\"nameI18nKey\":\"resource.param.aa_00005.param_workclothesset.featureinput.1.name\"},{\"type\":\"commoditySet\",\"description\":\"选择需要比对的机物分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.commoditySet\",\"name\":\"绑定机物分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"2\"},\"level\":\"2\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00005.param_commodityset.featureinput.2.description\",\"failedTipI18nKey\":\"resource.param.aa_00005.param_commodityset.featureinput.2.failedtip\",\"nameI18nKey\":\"resource.param.aa_00005.param_commodityset.featureinput.2.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"匹配标志\",\"failedTip\":\"请选择正确的值\",\"key\":\"matchFlag\",\"name\":\"匹配标志\",\"options\":[{\"name\":\"未命中告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.aa_00005.matchflag.0.options_name\"},{\"name\":\"命中告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.aa_00005.matchflag.1.options_name\"}],\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"1\"},\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00005.matchflag.featureinput.1.description\",\"failedTipI18nKey\":\"resource.param.aa_00005.matchflag.featureinput.1.failedtip\",\"nameI18nKey\":\"resource.param.aa_00005.matchflag.featureinput.1.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"匹配标志\",\"failedTip\":\"请选择正确的值\",\"key\":\"matchFlag\",\"name\":\"匹配标志\",\"options\":[{\"name\":\"未命中告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.aa_00005.matchflag.0.options_name\"},{\"name\":\"命中告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.aa_00005.matchflag.1.options_name\"}],\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"2\"},\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.aa_00005.matchflag.featureinput.2.description\",\"failedTipI18nKey\":\"resource.param.aa_00005.matchflag.featureinput.2.failedtip\",\"nameI18nKey\":\"resource.param.aa_00005.matchflag.featureinput.2.name\"}]", + "remark": "支持人脸、人体、机物提取特征", + "actionNameI18nKey": "resource.action.aa_00005.actionname", + "remarkI18nKey": "resource.action.aa_00005.remark" + }, + { + "id": "AA_00011", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "文字识别", + "inputParamConfig": "[{\"type\":\"modelSelect_ocr\",\"defaultValue\":\"\",\"description\":\"选择 OCR 原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择 OCR 模型\",\"level\":\"1\",\"regexpr\":\"\"}]", + "remark": "接收上游四点关键点,对车牌透视矫正后进行文字识别", + "actionNameI18nKey": "resource.action.aa_00011.actionname", + "remarkI18nKey": "resource.action.aa_00011.remark" + }, + { + "id": "BA_00001", + "actionUsage": 1, + "actionType": 2, + "businessCategory": "2", + "actionName": "视频解码", + "inputParamConfig": "[]", + "remark": "视频解码", + "actionNameI18nKey": "resource.action.ba_00001.actionname", + "remarkI18nKey": "resource.action.ba_00001.remark" + }, + { + "id": "BA_00002", + "actionUsage": 1, + "actionType": 2, + "businessCategory": "2", + "actionName": "类别筛选", + "inputParamConfig": "[{\"type\":\"labelFilterList\",\"defaultValue\":\"\",\"description\":\"\",\"failedTip\":\"请选择\",\"key\":\"\",\"name\":\"标签参数\",\"level\":\"1\",\"regexpr\":\"\",\"failedTipI18nKey\":\"resource.param.ba_00002.0.failedtip\",\"nameI18nKey\":\"resource.param.ba_00002.0.name\"}]", + "remark": "对目标进行筛选", + "actionNameI18nKey": "resource.action.ba_00002.actionname", + "remarkI18nKey": "resource.action.ba_00002.remark" + }, + { + "id": "BA_00003", + "actionUsage": 1, + "actionType": 2, + "businessCategory": "2", + "actionName": "灵敏度计算-计时", + "inputParamConfig": "[{\"key\":\"param.sensitivity\",\"name\":\"灵敏度\",\"defaultValue\":\"5\",\"description\":\"灵敏度:范围1-10,默认:5。值越大,越容易进行告警的触发。\",\"type\":\"slider\",\"regexpr\":\"/^([1-9]|10)$/\",\"failedTip\":\"请输入1-10的整数\",\"isColumn\":true,\"range\":\"1,10\",\"step\":\"1\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.ba_00003.param_sensitivity.name\",\"descriptionI18nKey\":\"resource.param.ba_00003.param_sensitivity.description\",\"failedTipI18nKey\":\"resource.param.ba_00003.param_sensitivity.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"1\",\"description\":\"检测时间类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"detectionTimeType\",\"name\":\"检测时间单位类型\",\"options\":[{\"name\":\"秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00003.detectiontimetype.1.options_name\"},{\"name\":\"毫秒\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ba_00003.detectiontimetype.2.options_name\"}],\"level\":\"1\",\"regexpr\":\"/^[1-2]$/\",\"descriptionI18nKey\":\"resource.param.ba_00003.detectiontimetype.description\",\"failedTipI18nKey\":\"resource.param.ba_00003.detectiontimetype.failedtip\",\"nameI18nKey\":\"resource.param.ba_00003.detectiontimetype.name\"},{\"key\":\"param.detectionDuration\",\"name\":\"检测时间(秒)\",\"defaultValue\":\"2\",\"description\":\"检测时间:范围:1-3600。默认2。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"1\"},\"nameI18nKey\":\"resource.param.ba_00003.param_detectionduration.detectiontimetype.1.name\",\"descriptionI18nKey\":\"resource.param.ba_00003.param_detectionduration.detectiontimetype.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00003.param_detectionduration.detectiontimetype.1.failedtip\"},{\"key\":\"param.detectionDurationMs\",\"name\":\"检测时间(毫秒)\",\"defaultValue\":\"2000\",\"description\":\"检测时间:范围:1-3600000。默认2000。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-3600000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"detectionTimeType\",\"value\":\"2\"},\"nameI18nKey\":\"resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00003.param_detectiondurationms.detectiontimetype.2.failedtip\"}]", + "remark": "灵敏度计算", + "actionNameI18nKey": "resource.action.ba_00003.actionname", + "remarkI18nKey": "resource.action.ba_00003.remark" + }, + { + "id": "BA_00004", + "actionUsage": 1, + "actionType": 2, + "businessCategory": "2", + "actionName": "事件上报", + "inputParamConfig": "[{\"type\":\"select\",\"defaultValue\":\"1\",\"description\":\"目标是否带跟踪,选择不同的告警抑制方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"custParam.alarmType\",\"name\":\"目标是否带跟踪\",\"options\":[{\"name\":\"不带目标跟踪\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00004.custparam_alarmtype.1.options_name\"},{\"name\":\"带目标跟踪\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ba_00004.custparam_alarmtype.2.options_name\"},{\"name\":\"不需要抑制\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.ba_00004.custparam_alarmtype.3.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.ba_00004.custparam_alarmtype.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.custparam_alarmtype.failedtip\",\"nameI18nKey\":\"resource.param.ba_00004.custparam_alarmtype.name\"},{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"1\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_alarminterval.custparam_alarmtype.1.failedtip\"},{\"key\":\"param.targetAlarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"告警时间间隔:2次告警事件的间隔。范围:1~36000秒,默认:3秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_targetalarminterval.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.targetAlarmCount\",\"name\":\"告警次数\",\"defaultValue\":\"1\",\"description\":\"告警次数:范围:0-100,默认为1。0表示不限次数。\",\"type\":\"text\",\"regexpr\":\"/^(0|[1-9]|[1-9][0-9]|100)$/\",\"failedTip\":\"请输入0-100的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_targetalarmcount.custparam_alarmtype.2.failedtip\"},{\"key\":\"param.restrainSwitch\",\"name\":\"静止目标去重\",\"defaultValue\":\"0\",\"description\":\"静止目标去重:对于告警目标,开启此功能后,将进行目标静止状态检测,如判定为静止目标,则不会重复报警。\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开告警抑制服务\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_restrainswitch.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_restrainswitch.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_restrainswitch.failedtip\"},{\"key\":\"param.overlapRate\",\"name\":\"静止目标重叠率\",\"defaultValue\":\"0.2\",\"description\":\"静止目标重叠率,范围:0.0~1.0,限小数点后3位,默认:0.2。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_overlaprate.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_overlaprate.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_overlaprate.failedtip\"},{\"key\":\"param.restrainTime\",\"name\":\"静止目标去重时间(小时)\",\"defaultValue\":\"6\",\"description\":\"静止目标去重时间,范围:1~24小时,默认:6小时。\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1][0-9]|[2][0-4])$/\",\"failedTip\":\"请输入0-24的整数。\",\"level\":\"2\",\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00004.param_restraintime.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_restraintime.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_restraintime.failedtip\"},{\"key\":\"param.overlayTrajectory\",\"name\":\"全景图叠加轨迹\",\"defaultValue\":\"0\",\"description\":\"打开后会在全景图上叠加目标运动轨迹\",\"type\":\"switch\",\"regexpr\":\"/^[01]$/\",\"failedTip\":\"请选择是否打开叠加轨迹\",\"level\":\"2\",\"dependsOn\":{\"key\":\"custParam.alarmType\",\"value\":\"2\"},\"senior\":1,\"nameI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.name\",\"descriptionI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.param_overlaytrajectory.custparam_alarmtype.2.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"上报数据中,部分特殊事件需要额外送参数\",\"failedTip\":\"请选择正确的值\",\"key\":\"alarmProperty\",\"name\":\"事件扩展属性\",\"options\":[{\"name\":\"普通告警(无属性)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.0.options_name\"},{\"name\":\"人脸检测/比对(特征属性)\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.1.options_name\"},{\"name\":\"车辆属性\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.3.options_name\"},{\"name\":\"机物类特殊检测属性(如滤波状态开关/机物比对结果)\",\"value\":\"5\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.5.options_name\"},{\"name\":\"人流量统计属性\",\"value\":\"6\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.6.options_name\"},{\"name\":\"车流量统计属性\",\"value\":\"7\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.7.options_name\"},{\"name\":\"聚集人数\",\"value\":\"8\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.8.options_name\"},{\"name\":\"人数统计属性(区域人数)\",\"value\":\"9\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.9.options_name\"},{\"name\":\"人体特征上报\",\"value\":\"10\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.10.options_name\"},{\"name\":\"工服比对结果\",\"value\":\"11\",\"labelI18nKey\":\"resource.option.ba_00004.alarmproperty.11.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.ba_00004.alarmproperty.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.alarmproperty.failedtip\",\"nameI18nKey\":\"resource.param.ba_00004.alarmproperty.name\"},{\"type\":\"switch\",\"defaultValue\":\"1\",\"description\":\"触发类上报事件是否需要视频片段\",\"failedTip\":\"请选择\",\"key\":\"triggerEventRecordType\",\"name\":\"触发类上报事件是否需要视频片段\",\"level\":\"1\",\"regexpr\":\"/^[0-1]$/\",\"descriptionI18nKey\":\"resource.param.ba_00004.triggereventrecordtype.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.triggereventrecordtype.failedtip\",\"nameI18nKey\":\"resource.param.ba_00004.triggereventrecordtype.name\"},{\"type\":\"switch\",\"defaultValue\":\"0\",\"description\":\"定时上报事件是否需要视频片段\",\"failedTip\":\"请选择\",\"key\":\"realtimeEventRecordType\",\"name\":\"定时上报事件是否需要视频片段\",\"level\":\"1\",\"regexpr\":\"/^[0-1]$/\",\"descriptionI18nKey\":\"resource.param.ba_00004.realtimeeventrecordtype.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.realtimeeventrecordtype.failedtip\",\"nameI18nKey\":\"resource.param.ba_00004.realtimeeventrecordtype.name\"},{\"type\":\"switch\",\"defaultValue\":\"0\",\"description\":\"启用后,告警事件在上报前将由Qwen3VL大模型进行二次审核验证,过滤误报。仅对触发类事件生效。\",\"failedTip\":\"请选择\",\"key\":\"enableLlmReview\",\"name\":\"大模型审核\",\"level\":\"1\",\"regexpr\":\"/^[0-1]$/\",\"descriptionI18nKey\":\"resource.param.ba_00004.enablellmreview.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.enablellmreview.failedtip\",\"nameI18nKey\":\"resource.param.ba_00004.enablellmreview.name\"},{\"type\":\"select\",\"defaultValue\":\"local_model\",\"description\":\"Choose local review model or OpenAI-compatible API\",\"failedTip\":\"Please select a valid value\",\"key\":\"llmProvider\",\"name\":\"Review Inference Mode\",\"options\":[{\"name\":\"Local Atomic Model\",\"value\":\"local_model\",\"labelI18nKey\":\"resource.option.ba_00004.llmprovider.local_model.options_name\"},{\"name\":\"OpenAI API\",\"value\":\"openai_vlm\",\"labelI18nKey\":\"resource.option.ba_00004.llmprovider.openai_vlm.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"enableLlmReview\",\"value\":\"1\"},\"descriptionI18nKey\":\"resource.param.ba_00004.llmprovider.enablellmreview.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.llmprovider.enablellmreview.1.failedtip\",\"nameI18nKey\":\"resource.param.ba_00004.llmprovider.enablellmreview.1.name\"},{\"type\":\"text\",\"defaultValue\":\"http://127.0.0.1:8000/v1\",\"description\":\"OpenAI-compatible API base URL, for example http://127.0.0.1:8000/v1\",\"failedTip\":\"Please enter API base URL\",\"key\":\"llmOpenaiBaseUrl\",\"name\":\"base_url\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"llmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.llmopenai_base_url.llmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"\",\"description\":\"OpenAI API key; leave empty when local vLLM authentication is disabled\",\"failedTip\":\"Please enter API key\",\"key\":\"llmOpenaiApiKey\",\"name\":\"api_key\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"llmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.llmopenai_api_key.llmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"Qwen/Qwen3-VL-2B-Instruct\",\"description\":\"OpenAI API model name\",\"failedTip\":\"Please enter model name\",\"key\":\"llmOpenaiModel\",\"name\":\"model\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"llmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.llmopenai_model.llmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"/chat/completions\",\"description\":\"OpenAI-compatible API path, default /chat/completions\",\"failedTip\":\"Please enter API path\",\"key\":\"llmOpenaiEndpoint\",\"name\":\"endpoint\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"llmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.llmopenai_endpoint.llmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"60000\",\"description\":\"Request timeout in milliseconds\",\"failedTip\":\"Please enter timeout\",\"key\":\"llmOpenaiTimeoutMs\",\"name\":\"timeout_ms\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"llmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.llmopenai_timeout_ms.llmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"256\",\"description\":\"Maximum output token count\",\"failedTip\":\"Please enter maximum output token count\",\"key\":\"llmOpenaiMaxTokens\",\"name\":\"max_tokens\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"llmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.llmopenai_max_tokens.llmprovider.openai_vlm.failedtip\"},{\"type\":\"modelSelect_qwen3vl\",\"defaultValue\":\"\",\"description\":\"选择用于告警审核的Qwen3VL语言视觉大模型\",\"failedTip\":\"请选择审核模型\",\"key\":\"llmAtomicCode\",\"name\":\"审核模型\",\"level\":\"1\",\"dependsOn\":{\"key\":\"llmProvider\",\"value\":\"local_model\"},\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.failedtip\",\"nameI18nKey\":\"resource.param.ba_00004.llmatomiccode.enablellmreview.1.name\"},{\"type\":\"text\",\"defaultValue\":\"\",\"description\":\"用于审核的内容描述,比如:火焰、未带安全帽的人、烟雾等。留空则自动使用算法名称。\",\"failedTip\":\"\",\"key\":\"llmReviewContent\",\"name\":\"审核内容\",\"level\":\"1\",\"dependsOn\":{\"key\":\"enableLlmReview\",\"value\":\"1\"},\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.ba_00004.llmreviewcontent.enablellmreview.1.description\",\"nameI18nKey\":\"resource.param.ba_00004.llmreviewcontent.enablellmreview.1.name\"}]", + "remark": "事件上报", + "actionNameI18nKey": "resource.action.ba_00004.actionname", + "remarkI18nKey": "resource.action.ba_00004.remark" + }, + { + "id": "BA_00005", + "actionUsage": 1, + "actionType": 2, + "businessCategory": "2", + "actionName": "区域告警判断", + "inputParamConfig": "[{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"区域告警统计方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"areaAlarmType\",\"name\":\"区域告警统计方式\",\"options\":[{\"name\":\"数量限制(用于离岗/聚集)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00005.areaalarmtype.0.options_name\"},{\"name\":\"流量统计和区域数量统计\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.areaalarmtype.1.options_name\"},{\"name\":\"过线(用于绊线)\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ba_00005.areaalarmtype.2.options_name\"},{\"name\":\"目标方向告警(用于逆行)\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.ba_00005.areaalarmtype.3.options_name\"},{\"name\":\"目标进入区域一段时间(用于入侵)\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.ba_00005.areaalarmtype.4.options_name\"},{\"name\":\"侦测类(用于人体侦测)\",\"value\":\"5\",\"labelI18nKey\":\"resource.option.ba_00005.areaalarmtype.5.options_name\"},{\"name\":\"多实例的数量限制(一个流程中有多个实例)\",\"value\":\"6\",\"labelI18nKey\":\"resource.option.ba_00005.areaalarmtype.6.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.ba_00005.areaalarmtype.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.areaalarmtype.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.areaalarmtype.name\"},{\"type\":\"select\",\"defaultValue\":\"1\",\"description\":\"输入区域类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"inputAreaType\",\"name\":\"输入区域类型\",\"options\":[{\"name\":\"主区域\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.inputareatype.1.options_name\"},{\"name\":\"关联区域\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ba_00005.inputareatype.2.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.ba_00005.inputareatype.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.inputareatype.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.inputareatype.name\"},{\"key\":\"param.areaLimitTargetCount\",\"name\":\"目标数量阈值\",\"defaultValue\":\"0\",\"description\":\"用于和区域内实际有效目标数量进行比较的阈值\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入0-3600的整数\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_arealimittargetcount.areaalarmtype.0.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"区域中目标数限制类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.areaLimitTargetType\",\"name\":\"触发条件\",\"options\":[{\"name\":\"小于目标数告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimittargettype.0.options_name\"},{\"name\":\"大于目标数告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimittargettype.1.options_name\"},{\"name\":\"小于等于目标数告警\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimittargettype.2.options_name\"},{\"name\":\"大于等于目标数告警\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimittargettype.3.options_name\"},{\"name\":\"等于目标数告警\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimittargettype.4.options_name\"}],\"regexpr\":\"/^[0-4]$/\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":1,\"descriptionI18nKey\":\"resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.param_arealimittargettype.areaalarmtype.0.name\"},{\"key\":\"param.areaLimitDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_arealimitduration.areaalarmtype.0.failedtip\"},{\"key\":\"param.areaCalcDuration\",\"name\":\"数量上报间隔\",\"defaultValue\":\"0\",\"description\":\"数量上报间隔:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"1\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_areacalcduration.areaalarmtype.1.failedtip\"},{\"key\":\"param.areaDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"4\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00005.param_areaduration.areaalarmtype.4.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.param_areaduration.areaalarmtype.4.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_areaduration.areaalarmtype.4.failedtip\"},{\"key\":\"param.areaLimitDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimitdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimitdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimitdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.ba_00005.param_arealimitdurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"0\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_arealimitdurationtimetype.areaalarmtype.0.failedtip\"},{\"key\":\"param.areaDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.param_areadurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.ba_00005.param_areadurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.ba_00005.param_areadurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.ba_00005.param_areadurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"4\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_areadurationtimetype.areaalarmtype.4.failedtip\"},{\"key\":\"param.areaCalcDurationTimeType\",\"name\":\"数量上报间隔时间单位\",\"defaultValue\":\"1000\",\"description\":\"数量上报间隔时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的单位\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.param_areacalcdurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.ba_00005.param_areacalcdurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.ba_00005.param_areacalcdurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.ba_00005.param_areacalcdurationtimetype.3600000.options_name\"}],\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"1\"},\"senior\":0,\"nameI18nKey\":\"resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_areacalcdurationtimetype.areaalarmtype.1.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"101\",\"description\":\"进出区域线方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"breakAreaType\",\"name\":\"进出区域线方式\",\"options\":[{\"name\":\"正向过线\",\"value\":\"101\",\"labelI18nKey\":\"resource.option.ba_00005.breakareatype.101.options_name\"}],\"regexpr\":\"\",\"level\":\"1\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"2\"},\"senior\":0,\"descriptionI18nKey\":\"resource.param.ba_00005.breakareatype.areaalarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.breakareatype.areaalarmtype.2.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.breakareatype.areaalarmtype.2.name\"},{\"type\":\"select\",\"defaultValue\":\"1\",\"description\":\"告警条件:目标过线的数量\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.trippingWireType\",\"name\":\"绊线类型\",\"options\":[{\"name\":\"单线\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.param_trippingwiretype.1.options_name\"},{\"name\":\"双线\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ba_00005.param_trippingwiretype.2.options_name\"}],\"regexpr\":\"\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"2\"},\"senior\":0,\"descriptionI18nKey\":\"resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.param_trippingwiretype.areaalarmtype.2.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"统计类进出区域线方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"detectBreakAreaType\",\"name\":\"统计类进出区域线方式\",\"options\":[{\"name\":\"在区域内告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00005.detectbreakareatype.0.options_name\"}],\"regexpr\":\"\",\"level\":\"1\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"5\"},\"senior\":0,\"descriptionI18nKey\":\"resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.detectbreakareatype.areaalarmtype.5.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"统计类进出区域线方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"countBreakAreaType\",\"name\":\"统计类进出区域线方式\",\"options\":[{\"name\":\"在区域内告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00005.countbreakareatype.0.options_name\"},{\"name\":\"双向过线统计\",\"value\":\"103\",\"labelI18nKey\":\"resource.option.ba_00005.countbreakareatype.103.options_name\"}],\"regexpr\":\"\",\"level\":\"1\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"1\"},\"senior\":0,\"descriptionI18nKey\":\"resource.param.ba_00005.countbreakareatype.areaalarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.countbreakareatype.areaalarmtype.1.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.countbreakareatype.areaalarmtype.1.name\"},{\"type\":\"switch\",\"defaultValue\":\"0\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"1\"},\"description\":\"打开后,目标数量变化时立即上报,即便没有满足时间间隔条件\",\"failedTip\":\"请选择\",\"key\":\"targetCountChange\",\"name\":\"目标数量变化状态\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.ba_00005.targetcountchange.areaalarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.targetcountchange.areaalarmtype.1.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.targetcountchange.areaalarmtype.1.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"统计类进出区域线方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"durationBreakAreaType\",\"name\":\"统计类进出区域线方式\",\"options\":[{\"name\":\"在区域内告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00005.durationbreakareatype.0.options_name\"},{\"name\":\"从外到内\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ba_00005.durationbreakareatype.2.options_name\"}],\"regexpr\":\"\",\"level\":\"1\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"4\"},\"senior\":0,\"descriptionI18nKey\":\"resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.durationbreakareatype.areaalarmtype.4.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"目标统计方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.targetCalcType\",\"name\":\"目标统计方式\",\"options\":[{\"name\":\"瞬时(区域人数统计)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00005.param_targetcalctype.0.options_name\"},{\"name\":\"周期总人数 (人流量)\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.param_targetcalctype.1.options_name\"}],\"regexpr\":\"/^[0-1]$/\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"1\"},\"senior\":1,\"descriptionI18nKey\":\"resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.param_targetcalctype.areaalarmtype.1.name\"},{\"type\":\"retroDirect\",\"defaultValue\":\"0\",\"description\":\"目标逆行告警方向\",\"failedTip\":\"请选择正确的值\",\"key\":\"param.retroDirect\",\"name\":\"目标逆行告警方向\",\"options\":[{\"name\":\"从下往上\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00005.param_retrodirect.0.options_name\"},{\"name\":\"从上往下\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.param_retrodirect.1.options_name\"}],\"regexpr\":\"/^[0-1]$/\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"3\"},\"senior\":0,\"descriptionI18nKey\":\"resource.param.ba_00005.param_retrodirect.areaalarmtype.3.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_retrodirect.areaalarmtype.3.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.param_retrodirect.areaalarmtype.3.name\"},{\"key\":\"param.retroDistance\",\"name\":\"逆行距离: Y轴移动距离(相对值) \",\"defaultValue\":\"0.05\",\"description\":\"逆行距离:Y轴移动距离(相对值) ,范围:0.00~1.0,默认:0.05。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的值\",\"level\":\"2\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"3\"},\"senior\":1,\"nameI18nKey\":\"resource.param.ba_00005.param_retrodistance.areaalarmtype.3.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.param_retrodistance.areaalarmtype.3.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.param_retrodistance.areaalarmtype.3.failedtip\"},{\"key\":\"areaLimitTargetCount\",\"name\":\"区域中的目标数\",\"defaultValue\":\"0\",\"description\":\"区域中的目标数\",\"type\":\"text\",\"regexpr\":\"/^([0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入0-3600的整数\",\"level\":\"1\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"6\"},\"nameI18nKey\":\"resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.arealimittargetcount.areaalarmtype.6.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"区域中目标数限制类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"areaLimitTargetType\",\"name\":\"区域中目标数限制类型\",\"options\":[{\"name\":\"小于目标数告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ba_00005.arealimittargettype.0.options_name\"},{\"name\":\"大于目标数告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.arealimittargettype.1.options_name\"},{\"name\":\"小于等于目标数告警\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ba_00005.arealimittargettype.2.options_name\"},{\"name\":\"大于等于目标数告警\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.ba_00005.arealimittargettype.3.options_name\"},{\"name\":\"等于目标数告警\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.ba_00005.arealimittargettype.4.options_name\"}],\"regexpr\":\"/^[0-4]$/\",\"level\":\"1\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"6\"},\"descriptionI18nKey\":\"resource.param.ba_00005.arealimittargettype.areaalarmtype.6.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.arealimittargettype.areaalarmtype.6.failedtip\",\"nameI18nKey\":\"resource.param.ba_00005.arealimittargettype.areaalarmtype.6.name\"},{\"key\":\"areaLimitDuration\",\"name\":\"检测时间\",\"defaultValue\":\"0\",\"description\":\"检测时间:范围:1-3600000,注意时间单位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入正确的数值\",\"level\":\"1\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"6\"},\"nameI18nKey\":\"resource.param.ba_00005.arealimitduration.areaalarmtype.6.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.arealimitduration.areaalarmtype.6.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.arealimitduration.areaalarmtype.6.failedtip\"},{\"key\":\"areaDurationTimeType\",\"name\":\"检测时间单位\",\"defaultValue\":\"1000\",\"description\":\"检测时间单位\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择正确的数值\",\"options\":[{\"name\":\"毫秒\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ba_00005.areadurationtimetype.1.options_name\"},{\"name\":\"秒\",\"value\":\"1000\",\"labelI18nKey\":\"resource.option.ba_00005.areadurationtimetype.1000.options_name\"},{\"name\":\"分钟\",\"value\":\"60000\",\"labelI18nKey\":\"resource.option.ba_00005.areadurationtimetype.60000.options_name\"},{\"name\":\"小时\",\"value\":\"3600000\",\"labelI18nKey\":\"resource.option.ba_00005.areadurationtimetype.3600000.options_name\"}],\"level\":\"1\",\"dependsOn\":{\"key\":\"areaAlarmType\",\"value\":\"6\"},\"nameI18nKey\":\"resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.name\",\"descriptionI18nKey\":\"resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.description\",\"failedTipI18nKey\":\"resource.param.ba_00005.areadurationtimetype.areaalarmtype.6.failedtip\"}]", + "remark": "处理特殊区域参数,如入侵/绊线/区域人数统计等区域判断告警相关算法", + "actionNameI18nKey": "resource.action.ba_00005.actionname", + "remarkI18nKey": "resource.action.ba_00005.remark" + }, + { + "id": "BA_10003", + "actionUsage": 1, + "actionType": 2, + "businessCategory": "2", + "actionName": "灵敏度计算-计数", + "inputParamConfig": "[{\"key\":\"param.senHitCount\",\"name\":\"灵敏度计算命中数\",\"defaultValue\":\"5\",\"description\":\"灵敏度计算命中数,范围:1-总数。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-2][0-9][0-9][0-9]|[3][0-5][0-9][0-9]|3600)$/\",\"failedTip\":\"请输入1-3600的整数\",\"level\":\"2\",\"senior\":0,\"dependsOn\":null,\"nameI18nKey\":\"resource.param.ba_10003.param_senhitcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_senhitcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_senhitcount.failedtip\"},{\"key\":\"param.senTotalCount\",\"name\":\"灵敏度计算总数\",\"defaultValue\":\"10\",\"description\":\"灵敏度计算总数\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-3600000的整数\",\"level\":\"2\",\"senior\":0,\"dependsOn\":null,\"nameI18nKey\":\"resource.param.ba_10003.param_sentotalcount.name\",\"descriptionI18nKey\":\"resource.param.ba_10003.param_sentotalcount.description\",\"failedTipI18nKey\":\"resource.param.ba_10003.param_sentotalcount.failedtip\"}]", + "remark": "灵敏度计算", + "actionNameI18nKey": "resource.action.ba_10003.actionname", + "remarkI18nKey": "resource.action.ba_10003.remark" + }, + { + "id": "BA_90001", + "actionUsage": 1, + "actionType": 2, + "businessCategory": "2", + "actionName": "目标判断", + "inputParamConfig": "[{\"type\":\"condition\",\"defaultValue\":\"\",\"description\":\"配置条件使其结果为真,并运行下面的动作\",\"failedTip\":\"请选择\",\"key\":\"condition\",\"name\":\"条件配置\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.ba_90001.condition.description\",\"failedTipI18nKey\":\"resource.param.ba_90001.condition.failedtip\",\"nameI18nKey\":\"resource.param.ba_90001.condition.name\"}]", + "remark": "目标判断", + "actionNameI18nKey": "resource.action.ba_90001.actionname", + "remarkI18nKey": "resource.action.ba_90001.remark" + }, + { + "id": "DA_00001", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "检测视觉大模型", + "inputParamConfig": "[{\"type\":\"modelSelect_dino\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00001.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.da_00001.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.da_00001.atomiccode.name\"},{\"type\":\"text\",\"defaultValue\":\"1\",\"description\":\"自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:1。\",\"failedTip\":\"请输入正确的值\",\"key\":\"fps\",\"name\":\"取帧频率\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00001.fps.description\",\"failedTipI18nKey\":\"resource.param.da_00001.fps.failedtip\",\"nameI18nKey\":\"resource.param.da_00001.fps.name\"},{\"key\":\"keywords\",\"name\":\"提示词\",\"defaultValue\":\"\",\"description\":\"多个提示词可以使用英文句号隔开\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入英文\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.da_00001.keywords.name\",\"descriptionI18nKey\":\"resource.param.da_00001.keywords.description\",\"failedTipI18nKey\":\"resource.param.da_00001.keywords.failedtip\"},{\"key\":\"aiParam.box.confidence\",\"name\":\"目标置信度\",\"defaultValue\":\"0.25\",\"description\":\"目标置信度,范围:0.0~1.0,限小数点后3位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.da_00001.aiparam_box_confidence.name\",\"descriptionI18nKey\":\"resource.param.da_00001.aiparam_box_confidence.description\",\"failedTipI18nKey\":\"resource.param.da_00001.aiparam_box_confidence.failedtip\"},{\"key\":\"aiParam.text.confidence\",\"name\":\"文字置信度\",\"defaultValue\":\"0.3\",\"description\":\"文字置信度,范围:0.0~1.0,限小数点后3位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.da_00001.aiparam_text_confidence.name\",\"descriptionI18nKey\":\"resource.param.da_00001.aiparam_text_confidence.description\",\"failedTipI18nKey\":\"resource.param.da_00001.aiparam_text_confidence.failedtip\"}]", + "remark": "检测视觉大模型", + "actionNameI18nKey": "resource.action.da_00001.actionname", + "remarkI18nKey": "resource.action.da_00001.remark" + }, + { + "id": "DA_00002", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "分割视觉大模型", + "inputParamConfig": "[{\"type\":\"modelSelect_sam2\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00002.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.da_00002.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.da_00002.atomiccode.name\"},{\"type\":\"text\",\"defaultValue\":\"1\",\"description\":\"自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:1。\",\"failedTip\":\"请输入正确的值\",\"key\":\"fps\",\"name\":\"取帧频率\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00002.fps.description\",\"failedTipI18nKey\":\"resource.param.da_00002.fps.failedtip\",\"nameI18nKey\":\"resource.param.da_00002.fps.name\"},{\"type\":\"select\",\"defaultValue\":\"box\",\"description\":\"输入类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"inputType\",\"name\":\"输入类型\",\"options\":[{\"name\":\"框\",\"value\":\"box\",\"labelI18nKey\":\"resource.option.da_00002.inputtype.box.options_name\"},{\"name\":\"点\",\"value\":\"point\",\"labelI18nKey\":\"resource.option.da_00002.inputtype.point.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00002.inputtype.description\",\"failedTipI18nKey\":\"resource.param.da_00002.inputtype.failedtip\",\"nameI18nKey\":\"resource.param.da_00002.inputtype.name\"}]", + "remark": "分割视觉大模型", + "actionNameI18nKey": "resource.action.da_00002.actionname", + "remarkI18nKey": "resource.action.da_00002.remark" + }, + { + "id": "DA_00003", + "actionUsage": 1, + "actionType": 1, + "businessCategory": "1", + "actionName": "语言视觉大模型", + "inputParamConfig": "[{\"type\":\"select\",\"defaultValue\":\"local_model\",\"description\":\"Choose local atomic model or OpenAI-compatible API\",\"failedTip\":\"Please select a valid value\",\"key\":\"vlmProvider\",\"name\":\"Inference Mode\",\"options\":[{\"name\":\"Local Atomic Model\",\"value\":\"local_model\",\"labelI18nKey\":\"resource.option.da_00003.vlmprovider.local_model.options_name\"},{\"name\":\"OpenAI API\",\"value\":\"openai_vlm\",\"labelI18nKey\":\"resource.option.da_00003.vlmprovider.openai_vlm.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00003.vlmprovider.description\",\"failedTipI18nKey\":\"resource.param.da_00003.vlmprovider.failedtip\",\"nameI18nKey\":\"resource.param.da_00003.vlmprovider.name\"},{\"type\":\"modelSelect_qwen3vl\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00003.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.da_00003.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.da_00003.atomiccode.name\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"local_model\"}},{\"type\":\"text\",\"defaultValue\":\"http://127.0.0.1:8000/v1\",\"description\":\"OpenAI-compatible API base URL, for example http://127.0.0.1:8000/v1\",\"failedTip\":\"Please enter API base URL\",\"key\":\"openai.base_url\",\"name\":\"base_url\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.da_00003.openai_base_url.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.da_00003.openai_base_url.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"\",\"description\":\"OpenAI API key; leave empty when local vLLM authentication is disabled\",\"failedTip\":\"Please enter API key\",\"key\":\"openai.api_key\",\"name\":\"api_key\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.da_00003.openai_api_key.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.da_00003.openai_api_key.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"Qwen/Qwen3-VL-2B-Instruct\",\"description\":\"OpenAI API model name\",\"failedTip\":\"Please enter model name\",\"key\":\"openai.model\",\"name\":\"model\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.da_00003.openai_model.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.da_00003.openai_model.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"/chat/completions\",\"description\":\"OpenAI-compatible API path, default /chat/completions\",\"failedTip\":\"Please enter API path\",\"key\":\"openai.endpoint\",\"name\":\"endpoint\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.da_00003.openai_endpoint.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.da_00003.openai_endpoint.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"60000\",\"description\":\"Request timeout in milliseconds\",\"failedTip\":\"Please enter timeout\",\"key\":\"openai.timeout_ms\",\"name\":\"timeout_ms\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.da_00003.openai_timeout_ms.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.da_00003.openai_timeout_ms.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"256\",\"description\":\"Maximum output token count\",\"failedTip\":\"Please enter maximum output token count\",\"key\":\"openai.max_tokens\",\"name\":\"max_tokens\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.da_00003.openai_max_tokens.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.da_00003.openai_max_tokens.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"1\",\"description\":\"自定义帧率,不要高于上游帧率。范围:0.01~1000,默认:1。\",\"failedTip\":\"请输入正确的值\",\"key\":\"fps\",\"name\":\"取帧频率\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00003.fps.description\",\"failedTipI18nKey\":\"resource.param.da_00003.fps.failedtip\",\"nameI18nKey\":\"resource.param.da_00003.fps.name\"},{\"type\":\"switch\",\"defaultValue\":\"0\",\"description\":\"开启高级模式可完整自定义前半段提示词。不开启(如输入:安全帽),实际为“判断图片中是否存在【安全帽】目标,回答...”;开启(如输入:判断画面有无安全帽),实际为“判断画面有无安全帽,回答...”\",\"failedTip\":\"请选择\",\"key\":\"advanced_mode\",\"name\":\"高级提示词模式\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00003.advanced_mode.description\",\"failedTipI18nKey\":\"resource.param.da_00003.advanced_mode.failedtip\",\"nameI18nKey\":\"resource.param.da_00003.advanced_mode.name\"},{\"key\":\"keywords\",\"name\":\"提示词\",\"defaultValue\":\"\",\"description\":\"输入提示词\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入提示词\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.da_00003.keywords.name\",\"descriptionI18nKey\":\"resource.param.da_00003.keywords.description\",\"failedTipI18nKey\":\"resource.param.da_00003.keywords.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"standard\",\"description\":\"生成风格\",\"failedTip\":\"请选择正确的值\",\"key\":\"generationStyle\",\"name\":\"生成风格\",\"options\":[{\"name\":\"严谨\",\"value\":\"strict\",\"labelI18nKey\":\"resource.option.da_00003.generationstyle.strict.options_name\"},{\"name\":\"标准\",\"value\":\"standard\",\"labelI18nKey\":\"resource.option.da_00003.generationstyle.standard.options_name\"},{\"name\":\"发散\",\"value\":\"creative\",\"labelI18nKey\":\"resource.option.da_00003.generationstyle.creative.options_name\"},{\"name\":\"自定义\",\"value\":\"custom\",\"labelI18nKey\":\"resource.option.da_00003.generationstyle.custom.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.da_00003.generationstyle.description\",\"failedTipI18nKey\":\"resource.param.da_00003.generationstyle.failedtip\",\"nameI18nKey\":\"resource.param.da_00003.generationstyle.name\"},{\"type\":\"switch\",\"defaultValue\":\"1\",\"description\":\"启用随机采样\",\"failedTip\":\"请选择\",\"key\":\"doSample\",\"name\":\"do_sample\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"generationStyle\",\"value\":\"custom\"},\"descriptionI18nKey\":\"resource.param.da_00003.dosample.generationstyle.custom.description\",\"failedTipI18nKey\":\"resource.param.da_00003.dosample.generationstyle.custom.failedtip\"},{\"key\":\"topK\",\"name\":\"top_k\",\"defaultValue\":\"20\",\"description\":\"每一步只从概率最高的 K 个 token 里选,范围:1~100,默认:20\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-100的整数\",\"level\":\"1\",\"dependsOn\":{\"key\":\"generationStyle\",\"value\":\"custom\"},\"descriptionI18nKey\":\"resource.param.da_00003.topk.generationstyle.custom.description\",\"failedTipI18nKey\":\"resource.param.da_00003.topk.generationstyle.custom.failedtip\"},{\"key\":\"topP\",\"name\":\"top_p\",\"defaultValue\":\"0.8\",\"description\":\"只在累计概率 ≤ top_p 的 token 集合中采样,范围:0.1~1.0,默认:0.8\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0.1-1.0的数值\",\"level\":\"1\",\"dependsOn\":{\"key\":\"generationStyle\",\"value\":\"custom\"},\"descriptionI18nKey\":\"resource.param.da_00003.topp.generationstyle.custom.description\",\"failedTipI18nKey\":\"resource.param.da_00003.topp.generationstyle.custom.failedtip\"},{\"key\":\"temperature\",\"name\":\"temperature\",\"defaultValue\":\"0.7\",\"description\":\"回答发散度,数值越低,回答越严谨、越稳定,范围:0.0~2.0,默认:0.7\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0.0-2.0的数值\",\"level\":\"1\",\"dependsOn\":{\"key\":\"generationStyle\",\"value\":\"custom\"},\"descriptionI18nKey\":\"resource.param.da_00003.temperature.generationstyle.custom.description\",\"failedTipI18nKey\":\"resource.param.da_00003.temperature.generationstyle.custom.failedtip\"}]", + "remark": "语言视觉大模型", + "actionNameI18nKey": "resource.action.da_00003.actionname", + "remarkI18nKey": "resource.action.da_00003.remark" + }, + { + "id": "PA_00001", + "actionUsage": 2, + "actionType": 1, + "businessCategory": "1", + "actionName": "目标检测算法", + "inputParamConfig": "[{\"type\":\"modelSelect_detector\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00001.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.pa_00001.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.pa_00001.atomiccode.name\"}]", + "remark": "检测算法,需要选择算法模型", + "actionNameI18nKey": "resource.action.pa_00001.actionname", + "remarkI18nKey": "resource.action.pa_00001.remark" + }, + { + "id": "PA_00002", + "actionUsage": 2, + "actionType": 1, + "businessCategory": "1", + "actionName": "目标分类算法", + "inputParamConfig": "[{\"type\":\"modelSelect_classify\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00002.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.pa_00002.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.pa_00002.atomiccode.name\"}]", + "remark": "检测目标送分类算法,需要选择一个分类模型", + "actionNameI18nKey": "resource.action.pa_00002.actionname", + "remarkI18nKey": "resource.action.pa_00002.remark" + }, + { + "id": "PA_00005", + "actionUsage": 2, + "actionType": 1, + "businessCategory": "1", + "actionName": "特征提取算法", + "inputParamConfig": "[{\"type\":\"modelSelect_feature\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00005.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.pa_00005.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.pa_00005.atomiccode.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"特征输入类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"featureInput\",\"name\":\"特征输入类型\",\"options\":[{\"name\":\"人脸特征提取(暂不支持)\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.pa_00005.featureinput.0.options_name\"},{\"name\":\"工服特征提取\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.pa_00005.featureinput.1.options_name\"},{\"name\":\"机物特征提取\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.pa_00005.featureinput.2.options_name\"},{\"name\":\"人体特征提取(暂不支持)\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.pa_00005.featureinput.3.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00005.featureinput.description\",\"failedTipI18nKey\":\"resource.param.pa_00005.featureinput.failedtip\",\"nameI18nKey\":\"resource.param.pa_00005.featureinput.name\"},{\"type\":\"faceSet\",\"description\":\"选择需要比对的脸库分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.faceSet\",\"name\":\"绑定人脸分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"0\"},\"level\":\"2\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00005.param_faceset.featureinput.0.description\",\"failedTipI18nKey\":\"resource.param.pa_00005.param_faceset.featureinput.0.failedtip\",\"nameI18nKey\":\"resource.param.pa_00005.param_faceset.featureinput.0.name\"},{\"type\":\"workClothesSet\",\"description\":\"选择需要比对的工服分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.workClothesSet\",\"name\":\"绑定工服分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"1\"},\"level\":\"2\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00005.param_workclothesset.featureinput.1.description\",\"failedTipI18nKey\":\"resource.param.pa_00005.param_workclothesset.featureinput.1.failedtip\",\"nameI18nKey\":\"resource.param.pa_00005.param_workclothesset.featureinput.1.name\"},{\"type\":\"commoditySet\",\"description\":\"选择需要比对的机物分组\",\"failedTip\":\"请选择正确的值\",\"defaultValue\":\"\",\"key\":\"param.commoditySet\",\"name\":\"绑定机物分组\",\"senior\":0,\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"2\"},\"level\":\"2\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00005.param_commodityset.featureinput.2.description\",\"failedTipI18nKey\":\"resource.param.pa_00005.param_commodityset.featureinput.2.failedtip\",\"nameI18nKey\":\"resource.param.pa_00005.param_commodityset.featureinput.2.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"匹配标志\",\"failedTip\":\"请选择正确的值\",\"key\":\"matchFlag\",\"name\":\"匹配标志\",\"options\":[{\"name\":\"未命中告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.pa_00005.matchflag.0.options_name\"},{\"name\":\"命中告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.pa_00005.matchflag.1.options_name\"}],\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"1\"},\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00005.matchflag.featureinput.1.description\",\"failedTipI18nKey\":\"resource.param.pa_00005.matchflag.featureinput.1.failedtip\",\"nameI18nKey\":\"resource.param.pa_00005.matchflag.featureinput.1.name\"},{\"type\":\"select\",\"defaultValue\":\"0\",\"description\":\"匹配标志\",\"failedTip\":\"请选择正确的值\",\"key\":\"matchFlag\",\"name\":\"匹配标志\",\"options\":[{\"name\":\"未命中告警\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.pa_00005.matchflag.0.options_name\"},{\"name\":\"命中告警\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.pa_00005.matchflag.1.options_name\"}],\"dependsOn\":{\"key\":\"featureInput\",\"value\":\"2\"},\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pa_00005.matchflag.featureinput.2.description\",\"failedTipI18nKey\":\"resource.param.pa_00005.matchflag.featureinput.2.failedtip\",\"nameI18nKey\":\"resource.param.pa_00005.matchflag.featureinput.2.name\"}]", + "remark": "支持人脸、人体、机物提取特征", + "actionNameI18nKey": "resource.action.pa_00005.actionname", + "remarkI18nKey": "resource.action.pa_00005.remark" + }, + { + "id": "PB_90001", + "actionUsage": 2, + "actionType": 2, + "businessCategory": "2", + "actionName": "目标判断", + "inputParamConfig": "[{\"type\":\"condition\",\"defaultValue\":\"\",\"description\":\"配置条件使其结果为真,并运行下面的动作\",\"failedTip\":\"请选择\",\"key\":\"condition\",\"name\":\"条件配置\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pb_90001.condition.description\",\"failedTipI18nKey\":\"resource.param.pb_90001.condition.failedtip\",\"nameI18nKey\":\"resource.param.pb_90001.condition.name\"}]", + "remark": "目标判断", + "actionNameI18nKey": "resource.action.pb_90001.actionname", + "remarkI18nKey": "resource.action.pb_90001.remark" + }, + { + "id": "PDA_00001", + "actionUsage": 2, + "actionType": 1, + "businessCategory": "1", + "actionName": "检测视觉大模型", + "inputParamConfig": "[{\"type\":\"modelSelect_dino\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pda_00001.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.pda_00001.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.pda_00001.atomiccode.name\"},{\"key\":\"keywords\",\"name\":\"提示词\",\"defaultValue\":\"\",\"description\":\"多个提示词可以使用英文句号隔开\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入英文\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pda_00001.keywords.name\",\"descriptionI18nKey\":\"resource.param.pda_00001.keywords.description\",\"failedTipI18nKey\":\"resource.param.pda_00001.keywords.failedtip\"},{\"key\":\"aiParam.box.confidence\",\"name\":\"目标置信度\",\"defaultValue\":\"0.25\",\"description\":\"目标置信度,范围:0.0~1.0,限小数点后3位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pda_00001.aiparam_box_confidence.name\",\"descriptionI18nKey\":\"resource.param.pda_00001.aiparam_box_confidence.description\",\"failedTipI18nKey\":\"resource.param.pda_00001.aiparam_box_confidence.failedtip\"},{\"key\":\"aiParam.text.confidence\",\"name\":\"文字置信度\",\"defaultValue\":\"0.3\",\"description\":\"文字置信度,范围:0.0~1.0,限小数点后3位\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pda_00001.aiparam_text_confidence.name\",\"descriptionI18nKey\":\"resource.param.pda_00001.aiparam_text_confidence.description\",\"failedTipI18nKey\":\"resource.param.pda_00001.aiparam_text_confidence.failedtip\"}]", + "remark": "检测视觉大模型(图片)", + "actionNameI18nKey": "resource.action.pda_00001.actionname", + "remarkI18nKey": "resource.action.pda_00001.remark" + }, + { + "id": "PDA_00002", + "actionUsage": 2, + "actionType": 1, + "businessCategory": "1", + "actionName": "分割视觉大模型", + "inputParamConfig": "[{\"type\":\"modelSelect_sam2\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pda_00002.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.pda_00002.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.pda_00002.atomiccode.name\"},{\"type\":\"select\",\"defaultValue\":\"box\",\"description\":\"输入类型\",\"failedTip\":\"请选择正确的值\",\"key\":\"inputType\",\"name\":\"输入类型\",\"options\":[{\"name\":\"框\",\"value\":\"box\",\"labelI18nKey\":\"resource.option.pda_00002.inputtype.box.options_name\"},{\"name\":\"点\",\"value\":\"point\",\"labelI18nKey\":\"resource.option.pda_00002.inputtype.point.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pda_00002.inputtype.description\",\"failedTipI18nKey\":\"resource.param.pda_00002.inputtype.failedtip\",\"nameI18nKey\":\"resource.param.pda_00002.inputtype.name\"}]", + "remark": "分割视觉大模型(图片)", + "actionNameI18nKey": "resource.action.pda_00002.actionname", + "remarkI18nKey": "resource.action.pda_00002.remark" + }, + { + "id": "PDA_00003", + "actionUsage": 2, + "actionType": 1, + "businessCategory": "1", + "actionName": "语言视觉大模型", + "inputParamConfig": "[{\"type\":\"select\",\"defaultValue\":\"local_model\",\"description\":\"Choose local atomic model or OpenAI-compatible API\",\"failedTip\":\"Please select a valid value\",\"key\":\"vlmProvider\",\"name\":\"Inference Mode\",\"options\":[{\"name\":\"Local Atomic Model\",\"value\":\"local_model\",\"labelI18nKey\":\"resource.option.pda_00003.vlmprovider.local_model.options_name\"},{\"name\":\"OpenAI API\",\"value\":\"openai_vlm\",\"labelI18nKey\":\"resource.option.pda_00003.vlmprovider.openai_vlm.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pda_00003.vlmprovider.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.vlmprovider.failedtip\",\"nameI18nKey\":\"resource.param.pda_00003.vlmprovider.name\"},{\"type\":\"modelSelect_qwen3vl\",\"defaultValue\":\"\",\"description\":\"选择原子模型\",\"failedTip\":\"请选择\",\"key\":\"atomicCode\",\"name\":\"选择原子模型\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pda_00003.atomiccode.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.atomiccode.failedtip\",\"nameI18nKey\":\"resource.param.pda_00003.atomiccode.name\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"local_model\"}},{\"type\":\"text\",\"defaultValue\":\"http://127.0.0.1:8000/v1\",\"description\":\"OpenAI-compatible API base URL, for example http://127.0.0.1:8000/v1\",\"failedTip\":\"Please enter API base URL\",\"key\":\"openai.base_url\",\"name\":\"base_url\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.pda_00003.openai_base_url.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.openai_base_url.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"\",\"description\":\"OpenAI API key; leave empty when local vLLM authentication is disabled\",\"failedTip\":\"Please enter API key\",\"key\":\"openai.api_key\",\"name\":\"api_key\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.pda_00003.openai_api_key.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.openai_api_key.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"Qwen/Qwen3-VL-2B-Instruct\",\"description\":\"OpenAI API model name\",\"failedTip\":\"Please enter model name\",\"key\":\"openai.model\",\"name\":\"model\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.pda_00003.openai_model.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.openai_model.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"/chat/completions\",\"description\":\"OpenAI-compatible API path, default /chat/completions\",\"failedTip\":\"Please enter API path\",\"key\":\"openai.endpoint\",\"name\":\"endpoint\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.pda_00003.openai_endpoint.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.openai_endpoint.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"60000\",\"description\":\"Request timeout in milliseconds\",\"failedTip\":\"Please enter timeout\",\"key\":\"openai.timeout_ms\",\"name\":\"timeout_ms\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.pda_00003.openai_timeout_ms.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.openai_timeout_ms.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"text\",\"defaultValue\":\"256\",\"description\":\"Maximum output token count\",\"failedTip\":\"Please enter maximum output token count\",\"key\":\"openai.max_tokens\",\"name\":\"max_tokens\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"vlmProvider\",\"value\":\"openai_vlm\"},\"descriptionI18nKey\":\"resource.param.pda_00003.openai_max_tokens.vlmprovider.openai_vlm.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.openai_max_tokens.vlmprovider.openai_vlm.failedtip\"},{\"type\":\"switch\",\"defaultValue\":\"0\",\"description\":\"开启高级模式可完整自定义前半段提示词。不开启(如输入:安全帽),实际为“判断图片中是否存在【安全帽】目标,回答...”;开启(如输入:判断画面有无安全帽),实际为“判断画面有无安全帽,回答...”\",\"failedTip\":\"请选择\",\"key\":\"advanced_mode\",\"name\":\"高级提示词模式\",\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pda_00003.advanced_mode.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.advanced_mode.failedtip\",\"nameI18nKey\":\"resource.param.pda_00003.advanced_mode.name\"},{\"key\":\"keywords\",\"name\":\"提示词\",\"defaultValue\":\"\",\"description\":\"输入提示词\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入提示词\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pda_00003.keywords.name\",\"descriptionI18nKey\":\"resource.param.pda_00003.keywords.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.keywords.failedtip\"},{\"type\":\"select\",\"defaultValue\":\"standard\",\"description\":\"生成风格\",\"failedTip\":\"请选择正确的值\",\"key\":\"generationStyle\",\"name\":\"生成风格\",\"options\":[{\"name\":\"严谨\",\"value\":\"strict\",\"labelI18nKey\":\"resource.option.pda_00003.generationstyle.strict.options_name\"},{\"name\":\"标准\",\"value\":\"standard\",\"labelI18nKey\":\"resource.option.pda_00003.generationstyle.standard.options_name\"},{\"name\":\"发散\",\"value\":\"creative\",\"labelI18nKey\":\"resource.option.pda_00003.generationstyle.creative.options_name\"},{\"name\":\"自定义\",\"value\":\"custom\",\"labelI18nKey\":\"resource.option.pda_00003.generationstyle.custom.options_name\"}],\"level\":\"1\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.pda_00003.generationstyle.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.generationstyle.failedtip\",\"nameI18nKey\":\"resource.param.pda_00003.generationstyle.name\"},{\"type\":\"switch\",\"defaultValue\":\"1\",\"description\":\"启用随机采样\",\"failedTip\":\"请选择\",\"key\":\"doSample\",\"name\":\"do_sample\",\"level\":\"1\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"generationStyle\",\"value\":\"custom\"},\"descriptionI18nKey\":\"resource.param.pda_00003.dosample.generationstyle.custom.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.dosample.generationstyle.custom.failedtip\"},{\"key\":\"topK\",\"name\":\"top_k\",\"defaultValue\":\"20\",\"description\":\"每一步只从概率最高的 K 个 token 里选,范围:1~100,默认:20\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入1-100的整数\",\"level\":\"1\",\"dependsOn\":{\"key\":\"generationStyle\",\"value\":\"custom\"},\"descriptionI18nKey\":\"resource.param.pda_00003.topk.generationstyle.custom.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.topk.generationstyle.custom.failedtip\"},{\"key\":\"topP\",\"name\":\"top_p\",\"defaultValue\":\"0.8\",\"description\":\"只在累计概率 ≤ top_p 的 token 集合中采样,范围:0.1~1.0,默认:0.8\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0.1-1.0的数值\",\"level\":\"1\",\"dependsOn\":{\"key\":\"generationStyle\",\"value\":\"custom\"},\"descriptionI18nKey\":\"resource.param.pda_00003.topp.generationstyle.custom.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.topp.generationstyle.custom.failedtip\"},{\"key\":\"temperature\",\"name\":\"temperature\",\"defaultValue\":\"0.7\",\"description\":\"回答发散度,数值越低,回答越严谨、越稳定,范围:0.0~2.0,默认:0.7\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0.0-2.0的数值\",\"level\":\"1\",\"dependsOn\":{\"key\":\"generationStyle\",\"value\":\"custom\"},\"descriptionI18nKey\":\"resource.param.pda_00003.temperature.generationstyle.custom.description\",\"failedTipI18nKey\":\"resource.param.pda_00003.temperature.generationstyle.custom.failedtip\"}]", + "remark": "语言视觉大模型(图片)", + "actionNameI18nKey": "resource.action.pda_00003.actionname", + "remarkI18nKey": "resource.action.pda_00003.remark" + } +] diff --git a/data/resource/aiboxresource_cv186x/layout/linkageStorages.json b/data/resource/aiboxresource_cv186x/layout/linkageStorages.json new file mode 100644 index 000000000..a7ee0f1f2 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/layout/linkageStorages.json @@ -0,0 +1,20 @@ +[ + { + "id": "LA_AlarmData_Code", + "businessCategory": "1", + "actionName": "算法告警数据", + "remark": "配置通道中的算法告警数据,用于触发联动流程", + "inputParamConfig": "[{\"type\":\"taskList\",\"defaultValue\":\"\",\"description\":\"\",\"failedTip\":\"请选择\",\"queryDict\":\"IP_SOUND_COLUMN_LIST\",\"key\":\"algs\",\"regexpr\":\"\",\"failedTipI18nKey\":\"resource.param.la_alarmdata_code.algs.failedtip\"}]", + "actionNameI18nKey": "resource.action.la_alarmdata_code.actionname", + "remarkI18nKey": "resource.action.la_alarmdata_code.remark" + }, + { + "id": "LA_AudioDevice_Code", + "businessCategory": "2", + "actionName": "网络音柱联动", + "remark": "配置IP音设备进行告警播报", + "inputParamConfig": "[{\"type\":\"select\",\"defaultValue\":\"\",\"description\":\"选择网络音柱\",\"failedTip\":\"选择网络音柱\",\"key\":\"audioDeviceId\",\"name\":\"选择网络音柱\",\"queryDict\":\"IP_SOUND_COLUMN_LIST\",\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.audiodeviceid.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.audiodeviceid.failedtip\",\"nameI18nKey\":\"resource.param.la_audiodevice_code.audiodeviceid.name\"},{\"type\":\"radio\",\"defaultValue\":\"1\",\"description\":\"播放方式\",\"failedTip\":\"请选择正确的值\",\"key\":\"operation\",\"name\":\"播放方式\",\"options\":[{\"label\":\"音频播放\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.la_audiodevice_code.operation.1.options_label\"},{\"label\":\"文字播放\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.la_audiodevice_code.operation.2.options_label\"}],\"regexpr\":\"\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.operation.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.operation.failedtip\",\"nameI18nKey\":\"resource.param.la_audiodevice_code.operation.name\"},{\"name\":\"音频文件\",\"key\":\"data\",\"failedTip\":\"选择对应的告警音频文件.\",\"defaultValue\":\"\",\"description\":\"选择对应的告警音频文件。\",\"type\":\"select\",\"queryDict\":\"QUERY_AUDIO_FILE\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"operation\",\"value\":\"1\"},\"nameI18nKey\":\"resource.param.la_audiodevice_code.data.operation.1.name\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.data.operation.1.failedtip\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.data.operation.1.description\"},{\"name\":\"播放文字\",\"key\":\"text\",\"defaultValue\":\"\",\"description\":\"播放文字:限制32字符。\",\"failedTip\":\"请输入32字符以下\",\"type\":\"text\",\"inputType\":\"str\",\"regexpr\":\"\",\"dependsOn\":{\"key\":\"operation\",\"value\":\"2\"},\"nameI18nKey\":\"resource.param.la_audiodevice_code.text.operation.2.name\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.text.operation.2.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.text.operation.2.failedtip\"},{\"name\":\"音色\",\"key\":\"tone\",\"defaultValue\":\"1\",\"description\":\"音色:可选择男声、女声,默认男声。\",\"type\":\"select\",\"regexpr\":\"\",\"failedTip\":\"请选择\",\"options\":[{\"label\":\"男声\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.la_audiodevice_code.tone.1.options_label\"},{\"label\":\"女声\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.la_audiodevice_code.tone.2.options_label\"}],\"dependsOn\":{\"key\":\"operation\",\"value\":\"2\"},\"inputType\":\"num\",\"nameI18nKey\":\"resource.param.la_audiodevice_code.tone.operation.2.name\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.tone.operation.2.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.tone.operation.2.failedtip\"},{\"name\":\"音速\",\"key\":\"speed\",\"defaultValue\":\"5\",\"description\":\"音速\",\"type\":\"text\",\"inputType\":\"num\",\"regexpr\":\"\",\"failedTip\":\"请输入整数\",\"dependsOn\":{\"key\":\"operation\",\"value\":\"2\"},\"nameI18nKey\":\"resource.param.la_audiodevice_code.speed.operation.2.name\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.speed.operation.2.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.speed.operation.2.failedtip\"},{\"name\":\"音量\",\"key\":\"volume\",\"defaultValue\":\"50\",\"description\":\"音量\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入整数\",\"inputType\":\"num\",\"nameI18nKey\":\"resource.param.la_audiodevice_code.volume.name\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.volume.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.volume.failedtip\"},{\"name\":\"播放时长(秒)\",\"key\":\"duration\",\"defaultValue\":\"60\",\"description\":\"播放时长(秒)\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入整数\",\"inputType\":\"num\",\"nameI18nKey\":\"resource.param.la_audiodevice_code.duration.name\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.duration.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.duration.failedtip\"},{\"name\":\"播放次数\",\"key\":\"times\",\"defaultValue\":\"1\",\"description\":\"播放次数\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入整数\",\"inputType\":\"num\",\"nameI18nKey\":\"resource.param.la_audiodevice_code.times.name\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.times.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.times.failedtip\"},{\"name\":\"播放间隔(秒)\",\"key\":\"gap\",\"defaultValue\":\"1\",\"description\":\"播放间隔(秒)\",\"type\":\"text\",\"regexpr\":\"\",\"inputType\":\"num\",\"failedTip\":\"请输入整数\",\"nameI18nKey\":\"resource.param.la_audiodevice_code.gap.name\",\"descriptionI18nKey\":\"resource.param.la_audiodevice_code.gap.description\",\"failedTipI18nKey\":\"resource.param.la_audiodevice_code.gap.failedtip\"}]", + "actionNameI18nKey": "resource.action.la_audiodevice_code.actionname", + "remarkI18nKey": "resource.action.la_audiodevice_code.remark" + } +] diff --git a/data/resource/aiboxresource_cv186x/layout/modelComponents.json b/data/resource/aiboxresource_cv186x/layout/modelComponents.json new file mode 100644 index 000000000..af6813b29 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/layout/modelComponents.json @@ -0,0 +1,142 @@ +[ + { + "id": "IP0001", + "componentType": "input", + "componentName": "输入节点组件", + "inputParamConfig": "[{\"type\":\"text\",\"key\":\"input_node\",\"name\":\"输入节点名称\",\"defaultValue\":\"images\",\"description\":\"模型输入节点名称\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.ip0001.input_node.name\",\"descriptionI18nKey\":\"resource.param.ip0001.input_node.description\"},{\"type\":\"text\",\"key\":\"shape\",\"name\":\"输入形状\",\"defaultValue\":\"[-1, 3, 640, 640]\",\"description\":\"输入张量形状,格式:[batch, channel, height, width]\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.ip0001.shape.name\",\"descriptionI18nKey\":\"resource.param.ip0001.shape.description\"},{\"type\":\"select\",\"key\":\"data_type\",\"name\":\"数据类型\",\"defaultValue\":\"0\",\"description\":\"数据类型选择\",\"options\":[{\"name\":\"32位浮点数\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.ip0001.data_type.0.options_name\"},{\"name\":\"32位有符号整数\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.ip0001.data_type.1.options_name\"},{\"name\":\"16位半精度浮点数\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.ip0001.data_type.2.options_name\"},{\"name\":\"16位浮点数\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.ip0001.data_type.3.options_name\"},{\"name\":\"8位无符号整数\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.ip0001.data_type.4.options_name\"},{\"name\":\"8位有符号整数\",\"value\":\"5\",\"labelI18nKey\":\"resource.option.ip0001.data_type.5.options_name\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.ip0001.data_type.name\",\"descriptionI18nKey\":\"resource.param.ip0001.data_type.description\"}]", + "componentNameI18nKey": "resource.action.ip0001.componentname" + }, + { + "id": "PR0001", + "componentType": "resize", + "componentName": "resize组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"预处理操作类型\",\"defaultValue\":\"resize\",\"description\":\"预处理操作类型\",\"options\":[{\"name\":\"resize\",\"value\":\"resize\"},{\"name\":\"normalize\",\"value\":\"normalize\"},{\"name\":\"crop\",\"value\":\"crop\"},{\"name\":\"expand\",\"value\":\"expand\"},{\"name\":\"affine_crop\",\"value\":\"affine_crop\"},{\"name\":\"sequence\",\"value\":\"sequence\"},{\"name\":\"combine_image\",\"value\":\"combine_image\"},{\"name\":\"dino_encode\",\"value\":\"dino_encode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0001.op.name\",\"descriptionI18nKey\":\"resource.param.pr0001.op.description\"},{\"type\":\"text\",\"key\":\"dsize\",\"name\":\"目标尺寸\",\"defaultValue\":\"[640, 640]\",\"description\":\"调整后的图像尺寸 [height, width]\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0001.dsize.name\",\"descriptionI18nKey\":\"resource.param.pr0001.dsize.description\"},{\"type\":\"select\",\"key\":\"gravity\",\"name\":\"缩放策略\",\"defaultValue\":\"0\",\"description\":\"缩放策略:0-直接缩放,1-等比缩放后居中填充,2-等比缩放顶左对齐(与 cwnn_sophon 一致)\",\"options\":[{\"name\":\"直接缩放\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.pr0001.gravity.0.options_name\"},{\"name\":\"等比缩放后居中填充\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.pr0001.gravity.1.options_name\"},{\"name\":\"等比缩放顶左对齐\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.pr0001.gravity.2.options_name\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0001.gravity.name\",\"descriptionI18nKey\":\"resource.param.pr0001.gravity.description\"},{\"type\":\"text\",\"key\":\"color\",\"name\":\"填充颜色\",\"defaultValue\":\"[114, 114, 114]\",\"description\":\"填充颜色 [R, G, B](gravity 非 0 时生效)\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0001.color.name\",\"descriptionI18nKey\":\"resource.param.pr0001.color.description\"}]", + "componentNameI18nKey": "resource.action.pr0001.componentname" + }, + { + "id": "PR0002", + "componentType": "normalize", + "componentName": "normalize组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"预处理操作类型\",\"defaultValue\":\"normalize\",\"description\":\"预处理操作类型\",\"options\":[{\"name\":\"resize\",\"value\":\"resize\"},{\"name\":\"normalize\",\"value\":\"normalize\"},{\"name\":\"crop\",\"value\":\"crop\"},{\"name\":\"expand\",\"value\":\"expand\"},{\"name\":\"affine_crop\",\"value\":\"affine_crop\"},{\"name\":\"sequence\",\"value\":\"sequence\"},{\"name\":\"combine_image\",\"value\":\"combine_image\"},{\"name\":\"dino_encode\",\"value\":\"dino_encode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0002.op.name\",\"descriptionI18nKey\":\"resource.param.pr0002.op.description\"},{\"type\":\"text\",\"key\":\"mean\",\"name\":\"均值\",\"defaultValue\":\"[0, 0, 0]\",\"description\":\"归一化均值 [R, G, B]\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0002.mean.name\",\"descriptionI18nKey\":\"resource.param.pr0002.mean.description\"},{\"type\":\"text\",\"key\":\"std\",\"name\":\"标准差\",\"defaultValue\":\"\",\"description\":\"归一化标准差 [R, G, B],可选,若提供则使用 1/std;若不提供,则按 scale 使用\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0002.std.name\",\"descriptionI18nKey\":\"resource.param.pr0002.std.description\"},{\"type\":\"text\",\"key\":\"scale\",\"name\":\"缩放因子\",\"defaultValue\":\"1.0\",\"description\":\"归一化缩放因子\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0002.scale.name\",\"descriptionI18nKey\":\"resource.param.pr0002.scale.description\"},{\"type\":\"switch\",\"key\":\"is_bgr\",\"name\":\"BGR格式\",\"defaultValue\":\"1\",\"description\":\"是否为BGR格式\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0002.is_bgr.name\",\"descriptionI18nKey\":\"resource.param.pr0002.is_bgr.description\"}]", + "componentNameI18nKey": "resource.action.pr0002.componentname" + }, + { + "id": "PR0003", + "componentType": "crop", + "componentName": "crop组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"预处理操作类型\",\"defaultValue\":\"crop\",\"description\":\"预处理操作类型\",\"options\":[{\"name\":\"resize\",\"value\":\"resize\"},{\"name\":\"normalize\",\"value\":\"normalize\"},{\"name\":\"crop\",\"value\":\"crop\"},{\"name\":\"expand\",\"value\":\"expand\"},{\"name\":\"affine_crop\",\"value\":\"affine_crop\"},{\"name\":\"sequence\",\"value\":\"sequence\"},{\"name\":\"combine_image\",\"value\":\"combine_image\"},{\"name\":\"dino_encode\",\"value\":\"dino_encode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0003.op.name\",\"descriptionI18nKey\":\"resource.param.pr0003.op.description\"},{\"type\":\"text\",\"key\":\"h_top_crop\",\"name\":\"顶部\",\"defaultValue\":\"-0.1\",\"description\":\"范围 -1~1:负值或 0 表示该边裁剪(如 -0.1 裁 10%),正值表示扩展(如 0.1 扩 10%)\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0003.h_top_crop.name\",\"descriptionI18nKey\":\"resource.param.pr0003.h_top_crop.description\"},{\"type\":\"text\",\"key\":\"h_bottom_crop\",\"name\":\"底部\",\"defaultValue\":\"-0.1\",\"description\":\"-1~1:负或 0=裁剪,正=扩展\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0003.h_bottom_crop.name\",\"descriptionI18nKey\":\"resource.param.pr0003.h_bottom_crop.description\"},{\"type\":\"text\",\"key\":\"w_left_crop\",\"name\":\"左侧\",\"defaultValue\":\"-0.05\",\"description\":\"-1~1:负或 0=裁剪,正=扩展\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0003.w_left_crop.name\",\"descriptionI18nKey\":\"resource.param.pr0003.w_left_crop.description\"},{\"type\":\"text\",\"key\":\"w_right_crop\",\"name\":\"右侧\",\"defaultValue\":\"-0.05\",\"description\":\"-1~1:负或 0=裁剪,正=扩展\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0003.w_right_crop.name\",\"descriptionI18nKey\":\"resource.param.pr0003.w_right_crop.description\"},{\"type\":\"switch\",\"key\":\"square\",\"name\":\"强制正方形\",\"defaultValue\":\"0\",\"description\":\"是否强制为正方形\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0003.square.name\",\"descriptionI18nKey\":\"resource.param.pr0003.square.description\"},{\"type\":\"select\",\"key\":\"square_mode\",\"name\":\"正方形模式\",\"defaultValue\":\"0\",\"description\":\"正方形模式:0-max, 1-min, 2-avg\",\"options\":[{\"name\":\"max\",\"value\":\"0\"},{\"name\":\"min\",\"value\":\"1\"},{\"name\":\"avg\",\"value\":\"2\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0003.square_mode.name\",\"descriptionI18nKey\":\"resource.param.pr0003.square_mode.description\"},{\"type\":\"switch\",\"key\":\"skip\",\"name\":\"跳过操作\",\"defaultValue\":\"0\",\"description\":\"是否跳过此操作\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0003.skip.name\",\"descriptionI18nKey\":\"resource.param.pr0003.skip.description\"}]", + "componentNameI18nKey": "resource.action.pr0003.componentname" + }, + { + "id": "PR0004", + "componentType": "expand", + "componentName": "expand组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"预处理操作类型\",\"defaultValue\":\"expand\",\"description\":\"与 crop 共用 -1~1 语义:负或 0=裁剪,正=扩展。expand 时常用正值\",\"options\":[{\"name\":\"resize\",\"value\":\"resize\"},{\"name\":\"normalize\",\"value\":\"normalize\"},{\"name\":\"crop\",\"value\":\"crop\"},{\"name\":\"expand\",\"value\":\"expand\"},{\"name\":\"affine_crop\",\"value\":\"affine_crop\"},{\"name\":\"sequence\",\"value\":\"sequence\"},{\"name\":\"combine_image\",\"value\":\"combine_image\"},{\"name\":\"dino_encode\",\"value\":\"dino_encode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0004.op.name\",\"descriptionI18nKey\":\"resource.param.pr0004.op.description\"},{\"type\":\"text\",\"key\":\"h_top_crop\",\"name\":\"顶部\",\"defaultValue\":\"0.1\",\"description\":\"-1~1:负或 0=裁剪,正=扩展(如 0.1 扩 10%)\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0004.h_top_crop.name\",\"descriptionI18nKey\":\"resource.param.pr0004.h_top_crop.description\"},{\"type\":\"text\",\"key\":\"h_bottom_crop\",\"name\":\"底部\",\"defaultValue\":\"0.1\",\"description\":\"-1~1:负或 0=裁剪,正=扩展\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0004.h_bottom_crop.name\",\"descriptionI18nKey\":\"resource.param.pr0004.h_bottom_crop.description\"},{\"type\":\"text\",\"key\":\"w_left_crop\",\"name\":\"左侧\",\"defaultValue\":\"0.05\",\"description\":\"-1~1:负或 0=裁剪,正=扩展\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0004.w_left_crop.name\",\"descriptionI18nKey\":\"resource.param.pr0004.w_left_crop.description\"},{\"type\":\"text\",\"key\":\"w_right_crop\",\"name\":\"右侧\",\"defaultValue\":\"0.05\",\"description\":\"-1~1:负或 0=裁剪,正=扩展\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0004.w_right_crop.name\",\"descriptionI18nKey\":\"resource.param.pr0004.w_right_crop.description\"},{\"type\":\"switch\",\"key\":\"square\",\"name\":\"强制正方形\",\"defaultValue\":\"0\",\"description\":\"是否强制为正方形\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0004.square.name\",\"descriptionI18nKey\":\"resource.param.pr0004.square.description\"},{\"type\":\"select\",\"key\":\"square_mode\",\"name\":\"正方形模式\",\"defaultValue\":\"0\",\"description\":\"正方形模式:0-max, 1-min, 2-avg\",\"options\":[{\"name\":\"max\",\"value\":\"0\"},{\"name\":\"min\",\"value\":\"1\"},{\"name\":\"avg\",\"value\":\"2\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0004.square_mode.name\",\"descriptionI18nKey\":\"resource.param.pr0004.square_mode.description\"},{\"type\":\"switch\",\"key\":\"skip\",\"name\":\"跳过操作\",\"defaultValue\":\"0\",\"description\":\"是否跳过此操作\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0004.skip.name\",\"descriptionI18nKey\":\"resource.param.pr0004.skip.description\"}]", + "componentNameI18nKey": "resource.action.pr0004.componentname" + }, + { + "id": "PR0005", + "componentType": "affine_crop", + "componentName": "affine_crop组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"预处理操作类型\",\"defaultValue\":\"affine_crop\",\"description\":\"预处理操作类型\",\"options\":[{\"name\":\"resize\",\"value\":\"resize\"},{\"name\":\"normalize\",\"value\":\"normalize\"},{\"name\":\"crop\",\"value\":\"crop\"},{\"name\":\"expand\",\"value\":\"expand\"},{\"name\":\"affine_crop\",\"value\":\"affine_crop\"},{\"name\":\"sequence\",\"value\":\"sequence\"},{\"name\":\"combine_image\",\"value\":\"combine_image\"},{\"name\":\"dino_encode\",\"value\":\"dino_encode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0005.op.name\",\"descriptionI18nKey\":\"resource.param.pr0005.op.description\"},{\"type\":\"select\",\"key\":\"NormMode\",\"name\":\"归一化模式\",\"defaultValue\":\"0\",\"description\":\"归一化模式:0/1/2\",\"options\":[{\"name\":\"模式0\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.pr0005.normmode.0.options_name\"},{\"name\":\"模式1\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.pr0005.normmode.1.options_name\"},{\"name\":\"模式2\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.pr0005.normmode.2.options_name\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0005.normmode.name\",\"descriptionI18nKey\":\"resource.param.pr0005.normmode.description\"},{\"type\":\"text\",\"key\":\"norm_ratio\",\"name\":\"归一化比例\",\"defaultValue\":\"0.6\",\"description\":\"归一化比例\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0005.norm_ratio.name\",\"descriptionI18nKey\":\"resource.param.pr0005.norm_ratio.description\"},{\"type\":\"text\",\"key\":\"output_hw\",\"name\":\"输出尺寸\",\"defaultValue\":\"[256, 256]\",\"description\":\"输出尺寸 [height, width]\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0005.output_hw.name\",\"descriptionI18nKey\":\"resource.param.pr0005.output_hw.description\"},{\"type\":\"text\",\"key\":\"center_index\",\"name\":\"中心点索引\",\"defaultValue\":\"\",\"description\":\"可选,决定中心点计算方式,如: [0, 1, 3, 4]\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0005.center_index.name\",\"descriptionI18nKey\":\"resource.param.pr0005.center_index.description\"}]", + "componentNameI18nKey": "resource.action.pr0005.componentname" + }, + { + "id": "PR0006", + "componentType": "sequence", + "componentName": "sequence组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"预处理操作类型\",\"defaultValue\":\"sequence\",\"description\":\"预处理操作类型\",\"options\":[{\"name\":\"resize\",\"value\":\"resize\"},{\"name\":\"normalize\",\"value\":\"normalize\"},{\"name\":\"crop\",\"value\":\"crop\"},{\"name\":\"expand\",\"value\":\"expand\"},{\"name\":\"affine_crop\",\"value\":\"affine_crop\"},{\"name\":\"sequence\",\"value\":\"sequence\"},{\"name\":\"combine_image\",\"value\":\"combine_image\"},{\"name\":\"dino_encode\",\"value\":\"dino_encode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0006.op.name\",\"descriptionI18nKey\":\"resource.param.pr0006.op.description\"},{\"type\":\"text\",\"key\":\"size\",\"name\":\"序列长度\",\"defaultValue\":\"4\",\"description\":\"序列长度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0006.size.name\",\"descriptionI18nKey\":\"resource.param.pr0006.size.description\"},{\"type\":\"text\",\"key\":\"scale\",\"name\":\"缩放\",\"defaultValue\":\"1.0\",\"description\":\"缩放因子\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0006.scale.name\",\"descriptionI18nKey\":\"resource.param.pr0006.scale.description\"},{\"type\":\"text\",\"key\":\"dsize\",\"name\":\"目标尺寸\",\"defaultValue\":\"[224, 224]\",\"description\":\"目标尺寸 [height, width]\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0006.dsize.name\",\"descriptionI18nKey\":\"resource.param.pr0006.dsize.description\"},{\"type\":\"switch\",\"key\":\"is_bgr\",\"name\":\"BGR格式\",\"defaultValue\":\"1\",\"description\":\"是否为BGR格式\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0006.is_bgr.name\",\"descriptionI18nKey\":\"resource.param.pr0006.is_bgr.description\"}]", + "componentNameI18nKey": "resource.action.pr0006.componentname" + }, + { + "id": "PR0007", + "componentType": "combine_image", + "componentName": "combine_image组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"预处理操作类型\",\"defaultValue\":\"combine_image\",\"description\":\"预处理操作类型\",\"options\":[{\"name\":\"resize\",\"value\":\"resize\"},{\"name\":\"normalize\",\"value\":\"normalize\"},{\"name\":\"crop\",\"value\":\"crop\"},{\"name\":\"expand\",\"value\":\"expand\"},{\"name\":\"affine_crop\",\"value\":\"affine_crop\"},{\"name\":\"sequence\",\"value\":\"sequence\"},{\"name\":\"combine_image\",\"value\":\"combine_image\"},{\"name\":\"dino_encode\",\"value\":\"dino_encode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0007.op.name\",\"descriptionI18nKey\":\"resource.param.pr0007.op.description\"},{\"type\":\"text\",\"key\":\"count\",\"name\":\"图像数量\",\"defaultValue\":\"4\",\"description\":\"图像数量\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0007.count.name\",\"descriptionI18nKey\":\"resource.param.pr0007.count.description\"},{\"type\":\"text\",\"key\":\"dst_width\",\"name\":\"目标宽度\",\"defaultValue\":\"640\",\"description\":\"目标宽度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0007.dst_width.name\",\"descriptionI18nKey\":\"resource.param.pr0007.dst_width.description\"},{\"type\":\"text\",\"key\":\"dst_height\",\"name\":\"目标高度\",\"defaultValue\":\"640\",\"description\":\"目标高度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0007.dst_height.name\",\"descriptionI18nKey\":\"resource.param.pr0007.dst_height.description\"}]", + "componentNameI18nKey": "resource.action.pr0007.componentname" + }, + { + "id": "PR0008", + "componentType": "dino_encode", + "componentName": "dino_encode组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"预处理操作类型\",\"defaultValue\":\"dino_encode\",\"description\":\"预处理操作类型\",\"options\":[{\"name\":\"resize\",\"value\":\"resize\"},{\"name\":\"normalize\",\"value\":\"normalize\"},{\"name\":\"crop\",\"value\":\"crop\"},{\"name\":\"expand\",\"value\":\"expand\"},{\"name\":\"affine_crop\",\"value\":\"affine_crop\"},{\"name\":\"sequence\",\"value\":\"sequence\"},{\"name\":\"combine_image\",\"value\":\"combine_image\"},{\"name\":\"dino_encode\",\"value\":\"dino_encode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0008.op.name\",\"descriptionI18nKey\":\"resource.param.pr0008.op.description\"},{\"type\":\"text\",\"key\":\"dst_width\",\"name\":\"目标宽度\",\"defaultValue\":\"1024\",\"description\":\"目标宽度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0008.dst_width.name\",\"descriptionI18nKey\":\"resource.param.pr0008.dst_width.description\"},{\"type\":\"text\",\"key\":\"dst_height\",\"name\":\"目标高度\",\"defaultValue\":\"1024\",\"description\":\"目标高度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0008.dst_height.name\",\"descriptionI18nKey\":\"resource.param.pr0008.dst_height.description\"},{\"type\":\"switch\",\"key\":\"is_bgr\",\"name\":\"BGR格式\",\"defaultValue\":\"1\",\"description\":\"是否为BGR格式\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0008.is_bgr.name\",\"descriptionI18nKey\":\"resource.param.pr0008.is_bgr.description\"},{\"type\":\"text\",\"key\":\"mean\",\"name\":\"均值\",\"defaultValue\":\"[0.485, 0.456, 0.406]\",\"description\":\"归一化均值 [R, G, B]\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0008.mean.name\",\"descriptionI18nKey\":\"resource.param.pr0008.mean.description\"},{\"type\":\"text\",\"key\":\"std\",\"name\":\"标准差\",\"defaultValue\":\"[0.229, 0.224, 0.225]\",\"description\":\"归一化标准差 [R, G, B]\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pr0008.std.name\",\"descriptionI18nKey\":\"resource.param.pr0008.std.description\"}]", + "componentNameI18nKey": "resource.action.pr0008.componentname" + }, + { + "id": "PT0001", + "componentType": "yolo_postprocess", + "componentName": "yolo_postprocess组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"yolo_postprocess\",\"description\":\"后处理操作类型\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0001.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0001.op.name\",\"descriptionI18nKey\":\"resource.param.pt0001.op.description\"},{\"type\":\"text\",\"key\":\"nms_threshold\",\"name\":\"NMS阈值\",\"defaultValue\":\"0.35\",\"description\":\"NMS阈值\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0001.nms_threshold.name\",\"descriptionI18nKey\":\"resource.param.pt0001.nms_threshold.description\"},{\"type\":\"text\",\"key\":\"nms_detection_conf\",\"name\":\"检测置信度\",\"defaultValue\":\"0.1\",\"description\":\"NMS检测置信度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0001.nms_detection_conf.name\",\"descriptionI18nKey\":\"resource.param.pt0001.nms_detection_conf.description\"},{\"type\":\"text\",\"key\":\"top_k\",\"name\":\"Top K\",\"defaultValue\":\"1000\",\"description\":\"保留前K个检测结果\",\"level\":\"1\",\"descriptionI18nKey\":\"resource.param.pt0001.top_k.description\"}]", + "componentNameI18nKey": "resource.action.pt0001.componentname" + }, + { + "id": "PT0002", + "componentType": "yolo_npu_postprocess", + "componentName": "yolo_npu_postprocess组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"yolo_npu_postprocess\",\"description\":\"后处理操作类型\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0002.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0002.op.name\",\"descriptionI18nKey\":\"resource.param.pt0002.op.description\"},{\"type\":\"text\",\"key\":\"anchors\",\"name\":\"锚点\",\"defaultValue\":\"[[[10, 13], [16, 30], [33, 23]], [[30, 61], [62, 45], [59, 119]], [[116, 90], [156, 198], [373, 326]]]\",\"description\":\"YOLO锚点配置\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0002.anchors.name\",\"descriptionI18nKey\":\"resource.param.pt0002.anchors.description\"},{\"type\":\"text\",\"key\":\"stride\",\"name\":\"步长\",\"defaultValue\":\"[8, 16, 32]\",\"description\":\"YOLO步长\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0002.stride.name\",\"descriptionI18nKey\":\"resource.param.pt0002.stride.description\"},{\"type\":\"text\",\"key\":\"nms_threshold\",\"name\":\"NMS阈值\",\"defaultValue\":\"0.35\",\"description\":\"NMS阈值\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0002.nms_threshold.name\",\"descriptionI18nKey\":\"resource.param.pt0002.nms_threshold.description\"},{\"type\":\"text\",\"key\":\"nms_detection_conf\",\"name\":\"检测置信度\",\"defaultValue\":\"0.1\",\"description\":\"NMS检测置信度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0002.nms_detection_conf.name\",\"descriptionI18nKey\":\"resource.param.pt0002.nms_detection_conf.description\"},{\"type\":\"text\",\"key\":\"top_k\",\"name\":\"Top K\",\"defaultValue\":\"1000\",\"description\":\"保留前K个检测结果\",\"level\":\"1\",\"descriptionI18nKey\":\"resource.param.pt0002.top_k.description\"}]", + "componentNameI18nKey": "resource.action.pt0002.componentname" + }, + { + "id": "PT0003", + "componentType": "yolov8_postprocess", + "componentName": "yolov8_postprocess组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"yolov8_postprocess\",\"description\":\"后处理操作类型\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0003.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0003.op.name\",\"descriptionI18nKey\":\"resource.param.pt0003.op.description\"},{\"type\":\"text\",\"key\":\"nms_threshold\",\"name\":\"NMS阈值\",\"defaultValue\":\"0.35\",\"description\":\"NMS阈值\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0003.nms_threshold.name\",\"descriptionI18nKey\":\"resource.param.pt0003.nms_threshold.description\"},{\"type\":\"text\",\"key\":\"nms_detection_conf\",\"name\":\"检测置信度\",\"defaultValue\":\"0.1\",\"description\":\"NMS检测置信度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0003.nms_detection_conf.name\",\"descriptionI18nKey\":\"resource.param.pt0003.nms_detection_conf.description\"},{\"type\":\"text\",\"key\":\"top_k\",\"name\":\"Top K\",\"defaultValue\":\"1000\",\"description\":\"保留前K个检测结果\",\"level\":\"1\",\"descriptionI18nKey\":\"resource.param.pt0003.top_k.description\"}]", + "componentNameI18nKey": "resource.action.pt0003.componentname" + }, + { + "id": "PT0009", + "componentType": "yolo_e2e_postprocess", + "componentName": "yolo_e2e_postprocess组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"yolo_e2e_postprocess\",\"description\":\"端到端检测(NMS已内置,如YOLO26)\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0009.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0009.op.name\",\"descriptionI18nKey\":\"resource.param.pt0009.op.description\"},{\"type\":\"text\",\"key\":\"nms_detection_conf\",\"name\":\"置信度阈值\",\"defaultValue\":\"0.25\",\"description\":\"检测置信度阈值(无NMS)\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0009.nms_detection_conf.name\",\"descriptionI18nKey\":\"resource.param.pt0009.nms_detection_conf.description\"},{\"type\":\"text\",\"key\":\"top_k\",\"name\":\"Top K\",\"defaultValue\":\"300\",\"description\":\"保留前K个检测结果\",\"level\":\"1\",\"descriptionI18nKey\":\"resource.param.pt0009.top_k.description\"}]", + "componentNameI18nKey": "resource.action.pt0009.componentname" + }, + { + "id": "PT0004", + "componentType": "sum", + "componentName": "sum组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"sum\",\"description\":\"后处理操作类型\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0004.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0004.op.name\",\"descriptionI18nKey\":\"resource.param.pt0004.op.description\"}]", + "componentNameI18nKey": "resource.action.pt0004.componentname" + }, + { + "id": "PT0005", + "componentType": "arg_max", + "componentName": "arg_max组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"arg_max\",\"description\":\"后处理操作类型\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0005.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0005.op.name\",\"descriptionI18nKey\":\"resource.param.pt0005.op.description\"},{\"type\":\"text\",\"key\":\"axis\",\"name\":\"轴\",\"defaultValue\":\"0\",\"description\":\"按指定轴做 argmax\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0005.axis.name\",\"descriptionI18nKey\":\"resource.param.pt0005.axis.description\"}]", + "componentNameI18nKey": "resource.action.pt0005.componentname" + }, + { + "id": "PT0006", + "componentType": "split", + "componentName": "split组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"split\",\"description\":\"后处理操作类型\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0006.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0006.op.name\",\"descriptionI18nKey\":\"resource.param.pt0006.op.description\"},{\"type\":\"text\",\"key\":\"axis\",\"name\":\"轴\",\"defaultValue\":\"1\",\"description\":\"当前实现要求为 1\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0006.axis.name\",\"descriptionI18nKey\":\"resource.param.pt0006.axis.description\"},{\"type\":\"text\",\"key\":\"split\",\"name\":\"分割配置\",\"defaultValue\":\"[32, 16, 16]\",\"description\":\"各段宽度之和需等于该维度长度\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0006.split.name\",\"descriptionI18nKey\":\"resource.param.pt0006.split.description\"}]", + "componentNameI18nKey": "resource.action.pt0006.componentname" + }, + { + "id": "PT0007", + "componentType": "split_arg_max", + "componentName": "split_arg_max组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"split_arg_max\",\"description\":\"后处理操作类型\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0007.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0007.op.name\",\"descriptionI18nKey\":\"resource.param.pt0007.op.description\"},{\"type\":\"text\",\"key\":\"split\",\"name\":\"分割配置\",\"defaultValue\":\"[128, 256, 64]\",\"description\":\"分割配置数组\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0007.split.name\",\"descriptionI18nKey\":\"resource.param.pt0007.split.description\"}]", + "componentNameI18nKey": "resource.action.pt0007.componentname" + }, + { + "id": "PT0008", + "componentType": "dino_decode", + "componentName": "dino_decode组件", + "inputParamConfig": "[{\"type\":\"select\",\"key\":\"op\",\"name\":\"后处理操作类型\",\"defaultValue\":\"dino_decode\",\"description\":\"后处理操作类型\",\"options\":[{\"name\":\"yolo_postprocess\",\"value\":\"yolo_postprocess\"},{\"name\":\"yolo_npu_postprocess\",\"value\":\"yolo_npu_postprocess\"},{\"name\":\"yolov8_postprocess\",\"value\":\"yolov8_postprocess\"},{\"name\":\"yolo_e2e_postprocess(YOLO26等)\",\"value\":\"yolo_e2e_postprocess\",\"labelI18nKey\":\"resource.option.pt0008.op.yolo_e2e_postprocess.options_name\"},{\"name\":\"sum\",\"value\":\"sum\"},{\"name\":\"arg_max\",\"value\":\"arg_max\"},{\"name\":\"split\",\"value\":\"split\"},{\"name\":\"split_arg_max\",\"value\":\"split_arg_max\"},{\"name\":\"dino_decode\",\"value\":\"dino_decode\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0008.op.name\",\"descriptionI18nKey\":\"resource.param.pt0008.op.description\"},{\"type\":\"text\",\"key\":\"text_threshold\",\"name\":\"文本阈值\",\"defaultValue\":\"0.3\",\"description\":\"文本阈值\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0008.text_threshold.name\",\"descriptionI18nKey\":\"resource.param.pt0008.text_threshold.description\"},{\"type\":\"text\",\"key\":\"box_threshold\",\"name\":\"框阈值\",\"defaultValue\":\"0.25\",\"description\":\"框阈值\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.pt0008.box_threshold.name\",\"descriptionI18nKey\":\"resource.param.pt0008.box_threshold.description\"}]", + "componentNameI18nKey": "resource.action.pt0008.componentname" + }, + { + "id": "ON0001", + "componentType": "output", + "componentName": "输出节点组件", + "inputParamConfig": "[{\"type\":\"text\",\"key\":\"output_node\",\"name\":\"输出节点名称\",\"defaultValue\":\"output\",\"description\":\"模型输出节点名称\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.on0001.output_node.name\",\"descriptionI18nKey\":\"resource.param.on0001.output_node.description\"},{\"type\":\"text\",\"key\":\"shape\",\"name\":\"输出形状\",\"defaultValue\":\"[-1, 2]\",\"description\":\"输出张量形状\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.on0001.shape.name\",\"descriptionI18nKey\":\"resource.param.on0001.shape.description\"},{\"type\":\"select\",\"key\":\"data_type\",\"name\":\"数据类型\",\"defaultValue\":\"0\",\"description\":\"数据类型选择\",\"options\":[{\"name\":\"32位浮点数\",\"value\":\"0\",\"labelI18nKey\":\"resource.option.on0001.data_type.0.options_name\"},{\"name\":\"32位有符号整数\",\"value\":\"1\",\"labelI18nKey\":\"resource.option.on0001.data_type.1.options_name\"},{\"name\":\"16位半精度浮点数\",\"value\":\"2\",\"labelI18nKey\":\"resource.option.on0001.data_type.2.options_name\"},{\"name\":\"16位浮点数\",\"value\":\"3\",\"labelI18nKey\":\"resource.option.on0001.data_type.3.options_name\"},{\"name\":\"8位无符号整数\",\"value\":\"4\",\"labelI18nKey\":\"resource.option.on0001.data_type.4.options_name\"},{\"name\":\"8位有符号整数\",\"value\":\"5\",\"labelI18nKey\":\"resource.option.on0001.data_type.5.options_name\"}],\"level\":\"1\",\"nameI18nKey\":\"resource.param.on0001.data_type.name\",\"descriptionI18nKey\":\"resource.param.on0001.data_type.description\"}]", + "componentNameI18nKey": "resource.action.on0001.componentname" + }, + { + "id": "LB0001", + "componentType": "config", + "componentName": "配置组件", + "inputParamConfig": "[{\"type\":\"text\",\"key\":\"output_node\",\"name\":\"输出节点名称\",\"defaultValue\":\"output\",\"description\":\"配置对应的输出节点名称\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.lb0001.output_node.name\",\"descriptionI18nKey\":\"resource.param.lb0001.output_node.description\"},{\"type\":\"text\",\"key\":\"shape\",\"name\":\"输出形状\",\"defaultValue\":\"[-1, -1, 6]\",\"description\":\"输出张量形状\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.lb0001.shape.name\",\"descriptionI18nKey\":\"resource.param.lb0001.shape.description\"},{\"type\":\"text\",\"key\":\"output_info\",\"name\":\"输出信息\",\"defaultValue\":\"\",\"description\":\"输出标签信息配置(JSON格式)\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.lb0001.output_info.name\",\"descriptionI18nKey\":\"resource.param.lb0001.output_info.description\"},{\"type\":\"text\",\"key\":\"categories\",\"name\":\"类别信息\",\"defaultValue\":\"\",\"description\":\"类别信息配置(JSON格式)\",\"level\":\"1\",\"nameI18nKey\":\"resource.param.lb0001.categories.name\",\"descriptionI18nKey\":\"resource.param.lb0001.categories.description\"}]", + "componentNameI18nKey": "resource.action.lb0001.componentname" + } +] diff --git a/data/resource/aiboxresource_cv186x/model_template/classify.json b/data/resource/aiboxresource_cv186x/model_template/classify.json new file mode 100644 index 000000000..6ac7a506c --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/classify.json @@ -0,0 +1,82 @@ +{ + "model_type": "classify", + "chip_type": "BM1688", + "algorithm_code": "4000002", + "version": "V1.0.0", + "reduce": "", + "models": [ + { + "name": "yolov8分类", + "file_name": "", + "file_md5": "", + "max_batch": 4, + "inputs": [ + { + "name": "images", + "shape": [ + -1, + 3, + 224, + 224 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output0", + "shape": [ + 4, + 1000 + ], + "data_type": 0 + } + ], + "params": { + "crop": true, + "crop_h_top": 0.0, + "crop_h_bottom": 0.0, + "crop_w_left": 0.0, + "crop_w_right": 0.0, + "square": false, + "square_mode": 0, + "input_size": [ + 224, + 224 + ], + "padding_color": [ + 114, + 114, + 114 + ], + "normalize_mean": [ + 0, + 0, + 0 + ], + "normalize_scale": 0.00392157, + "is_bgr": false, + "gravity": 0 + }, + "nameI18nKey": "resource.model.4000002.classify.name" + } + ], + "labels": [ + { + "id": "0", + "name": "tench", + "threshold": [ + 0.5, + 0.5 + ] + }, + { + "id": "1", + "name": "goldfish", + "threshold": [ + 0.5, + 0.5 + ] + } + ] +} diff --git a/data/resource/aiboxresource_cv186x/model_template/dino.json b/data/resource/aiboxresource_cv186x/model_template/dino.json new file mode 100644 index 000000000..fb8b50835 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/dino.json @@ -0,0 +1,124 @@ +{ + "model_type": "dino", + "chip_type": "BM1688", + "algorithm_code": "5000001", + "version": "V1", + "reduce": "", + "models": [ + { + "name": "GroundingDinoDetection", + "file_name": "groundingdino_bm1688_fp16.bmodel", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "samples", + "shape": [ + 1, + 3, + 800, + 800 + ], + "data_type": 0 + }, + { + "name": "position_ids", + "shape": [ + 1, + 256 + ], + "data_type": 0 + }, + { + "name": "text_self_attention_masks", + "shape": [ + 1, + 256, + 256 + ], + "data_type": 0 + }, + { + "name": "input_ids", + "shape": [ + 1, + 256 + ], + "data_type": 0 + }, + { + "name": "token_type_ids", + "shape": [ + 1, + 256 + ], + "data_type": 0 + }, + { + "name": "attention_mask", + "shape": [ + 1, + 256, + 256 + ], + "data_type": 0 + }, + { + "name": "text_token_mask", + "shape": [ + 1, + 256 + ], + "data_type": 0 + }, + { + "name": "proposals", + "shape": [ + 1, + 13294, + 4 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "/class_embed.0/Where_output_0_Where_f32", + "shape": [ + 1, + 900, + 256 + ], + "data_type": 0 + }, + { + "name": "boxes_Sigmoid", + "shape": [ + 1, + 900, + 4 + ], + "data_type": 0 + } + ], + "params": { + "input_width": 800, + "input_height": 800, + "is_bgr": false, + "normalize_mean": [ + 0.485, + 0.456, + 0.406 + ], + "normalize_std": [ + 0.229, + 0.224, + 0.225 + ], + "text_threshold": 0.25, + "box_threshold": 0.3 + } + } + ], + "labels": [] +} \ No newline at end of file diff --git a/data/resource/aiboxresource_cv186x/model_template/feature.json b/data/resource/aiboxresource_cv186x/model_template/feature.json new file mode 100644 index 000000000..33abc09d5 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/feature.json @@ -0,0 +1,73 @@ +{ + "model_type": "feature", + "chip_type": "BM1688", + "algorithm_code": "1000005", + "version": "V1", + "reduce": "concat", + "models": [ + { + "name": "FaceRGBRecognition", + "file_name": "2020-04-10-07-13_CombineMargin-zyGRB-m0.9m0.4m0.15s64_le_re_0.4_112x112_2020-03-26-PadMaskGlassClean-Rest-NeighborGlass+TiktokGE5_fResNet50v3cv-d512_model_iter-226147_GLXSIRMask-0.6532_XSIR-0.7816.onnx", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "input", + "shape": [ + -1, + 3, + 112, + 112 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output", + "shape": [ + -1, + 512 + ], + "data_type": 0 + } + ], + "params": { + "use_affine_crop": true, + "norm_ratio": 0.4, + "norm_mode": 1, + "output_hw": [ + 112, + 112 + ], + "center_index": [ + 0, + 1 + ], + "normalize_mean": [ + 0, + 0, + 0 + ], + "normalize_scale": 1, + "is_bgr": true + } + } + ], + "labels": [], + "config": { + "feature_info": { + "testset_name": "BushardcapClean-ssd", + "score_level": [ + 1.4413, + 1.6555, + 3.4066 + ], + "cmp_score": [ + 82.83 + ], + "feature_dim": 1536 + } + }, + "extra_config_json": "{\"feature_info\": {\"testset_name\": \"BushardcapClean-ssd\", \"score_level\": [1.4413, 1.6555, 3.4066], \"cmp_score\": [82.83], \"feature_dim\": 1536}}" +} \ No newline at end of file diff --git a/data/resource/aiboxresource_cv186x/model_template/keypoints.json b/data/resource/aiboxresource_cv186x/model_template/keypoints.json new file mode 100644 index 000000000..e24ad5e51 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/keypoints.json @@ -0,0 +1,64 @@ +{ + "model_type": "keypoints", + "chip_type": "BM1688", + "algorithm_code": "1000016", + "version": "V1", + "reduce": "", + "models": [ + { + "name": "FaceLandmark", + "file_name": "modified_ONet_landmark_2020-03-01-03-05-13_onet_epoch_42_v2.onnx", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "actual_input_1", + "shape": [ + -1, + 3, + 48, + 48 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "landmark", + "shape": [ + -1, + 10 + ], + "data_type": 0 + } + ], + "params": { + "crop": true, + "crop_h_top": 0.0, + "crop_h_bottom": 0.0, + "crop_w_left": 0.0, + "crop_w_right": 0.0, + "square": false, + "square_mode": 0, + "input_size": [ + 48, + 48 + ], + "padding_color": [ + 0, + 0, + 0 + ], + "normalize_mean": [ + 127.5, + 127.5, + 127.5 + ], + "normalize_scale": 0.0078125, + "is_bgr": true, + "gravity": 0 + } + } + ], + "labels": [] +} \ No newline at end of file diff --git a/data/resource/aiboxresource_cv186x/model_template/ocr.json b/data/resource/aiboxresource_cv186x/model_template/ocr.json new file mode 100644 index 000000000..3b9fe9574 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/ocr.json @@ -0,0 +1,41 @@ +{ + "model_type": "ocr", + "chip_type": "BM1688", + "algorithm_code": "", + "version": "V1.0.0", + "reduce": "", + "models": [ + { + "name": "OCR", + "file_name": "", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "images", + "shape": [-1, 3, 32, 320], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output", + "shape": [-1, -1, -1], + "data_type": 0 + } + ], + "params": { + "input_size": [32, 320], + "normalize_mean": [127.5, 127.5, 127.5], + "normalize_scale": 0.00784314, + "is_bgr": true, + "character_table_file": "character_table.txt", + "ctc_blank_index": 0, + "ctc_prepend_tokens": [], + "ctc_append_tokens": [], + "ctc_class_count": 0 + } + } + ], + "labels": [] +} diff --git a/data/resource/aiboxresource_cv186x/model_template/qwen3_5.json b/data/resource/aiboxresource_cv186x/model_template/qwen3_5.json new file mode 100644 index 000000000..e370df20e --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/qwen3_5.json @@ -0,0 +1,70 @@ +{ + "model_type": "qwen3_5", + "chip_type": "BM1688", + "algorithm_code": "7000001", + "version": "V1", + "reduce": "", + "models": [ + { + "name": "Qwen3_5", + "file_name": "qwen3_5.bmodel", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "image", + "shape": [ + 1, + 3, + 224, + 224 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output", + "shape": [ + 1, + 1 + ], + "data_type": 0 + } + ], + "params": {} + } + ], + "labels": [], + "config": { + "face_info": null, + "instruction": null, + "config_dir": "", + "tokenizer_file": "tokenizer.json", + "model_params": { + "image_token_id": 248056, + "video_token_id": 248057, + "vision_start_token_id": 248053, + "vision_end_token_id": 248054, + "patch_size": 16, + "spatial_merge_size": 2, + "temporal_patch_size": 2, + "max_pixels": 301056 + }, + "generation": { + "do_sample": false, + "top_k": 20, + "top_p": 0.8, + "temperature": 0.7, + "repetition_penalty": 1.0, + "eos_token_id": [ + 248046, + 248044 + ], + "bos_token_id": 248044, + "pad_token_id": 248044, + "stop_strings": [], + "transformers_version": "4.57.0.dev0" + } + } +} diff --git a/data/resource/aiboxresource_cv186x/model_template/qwen3vl.json b/data/resource/aiboxresource_cv186x/model_template/qwen3vl.json new file mode 100644 index 000000000..a4da4ed79 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/qwen3vl.json @@ -0,0 +1,69 @@ +{ + "model_type": "qwen3vl", + "chip_type": "BM1688", + "algorithm_code": "7000001", + "version": "V1", + "reduce": "", + "models": [ + { + "name": "Qwen3VL", + "file_name": "qwen3vl.bmodel", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "image", + "shape": [ + 1, + 3, + 224, + 224 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output", + "shape": [ + 1, + 1 + ], + "data_type": 0 + } + ], + "params": {} + } + ], + "labels": [], + "config": { + "face_info": null, + "instruction": null, + "config_dir": "", + "tokenizer_file": "tokenizer.json", + "model_params": { + "image_token_id": 151655, + "video_token_id": 151656, + "vision_start_token_id": 151652, + "vision_end_token_id": 151653, + "patch_size": 16, + "spatial_merge_size": 2, + "temporal_patch_size": 2 + }, + "generation": { + "do_sample": true, + "top_k": 20, + "top_p": 0.8, + "temperature": 0.7, + "repetition_penalty": 1.0, + "eos_token_id": [ + 151645, + 151643 + ], + "bos_token_id": 151643, + "pad_token_id": 151643, + "stop_strings": [], + "transformers_version": "4.57.0.dev0" + } + } +} \ No newline at end of file diff --git a/data/resource/aiboxresource_cv186x/model_template/sam2.json b/data/resource/aiboxresource_cv186x/model_template/sam2.json new file mode 100644 index 000000000..484dcaef6 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/sam2.json @@ -0,0 +1,187 @@ +{ + "model_type": "SAM2", + "chip_type": "BM1688", + "algorithm_code": "6000001", + "version": "V1", + "reduce": "sequential", + "models": [ + { + "name": "SAM2ImageEncoder", + "file_name": "sam2_encoder_f16_1b.bmodel", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "image", + "shape": [ + 1, + 3, + 1024, + 1024 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "high_res_feats_0", + "shape": [ + 1, + 32, + 256, + 256 + ], + "data_type": 0 + }, + { + "name": "high_res_feats_1", + "shape": [ + 1, + 64, + 128, + 128 + ], + "data_type": 0 + }, + { + "name": "image_embed", + "shape": [ + 1, + 256, + 64, + 64 + ], + "data_type": 0 + } + ], + "params": { + "input_size": [ + 1024, + 1024 + ], + "padding_color": [ + 0, + 0, + 0 + ], + "normalize_mean": [ + 123.675, + 116.28, + 103.53 + ], + "normalize_scale": 0.0, + "is_bgr": false, + "normalize_std": [ + 58.395, + 57.12, + 57.375 + ], + "gravity": 0 + } + }, + { + "name": "SAM2MaskDecoder", + "file_name": "sam2_decoder_f16_1b.bmodel", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "point_coords", + "shape": [ + 1, + 6, + 2 + ], + "data_type": 0 + }, + { + "name": "image_embed", + "shape": [ + 1, + 256, + 64, + 64 + ], + "data_type": 0 + }, + { + "name": "high_res_feats_0", + "shape": [ + 1, + 32, + 256, + 256 + ], + "data_type": 0 + }, + { + "name": "high_res_feats_1", + "shape": [ + 1, + 64, + 128, + 128 + ], + "data_type": 0 + }, + { + "name": "point_labels", + "shape": [ + 1, + 6 + ], + "data_type": 0 + }, + { + "name": "mask_input", + "shape": [ + 1, + 1, + 256, + 256 + ], + "data_type": 0 + }, + { + "name": "has_mask_input", + "shape": [ + 1 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "masks_Clip_f32", + "shape": [ + 1, + 3, + 256, + 256 + ], + "data_type": 0 + }, + { + "name": "iou_predictions_Slice_f32", + "shape": [ + 1, + 3 + ], + "data_type": 0 + } + ], + "params": { + "prompt_type": "point", + "normalize_prompt": true, + "encoder_size": 1024, + "max_points": 6, + "threshold": 0.0, + "output_size": [ + 1024, + 1024 + ] + } + } + ], + "labels": [] +} \ No newline at end of file diff --git a/data/resource/aiboxresource_cv186x/model_template/yolo26_det.json b/data/resource/aiboxresource_cv186x/model_template/yolo26_det.json new file mode 100644 index 000000000..0ba3fda05 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/yolo26_det.json @@ -0,0 +1,70 @@ +{ + "model_type": "yolo26_det", + "chip_type": "BM1688", + "algorithm_code": "4000001", + "version": "V1.0.0", + "reduce": "", + "models": [ + { + "name": "yolo26检测", + "file_name": "", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "images", + "shape": [ + 1, + 3, + 640, + 640 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output0_Concat", + "shape": [ + 1, + 300, + 6 + ], + "data_type": 0 + } + ], + "params": { + "input_size": [ + 640, + 640 + ], + "padding_color": [ + 114, + 114, + 114 + ], + "normalize_mean": [ + 0, + 0, + 0 + ], + "normalize_scale": 0.00392157, + "is_bgr": false, + "confidence_threshold": 0.25, + "top_k": 300, + "gravity": 1 + }, + "nameI18nKey": "resource.model.4000001.yolo26_det.name" + } + ], + "labels": [ + { + "id": "0", + "name": "pedestrian", + "threshold": [ + 0.25, + 0.25 + ] + } + ] +} diff --git a/data/resource/aiboxresource_cv186x/model_template/yolov11_det.json b/data/resource/aiboxresource_cv186x/model_template/yolov11_det.json new file mode 100644 index 000000000..d4e1831a1 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/yolov11_det.json @@ -0,0 +1,71 @@ +{ + "model_type": "yolov11_det", + "chip_type": "BM1688", + "algorithm_code": "4000001", + "version": "V1.0.0", + "reduce": "", + "models": [ + { + "name": "yolov8检测", + "file_name": "", + "file_md5": "", + "max_batch": 4, + "inputs": [ + { + "name": "images", + "shape": [ + -1, + 3, + 640, + 640 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output", + "shape": [ + 4, + 8400, + 84 + ], + "data_type": 0 + } + ], + "params": { + "input_size": [ + 640, + 640 + ], + "padding_color": [ + 114, + 114, + 114 + ], + "normalize_mean": [ + 0, + 0, + 0 + ], + "normalize_scale": 0.00392157, + "is_bgr": false, + "nms_threshold": 0.7, + "confidence_threshold": 0.25, + "top_k": 1000, + "gravity": 1 + }, + "nameI18nKey": "resource.model.4000001.yolov11_det.name" + } + ], + "labels": [ + { + "id": "0", + "name": "pedestrian", + "threshold": [ + 0.25, + 0.25 + ] + } + ] +} diff --git a/data/resource/aiboxresource_cv186x/model_template/yolov12_det.json b/data/resource/aiboxresource_cv186x/model_template/yolov12_det.json new file mode 100644 index 000000000..d0090d239 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/yolov12_det.json @@ -0,0 +1,71 @@ +{ + "model_type": "yolov12_det", + "chip_type": "BM1688", + "algorithm_code": "4000001", + "version": "V1.0.0", + "reduce": "", + "models": [ + { + "name": "yolov8检测", + "file_name": "", + "file_md5": "", + "max_batch": 4, + "inputs": [ + { + "name": "images", + "shape": [ + -1, + 3, + 640, + 640 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output", + "shape": [ + 4, + 8400, + 84 + ], + "data_type": 0 + } + ], + "params": { + "input_size": [ + 640, + 640 + ], + "padding_color": [ + 114, + 114, + 114 + ], + "normalize_mean": [ + 0, + 0, + 0 + ], + "normalize_scale": 0.00392157, + "is_bgr": false, + "nms_threshold": 0.7, + "confidence_threshold": 0.25, + "top_k": 1000, + "gravity": 1 + }, + "nameI18nKey": "resource.model.4000001.yolov12_det.name" + } + ], + "labels": [ + { + "id": "0", + "name": "pedestrian", + "threshold": [ + 0.25, + 0.25 + ] + } + ] +} diff --git a/data/resource/aiboxresource_cv186x/model_template/yolov5_det.json b/data/resource/aiboxresource_cv186x/model_template/yolov5_det.json new file mode 100644 index 000000000..80edb68a7 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/yolov5_det.json @@ -0,0 +1,144 @@ +{ + "model_type": "yolov5_det", + "chip_type": "BM1688", + "algorithm_code": "1001003", + "version": "V1", + "reduce": "", + "models": [ + { + "name": "PedestrianDetection", + "file_name": "20241221161519_Pedestrian_MS320-672_2024-12-19_ig0.5-sz30_iouv0.5-0.95_yolov5m_ep78-best_map", + "file_md5": "", + "max_batch": 1, + "inputs": [ + { + "name": "images", + "shape": [ + -1, + 3, + 640, + 640 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output1", + "shape": [ + 1, + 3, + 80, + 80, + 6 + ], + "data_type": 0 + }, + { + "name": "output2", + "shape": [ + 1, + 3, + 40, + 40, + 6 + ], + "data_type": 0 + }, + { + "name": "output3", + "shape": [ + 1, + 3, + 20, + 20, + 6 + ], + "data_type": 0 + } + ], + "params": { + "input_size": [ + 640, + 640 + ], + "padding_color": [ + 114, + 114, + 114 + ], + "normalize_mean": [ + 0, + 0, + 0 + ], + "normalize_scale": 0.00392157, + "is_bgr": true, + "use_npu_postprocess": true, + "nms_threshold": 0.35, + "confidence_threshold": 0.1, + "top_k": 1000, + "anchors": [ + [ + [ + 10, + 13 + ], + [ + 16, + 30 + ], + [ + 33, + 23 + ] + ], + [ + [ + 30, + 61 + ], + [ + 62, + 45 + ], + [ + 59, + 119 + ] + ], + [ + [ + 116, + 90 + ], + [ + 156, + 198 + ], + [ + 373, + 326 + ] + ] + ], + "stride": [ + 8, + 16, + 32 + ], + "gravity": 1 + } + } + ], + "labels": [ + { + "id": "0", + "name": "pedestrian", + "threshold": [ + 0.63, + 0.63 + ] + } + ] +} \ No newline at end of file diff --git a/data/resource/aiboxresource_cv186x/model_template/yolov8_det.json b/data/resource/aiboxresource_cv186x/model_template/yolov8_det.json new file mode 100644 index 000000000..bd10167d1 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/yolov8_det.json @@ -0,0 +1,71 @@ +{ + "model_type": "yolov8_det", + "chip_type": "BM1688", + "algorithm_code": "4000001", + "version": "V1.0.0", + "reduce": "", + "models": [ + { + "name": "yolov8检测", + "file_name": "", + "file_md5": "", + "max_batch": 4, + "inputs": [ + { + "name": "images", + "shape": [ + -1, + 3, + 640, + 640 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output", + "shape": [ + 4, + 8400, + 84 + ], + "data_type": 0 + } + ], + "params": { + "input_size": [ + 640, + 640 + ], + "padding_color": [ + 114, + 114, + 114 + ], + "normalize_mean": [ + 0, + 0, + 0 + ], + "normalize_scale": 0.00392157, + "is_bgr": false, + "nms_threshold": 0.7, + "confidence_threshold": 0.25, + "top_k": 1000, + "gravity": 1 + }, + "nameI18nKey": "resource.model.4000001.yolov8_det.name" + } + ], + "labels": [ + { + "id": "0", + "name": "pedestrian", + "threshold": [ + 0.25, + 0.25 + ] + } + ] +} diff --git a/data/resource/aiboxresource_cv186x/model_template/yolov9_det.json b/data/resource/aiboxresource_cv186x/model_template/yolov9_det.json new file mode 100644 index 000000000..dfb3c4e7f --- /dev/null +++ b/data/resource/aiboxresource_cv186x/model_template/yolov9_det.json @@ -0,0 +1,71 @@ +{ + "model_type": "yolov9_det", + "chip_type": "BM1688", + "algorithm_code": "4000001", + "version": "V1.0.0", + "reduce": "", + "models": [ + { + "name": "yolov8检测", + "file_name": "", + "file_md5": "", + "max_batch": 4, + "inputs": [ + { + "name": "images", + "shape": [ + -1, + 3, + 640, + 640 + ], + "data_type": 0 + } + ], + "outputs": [ + { + "name": "output", + "shape": [ + 4, + 8400, + 84 + ], + "data_type": 0 + } + ], + "params": { + "input_size": [ + 640, + 640 + ], + "padding_color": [ + 114, + 114, + 114 + ], + "normalize_mean": [ + 0, + 0, + 0 + ], + "normalize_scale": 0.00392157, + "is_bgr": false, + "nms_threshold": 0.7, + "confidence_threshold": 0.25, + "top_k": 1000, + "gravity": 1 + }, + "nameI18nKey": "resource.model.4000001.yolov9_det.name" + } + ], + "labels": [ + { + "id": "0", + "name": "pedestrian", + "threshold": [ + 0.25, + 0.25 + ] + } + ] +} diff --git a/data/resource/aiboxresource_cv186x/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/config.json b/data/resource/aiboxresource_cv186x/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/config.json new file mode 100644 index 000000000..3862fde15 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/config.json @@ -0,0 +1 @@ +{"algorithm_code":"6047042","chip_type":"BM1688","labels":[{"id":"0","name":"Pedestrian","threshold":[0.5,0.5]},{"id":"1","name":"category1","threshold":[0.25,0.25]},{"id":"2","name":"category2","threshold":[0.25,0.25]},{"id":"3","name":"category3","threshold":[0.25,0.25]},{"id":"4","name":"category4","threshold":[0.25,0.25]},{"id":"5","name":"category5","threshold":[0.25,0.25]},{"id":"6","name":"category6","threshold":[0.25,0.25]},{"id":"7","name":"category7","threshold":[0.25,0.25]},{"id":"8","name":"category8","threshold":[0.25,0.25]},{"id":"9","name":"category9","threshold":[0.25,0.25]},{"id":"10","name":"category10","threshold":[0.25,0.25]},{"id":"11","name":"category11","threshold":[0.25,0.25]},{"id":"12","name":"category12","threshold":[0.25,0.25]},{"id":"13","name":"category13","threshold":[0.25,0.25]},{"id":"14","name":"category14","threshold":[0.25,0.25]},{"id":"15","name":"category15","threshold":[0.25,0.25]},{"id":"16","name":"category16","threshold":[0.25,0.25]},{"id":"17","name":"category17","threshold":[0.25,0.25]},{"id":"18","name":"category18","threshold":[0.25,0.25]},{"id":"19","name":"category19","threshold":[0.25,0.25]},{"id":"20","name":"category20","threshold":[0.25,0.25]},{"id":"21","name":"category21","threshold":[0.25,0.25]},{"id":"22","name":"category22","threshold":[0.25,0.25]},{"id":"23","name":"category23","threshold":[0.25,0.25]},{"id":"24","name":"category24","threshold":[0.25,0.25]},{"id":"25","name":"category25","threshold":[0.25,0.25]},{"id":"26","name":"category26","threshold":[0.25,0.25]},{"id":"27","name":"category27","threshold":[0.25,0.25]},{"id":"28","name":"category28","threshold":[0.25,0.25]},{"id":"29","name":"category29","threshold":[0.25,0.25]},{"id":"30","name":"category30","threshold":[0.25,0.25]},{"id":"31","name":"category31","threshold":[0.25,0.25]},{"id":"32","name":"category32","threshold":[0.25,0.25]},{"id":"33","name":"category33","threshold":[0.25,0.25]},{"id":"34","name":"category34","threshold":[0.25,0.25]},{"id":"35","name":"category35","threshold":[0.25,0.25]},{"id":"36","name":"category36","threshold":[0.25,0.25]},{"id":"37","name":"category37","threshold":[0.25,0.25]},{"id":"38","name":"category38","threshold":[0.25,0.25]},{"id":"39","name":"category39","threshold":[0.25,0.25]},{"id":"40","name":"category40","threshold":[0.25,0.25]},{"id":"41","name":"category41","threshold":[0.25,0.25]},{"id":"42","name":"category42","threshold":[0.25,0.25]},{"id":"43","name":"category43","threshold":[0.25,0.25]},{"id":"44","name":"category44","threshold":[0.25,0.25]},{"id":"45","name":"category45","threshold":[0.25,0.25]},{"id":"46","name":"category46","threshold":[0.25,0.25]},{"id":"47","name":"category47","threshold":[0.25,0.25]},{"id":"48","name":"category48","threshold":[0.25,0.25]},{"id":"49","name":"category49","threshold":[0.25,0.25]},{"id":"50","name":"category50","threshold":[0.25,0.25]},{"id":"51","name":"category51","threshold":[0.25,0.25]},{"id":"52","name":"category52","threshold":[0.25,0.25]},{"id":"53","name":"category53","threshold":[0.25,0.25]},{"id":"54","name":"category54","threshold":[0.25,0.25]},{"id":"55","name":"category55","threshold":[0.25,0.25]},{"id":"56","name":"category56","threshold":[0.25,0.25]},{"id":"57","name":"category57","threshold":[0.25,0.25]},{"id":"58","name":"category58","threshold":[0.25,0.25]},{"id":"59","name":"category59","threshold":[0.25,0.25]},{"id":"60","name":"category60","threshold":[0.25,0.25]},{"id":"61","name":"category61","threshold":[0.25,0.25]},{"id":"62","name":"category62","threshold":[0.25,0.25]},{"id":"63","name":"category63","threshold":[0.25,0.25]},{"id":"64","name":"category64","threshold":[0.25,0.25]},{"id":"65","name":"category65","threshold":[0.25,0.25]},{"id":"66","name":"category66","threshold":[0.25,0.25]},{"id":"67","name":"category67","threshold":[0.25,0.25]},{"id":"68","name":"category68","threshold":[0.25,0.25]},{"id":"69","name":"category69","threshold":[0.25,0.25]},{"id":"70","name":"category70","threshold":[0.25,0.25]},{"id":"71","name":"category71","threshold":[0.25,0.25]},{"id":"72","name":"category72","threshold":[0.25,0.25]},{"id":"73","name":"category73","threshold":[0.25,0.25]},{"id":"74","name":"category74","threshold":[0.25,0.25]},{"id":"75","name":"category75","threshold":[0.25,0.25]},{"id":"76","name":"category76","threshold":[0.25,0.25]},{"id":"77","name":"category77","threshold":[0.25,0.25]},{"id":"78","name":"category78","threshold":[0.25,0.25]},{"id":"79","name":"category79","threshold":[0.25,0.25]}],"model_type":"yolov8_det","models":[{"description":"YOLOV8n","file_md5":"","file_name":"","inputs":[{"data_type":0,"name":"images","shape":[1,3,640,640]}],"max_batch":1,"name":"YOLOV8n","nameI18nKey":"resource.model.4000001.yolov8_det.name","outputs":[{"data_type":0,"name":"output0_Concat_f32","shape":[1,84,8400]}],"params":{"confidence_threshold":0.25,"gravity":1,"input_size":[640,640],"is_bgr":false,"nms_threshold":0.7,"normalize_mean":[0,0,0],"normalize_scale":0.00392157,"padding_color":[114,114,114],"top_k":1000}}],"reduce":"","version":"V1.0.0"} \ No newline at end of file diff --git a/data/resource/aiboxresource_cv186x/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/model.nn b/data/resource/aiboxresource_cv186x/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/model.nn new file mode 100644 index 000000000..5b8cdfcba Binary files /dev/null and b/data/resource/aiboxresource_cv186x/models/prod_BM1688_6047042_YOLOV8n_V1.0.0/model.nn differ diff --git a/data/resource/aiboxresource_cv186x/models/prod_BM1688_7486163_helmet_V1.0.0/config.json b/data/resource/aiboxresource_cv186x/models/prod_BM1688_7486163_helmet_V1.0.0/config.json new file mode 100644 index 000000000..65d5bacc4 --- /dev/null +++ b/data/resource/aiboxresource_cv186x/models/prod_BM1688_7486163_helmet_V1.0.0/config.json @@ -0,0 +1 @@ +{"algorithm_code":"7486163","chip_type":"BM1688","labels":[{"id":"0","name":"helmet","threshold":[0.5,0.5]},{"id":"1","name":"nohelmet","threshold":[0.5,0.5]}],"model_type":"classify","models":[{"description":"helmet","file_md5":"","file_name":"","inputs":[{"data_type":0,"name":"images","shape":[1,3,224,224]}],"max_batch":1,"name":"helmet","nameI18nKey":"resource.model.4000002.classify.name","outputs":[{"data_type":0,"name":"output0_Softmax_f32","shape":[1,2]}],"params":{"crop":true,"crop_h_bottom":0,"crop_h_top":0,"crop_w_left":0,"crop_w_right":0,"gravity":0,"input_size":[224,224],"is_bgr":false,"normalize_mean":[0,0,0],"normalize_scale":0.00392157,"padding_color":[114,114,114],"square":false,"square_mode":0}}],"reduce":"","version":"V1.0.0"} \ No newline at end of file diff --git a/data/resource/aiboxresource_cv186x/models/prod_BM1688_7486163_helmet_V1.0.0/model.nn b/data/resource/aiboxresource_cv186x/models/prod_BM1688_7486163_helmet_V1.0.0/model.nn new file mode 100644 index 000000000..53b9cbe92 Binary files /dev/null and b/data/resource/aiboxresource_cv186x/models/prod_BM1688_7486163_helmet_V1.0.0/model.nn differ diff --git a/data/resource/aiboxresource_rknn/algorithm/7463001_RK3576_Helmet_Image_Analysis_20260804152000.json b/data/resource/aiboxresource_rknn/algorithm/7463001_RK3576_Helmet_Image_Analysis_20260804152000.json new file mode 100644 index 000000000..0ccf3acdc --- /dev/null +++ b/data/resource/aiboxresource_rknn/algorithm/7463001_RK3576_Helmet_Image_Analysis_20260804152000.json @@ -0,0 +1,29 @@ +{ + "algorithmCategory": 2, + "algorithmCode": 7463001, + "algorithmId": "7463001", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[]},\"regionType\":\"0\",\"scheduleSupport\":false,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmName": "RK3576 Helmet Image Analysis", + "algorithmProcessdata": "[{\"actionId\":\"PA_00001\",\"actionName\":\"Person Detection\",\"flowActionId\":\"rk3576-det\",\"preFlowActionId\":\"-1\",\"configObject\":{\"params\":[{\"key\":\"atomicCode\",\"value\":\"9275710\"}]}},{\"actionId\":\"PA_00002\",\"actionName\":\"Helmet Classification\",\"flowActionId\":\"rk3576-cls\",\"preFlowActionId\":\"rk3576-det\",\"configObject\":{\"params\":[{\"key\":\"atomicCode\",\"value\":\"7982161\"}]}}]", + "algorithmUsage": 2, + "atomicList": "[{\"atomicCode\":\"9275710\",\"atomicName\":\"YOLOV8\",\"position\":\"rk3576-det\",\"labelList\":[{\"class_name\":\"Pedestrian\",\"label\":\"0\",\"nameCN\":\"Pedestrian\",\"threshold\":[0.25],\"used\":true,\"position\":\"rk3576-det\",\"atomicCode\":\"9275710\"}],\"categoriesLabelList\":[]},{\"atomicCode\":\"7982161\",\"atomicName\":\"helmet\",\"position\":\"rk3576-cls\",\"labelList\":[{\"class_name\":\"helmet\",\"label\":\"0\",\"nameCN\":\"helmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"rk3576-cls\",\"atomicCode\":\"7982161\"},{\"class_name\":\"nohelmet\",\"label\":\"1\",\"nameCN\":\"nohelmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"rk3576-cls\",\"atomicCode\":\"7982161\"}],\"categoriesLabelList\":[]}]", + "checkType": 0, + "confVersionId": "rk3576-helmet-image-v1", + "confVersionName": "V1", + "configVersionList": [ + { + "algorithmCode": "7463001", + "algorithmMetadata": "{\"params\":[],\"region\":{\"heads\":[]},\"regionType\":\"0\",\"scheduleSupport\":false,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", + "algorithmProcessdata": "[{\"actionId\":\"PA_00001\",\"actionName\":\"Person Detection\",\"flowActionId\":\"rk3576-det\",\"preFlowActionId\":\"-1\",\"configObject\":{\"params\":[{\"key\":\"atomicCode\",\"value\":\"9275710\"}]}},{\"actionId\":\"PA_00002\",\"actionName\":\"Helmet Classification\",\"flowActionId\":\"rk3576-cls\",\"preFlowActionId\":\"rk3576-det\",\"configObject\":{\"params\":[{\"key\":\"atomicCode\",\"value\":\"7982161\"}]}}]", + "algorithmUpdateTime": 1785828000000, + "atomicList": "[{\"atomicCode\":\"9275710\",\"atomicName\":\"YOLOV8\",\"position\":\"rk3576-det\",\"labelList\":[{\"class_name\":\"Pedestrian\",\"label\":\"0\",\"nameCN\":\"Pedestrian\",\"threshold\":[0.25],\"used\":true,\"position\":\"rk3576-det\",\"atomicCode\":\"9275710\"}],\"categoriesLabelList\":[]},{\"atomicCode\":\"7982161\",\"atomicName\":\"helmet\",\"position\":\"rk3576-cls\",\"labelList\":[{\"class_name\":\"helmet\",\"label\":\"0\",\"nameCN\":\"helmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"rk3576-cls\",\"atomicCode\":\"7982161\"},{\"class_name\":\"nohelmet\",\"label\":\"1\",\"nameCN\":\"nohelmet\",\"threshold\":[0.5],\"used\":true,\"position\":\"rk3576-cls\",\"atomicCode\":\"7982161\"}],\"categoriesLabelList\":[]}]", + "id": "rk3576-helmet-image-v1", + "name": "V1" + } + ], + "createTime": 1785828000000, + "description": "RK3576 picture pipeline for person detection followed by helmet classification", + "remark": "RK3576 picture pipeline for person detection followed by helmet classification", + "supplier": "CWAI", + "updateTime": 1785828000000 +} diff --git a/data/resource/aiboxresource_rknn/models/prod_RK3576_7982161_helmet_V1.0.0/config.json b/data/resource/aiboxresource_rknn/models/prod_RK3576_7982161_helmet_V1.0.0/config.json new file mode 100644 index 000000000..632695291 --- /dev/null +++ b/data/resource/aiboxresource_rknn/models/prod_RK3576_7982161_helmet_V1.0.0/config.json @@ -0,0 +1 @@ +{"algorithm_code":"7982161","chip_type":"RK3576","labels":[{"id":"0","name":"helmet","threshold":[0.5,0.5]},{"id":"1","name":"nohelmet","threshold":[0.5,0.5]}],"model_type":"classify","models":[{"description":"","file_md5":"","file_name":"","inputs":[{"data_type":0,"name":"images","shape":[1,3,224,224]}],"max_batch":1,"name":"helmet","outputs":[{"data_type":0,"name":"output0","shape":[1,2]}],"params":{"crop":true,"crop_h_bottom":0,"crop_h_top":0,"crop_w_left":0,"crop_w_right":0,"gravity":0,"input_size":[224,224],"is_bgr":false,"normalize_mean":[0,0,0],"normalize_scale":0.00392157,"padding_color":[114,114,114],"square":false,"square_mode":0}}],"reduce":"","version":"V1.0.0"} \ No newline at end of file diff --git a/data/resource/aiboxresource_rknn/models/prod_RK3576_7982161_helmet_V1.0.0/model.rknn b/data/resource/aiboxresource_rknn/models/prod_RK3576_7982161_helmet_V1.0.0/model.rknn new file mode 100644 index 000000000..4ec8b500b Binary files /dev/null and b/data/resource/aiboxresource_rknn/models/prod_RK3576_7982161_helmet_V1.0.0/model.rknn differ diff --git a/data/resource/aiboxresource_rknn/models/prod_RK3576_9275710_YOLOV8_V1.0.0/config.json b/data/resource/aiboxresource_rknn/models/prod_RK3576_9275710_YOLOV8_V1.0.0/config.json new file mode 100644 index 000000000..f04d58bd4 --- /dev/null +++ b/data/resource/aiboxresource_rknn/models/prod_RK3576_9275710_YOLOV8_V1.0.0/config.json @@ -0,0 +1 @@ +{"algorithm_code":"9275710","chip_type":"RK3576","labels":[{"id":"0","name":"Pedestrian","threshold":[0.25,0.25]},{"id":"1","name":"category1","threshold":[0.25,0.25]},{"id":"2","name":"category2","threshold":[0.25,0.25]},{"id":"3","name":"category3","threshold":[0.25,0.25]},{"id":"4","name":"category4","threshold":[0.25,0.25]},{"id":"5","name":"category5","threshold":[0.25,0.25]},{"id":"6","name":"category6","threshold":[0.25,0.25]},{"id":"7","name":"category7","threshold":[0.25,0.25]},{"id":"8","name":"category8","threshold":[0.25,0.25]},{"id":"9","name":"category9","threshold":[0.25,0.25]},{"id":"10","name":"category10","threshold":[0.25,0.25]},{"id":"11","name":"category11","threshold":[0.25,0.25]},{"id":"12","name":"category12","threshold":[0.25,0.25]},{"id":"13","name":"category13","threshold":[0.25,0.25]},{"id":"14","name":"category14","threshold":[0.25,0.25]},{"id":"15","name":"category15","threshold":[0.25,0.25]},{"id":"16","name":"category16","threshold":[0.25,0.25]},{"id":"17","name":"category17","threshold":[0.25,0.25]},{"id":"18","name":"category18","threshold":[0.25,0.25]},{"id":"19","name":"category19","threshold":[0.25,0.25]},{"id":"20","name":"category20","threshold":[0.25,0.25]},{"id":"21","name":"category21","threshold":[0.25,0.25]},{"id":"22","name":"category22","threshold":[0.25,0.25]},{"id":"23","name":"category23","threshold":[0.25,0.25]},{"id":"24","name":"category24","threshold":[0.25,0.25]},{"id":"25","name":"category25","threshold":[0.25,0.25]},{"id":"26","name":"category26","threshold":[0.25,0.25]},{"id":"27","name":"category27","threshold":[0.25,0.25]},{"id":"28","name":"category28","threshold":[0.25,0.25]},{"id":"29","name":"category29","threshold":[0.25,0.25]},{"id":"30","name":"category30","threshold":[0.25,0.25]},{"id":"31","name":"category31","threshold":[0.25,0.25]},{"id":"32","name":"category32","threshold":[0.25,0.25]},{"id":"33","name":"category33","threshold":[0.25,0.25]},{"id":"34","name":"category34","threshold":[0.25,0.25]},{"id":"35","name":"category35","threshold":[0.25,0.25]},{"id":"36","name":"category36","threshold":[0.25,0.25]},{"id":"37","name":"category37","threshold":[0.25,0.25]},{"id":"38","name":"category38","threshold":[0.25,0.25]},{"id":"39","name":"category39","threshold":[0.25,0.25]},{"id":"40","name":"category40","threshold":[0.25,0.25]},{"id":"41","name":"category41","threshold":[0.25,0.25]},{"id":"42","name":"category42","threshold":[0.25,0.25]},{"id":"43","name":"category43","threshold":[0.25,0.25]},{"id":"44","name":"category44","threshold":[0.25,0.25]},{"id":"45","name":"category45","threshold":[0.25,0.25]},{"id":"46","name":"category46","threshold":[0.25,0.25]},{"id":"47","name":"category47","threshold":[0.25,0.25]},{"id":"48","name":"category48","threshold":[0.25,0.25]},{"id":"49","name":"category49","threshold":[0.25,0.25]},{"id":"50","name":"category50","threshold":[0.25,0.25]},{"id":"51","name":"category51","threshold":[0.25,0.25]},{"id":"52","name":"category52","threshold":[0.25,0.25]},{"id":"53","name":"category53","threshold":[0.25,0.25]},{"id":"54","name":"category54","threshold":[0.25,0.25]},{"id":"55","name":"category55","threshold":[0.25,0.25]},{"id":"56","name":"category56","threshold":[0.25,0.25]},{"id":"57","name":"category57","threshold":[0.25,0.25]},{"id":"58","name":"category58","threshold":[0.25,0.25]},{"id":"59","name":"category59","threshold":[0.25,0.25]},{"id":"60","name":"category60","threshold":[0.25,0.25]},{"id":"61","name":"category61","threshold":[0.25,0.25]},{"id":"62","name":"category62","threshold":[0.25,0.25]},{"id":"63","name":"category63","threshold":[0.25,0.25]},{"id":"64","name":"category64","threshold":[0.25,0.25]},{"id":"65","name":"category65","threshold":[0.25,0.25]},{"id":"66","name":"category66","threshold":[0.25,0.25]},{"id":"67","name":"category67","threshold":[0.25,0.25]},{"id":"68","name":"category68","threshold":[0.25,0.25]},{"id":"69","name":"category69","threshold":[0.25,0.25]},{"id":"70","name":"category70","threshold":[0.25,0.25]},{"id":"71","name":"category71","threshold":[0.25,0.25]},{"id":"72","name":"category72","threshold":[0.25,0.25]},{"id":"73","name":"category73","threshold":[0.25,0.25]},{"id":"74","name":"category74","threshold":[0.25,0.25]},{"id":"75","name":"category75","threshold":[0.25,0.25]},{"id":"76","name":"category76","threshold":[0.25,0.25]},{"id":"77","name":"category77","threshold":[0.25,0.25]},{"id":"78","name":"category78","threshold":[0.25,0.25]},{"id":"79","name":"category79","threshold":[0.25,0.25]}],"model_type":"yolov8_det","models":[{"description":"YOLOV8检测","file_md5":"","file_name":"","inputs":[{"data_type":0,"name":"images","shape":[1,3,640,640]}],"max_batch":1,"name":"YOLOV8","outputs":[{"data_type":0,"name":"output0","shape":[1,84,8400]}],"params":{"confidence_threshold":0.25,"gravity":1,"input_size":[640,640],"is_bgr":false,"nms_threshold":0.7,"normalize_mean":[0,0,0],"normalize_scale":0.00392157,"padding_color":[114,114,114],"top_k":1000}}],"reduce":"","version":"V1.0.0"} \ No newline at end of file diff --git a/data/resource/aiboxresource_rknn/models/prod_RK3576_9275710_YOLOV8_V1.0.0/model.rknn b/data/resource/aiboxresource_rknn/models/prod_RK3576_9275710_YOLOV8_V1.0.0/model.rknn new file mode 100644 index 000000000..37a433c64 Binary files /dev/null and b/data/resource/aiboxresource_rknn/models/prod_RK3576_9275710_YOLOV8_V1.0.0/model.rknn differ diff --git "a/data/resource/aiboxresource_x86/algorithm/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" "b/data/resource/aiboxresource_x86/algorithm/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" deleted file mode 100644 index 5680de854..000000000 --- "a/data/resource/aiboxresource_x86/algorithm/29_\350\275\246\347\211\214\350\257\206\345\210\253_1783987200.json" +++ /dev/null @@ -1,23 +0,0 @@ -{ - "algorithmCategory": 10, - "algorithmId": "029", - "id": "029", - "algorithmCode": 29, - "algorithmMetadata": "{\"params\":[{\"defaultValue\":\"\",\"description\":\"车牌置信度,范围:0.0~1.0,限小数点后3位。\",\"failedTip\":\"请输入0-1的三位小数。\",\"key\":\"aiParam.car_plate.confidence\",\"name\":\"车牌置信度\",\"senior\":1,\"regexpr\":\"\",\"type\":\"text\",\"value\":\"\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.029.029.aiparam_car_plate_confidence.name\",\"descriptionI18nKey\":\"resource.param.029.029.aiparam_car_plate_confidence.description\",\"failedTipI18nKey\":\"resource.param.029.029.aiparam_car_plate_confidence.failedtip\"},{\"defaultValue\":\"3\",\"description\":\"两次车牌告警的最小间隔,范围:1~36000秒。\",\"failedTip\":\"请输入1-36000的整数。\",\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"type\":\"text\",\"value\":\"3\",\"level\":\"2\",\"nameI18nKey\":\"resource.param.029.029.param_alarminterval.name\",\"descriptionI18nKey\":\"resource.param.029.029.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.029.029.param_alarminterval.failedtip\"}],\"region\":{\"heads\":[{\"defaultValue\":\"\",\"description\":\"区域名称:必填,限制32字符。\",\"failedTip\":\"请输入长度小于32位且不包含空格的字符串。\",\"isColumn\":true,\"key\":\"name\",\"name\":\"区域名称\",\"range\":\"\",\"regexpr\":\"/^\\\\S{1,32}$/\",\"type\":\"text\",\"nameI18nKey\":\"resource.param.029.029.name.name\",\"descriptionI18nKey\":\"resource.param.029.029.name.description\",\"failedTipI18nKey\":\"resource.param.029.029.name.failedtip\"}]},\"regionType\":\"hexagon\",\"scheduleSupport\":true,\"defaultFullScreen\":true,\"maxAreaCount\":4,\"shieldedRegion\":{}}", - "algorithmName": "车牌识别", - "algorithmProcessdata": "[{\"actionId\":\"BA_00001\",\"actionName\":\"视频解码\",\"remark\":\"视频解码\",\"flowActionId\":\"1\",\"preFlowActionId\":\"-1\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{}},\"params\":[]},\"actionNameI18nKey\":\"resource.action.ba_00001.actionname\",\"remarkI18nKey\":\"resource.action.ba_00001.remark\"},{\"actionId\":\"AA_00001\",\"actionName\":\"车牌检测\",\"remark\":\"检测视频中的车牌目标\",\"flowActionId\":\"2\",\"preFlowActionId\":\"1\",\"configObject\":{\"webConfig\":{\"labelList\":[{\"label\":\"0\",\"class_name\":\"car_plate\",\"threshold\":[0.536,0.536],\"nameCN\":\"车牌\",\"used\":true,\"position\":\"2\",\"atomicCode\":\"6380473\"}],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"aiParam.car_plate.confidence\",\"value\":\"\",\"name\":\"车牌置信度\",\"defaultValue\":\"\",\"description\":\"车牌置信度,范围:0.0~1.0,限小数点后3位。\",\"type\":\"text\",\"regexpr\":\"\",\"failedTip\":\"请输入0-1的三位小数。\",\"level\":\"2\",\"senior\":1,\"nameI18nKey\":\"resource.param.029.029.aiparam_car_plate_confidence.name\",\"descriptionI18nKey\":\"resource.param.029.029.aiparam_car_plate_confidence.description\",\"failedTipI18nKey\":\"resource.param.029.029.aiparam_car_plate_confidence.failedtip\"}],\"atomic\":{\"atomicCode\":\"6380473\",\"atomicName\":\"CarPlateDetection\",\"position\":\"2\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"car_plate\",\"threshold\":[0.536,0.536],\"nameCN\":\"车牌\",\"used\":true,\"position\":\"2\",\"atomicCode\":\"6380473\"}]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6380473\"},{\"key\":\"Enableftp\",\"value\":\"1\"},{\"key\":\"fps\",\"value\":\"5.0\"}]},\"actionNameI18nKey\":\"resource.action.aa_00001.actionname\",\"remarkI18nKey\":\"resource.algorithm.029.process.aa_00001.remark\"},{\"actionId\":\"AA_00004\",\"actionName\":\"车牌关键点\",\"remark\":\"定位车牌左上、左下、右下、右上四个关键点\",\"flowActionId\":\"3\",\"preFlowActionId\":\"2\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"6954354\",\"atomicName\":\"CarPlateKeypoint\",\"position\":\"3\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"6954354\"}]},\"actionNameI18nKey\":\"resource.action.aa_00004.actionname\",\"remarkI18nKey\":\"resource.algorithm.029.process.aa_00004.remark\"},{\"actionId\":\"AA_00011\",\"actionName\":\"文字识别\",\"remark\":\"对四点矫正后的车牌执行 CTC OCR\",\"flowActionId\":\"4\",\"preFlowActionId\":\"3\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[],\"atomic\":{\"atomicCode\":\"3630070\",\"atomicName\":\"CarPlateRec\",\"position\":\"4\",\"labelList\":[]}},\"params\":[{\"key\":\"atomicCode\",\"value\":\"3630070\"}]},\"actionNameI18nKey\":\"resource.action.aa_00011.actionname\",\"remarkI18nKey\":\"resource.action.aa_00011.remark\"},{\"actionId\":\"BA_00004\",\"actionName\":\"事件上报\",\"remark\":\"以车辆属性格式上报车牌识别事件\",\"flowActionId\":\"5\",\"preFlowActionId\":\"4\",\"configObject\":{\"webConfig\":{\"labelList\":[],\"labelFilterList\":[],\"metaDataParams\":[{\"key\":\"param.alarmInterval\",\"name\":\"告警时间间隔(秒)\",\"defaultValue\":\"3\",\"description\":\"两次车牌告警的最小间隔,范围:1~36000秒。\",\"type\":\"text\",\"regexpr\":\"/^([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-2][0-9][0-9][0-9][0-9]|[3][0-5][0-9][0-9][0-9]|36000)$/\",\"failedTip\":\"请输入1-36000的整数。\",\"level\":\"2\",\"value\":\"3\",\"position\":\"5\",\"nameI18nKey\":\"resource.param.029.029.param_alarminterval.name\",\"descriptionI18nKey\":\"resource.param.029.029.param_alarminterval.description\",\"failedTipI18nKey\":\"resource.param.029.029.param_alarminterval.failedtip\"}],\"atomic\":{}},\"params\":[{\"key\":\"custParam.alarmType\",\"value\":\"1\"},{\"key\":\"param.alarmInterval\",\"value\":\"3\"},{\"key\":\"alarmProperty\",\"value\":\"3\",\"name\":\"车辆属性\",\"nameI18nKey\":\"resource.param.029.029.alarmproperty.name\"},{\"key\":\"triggerEventRecordType\",\"value\":\"1\"},{\"key\":\"realtimeEventRecordType\",\"value\":\"0\"}]},\"actionNameI18nKey\":\"resource.action.ba_00004.actionname\",\"remarkI18nKey\":\"resource.algorithm.029.process.ba_00004.remark\"}]", - "algorithmUsage": 1, - "atomicList": "[{\"position\":\"2\",\"atomicCode\":\"6380473\",\"atomicName\":\"CarPlateDetection\",\"labelList\":[{\"label\":\"0\",\"class_name\":\"car_plate\",\"threshold\":[0.536,0.536],\"nameCN\":\"车牌\",\"used\":true,\"position\":\"2\",\"atomicCode\":\"6380473\"}]},{\"position\":\"3\",\"atomicCode\":\"6954354\",\"atomicName\":\"CarPlateKeypoint\",\"labelList\":[]},{\"position\":\"4\",\"atomicCode\":\"3630070\",\"atomicName\":\"CarPlateRec\",\"labelList\":[]}]", - "checkType": 29, - "confVersionId": "default-029", - "confVersionName": "CWAI-AIBOX_V1.0.0", - "createTime": 1783987200000, - "eventType": "motorCommodity", - "remark": "检测视频中的车牌,提取四点关键点并进行文字识别,以车辆属性格式上报告警。需要安装车牌检测、车牌关键点和 OCR 模型。", - "status": 1, - "supplier": "CWAI", - "updateTime": 1783987200000, - "visualized": 1, - "algorithmNameI18nKey": "resource.algorithm.029.algorithmname", - "remarkI18nKey": "resource.algorithm.029.remark" -} diff --git a/docker-compose.rk3576.yml b/docker-compose.rk3576.yml new file mode 100644 index 000000000..4c05d799b --- /dev/null +++ b/docker-compose.rk3576.yml @@ -0,0 +1,52 @@ +services: + cosmo-rk3576-package: + image: ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_rk3576@sha256:135d25d0baf14e7918726f7efb040a0627926aedd5825f52fab6c1cd208da348 + platform: linux/amd64 + network_mode: host + volumes: + - .:/workspace + - ./build_output:/build_output + - cosmo-npm-cache:/root/.npm + working_dir: /workspace + environment: + RKNN_ROOT: /opt/rknn + RKLLM_ROOT: /opt/rkllm + ROCKCHIP_MEDIA_ROOT: /opt/rockchip-media + COSMO_RKLLM_REQUIRED: "ON" + NPM_CONFIG_MAXSOCKETS: "${NPM_CONFIG_MAXSOCKETS:-1}" + NPM_CONFIG_PROGRESS: "${NPM_CONFIG_PROGRESS:-false}" + NPM_CONFIG_FETCH_RETRIES: "${NPM_CONFIG_FETCH_RETRIES:-3}" + NPM_CONFIG_FETCH_TIMEOUT: "${NPM_CONFIG_FETCH_TIMEOUT:-120000}" + NPM_CONFIG_PREFER_OFFLINE: "${NPM_CONFIG_PREFER_OFFLINE:-true}" + NPM_CONFIG_UPDATE_NOTIFIER: "${NPM_CONFIG_UPDATE_NOTIFIER:-false}" + command: > + bash -lc " + set -euo pipefail; + echo 'Starting RK3576 Release cross-compilation...'; + rm -rf -- build_rknn; + ./scripts/build_rknn.sh -T; + output_dir=/build_output/rk3576; + rm -rf -- \"$${output_dir}\"; + mkdir -p -- \"$${output_dir}\"; + set -- build_rknn/packages/*.tar.gz; + if [ \"$${#}\" -ne 1 ] || [ ! -f \"$${1}\" ]; then + echo 'ERROR: expected exactly one RK3576 package artifact' >&2; + exit 1; + fi; + package_listing=$$(tar -tzf \"$${1}\"); + if ! grep -Eq '/lib/librkllmrt[.]so$$' <<<\"$${package_listing}\"; then + echo 'ERROR: RK3576 package is missing librkllmrt.so' >&2; + exit 1; + fi; + if ! grep -Eq '/share/licenses/rkllm/LICENSE$$' <<<\"$${package_listing}\"; then + echo 'ERROR: RK3576 package is missing the RKLLM license' >&2; + exit 1; + fi; + cp -f -- \"$${1}\" \"$${output_dir}/\"; + sha256sum -- \"$${output_dir}/\"*.tar.gz; + ls -lh \"$${output_dir}\"; + echo 'RK3576 build finished.' + " + +volumes: + cosmo-npm-cache: diff --git a/docker-compose.sophon.yml b/docker-compose.sophon.yml index afeb69c73..f7432c885 100644 --- a/docker-compose.sophon.yml +++ b/docker-compose.sophon.yml @@ -5,14 +5,21 @@ services: volumes: - .:/workspace - ./build_output:/build_output + - cosmo-npm-cache:/root/.npm working_dir: /workspace - command: > - bash -lc " - set -e; - echo 'Starting cross-compilation...'; - ./scripts/build.sh -T -m data/resource/aiboxresource; - mkdir -p /build_output; - cp -f build/packages/* /build_output/ 2>/dev/null || echo 'Warning: No packages found to copy.'; - ls -lh /build_output; - echo 'Build finished.' - " + environment: + COSMO_MODEL_GUARD_BUILD_PROFILE: "${COSMO_MODEL_GUARD_BUILD_PROFILE:-public-runtime}" + COSMO_PACKAGE_MODELS: "${COSMO_PACKAGE_MODELS:-include}" + NPM_CONFIG_MAXSOCKETS: "${NPM_CONFIG_MAXSOCKETS:-1}" + NPM_CONFIG_PROGRESS: "${NPM_CONFIG_PROGRESS:-false}" + NPM_CONFIG_FETCH_RETRIES: "${NPM_CONFIG_FETCH_RETRIES:-3}" + NPM_CONFIG_FETCH_TIMEOUT: "${NPM_CONFIG_FETCH_TIMEOUT:-120000}" + NPM_CONFIG_PREFER_OFFLINE: "${NPM_CONFIG_PREFER_OFFLINE:-true}" + NPM_CONFIG_UPDATE_NOTIFIER: "${NPM_CONFIG_UPDATE_NOTIFIER:-false}" + entrypoint: + - /bin/bash + - /workspace/scripts/build_sophon_package.sh + command: [] + +volumes: + cosmo-npm-cache: diff --git a/docker-compose.x86.macos.yml b/docker-compose.x86.macos.yml new file mode 100644 index 000000000..221d37a6b --- /dev/null +++ b/docker-compose.x86.macos.yml @@ -0,0 +1,49 @@ +name: cosmo-x86-macos-preview + +services: + cosmo-x86-macos: + # The x86 backend and its prebuilt dependencies are amd64-only today. + # Docker Desktop emulates this platform on Apple Silicon. + platform: linux/amd64 + build: + context: . + dockerfile: Dockerfile.x86 + args: + BUILD_ENV_IMAGE: "ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_x86:v1@sha256:3345825c9255b9b73369af7ab6346c2cc7079786eb23309258acf7212ca03c1d" + RUNTIME_BASE_IMAGE: "debian:12-slim@sha256:a7ffa3fd2ba09498788cd398575f4340599626c37610af57cc368e70fd564d75" + RESOURCE_DIR: data/resource/aiboxresource_x86 + # Nested GNU Make jobservers can lose pipe descriptors under amd64 + # emulation. Serial is slower but is the reproducible Preview default. + COSMO_BUILD_JOBS: "${COSMO_X86_BUILD_JOBS:-1}" + image: cosmo:x86-macos-preview + container_name: cosmo-x86-macos-preview + init: true + restart: unless-stopped + environment: + # Loopback HTTP-FLV avoids the long WebRTC ICE/media fallback window on + # Docker Desktop while preserving SRS as the media server. + COSMO_STREAM_PLAY_MODE: httpflv-srs + COSMO_STREAM_HTTP_PORT: "18088" + ports: + # Preview services are intentionally local-only. Do not remove the + # 127.0.0.1 bindings without a separate network and authentication review. + - "127.0.0.1:${COSMO_X86_WEB_PORT:-8080}:80" + - "127.0.0.1:1936:1936" + - "127.0.0.1:1985:1985" + - "127.0.0.1:18088:18088" + volumes: + - cosmo-x86-macos-data:/data/cwaiuserdata + - cosmo-x86-macos-app-resource:/appfs/cosmo_wander/cwai_data/resource + - ./build_output/macos-x86:/build_output + healthcheck: + test: ["CMD", "/usr/local/bin/cosmo-x86-healthcheck"] + interval: 10s + timeout: 5s + retries: 12 + start_period: 90s + +volumes: + cosmo-x86-macos-data: + name: cosmo-x86-macos-preview-data + cosmo-x86-macos-app-resource: + name: cosmo-x86-macos-preview-app-resource diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index aee9ce5ff..5d7afda35 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -2,6 +2,9 @@ import { defineConfig } from 'vitepress' const guideZh = [ { text: '构建指南', link: '/guide/build' }, + { text: 'CV186X 快速开始', link: '/guide/cv186x-quick-start' }, + { text: 'RK3576 / RKNN 集成', link: '/guide/rk3576-rknn-development' }, + { text: 'macOS Docker Preview', link: '/guide/macos-docker-preview' }, { text: '部署指南', link: '/guide/deployment' }, { text: '运行配置', link: '/guide/configuration' }, { text: '故障排查', link: '/guide/troubleshooting' }, @@ -30,6 +33,12 @@ const i18nZh = [ { text: 'Short Scope Rules', link: '/i18n/SHORT-SCOPES' } ] +const benchmarksZh = [ + { text: 'ScenarioBench v1.1', link: '/benchmarks/scenario-bench/v1.1/report.zh-CN.html' }, + { text: 'ScenarioBench v1.0', link: '/benchmarks/scenario-bench/v1.0/' }, + { text: '当前滚动刷新', link: '/benchmarks/scenario-bench/current/' } +] + const tutorialsZh = [ { text: '系统使用总览', link: '/tutorials/' }, { @@ -62,6 +71,9 @@ const communityZh = [ const guideEn = [ { text: 'Build Guide', link: '/en/guide/build' }, + { text: 'CV186X Quick Start', link: '/en/guide/cv186x-quick-start' }, + { text: 'RK3576 / RKNN Integration', link: '/en/guide/rk3576-rknn-development' }, + { text: 'macOS Docker Preview', link: '/en/guide/macos-docker-preview' }, { text: 'Deployment Guide', link: '/en/guide/deployment' }, { text: 'Runtime Configuration', link: '/en/guide/configuration' }, { text: 'Troubleshooting', link: '/en/guide/troubleshooting' }, @@ -109,6 +121,12 @@ const tutorialsEn = [ } ] +const benchmarksEn = [ + { text: 'ScenarioBench v1.1', link: '/benchmarks/scenario-bench/v1.1/report.html' }, + { text: 'ScenarioBench v1.0', link: '/benchmarks/scenario-bench/v1.0/README' }, + { text: 'Current Rolling Refresh', link: '/benchmarks/scenario-bench/current/README' } +] + const communityEn = [ { text: 'Community Overview', link: '/en/community/' }, { text: 'Recipes and Cases', link: '/en/community/cases/' }, @@ -124,7 +142,10 @@ export default defineConfig({ // Benchmark reports are checked in as static HTML files next to their // Markdown indexes. VitePress dead-link checking treats them as page routes. ignoreDeadLinks: [ - /^(?:\.\/)?(?:(?:\.\.\/)?current\/)?(vlm-77175-npu|vlm-55009-npu|helmet-7463-npu|pedestrian-45626-npu|pedestrian-helmet-mixed-npu|helmet-7463-x86)\/report(?:\.zh-CN)?$/ + /^(?:\.\/)?(?:(?:\.\.\/)?current\/)?(vlm-77175-npu|vlm-55009-npu|helmet-7463-npu|pedestrian-45626-npu|pedestrian-helmet-mixed-npu|helmet-7463-x86)\/report(?:\.zh-CN)?$/, + /^\.\/report(?:\.zh-CN)?$/, + /^\/benchmarks\/scenario-bench\/v1\.1\/report(?:\.zh-CN)?$/, + /^\.\/results\/(bm1688|cv186x|rk3576)\/(single-detector|dual-detector|vlm-observation)\/report$/ ], locales: { @@ -138,6 +159,7 @@ export default defineConfig({ { text: '系统使用', link: '/tutorials/' }, { text: '指南', link: '/guide/build' }, { text: '社区', link: '/community/' }, + { text: '性能报告', link: '/benchmarks/scenario-bench/v1.1/report.zh-CN.html' }, { text: '参考', link: '/reference/api' }, { text: '开发', link: '/development/frontend' }, { text: 'GitHub', link: 'https://github.com/cosmo-wander-ai/cosmo-edge' } @@ -149,10 +171,12 @@ export default defineConfig({ '/i18n/': [{ text: 'I18N', items: i18nZh }], '/tutorials/': [{ text: 'CosmoEdge 系统使用指南', items: tutorialsZh }], '/community/': [{ text: '社区', items: communityZh }], + '/benchmarks/': [{ text: '性能报告', items: benchmarksZh }], '/': [ { text: '开始', items: [{ text: '文档首页', link: '/' }, ...guideZh] }, { text: 'CosmoEdge 系统使用指南', items: tutorialsZh }, { text: '社区', items: communityZh }, + { text: '性能报告', items: benchmarksZh }, { text: '参考', items: referenceZh }, { text: '开发', items: developmentZh }, { text: 'I18N', items: i18nZh } @@ -183,6 +207,7 @@ export default defineConfig({ { text: 'Using CosmoEdge', link: '/en/tutorials/' }, { text: 'Guide', link: '/en/guide/build' }, { text: 'Community', link: '/en/community/' }, + { text: 'Benchmarks', link: '/benchmarks/scenario-bench/v1.1/report.html' }, { text: 'Reference', link: '/en/reference/api' }, { text: 'Development', link: '/en/development/frontend' }, { text: 'GitHub', link: 'https://github.com/cosmo-wander-ai/cosmo-edge' } @@ -193,10 +218,12 @@ export default defineConfig({ '/en/development/': [{ text: 'Development', items: developmentEn }], '/en/tutorials/': [{ text: 'Using CosmoEdge', items: tutorialsEn }], '/en/community/': [{ text: 'Community', items: communityEn }], + '/benchmarks/': [{ text: 'Benchmarks', items: benchmarksEn }], '/en/': [ { text: 'Start', items: [{ text: 'Documentation Home', link: '/en/' }, ...guideEn] }, { text: 'Using CosmoEdge', items: tutorialsEn }, { text: 'Community', items: communityEn }, + { text: 'Benchmarks', items: benchmarksEn }, { text: 'Reference', items: referenceEn }, { text: 'Development', items: developmentEn } ] diff --git a/docs/benchmarks/scenario-bench/v1.1/LICENSES.md b/docs/benchmarks/scenario-bench/v1.1/LICENSES.md new file mode 100644 index 000000000..dfcc4278c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/LICENSES.md @@ -0,0 +1,12 @@ +# License and redistribution status + +| Artifact | License / status | Included in this package | +| --- | --- | --- | +| CosmoEdge source and ScenarioBench | Apache-2.0 repository license | Source not vendored here | +| Safety Helmet sample | Tracked by the Apache-2.0 repository; maintainer provenance confirmation still required | No | +| Sophon YOLOv8n detector and helmet classifier used by the BM1688/CV186X benchmark | Apache-2.0 repository assets | Yes, in each platform-scoped resource set | +| Other Sophon preset model artifacts | Proprietary/preset distribution boundary | No | +| CV186X user-installed VLM artifact | Distribution rights not established | No | +| RK3576 target model artifacts | Distribution rights not established | No | + +The benchmark directory itself does not contain model binaries or the video sample. The two open Sophon detector/classifier artifacts used on BM1688 and CV186X are present in each platform-scoped resource set and referenced here by path and SHA-256. Other recorded hashes identify artifacts used or inspected and do not grant redistribution rights. diff --git a/docs/benchmarks/scenario-bench/v1.1/README.md b/docs/benchmarks/scenario-bench/v1.1/README.md new file mode 100644 index 000000000..632a0bb24 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/README.md @@ -0,0 +1,114 @@ +# CosmoEdge 1.1 Multi-Platform Video Analytics Benchmark + +> Person detection, safety-helmet detection, and concurrent multi-task workloads on BM1688, CV186X, and RK3576 + +Entry points: [English report](report.html) · [中文报告](report.zh-CN.html) · [methodology](methodology.md) · [machine-readable results index](results/index.json) + +## Summary + +> **Status: release-candidate public performance material. Repository and PR preparation are complete; external publication has not started.** + +We validated CosmoEdge 1.1 multi-stream video analytics on three edge-AI platforms. Under the model, video, device, and runtime conditions defined by this report, the short staircase runs completed 16 channels with two detectors at 5 FPS on BM1688, and 8 channels with two detectors at 5 FPS on CV186X and RK3576. These are measured workload results for the stated configurations, not theoretical chip limits. + +## Recommended profiles and observed boundaries + +| Platform | Recommended profile | Short-run observed boundary | Hold per step | Status | +| --- | --- | --- | ---: | --- | +| BM1688 reference device | Pending repeat and soak validation | 16 channels, two detectors, 5 FPS each | 15 s | Preliminary | +| CV186X reference device | Pending repeat and soak validation | 8 channels, two detectors, 5 FPS each | 30 s | Preliminary | +| RK3576 EVB | Pending repeat and soak validation | 8 channels, two detectors, 5 FPS each | 15 s | Preliminary | + +An observed boundary is the highest tested channel count that passed the configured gates. It is neither an official recommended profile nor proof of the absolute platform limit. + +## Public workload + +- Each channel runs person detection and safety-helmet detection concurrently. +- Each task targets 5 analysis FPS per channel. +- Input is a fixed local 1080p, 24 FPS video sample. +- Channels are added one at a time from one channel upward. +- Pass gates: minimum FPS ratio at least 80% for each task, zero missing telemetry, and average discard rate no greater than 5%. +- No preview client load was enabled; results represent background video analysis. + +## Last passing points + +| Platform | Channels | Person minimum FPS | Helmet minimum FPS | Average discard | Accelerator peak | CPU peak | Memory peak | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | +| BM1688 reference device | 16 | 4.92 | 4.90 | 0% | 60% | 61% | 46% | +| CV186X reference device | 8 | 5.00 | 5.00 | 0% | 60% | 19% | 42% | +| RK3576 EVB | 8 | 5.15 | 5.11 | 0% | 41% | 47% | 30% | + +## Single-detector capacity matrix + +Values are the last passing channel counts in short-run staircases. “≥” means the highest configured point passed. “*” means the next step was blocked by task binding and is not a measured performance limit. + +| Platform | Single-detector workload | 24 FPS | 10 FPS | 7 FPS | 5 FPS | Status | +| --- | --- | ---: | ---: | ---: | ---: | --- | +| BM1688 | Person detection | 7 | 15 | ≥16 | ≥16 | Preliminary | +| BM1688 | Safety-helmet detection | 7 | ≥12* | ≥16 | ≥16 | Preliminary | +| CV186X | Person detection | ≥3* | ≥8* | ≥11* | ≥15* | Preliminary | +| CV186X | Safety-helmet detection | ≥3* | ≥8* | ≥11* | ≥15* | Preliminary | +| RK3576 | Person detection | 6 | 12 | 15 | ≥16 | Preliminary | +| RK3576 | Safety-helmet detection | 5 | 10 | 12 | 15 | Preliminary | + +## Comparability statement + +The three platforms used platform-specific converted and validated artifacts. Internal algorithm identifiers are not public model identities and do not support a chip-performance ranking. Until model source and version, input shape, quantization, preprocessing, postprocessing, video, codec configuration, warm-up, steady-state duration, and repetition count are fully aligned, these results describe representative workloads per platform rather than a cross-chip benchmark ranking. + +## Experimental VLM results + +VLM results are excluded from the primary capacity claims. All three platforms used a 1→8 channel staircase with 120 seconds per step and a target of 0.1 FPS per channel. Analysis FPS was observed but excluded from PASS/FAIL; passing refers only to non-FPS gates such as discard rate, telemetry completeness, and system protection. + +| Platform | Last non-FPS pass | Equivalent FPS/channel at that point | First stop | Status | +| --- | ---: | ---: | --- | --- | +| BM1688 | ≥8 | 0.040 | Highest configured point observed | Experimental | +| CV186X | ≥8 | 0.080 | Highest configured point observed | Experimental | +| RK3576 | 7 | 0.063 | Channel 8 average discard reached 22.75% | Experimental | + +BM1688 and CV186X use device-provided per-channel observations. RK3576 exposes a shared task counter, so its attachment freezes the reviewed one-to-eight-channel equivalent series: `0.100 / 0.120 / 0.116 / 0.115 / 0.091 / 0.076 / 0.063 / 0.057`. VLM remains outside the formal capacity table until target-FPS, completion-count, missing-rate, and latency gates are enabled and passed. + +## Test environment + +The CosmoEdge 1.1 source baseline is frozen to `feat/model-guard-v2.3` commit `209bc2b52849864a15bdad91beb61f5bc982c17f`, tree `f64a98bce05b9ee8dc64dda8e56ad50f9d15687f`. It includes the RK3576 VLM inference path and performance changes used for this release line; subsequent changes at the freeze point affect Web linkage and upgrade-cache behavior plus formatting only, not inference, media, or memory lifecycle semantics. + +BM1688 and CV186X were tested with the same Open package, SHA-256 `8aee0bdb146d80647b4f517114c2920781ed6760e90e5bdf951fefd982dbecb2`. The packaged `cosmo-engine` and both running engines share SHA-256 `bc7274327896384bcf68abf7fc42ce9e133f15131f3be21cb265b8e4deb55d11`. The package does not embed a source commit and predates the final source freeze; this is therefore an explicit device/package binding, not a claim that the package was reproducibly built from the final source commit. The original RK3576 package was not recovered, so those results are bound to the installed version, model identity, environment, and captured evidence rather than a package digest. + +| Platform | Public device | OS | Runtime / media | Memory and storage | +| --- | --- | --- | --- | --- | +| BM1688 | BM1688 reference device | Ubuntu 22.04.5 LTS | libsophon/BMRT 0.4.12; Sophon FFmpeg/GStreamer 2.0.0 | 2,160,271,360 B system; 1,536 + 4,096 MiB accelerator heaps; 9,260,003,328 / 49,366,970,368 B system/data filesystems | +| CV186X | CV186X reference device | Ubuntu 22.04.5 LTS | libsophon/BMRT 0.4.12; Sophon FFmpeg/GStreamer 2.0.0 | 2,160,451,584 B system; 1,536 + 4,096 MiB accelerator heaps; 9,260,003,328 / 49,375,051,776 B system/data filesystems | +| RK3576 | Rockchip RK3576 EVB1 V10 | distribution not exposed by the read-only API | exact RKNN/Driver/RGA/MPP versions not exposed; Rockchip MPP/RGA media paths confirmed | 7,917 MiB shared system memory; device API reported 11.56 GB used and 2.13 GB available storage | + +See `models/` for artifact identities, I/O contracts, platform-scoped repository paths, and available SHA-256 values. The byte-identical BM1688 and CV186X detector/classifier files are distributed under `data/resource/aiboxresource_bm1688/models/` and `data/resource/aiboxresource_cv186x/models/` respectively. The video SHA-256 is `ec77182a264f3059a091b68c4973942dba3b80e93f20feaf4d7e146885caf9d2`; ScenarioBench version and source-file hashes are in `release-manifest.json`. Unknown RKNN/Driver/RGA/MPP versions and the RK VLM artifact hash remain explicit unknowns rather than inferred values. + +## Limitations + +- Results apply only to the bound models, video, device, runtime, and package. +- The multi-task staircases are short runs; they are not official recommended channel counts until repeat and soak validation passes. +- Results are not theoretical chip compute limits. +- Different model artifacts cannot be compared directly. +- A metric with a disabled gate does not count as a performance pass. +- A task-binding failure is a blocked test, not a performance limit. +- Any environment, model, media-path, or package change requires revalidation. + +## Reproduction + +The public pack contains the methodology, sanitized scenarios, machine-readable results, environment templates, and checksums. Device serial numbers, internal channel IDs, internal algorithm IDs, local absolute paths, customer media, and full debugging logs remain in the private evidence archive. + +GitHub's Code view displays checked-in HTML as source. The `open` links below use the same rendered documentation-site pattern as v1.0; they open as standalone reports after the documentation site is deployed and are expected to return 404 before that publication step. + +The release material includes separate `summary.json`, `metrics.json`, `command.txt`, sanitized log, and HTML attachments for single-detector, dual-detector, and VLM workloads. Before execution, resolve the public model references to device-local identifiers as described in `methodology.md`; device addresses, credentials, and internal identifiers are intentionally absent. + +| Platform | Single-detector staircase | Dual-detector staircase | VLM observation | Machine-readable summary | +| --- | --- | --- | --- | --- | +| BM1688 | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/report.html) | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/report.html) | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/report.html) | [summary.json](results/bm1688/summary.json) | +| CV186X | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/report.html) | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/report.html) | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/report.html) | [summary.json](results/cv186x/summary.json) | +| RK3576 | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/report.html) | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/report.html) | [open](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/report.html) | [summary.json](results/rk3576/summary.json) | + +## Product-release evidence boundary + +- final Protected package SHA-256 and controlled build provenance; +- final RK3576 package SHA-256 and source provenance; +- SHA-256 for the final RK3576 VLM artifact; +- repeat, soak, customer-journey, and accuracy qualification before any recommended-profile claim. + +These items do not block publication of this performance report. They do prevent the short-run boundary from being marketed as a recommended profile, and this report does not replace a complete product qualification report. The open detector/classifier files are present in the BM1688 and CV186X platform resource sets; the sample video and all other model binaries are not redistributed by this benchmark. Recorded SHA-256 values identify the exact artifacts. diff --git a/docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md b/docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md new file mode 100644 index 000000000..e2606cd92 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/README.zh-CN.md @@ -0,0 +1,114 @@ +# CosmoEdge 1.1 多平台多路视频分析性能报告 + +> BM1688、CV186X 与 RK3576 上的人员检测、安全帽检测和多任务并发测试 + +入口:[中文主报告](report.zh-CN.html) · [English report](report.html) · [测试方法](methodology.md) · [机器可读结果索引](results/index.json) + +## 摘要 + +> **状态:待发布公开性能材料。当前已完成仓库与 PR 收口,尚未对外发布。** + +我们在三类边缘 AI 平台上验证了 CosmoEdge 1.1 的多路视频分析能力。在本报告指定的模型、视频、设备和运行时条件下,BM1688 短时阶梯测试完成了 16 路双算法 × 5 FPS,CV186X 与 RK3576 完成了 8 路双算法 × 5 FPS。结果代表指定配置下的实测工作负载,不代表芯片理论峰值。 + +## 推荐配置与实测边界 + +| 平台 | 公开推荐配置 | 短时实测边界 | 单级稳态时长 | 状态 | +| --- | --- | --- | ---: | --- | +| BM1688 reference device | 待重复测试和长稳确认 | 16 路双算法 × 5 FPS | 15 秒 | Preliminary | +| CV186X reference device | 待重复测试和长稳确认 | 8 路双算法 × 5 FPS | 30 秒 | Preliminary | +| RK3576 EVB | 待重复测试和长稳确认 | 8 路双算法 × 5 FPS | 15 秒 | Preliminary | + +这里的“实测边界”是当前测试覆盖到且通过门禁的最高路数,不等同于官方推荐配置,也不表示已经探测到芯片的绝对上限。 + +## 公开工作负载 + +- 每路同时运行人员检测和安全帽检测两个任务。 +- 每个任务的目标分析帧率均为 5 FPS。 +- 输入为固定的 1080p、24 FPS 本地视频样本。 +- 路数从 1 路开始逐路增加。 +- 通过门禁:每个任务的最低 FPS 达标率不低于 80%,采样缺失率为 0,平均丢弃率不高于 5%。 +- 本轮未加载预览客户端,结果代表后台视频分析负载。 + +## 最后通过点 + +| 平台 | 路数 | 人员检测最低 FPS | 安全帽检测最低 FPS | 平均丢弃率 | 加速器峰值 | CPU 峰值 | 内存峰值 | +| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | +| BM1688 reference device | 16 | 4.92 | 4.90 | 0% | 60% | 61% | 46% | +| CV186X reference device | 8 | 5.00 | 5.00 | 0% | 60% | 19% | 42% | +| RK3576 EVB | 8 | 5.15 | 5.11 | 0% | 41% | 47% | 30% | + +## 单算法容量矩阵 + +以下数字表示各短时阶梯的最后通过路数。“≥”表示最高配置点仍通过;“*”表示下一路被任务绑定错误阻断,不是实测性能上限。 + +| 平台 | 单算法任务 | 24 FPS | 10 FPS | 7 FPS | 5 FPS | 状态 | +| --- | --- | ---: | ---: | ---: | ---: | --- | +| BM1688 | 人员检测 | 7 | 15 | ≥16 | ≥16 | Preliminary | +| BM1688 | 安全帽检测 | 7 | ≥12* | ≥16 | ≥16 | Preliminary | +| CV186X | 人员检测 | ≥3* | ≥8* | ≥11* | ≥15* | Preliminary | +| CV186X | 安全帽检测 | ≥3* | ≥8* | ≥11* | ≥15* | Preliminary | +| RK3576 | 人员检测 | 6 | 12 | 15 | ≥16 | Preliminary | +| RK3576 | 安全帽检测 | 5 | 10 | 12 | 15 | Preliminary | + +## 可比性声明 + +三平台使用了各自转换和验证的目标模型,当前内部算法编号不构成公开模型身份,也不能据此制作芯片性能排行榜。除非模型来源、模型版本、输入尺寸、量化精度、前后处理、视频、编解码配置、预热、稳态时长和重复次数全部统一,本报告只描述“各平台典型工作负载能力”,不作跨芯片性能排名。 + +## VLM 实验结果 + +VLM 结果不进入本报告主容量结论。三平台均使用每级 120 秒的 1→8 路阶梯,目标为每路 0.1 FPS;分析 FPS 仅记录、不参与 PASS/FAIL。表中通过仅指丢弃率、遥测完整性及系统保护等非 FPS 门禁。 + +| 平台 | 非 FPS 门禁最后通过路数 | 该点等效单路 FPS | 首个停止点 | 状态 | +| --- | ---: | ---: | --- | --- | +| BM1688 | ≥8 | 0.040 | 最高配置点完成观测 | Experimental | +| CV186X | ≥8 | 0.080 | 最高配置点完成观测 | Experimental | +| RK3576 | 7 | 0.063 | 第 8 路平均丢弃率 22.75% | Experimental | + +BM1688、CV186X 使用设备提供的单路观测;RK3576 原始遥测采用共享任务计数器,公开附件固定使用复核后的 1→8 路等效单路序列 `0.100 / 0.120 / 0.116 / 0.115 / 0.091 / 0.076 / 0.063 / 0.057`。在重新启用目标 FPS、完成次数、缺失率和延时门禁之前,VLM 不进入正式容量表。 + +## 测试环境 + +CosmoEdge 1.1 源码基线冻结为 `feat/model-guard-v2.3` 的 commit `209bc2b52849864a15bdad91beb61f5bc982c17f`、tree `f64a98bce05b9ee8dc64dda8e56ad50f9d15687f`。它包含本轮采用的 RK3576 VLM 推理路径与性能优化;冻结点新增变化只涉及 Web 联动、升级缓存行为与纯格式化,未改动推理、媒体或内存生命周期语义。 + +BM1688 与 CV186X 的实测设备使用同一 Open 安装包,SHA-256 为 `8aee0bdb146d80647b4f517114c2920781ed6760e90e5bdf951fefd982dbecb2`。包内 `cosmo-engine` SHA-256 与两台设备运行引擎均为 `bc7274327896384bcf68abf7fc42ce9e133f15131f3be21cb265b8e4deb55d11`。该安装包不嵌入 source commit,且早于最终源码冻结点;因此这是明确的设备/包绑定,不宣称为最终源码的可复现构建。RK3576 原始安装包未回收,相关结果按设备版本、模型身份、环境与测试证据绑定,不能视为 package-qualified 结果。 + +| 平台 | 公开设备 | OS | Runtime / Media | 内存与存储 | +| --- | --- | --- | --- | --- | +| BM1688 | BM1688 reference device | Ubuntu 22.04.5 LTS | libsophon/BMRT 0.4.12;Sophon FFmpeg/GStreamer 2.0.0 | 系统 2,160,271,360 B;加速器 heap 1,536 + 4,096 MiB;system/data 文件系统 9,260,003,328 / 49,366,970,368 B | +| CV186X | CV186X reference device | Ubuntu 22.04.5 LTS | libsophon/BMRT 0.4.12;Sophon FFmpeg/GStreamer 2.0.0 | 系统 2,160,451,584 B;加速器 heap 1,536 + 4,096 MiB;system/data 文件系统 9,260,003,328 / 49,375,051,776 B | +| RK3576 | Rockchip RK3576 EVB1 V10 | Linux 发行版未由只读接口暴露 | RKNN/Driver/RGA/MPP 精确版本未由只读接口暴露;已确认 Rockchip MPP/RGA 媒体路径 | 7,917 MiB 共享系统内存;设备 API 报告存储已用 11.56 GB、可用 2.13 GB | + +模型身份、输入输出合同、平台专属仓库路径与可用 SHA-256 见 `models/`。与压测字节一致的 BM1688、CV186X 检测和分类模型分别放入 `data/resource/aiboxresource_bm1688/models/` 与 `data/resource/aiboxresource_cv186x/models/`。视频 SHA-256 为 `ec77182a264f3059a091b68c4973942dba3b80e93f20feaf4d7e146885caf9d2`;ScenarioBench 版本及关键文件哈希见 `release-manifest.json`。没有证据的 RKNN/Driver/RGA/MPP 版本和 RK VLM 文件 SHA-256 均保持为空,不使用推测值。 + +## 限制说明 + +- 数据仅适用于报告绑定的模型、视频、设备、运行时和安装包。 +- 当前多任务容量阶梯属于短时测试;在重复测试和长稳通过前,不作为官方推荐路数。 +- 结果不是芯片理论算力。 +- 不同模型或转换产物之间不能直接横向比较。 +- 未启用门禁的指标不计为性能通过。 +- 任务绑定失败表示测试被阻断,不表示性能上限。 +- 环境、模型、媒体链路或安装包变化后必须重新验证。 + +## 复现 + +公开复现包提供方法说明、脱敏场景、机器可读结果、环境模板和文件哈希。原始设备序列号、内部通道 ID、内部算法 ID、本地绝对路径、客户素材和完整调试日志仅保存在内部证据包中。 + +本发布材料已经生成单算法、双算法与 VLM 的独立 `summary.json`、`metrics.json`、`command.txt`、脱敏日志和 HTML。执行前需按 `methodology.md` 将公开模型引用解析为设备本地编号;公开包不会携带设备地址、凭据或内部编号。 + +GitHub 的 Code 页面只显示仓库中的 HTML 源码。下表的“打开”链接使用与 v1.0 相同的官网静态报告入口;合并并部署文档站后会直接打开报告页面,正式部署前返回 404 属于预期状态。 + +| 平台 | 单算法逐路报告 | 双算法逐路报告 | VLM 观测报告 | 机器可读汇总 | +| --- | --- | --- | --- | --- | +| BM1688 | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/report.zh-CN.html) | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/report.zh-CN.html) | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/report.zh-CN.html) | [summary.json](results/bm1688/summary.json) | +| CV186X | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/report.zh-CN.html) | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/report.zh-CN.html) | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/report.zh-CN.html) | [summary.json](results/cv186x/summary.json) | +| RK3576 | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/report.zh-CN.html) | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/report.zh-CN.html) | [打开](https://www.cosmowander.ai/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/report.zh-CN.html) | [summary.json](results/rk3576/summary.json) | + +## 产品发版证据边界 + +- Protected 最终安装包 SHA-256 与受控构建来源; +- RK3576 最终安装包 SHA-256 与源码来源; +- RK3576 VLM 最终模型文件 SHA-256; +- 正式推荐配置所需的重复测试、长稳、客户旅程与精度资格材料。 + +这些项目不阻止公开本性能报告,但阻止把短时边界包装成官方推荐配置,也意味着本报告不能代替完整产品资格报告。开源检测和分类文件分别保存在 BM1688、CV186X 平台资源目录;样例视频和其他模型二进制不随本 benchmark 分发。已记录的 SHA-256 用于确认精确产物身份。 diff --git a/docs/benchmarks/scenario-bench/v1.1/RELEASE-CHECKLIST.md b/docs/benchmarks/scenario-bench/v1.1/RELEASE-CHECKLIST.md new file mode 100644 index 000000000..8abe371cf --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/RELEASE-CHECKLIST.md @@ -0,0 +1,41 @@ +# CosmoEdge 1.1 benchmark release checklist + +Status: **PUBLICATION-READY PERFORMANCE REPORT — PREPARED, NOT YET PUBLISHED** + +## Completed for the public benchmark + +- [x] CosmoEdge 1.1 source baseline commit and tree frozen in `release-manifest.json`. +- [x] BM1688 and CV186X evidence bound to the exact Open package SHA-256 and running engine SHA-256. +- [x] Known environment facts captured; unknown runtime fields remain explicit. +- [x] Public environment material applies the commercial disclosure policy; non-public environment fields remain only in the private archive. +- [x] Available model and dataset identities and SHA-256 values recorded. +- [x] Sanitized single-detector, dual-detector, and VLM attachments generated. +- [x] VLM target fixed at 0.1 FPS per channel and RK3576 shared-counter correction documented. +- [x] Bilingual HTML includes scope, method, reproduction, comparability, and limitations. +- [x] Capacity heatmap, throughput/latency curves, and resource-peak chart regenerated. +- [x] Public package and generator checked for device addresses, credentials, local paths, serial numbers, and internal IDs. +- [x] The two approved Open Sophon models are present in both platform-scoped resource sets; the benchmark directory contains no model bytes or video sample. +- [x] `SHA256SUMS` regenerated after all output files. + +## Product-release evidence outside this benchmark + +- [ ] Record the final Protected package SHA-256 and private build provenance. +- [ ] Recover the final RK3576 package SHA-256 and source provenance. +- [ ] Record the final RK3576 VLM artifact SHA-256. +- [ ] Complete repeat, soak, customer-journey, and accuracy qualification for any recommended-profile claim. + +The unchecked items do not block publication of this scoped performance report because it does not distribute package, non-approved model, or video binaries and does not claim an official recommended profile. They remain required for complete product-package qualification and any stronger capacity commitment. + +Do not copy `private-evidence/` into a release artifact. + +## Website publication handoff + +- [x] Local documentation build contains bilingual main reports, six bilingual platform-index pages, and eighteen bilingual standalone workload pages. +- [x] Local smoke test resolves every main-report attachment link to a generated file. +- [x] Platform indexes and all standalone workload attachments provide Chinese and English rendered pages with return navigation. +- [x] Desktop and 390 px mobile layouts keep wide tables inside local horizontal-scroll regions without page-level overflow. +- [ ] Deploy the documentation build containing `benchmarks/scenario-bench/v1.1/`. +- [ ] Confirm the Chinese and English primary report URLs return HTTP 200. +- [ ] Confirm all eighteen bilingual standalone workload report URLs return HTTP 200 and render as HTML rather than GitHub source. + +The last three checks remain intentionally open while this PR is prepared but not published. diff --git a/docs/benchmarks/scenario-bench/v1.1/SHA256SUMS b/docs/benchmarks/scenario-bench/v1.1/SHA256SUMS new file mode 100644 index 000000000..380fc074c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/SHA256SUMS @@ -0,0 +1,108 @@ +882c4f58ef4d2c720a3c02e416081e8e3a09dccf40141f140e43f0ffc10be69f LICENSES.md +cc3fc201c61d8dd7b2b714f4b0cd03a4a91ea936eaf3f3316be3fcfd777e4483 README.md +3405c4c075bffb999770f95a94bd204ecfdd8a14c3c7dfab6ad9cf0a554d611a README.zh-CN.md +75e7ab910ddd8fd7ce6ae163a2596ef43796cb6b6b444d5df16d672cc2c6ae8d RELEASE-CHECKLIST.md +77e18da28f3864372b2817a23d83bb8f6404d9c962b19c2edcb46a6ce026e0c7 assets/capacity-overview.svg +7d1443852033825bef6f428a83e724aca0c352f0232dc4258eace27c8ada8782 assets/capacity-overview.zh-CN.svg +12eb560b1d12b282ae4a793352cab52b4937cd5dfc2063e9af4b914584e3f93a assets/resource-peaks.svg +fdc081f5d6ffa16e867d9cf22c5e53ec71afbf448399da3adee00b6aa41e4245 assets/resource-peaks.zh-CN.svg +17ace94ab00466e22ef5153c393a00dc53cc92e82c774c5c8a39648f49fa52fc assets/throughput-curves.svg +d575538d66787fad40a155f48571288a066a894315ad103042e646f1f4097088 assets/throughput-curves.zh-CN.svg +141bc8b6db3f6ad747b9204a7e68cd4999d24ed4ac3150aab77d03c40ddd7633 dataset/dataset-card.md +55f224a188982df4f4eeb9ed424560288f340e54951e5ada9382d58f835c2380 dataset/download-samples.sh +aec84b354f4feadf0f883bccae38a4013273fd37438ae4391560853c8e7363fb environments/bm1688.json +fcd9e3873b4b1bf959286a6204404418d010f9085a65b51a29426ebcfa6a7ff3 environments/cv186x.json +f301df3e2a7e4c4b71e8801e6b9630d67863a830bef433c73399d4f6f4d27add environments/rk3576.json +b047e664eefa24af46bb121814ecaa08ffca784229a8fca46d8117cc7b7fe545 methodology.md +7d4fa8cae40e116edb548421cc9c8fb692f8f1467a7afa577a3a39fb4c87d7a2 models/bm1688.json +08bfcb051367e9608c19827a2ea0968d8b40c71f1fea3358990966d5e9ec1446 models/cv186x.json +79b619ef2abbd776e93c2ada8172a0192587d5f9c0f966fc825e187f34d6d3b3 models/download-model.sh +1d1268f84f5c21fa268a31a0b86bf891ff322dba79e4d388885da6a00a3c3a51 models/io-contract.json +fc1fb8695267a0fda27daeb281dbd2a94af0d4c37602a09203c0e7b8bba7d404 models/model-card.md +36852e979b152b91651f5fb57f15a20f1b47dbfb1a0d35ef6c5dc959610852f3 models/rk3576.json +48487add4424ed4967c1bc825b87d776303feaf43ecc0f90d99aa25951dc1642 release-manifest.json +f4bdaeb842d8250577d030f4ce7bf34a335c73c16795566e98bab9206862dfb6 report.html +bf0621387eee61ee52ed3112e61bb27f707f980a834e82fe21403f3bfff30e6c report.zh-CN.html +c090aa2db59c48fafa8789996b0dcce43b40eb0e33d48cd0bab7f3c32aa077f0 results/bm1688/command.txt +be4426f25784f4cb0d747f8c4c97ae3274b8efa1a2b4d02b10c6a60a9d68be61 results/bm1688/dual-detector/command.txt +7799bbc1902bcbb1cb2ca2740b81913460e3ac402bc19637a377768621650b88 results/bm1688/dual-detector/metrics.json +d38d36cb88b53dc47221ceb7fd2ea90cab4042084c16bbfe3119cb51392e1c22 results/bm1688/dual-detector/report.html +044616f32ee004d1fd90ea5bf23031757ba42fb49139e7de2e3220b481c4932b results/bm1688/dual-detector/report.zh-CN.html +e6f59eda814ece37ca767bd6b4b920c2367862454885b13d314cf81119b1bc3d results/bm1688/dual-detector/summary.json +266817e2ba6bc62540f3daa76df7970675c67e81d3d853e215941b5aa875c30b results/bm1688/dual-detector/test.log +aec84b354f4feadf0f883bccae38a4013273fd37438ae4391560853c8e7363fb results/bm1688/environment.json +358c591231313f9f3de5f57f9d45bcc7ec321ac9ca4b4dd20343abe5bd982189 results/bm1688/metrics.json +bc7d959b6c3977a56851a840e61a15af2b7f380a8d322fd19a2c91e2d3767ee0 results/bm1688/report.html +07041fe6c1e33f19e6f76382a49c207976d6911591ba9c4c737112f5d625809e results/bm1688/report.zh-CN.html +1a8bc1e06369cba30c3d997eb276651bba17bf1c6efe3596de569ff8659ffca8 results/bm1688/single-detector/command.txt +82fa36f51c043bb835552ba5fd2e331a0daf8887fa3566845909067b1c457b8c results/bm1688/single-detector/metrics.json +16fec421cf937cd63ff007269dcc5fe25f7ccf20b59bd3513b82c48fb99686b6 results/bm1688/single-detector/report.html +496f4f1cbfe307cc249c1a439e03ba20cb5c500c1890532f3d48b3ad2b128e04 results/bm1688/single-detector/report.zh-CN.html +8d079f0f3fb76a39f1fb3c8ca061c4bcbbf52eaff4e008acd9f8a52959d570bc results/bm1688/single-detector/summary.json +483e5df11b808a0d4e127659e8a5f9a9304dcdcc1f6f86edafaba163cd69ee6b results/bm1688/single-detector/test.log +40f4abdc3e8d0acc4bc2b22e9eb5ad83df0c7874fdda54a60fddbfc2c594a525 results/bm1688/summary.json +cd2dac97e0bcdf921a6cec0bea3d51a73f1b7e572abdf9436cbfc46f37f23f43 results/bm1688/test.log +5652be28dc5b12c1400a67b0a5d5a7eba20e5d40f2dcc84084038a5639ae7135 results/bm1688/vlm-observation/command.txt +9c932b879e28ff0d848fe220022dcf56ab5fcd4dcc898773444576b398ff9b17 results/bm1688/vlm-observation/metrics.json +7eafbcbba2367cb64b41dbc1f950ff7744f0af19bda46db81edf2b067702b1d8 results/bm1688/vlm-observation/report.html +c75488e6de47006ba2b0d5a984b453544cddf94ac9b2c3d37775cd77d53caf26 results/bm1688/vlm-observation/report.zh-CN.html +4e8741ec949c1fc037b08bb13f3cc9bd1e474c36e163396d01d3b5a8f7cb06e4 results/bm1688/vlm-observation/summary.json +49125275602f349916677ba7d7951aeb7c8ff20fa92e5d3309fc821e941e2fda results/bm1688/vlm-observation/test.log +c090aa2db59c48fafa8789996b0dcce43b40eb0e33d48cd0bab7f3c32aa077f0 results/cv186x/command.txt +47fbea04425906ee75a0c7dd5ac3fb960b624cfd5a97d33f0042ebd303bcb4aa results/cv186x/dual-detector/command.txt +19c8ce338c65963c5bd0defe3991edd468e1376ab698bb899dca48b78aa54e08 results/cv186x/dual-detector/metrics.json +4708c25d49ced68436aef374b837b81ad9741916c2ec316d83f400e53dd5d73d results/cv186x/dual-detector/report.html +ab6bb982e95a58e3e1af0701d75ec598c3e4cf30462fd61e3359c9d206bf3c17 results/cv186x/dual-detector/report.zh-CN.html +995902e3715b6e790f89cc32ff56dd76d9311c52eae7ed0d1f86328dcb1dbe32 results/cv186x/dual-detector/summary.json +663fccc8ccfed4b5aa971b9bcb2ead6c3e4e46b20e8c1cd6662ffbc69fee788e results/cv186x/dual-detector/test.log +fcd9e3873b4b1bf959286a6204404418d010f9085a65b51a29426ebcfa6a7ff3 results/cv186x/environment.json +a7cedd56fe1318adb141fa61b7eb19c5e9e8e499677b39a88dede322ce02ebe1 results/cv186x/metrics.json +8a06e23f99a06e8b1c9d3bf22d7af39abaeb3cd63b913c63957549e61cefb27e results/cv186x/report.html +4476488ee5fb8828c0d40eff522d71e4a0baa1324653603d2b77123649a60959 results/cv186x/report.zh-CN.html +888fc6b4285f3d927609f9494aef3252912a6d017d88cea7587d9b7f7eafe9bf results/cv186x/single-detector/command.txt +9f0da5db76033b43f5213c7a5c38b2388e8851ea21396dc33bbaf4f7e98a7b76 results/cv186x/single-detector/metrics.json +73514e754b93be89a9d4590c28b25517951c316af4d73ff68569a8a419809f11 results/cv186x/single-detector/report.html +f7fd393ed0d705de482bcf90b6675e883d799190303f8e7ca5016c271a0c0695 results/cv186x/single-detector/report.zh-CN.html +fe7a2298b2ed266bb09eedb7881966d274f29c265a34510125ca1a8979d2310d results/cv186x/single-detector/summary.json +2bb47e5216996b6032a6c1afb195f65c002c3a14dfa34de132f9a7791c42e914 results/cv186x/single-detector/test.log +3086d499a4ba2aea10015bef8f15049c38e0df9b6bdf6c51ebc51c7a488f5146 results/cv186x/summary.json +c8d60b7a009a7bbe52953a811c1fa99ecd94bb950152b9937e30446e2a0b5b7a results/cv186x/test.log +8d1dfbad879ace13404ea4faaf16243771cbe0984adf87b11e460b1d1c734ed6 results/cv186x/vlm-observation/command.txt +bafedd3c08d0c44522c8311dad7405c34e783f24ac1b18fb634af92d72125cd4 results/cv186x/vlm-observation/metrics.json +674f4b1809fb5a1252b261a548c9004646d7e234db5982aec645844146671df5 results/cv186x/vlm-observation/report.html +2557ad21fb02f6898dc455f6322a8eb152e9765c7438d84dfa186e94fd63bb52 results/cv186x/vlm-observation/report.zh-CN.html +ddd7628cb475d7fae8a6466ae4233b3af49d3b0ff0253acbeb00d4db48360acb results/cv186x/vlm-observation/summary.json +ecda1111b1c857844fa2204d25ac15b39a70c0afe13f1fbebca2ae021fa08e4e results/cv186x/vlm-observation/test.log +682044de6946b985f1a3c5c863a9e9a210b5f0f852e7a7d53be52ef74b9b2b40 results/index.json +c090aa2db59c48fafa8789996b0dcce43b40eb0e33d48cd0bab7f3c32aa077f0 results/rk3576/command.txt +9ff1831dbc5ddadd66ee54466d09eb72c43cc0163d910e3bf9db7253e4fccea9 results/rk3576/dual-detector/command.txt +d82a7eb815dd6b1e37dce1cf9e6269aa69b94f046777a33669a8a6df1afddb63 results/rk3576/dual-detector/metrics.json +eb40be10bfa2de646d5f43de9785c87fdcc64577f74f36aba85624d0a832e25c results/rk3576/dual-detector/report.html +b865986dca4552c717601db5bcad7b075bd2034ad303d04f2a815c702256d646 results/rk3576/dual-detector/report.zh-CN.html +ccb06948483894b71eab475ec7d9b4a3f55a449e726c4d575bb110ee2ff3eaa0 results/rk3576/dual-detector/summary.json +b09e9cc0dc0c345b31aecae11303403210cb33ad02a992bd85a0a8d2dd1ac7e9 results/rk3576/dual-detector/test.log +f301df3e2a7e4c4b71e8801e6b9630d67863a830bef433c73399d4f6f4d27add results/rk3576/environment.json +969ff6cefe2a0ad7554ddd51441a167795a22264dc603cf2df3e6fcdf490f064 results/rk3576/metrics.json +130e01d634450f1906a63f922646608c9291ee6652a62e64f647710f889aada0 results/rk3576/report.html +1b6518e1290f9a1bfd0592569197e093a0c1cf741b522f8f1a619c81fc9a6675 results/rk3576/report.zh-CN.html +eb4baaead36ad14320c768d74f067f30667bfeae6faa99a6fd8921e1bf6d9976 results/rk3576/single-detector/command.txt +d7a08fd402317bd5cc4e4ccbc5a6b32f65bd70b32904e9a712dd701b09068e98 results/rk3576/single-detector/metrics.json +230d5c619837b996554f4289cc90f79db3ea4de91b06491afb8843c37fde3645 results/rk3576/single-detector/report.html +ebbef18171952a5ba63bc39f3b4e2ae320850ebc7bb9b0acf4b78f843c45f750 results/rk3576/single-detector/report.zh-CN.html +2625be87619ce07f5c1fa060cfa457fe5b9be418cbf83b9e854832ad5f441036 results/rk3576/single-detector/summary.json +209eb23a7e787c18e6d23a8b076e9db9a1953ce74c726e44fb3cc90d72c86417 results/rk3576/single-detector/test.log +aba030331e2a849041a56bf7440049e93c20253add8eb0667f5be2d2bb52c439 results/rk3576/summary.json +cd1e803c60b9bb2c76b83d4792b17256e31a62a9dcea75c7d835aadbf971f3c6 results/rk3576/test.log +4e7a5e2e7a84a8dc97df5997b5d0feff0673bbcac77c14e29fcd19ccf68b7be6 results/rk3576/vlm-observation/command.txt +9332d29e3c63fb8ac0f9e4970cf7ea8224e00cef35ee28234bf5af2c676552d2 results/rk3576/vlm-observation/metrics.json +a838df82714222e9943e7b7e9faad82d5b808114efbf97b4f307514338b54892 results/rk3576/vlm-observation/report.html +a1b4047dfb6c356ec155708275d3da3f959cc24e3fa04e1aab1038e23d3c4615 results/rk3576/vlm-observation/report.zh-CN.html +5ca0a28bd3c52c1f018c0577dc1e77fd674aa4b20d307e9c3212b9d100df4f98 results/rk3576/vlm-observation/summary.json +c63206d1a75eaf86fe87ce0a5120a7556e9f0c7d31d9dd40960c022b84dccdae results/rk3576/vlm-observation/test.log +f3eadd4633ef113f7cfb37c098d2d92dc17f494cd1e2b38a95ca2a6e6a050acc results/workload-matrix.json +b8d87c66f22dbe1f269f49ef27124a779cd0457b207fd6cc76ae39e2af400bc6 scenarios/README.md +e37d78ac8fbf2e8b68e8d4a3977b9ce8b5f037f15b9575d6c7b12cb1757c4348 scenarios/dual-detector/scenario.public.yml +c570d360825c92efe68ca97dc9399d225b986d1b577213964fdcf65836dbe670 scenarios/single-detector/README.md +343b44c78b509f68663dc8b04e14271331807af3d1eafb1205128da00f4b14eb scenarios/single-detector/person-detector.public.yml +3b2c2da9d3d5761e8f0008b4848b185452eb795044294c06e9c8fe0395f20c16 scenarios/single-detector/safety-helmet-detector.public.yml +7ce4a80cbca3c146faa7841fc916ea0073aeacead5b1bdea13719b63a1e419f9 scenarios/vlm-observation/scenario.public.yml diff --git a/docs/benchmarks/scenario-bench/v1.1/assets/capacity-overview.svg b/docs/benchmarks/scenario-bench/v1.1/assets/capacity-overview.svg new file mode 100644 index 000000000..0e772eb3a --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/assets/capacity-overview.svg @@ -0,0 +1 @@ +Workload envelope by platformLast passing short-run channel count. Bars are scaled to 16 channels; VLM is an observation, not validated capacity.Workload envelope by platformLast passing short-run channel count. Bars are scaled to 16 channels; VLM is an observation, not validated capacity.BM1688CV186XRK3576WORKLOADPerson 24 FPS7≥3*6Person 10 FPS15≥8*12Person 7 FPS≥16≥11*15Person 5 FPS≥16≥15*≥16Helmet 24 FPS7≥3*5Helmet 10 FPS≥12*≥8*10Helmet 7 FPS≥16≥11*12Helmet 5 FPS≥16≥15*15Dual 5 FPS≥16≥8≥8VLM observation8 obs.8 obs.7 obs.Measured short-run boundarySetup-blocked lower bound (*)Experimental, non-FPS gates only diff --git a/docs/benchmarks/scenario-bench/v1.1/assets/capacity-overview.zh-CN.svg b/docs/benchmarks/scenario-bench/v1.1/assets/capacity-overview.zh-CN.svg new file mode 100644 index 000000000..bc5e8ab64 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/assets/capacity-overview.zh-CN.svg @@ -0,0 +1 @@ +多平台工作负载边界短时阶梯最后通过路数;条形按 16 路缩放,VLM 仅为运行观测,不是正式容量。多平台工作负载边界短时阶梯最后通过路数;条形按 16 路缩放,VLM 仅为运行观测,不是正式容量。BM1688CV186XRK3576工作负载人员检测 24 FPS7≥3*6人员检测 10 FPS15≥8*12人员检测 7 FPS≥16≥11*15人员检测 5 FPS≥16≥15*≥16安全帽检测 24 FPS7≥3*5安全帽检测 10 FPS≥12*≥8*10安全帽检测 7 FPS≥16≥11*12安全帽检测 5 FPS≥16≥15*15双算法 5 FPS≥16≥8≥8VLM 运行观测8 路观测8 路观测7 路观测短时实测边界受配置阻断的下界 (*)Experimental,仅非 FPS 门禁 diff --git a/docs/benchmarks/scenario-bench/v1.1/assets/resource-peaks.svg b/docs/benchmarks/scenario-bench/v1.1/assets/resource-peaks.svg new file mode 100644 index 000000000..9b93f2633 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/assets/resource-peaks.svg @@ -0,0 +1 @@ +Resource peaks at the highest verified pointPeak utilization at each platform’s highest configured dual-detector step; memory is general system memory.Resource peaks at the highest verified pointPeak utilization at each platform’s highest configured dual-detector step; memory is general system memory.AcceleratorCPUMemory0%25%50%75%100%BM168816 channels · dual 5 FPS60%61%46%CV186X8 channels · dual 5 FPS60%19%42%RK35768 channels · dual 5 FPS41%47%30%Peak device-reported utilization diff --git a/docs/benchmarks/scenario-bench/v1.1/assets/resource-peaks.zh-CN.svg b/docs/benchmarks/scenario-bench/v1.1/assets/resource-peaks.zh-CN.svg new file mode 100644 index 000000000..3413785b0 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/assets/resource-peaks.zh-CN.svg @@ -0,0 +1 @@ +最高验证点资源峰值各平台双算法最高配置点的资源峰值;内存为通用系统内存。最高验证点资源峰值各平台双算法最高配置点的资源峰值;内存为通用系统内存。加速器CPU内存0%25%50%75%100%BM168816 路 · 双算法 5 FPS60%61%46%CV186X8 路 · 双算法 5 FPS60%19%42%RK35768 路 · 双算法 5 FPS41%47%30%设备上报资源峰值 diff --git a/docs/benchmarks/scenario-bench/v1.1/assets/throughput-curves.svg b/docs/benchmarks/scenario-bench/v1.1/assets/throughput-curves.svg new file mode 100644 index 000000000..292bc10e0 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/assets/throughput-curves.svg @@ -0,0 +1 @@ +Dual-detector scalingMinimum task throughput and maximum critical-path latency at each short-run channel step.Dual-detector scalingMinimum task throughput and maximum critical-path latency at each short-run channel step.BM1688CV186XRK3576Minimum processing throughputFPS / task / channel4.555.514812165 FPS target16 ch · 4.98 ch · 58 ch · 5.1Maximum critical-path latencymilliseconds01002001481216200 ms gate16 ch · 103.78 ch · 64.38 ch · 90.1Active channels diff --git a/docs/benchmarks/scenario-bench/v1.1/assets/throughput-curves.zh-CN.svg b/docs/benchmarks/scenario-bench/v1.1/assets/throughput-curves.zh-CN.svg new file mode 100644 index 000000000..7bec32e8c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/assets/throughput-curves.zh-CN.svg @@ -0,0 +1 @@ +双算法扩容曲线短时阶梯各路数下的最低任务吞吐与最大关键路径延时。双算法扩容曲线短时阶梯各路数下的最低任务吞吐与最大关键路径延时。BM1688CV186XRK3576最低处理吞吐FPS / 任务 / 路4.555.514812165 FPS 目标16 路 · 4.98 路 · 58 路 · 5.1最大关键路径延时毫秒01002001481216200 ms 门禁16 路 · 103.78 路 · 64.38 路 · 90.1活动路数 diff --git a/docs/benchmarks/scenario-bench/v1.1/dataset/dataset-card.md b/docs/benchmarks/scenario-bench/v1.1/dataset/dataset-card.md new file mode 100644 index 000000000..065b32287 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/dataset/dataset-card.md @@ -0,0 +1,16 @@ +# Dataset card: Safety Helmet sample + +| Field | Frozen value | +| --- | --- | +| Public ID | `cosmoedge-safety-helmet-sample-v1` | +| File | `Safety Helmet.mp4` | +| SHA-256 | `ec77182a264f3059a091b68c4973942dba3b80e93f20feaf4d7e146885caf9d2` | +| Size | 20,049,063 bytes | +| Duration | 15.018667 seconds | +| Video | H.264, 1920×1080, yuv420p, 24 FPS | +| Audio | AAC | +| Repository blob | `88cfb35d0c7fc2be45ecc2ad4324e2470ab3c979` | +| First repository commit | `daeda95ccaf0119d384ff90d5d20c3e90fde8ccb` | +| Distribution policy | Metadata and hash only; the media binary is not redistributed by this benchmark | + +All benchmark channels replay this same fixed sample locally with repeat count `0` (continuous loop). This is a capacity input, not an accuracy dataset. It must not be used to infer precision, recall, F1, false-positive rate, or generalization. diff --git a/docs/benchmarks/scenario-bench/v1.1/dataset/download-samples.sh b/docs/benchmarks/scenario-bench/v1.1/dataset/download-samples.sh new file mode 100644 index 000000000..21f48446d --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/dataset/download-samples.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env sh +set -eu + +expected='ec77182a264f3059a091b68c4973942dba3b80e93f20feaf4d7e146885caf9d2' +output=${1:-'Safety Helmet.mp4'} +url='https://raw.githubusercontent.com/cosmo-wander-ai/cosmo-edge/daeda95ccaf0119d384ff90d5d20c3e90fde8ccb/data/test-video/Safety%20Helmet.mp4' + +echo 'The sample is not bundled. Confirm the provenance note in dataset-card.md before redistribution.' >&2 +if command -v curl >/dev/null 2>&1; then + curl -fL --retry 3 -o "$output" "$url" +elif command -v wget >/dev/null 2>&1; then + wget -O "$output" "$url" +else + echo 'curl or wget is required' >&2 + exit 1 +fi + +actual=$(sha256sum "$output" | awk '{print $1}') +if [ "$actual" != "$expected" ]; then + echo "SHA-256 mismatch: expected $expected, got $actual" >&2 + exit 1 +fi +echo "Verified $output" diff --git a/docs/benchmarks/scenario-bench/v1.1/environments/bm1688.json b/docs/benchmarks/scenario-bench/v1.1/environments/bm1688.json new file mode 100644 index 000000000..3c81c429c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/environments/bm1688.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "platform": "BM1688", + "deviceDescription": "BM1688 reference device", + "boardModel": "Sophon BM1688 reference design; commercial enclosure name withheld", + "memory": { + "systemBytes": 2160271360, + "acceleratorHeap0MiB": 1536, + "acceleratorHeap1MiB": 4096 + }, + "storage": { + "systemFilesystemBytes": 9260003328, + "dataFilesystemBytes": 49366970368 + }, + "os": "Ubuntu 22.04.5 LTS", + "architecture": "aarch64", + "bsp": "BSP package identity is not published in this benchmark", + "runtime": { + "inference": "libsophon/BMRT 0.4.12", + "media": "Sophon FFmpeg 2.0.0 / Sophon GStreamer 2.0.0", + "decoder": "bmvpu-decoder", + "encoder": "bmvpu-h264" + }, + "cosmoEdgeInstalledVersion": "V1.1.0.0", + "releaseSourceCommit": "209bc2b52849864a15bdad91beb61f5bc982c17f", + "releaseSourceTree": "f64a98bce05b9ee8dc64dda8e56ad50f9d15687f", + "packageProfile": "public-runtime", + "packageSha256": "8aee0bdb146d80647b4f517114c2920781ed6760e90e5bdf951fefd982dbecb2", + "runningEngineSha256": "bc7274327896384bcf68abf7fc42ce9e133f15131f3be21cb265b8e4deb55d11", + "packageBinding": "verified: packaged and running engine SHA-256 values match; package does not embed a source commit", + "capturedAt": "2026-08-12T16:10:00+08:00" +} diff --git a/docs/benchmarks/scenario-bench/v1.1/environments/cv186x.json b/docs/benchmarks/scenario-bench/v1.1/environments/cv186x.json new file mode 100644 index 000000000..0a8a4d74c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/environments/cv186x.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "platform": "CV186X", + "deviceDescription": "CV186X reference device", + "boardModel": "Sophon CV186X reference design; commercial enclosure name withheld", + "memory": { + "systemBytes": 2160451584, + "acceleratorHeap0MiB": 1536, + "acceleratorHeap1MiB": 4096 + }, + "storage": { + "systemFilesystemBytes": 9260003328, + "dataFilesystemBytes": 49375051776 + }, + "os": "Ubuntu 22.04.5 LTS", + "architecture": "aarch64", + "bsp": "BSP package identity is not published in this benchmark", + "runtime": { + "inference": "libsophon/BMRT 0.4.12", + "media": "Sophon FFmpeg 2.0.0 / Sophon GStreamer 2.0.0", + "decoder": "bmvpu-decoder", + "encoder": "bmvpu-h264" + }, + "cosmoEdgeInstalledVersion": "V1.1.0.0", + "releaseSourceCommit": "209bc2b52849864a15bdad91beb61f5bc982c17f", + "releaseSourceTree": "f64a98bce05b9ee8dc64dda8e56ad50f9d15687f", + "packageProfile": "public-runtime", + "packageSha256": "8aee0bdb146d80647b4f517114c2920781ed6760e90e5bdf951fefd982dbecb2", + "runningEngineSha256": "bc7274327896384bcf68abf7fc42ce9e133f15131f3be21cb265b8e4deb55d11", + "packageBinding": "verified: packaged and running engine SHA-256 values match; package does not embed a source commit", + "capturedAt": "2026-08-12T16:10:00+08:00" +} diff --git a/docs/benchmarks/scenario-bench/v1.1/environments/rk3576.json b/docs/benchmarks/scenario-bench/v1.1/environments/rk3576.json new file mode 100644 index 000000000..2bcf51f30 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/environments/rk3576.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "platform": "RK3576", + "deviceDescription": "RK3576 EVB", + "boardModel": "Rockchip RK3576 EVB1 V10 Board", + "memory": { + "sharedSystemMiB": 7917, + "memoryDomain": "shared-system" + }, + "storage": { + "usedGB": 11.56, + "availableGB": 2.13, + "note": "values are device-reported decimal GB at capture time" + }, + "os": "Linux distribution not exposed by the read-only device API", + "architecture": "aarch64 (inferred from RK3576 target; verify from the final package environment)", + "bsp": "BSP package identity is not published in this benchmark", + "runtime": { + "inference": "RKNN runtime version not exposed by the read-only device API", + "driver": "RKNN driver version not exposed by the read-only device API", + "rga": "version not exposed; runtime telemetry confirms RGA path", + "mpp": "version not exposed; runtime telemetry confirms Rockchip MPP VPU", + "decoder": "rockchip-mpp-vpu / copy-out I420", + "encoder": "rockchip-mpp / copy-first stride-aligned I420" + }, + "cosmoEdgeInstalledVersion": "V1.1.0.0", + "releaseSourceCommit": "209bc2b52849864a15bdad91beb61f5bc982c17f", + "releaseSourceTree": "f64a98bce05b9ee8dc64dda8e56ad50f9d15687f", + "packageSha256": null, + "packageBinding": "package bytes unavailable; evidence is bound to the installed V1.1.0.0 runtime, captured environment and model identities, not to a package digest", + "capturedAt": "2026-08-12T16:10:00+08:00" +} diff --git a/docs/benchmarks/scenario-bench/v1.1/methodology.md b/docs/benchmarks/scenario-bench/v1.1/methodology.md new file mode 100644 index 000000000..33759dd74 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/methodology.md @@ -0,0 +1,84 @@ +# Methodology and reproduction contract + +## Scope + +This package records three application workloads on BM1688, CV186X, and RK3576: + +1. single-detector FPS gradients for personnel detection and safety-helmet detection; +2. two concurrent detector tasks per channel at 5 FPS; +3. an Experimental VLM runtime observation at 0.1 requested analysis FPS per channel. + +The tests exercise CosmoEdge video decode, inference scheduling, post-processing, task orchestration, telemetry, and resource reporting. They are not synthetic NPU benchmarks and do not report theoretical chip throughput. + +## Fixed input + +Every channel loops the same 1920×1080, H.264, 24 FPS local sample. Its SHA-256 and media metadata are frozen in `release-manifest.json` and `dataset/dataset-card.md`. Preview/browser load is disabled. + +## Staircase procedure + +1. Warm and validate one channel. +2. Increase by one channel at each step. +3. Bind the same public workload to every active channel. +4. Hold for the duration recorded in the result attachment: 15 seconds for most BM1688/RK3576 CV steps, 30 seconds for CV186X CV steps, and 120 seconds for VLM steps. +5. Sample device and task telemetry approximately every 3 seconds for CV or 10 seconds for VLM. +6. Use the second half of each step as the stable evaluation window. +7. Stop on an enabled threshold, system protection, telemetry failure, or task-binding error. + +The short CV steps discover an observed boundary; they are not soak tests. A binding error is `BLOCKED`, not a measured performance limit. + +## Detector gates + +- minimum per-task processing-FPS ratio: 0.80; +- maximum telemetry missing rate: 0; +- maximum average discard rate: 0.05; +- critical-path and detector-node latency gates are applied when present in the source scenario; +- local-video packet discard is not interpreted as a network-quality result. + +`PASS` requires every enabled gate for the complete step. `FAIL` means at least one performance/stability gate failed. `BLOCKED` means the step did not create valid performance evidence. + +## VLM interpretation + +The VLM run requested 0.1 analysis FPS per channel, but the analysis-FPS ratio was intentionally disabled as a pass/fail gate. BM1688 and CV186X expose a per-channel observation directly. The RK3576 source telemetry exposes a shared task counter, so the public attachment uses the reviewed equivalent per-channel series from the corrected source report: `0.100, 0.120, 0.116, 0.115, 0.091, 0.076, 0.063, 0.057` for one through eight active channels. Raw shared-counter values are retained only in the private evidence archive. Consequently: + +- `runtime-observation-pass` means only that enabled non-FPS gates passed; +- it does not mean the requested 0.1 FPS was sustained on every channel; +- it does not establish an official VLM channel capacity; +- BM1688 and CV186X reached the highest configured eight-channel observation point; +- RK3576 passed non-FPS gates through seven channels and stopped at eight because average discard reached 22.75%. + +VLM can enter the formal capacity table only after enabling an FPS/completion-rate gate, sampling-miss gate, latency gate, fixed prompt/output contract, repeated runs, and a soak run. + +## Recommended profile versus observed boundary + +The report always separates: + +- `Recommended profile`: repeated and soak-qualified configuration on the final package; +- `Observed boundary`: the last short-run step that passed the enabled gates. + +This release report has observed boundaries only. Recommended profiles remain pending. + +## Reproduction + +1. Check `release-manifest.json`, especially `qualification.benchmarkReadyToPublish` and the package-binding status. +2. Obtain the sample with `dataset/download-samples.sh`; verify the recorded SHA-256. +3. Install licensed platform model artifacts matching `models/.json` and record their SHA-256. Different model bytes produce a community reproduction, not a byte-identical rerun. +4. Resolve the public scenario descriptor to local device algorithm layouts and schedules. Keep credentials and internal IDs out of the public package. +5. Run the exact ScenarioBench version identified by the three source-file hashes in the manifest. +6. Export `summary.json`, sanitized `metrics.json`, the HTML report, the command record, and the environment identity. +7. Recalculate `SHA256SUMS` and run the validation script before publication. + +Representative invocation after local resolution: + +```text +node scenario-bench/src/cli.js run --output +``` + +The checked-in `command.txt` attachments explain why the public descriptor cannot contain a ready-to-run device address, credential, algorithm ID, or schedule ID. + +## Publication rules + +- No serial numbers, device addresses, credentials, internal channel/algorithm IDs, or local paths. +- No chip ranking unless source model, precision, preprocessing, post-processing, input, media path, timing, and repetitions are identical. +- No recommended-channel claim from a single short staircase. +- State package qualification per platform. Missing Protected or RK3576 package provenance must not be generalized into a package-qualified claim. +- No redistribution of models or media; published hashes identify the tested or inspected artifact and do not grant redistribution rights. diff --git a/docs/benchmarks/scenario-bench/v1.1/models/bm1688.json b/docs/benchmarks/scenario-bench/v1.1/models/bm1688.json new file mode 100644 index 000000000..c9ea58ea9 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/models/bm1688.json @@ -0,0 +1,43 @@ +{ + "schemaVersion": 1, + "platform": "BM1688", + "artifactFormat": ".nn", + "models": [ + { + "publicId": "person-detector", + "name": "YOLOv8n detector", + "version": "V1.0.0", + "input": "1x3x640x640 RGB, scale 1/255, letterbox 114", + "output": "1x84x8400 candidate tensor", + "precision": "target artifact precision not exposed by the device catalog", + "sha256": "56b207ef2876da76505e403a049d3c44a411b9fe707ab73dc64f1cd9d9b6c5c8", + "sizeBytes": 7023600, + "repositoryPath": "data/resource/aiboxresource_bm1688/models/prod_BM1688_6047042_YOLOV8n_V1.0.0", + "redistribution": "included in the CosmoEdge repository and Sophon Open package under Apache-2.0" + }, + { + "publicId": "safety-helmet-classifier", + "name": "Helmet classifier", + "version": "V1.0.0", + "input": "1x3x224x224 RGB, scale 1/255", + "output": "1x2 classification tensor", + "precision": "target artifact precision not exposed by the device catalog", + "sha256": "33b0fb4bcb29e41a92f9c1c518671aefc69cbf9207934deaba32ca7cd8cd7c8a", + "sizeBytes": 6001416, + "repositoryPath": "data/resource/aiboxresource_bm1688/models/prod_BM1688_7486163_helmet_V1.0.0", + "redistribution": "included in the CosmoEdge repository and Sophon Open package under Apache-2.0" + }, + { + "publicId": "vlm-0.8b", + "name": "CosmoEdge VL Judge 0.8B", + "version": "V1.0.0", + "input": "catalog contract 1x3x224x224 plus text prompt/tokenizer", + "output": "catalog contract 1x1; semantic text result handled by the runtime", + "precision": "target artifact precision not exposed by the device catalog", + "sha256": "31a03f4845d612b3c9e946468c2032254c42be54594a0848eb5938fc0f4bd767", + "tokenizerSha256": "cb16258a9df7062f4c4d291a1501b07fb0750c9a8b247c5639dba0369e42f0cb", + "sizeBytes": 980885504, + "redistribution": "not included; preset model" + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/models/cv186x.json b/docs/benchmarks/scenario-bench/v1.1/models/cv186x.json new file mode 100644 index 000000000..80a2f586f --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/models/cv186x.json @@ -0,0 +1,47 @@ +{ + "schemaVersion": 1, + "platform": "CV186X", + "artifactFormat": ".nn", + "models": [ + { + "publicId": "person-detector", + "name": "YOLOv8n detector", + "version": "V1.0.0", + "input": "1x3x640x640 RGB, scale 1/255, letterbox 114", + "output": "1x84x8400 candidate tensor", + "modelType": "yolov8_det", + "precision": "target artifact precision not exposed by the device catalog", + "sha256": "56b207ef2876da76505e403a049d3c44a411b9fe707ab73dc64f1cd9d9b6c5c8", + "sizeBytes": 7023600, + "repositoryPath": "data/resource/aiboxresource_cv186x/models/prod_BM1688_6047042_YOLOV8n_V1.0.0", + "deviceBinding": "byte-identical artifact observed in the CV186X benchmark device catalog", + "redistribution": "device-verified copy included in the CV186X resource set and Open package under Apache-2.0" + }, + { + "publicId": "safety-helmet-classifier", + "name": "Helmet classifier", + "version": "V1.0.0", + "input": "1x3x224x224 RGB, scale 1/255", + "output": "1x2 classification tensor: helmet, nohelmet", + "modelType": "classify", + "precision": "target artifact precision not exposed by the device catalog", + "sha256": "33b0fb4bcb29e41a92f9c1c518671aefc69cbf9207934deaba32ca7cd8cd7c8a", + "sizeBytes": 6001416, + "repositoryPath": "data/resource/aiboxresource_cv186x/models/prod_BM1688_7486163_helmet_V1.0.0", + "deviceBinding": "byte-identical artifact observed in the CV186X benchmark device catalog", + "redistribution": "device-verified copy included in the CV186X resource set and Open package under Apache-2.0" + }, + { + "publicId": "vlm-0.8b", + "name": "Qwen 0.8B device VLM", + "version": "V1.0.0", + "input": "catalog contract 1x3x224x224 plus text prompt/tokenizer", + "output": "catalog contract 1x1; semantic text result handled by the runtime", + "precision": "target artifact precision not exposed by the device catalog", + "sha256": "8d258ab0d16bb8836fe8de4e66b241890d71e64f016961e7d63588b6f7f76f1b", + "tokenizerSha256": "cb16258a9df7062f4c4d291a1501b07fb0750c9a8b247c5639dba0369e42f0cb", + "sizeBytes": 980885504, + "redistribution": "not included; user-installed model" + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/models/download-model.sh b/docs/benchmarks/scenario-bench/v1.1/models/download-model.sh new file mode 100644 index 000000000..3f3916a7f --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/models/download-model.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -eu + +cat >&2 <<'EOF' +Model binaries are not redistributed by this benchmark package. + +Install a licensed platform artifact matching models/.json, then record +its SHA-256. A different hash is a community reproduction, not a byte-identical +rerun of the frozen evidence. +EOF +exit 1 diff --git a/docs/benchmarks/scenario-bench/v1.1/models/io-contract.json b/docs/benchmarks/scenario-bench/v1.1/models/io-contract.json new file mode 100644 index 000000000..2eaf5ab60 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/models/io-contract.json @@ -0,0 +1,59 @@ +{ + "schemaVersion": 1, + "contracts": [ + { + "publicId": "person-detector", + "taskType": "cv", + "input": { + "layout": "NCHW", + "shape": [1, 3, 640, 640], + "color": "RGB", + "scale": 0.00392157, + "mean": [0, 0, 0], + "letterboxColor": [114, 114, 114] + }, + "output": { + "semantic": "YOLOv8 candidate tensor", + "referenceShape": [1, 84, 8400] + }, + "postprocess": { + "confidenceThreshold": 0.25, + "nmsThreshold": 0.7, + "topK": 1000, + "publishedClass": "person" + } + }, + { + "publicId": "safety-helmet-classifier", + "taskType": "cv", + "input": { + "layout": "NCHW", + "shape": [1, 3, 224, 224], + "color": "RGB", + "scale": 0.00392157, + "mean": [0, 0, 0], + "source": "person crop from the detector/tracker pipeline" + }, + "output": { + "semantic": "helmet/no-helmet classification", + "referenceShape": [1, 2] + }, + "postprocess": { + "threshold": 0.5, + "publishedClasses": ["helmet", "no-helmet"] + } + }, + { + "publicId": "vlm-0.8b", + "taskType": "vlm", + "input": { + "imageCatalogShape": [1, 3, 224, 224], + "additionalInputs": ["text prompt", "tokenizer"] + }, + "output": { + "semantic": "runtime-managed text judgment" + }, + "benchmarkInterpretation": "analysis FPS is an observation only in this Experimental workload; it is not a PASS/FAIL gate" + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/models/model-card.md b/docs/benchmarks/scenario-bench/v1.1/models/model-card.md new file mode 100644 index 000000000..4b9c673f3 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/models/model-card.md @@ -0,0 +1,25 @@ +# Model identity and redistribution record + +BM1688 and CV186X use the same byte-identical Open Sophon detector/classifier artifacts in this benchmark. RK3576 uses platform-specific RKNN artifacts that are not proven to be equivalent conversions of the same frozen source checkpoint and precision. The report therefore describes typical workload capacity and does not rank chips. + +| Platform | Public model | Version | Input contract | Target artifact identity | Redistribution | +| --- | --- | --- | --- | --- | --- | +| BM1688 | YOLOv8n detector | V1.0.0 | `1x3x640x640`, RGB, `1/255`, letterbox 114 | SHA-256 `56b207ef…b6c5c8` | Included in `data/resource/aiboxresource_bm1688/models/` | +| BM1688 | Helmet classifier | V1.0.0 | `1x3x224x224`, RGB, `1/255` | SHA-256 `33b0fb4b…cd7c8a` | Included in `data/resource/aiboxresource_bm1688/models/` | +| BM1688 | CosmoEdge VL Judge 0.8B | V1.0.0 | image plus text prompt/tokenizer | SHA-256 `31a03f48…4bd767` | Not included; preset model | +| CV186X | YOLOv8n detector | V1.0.0 | `1x3x640x640`, RGB, `1/255`, letterbox 114 | SHA-256 `56b207ef…b6c5c8` | Device-verified copy in `data/resource/aiboxresource_cv186x/models/` | +| CV186X | Helmet classifier | V1.0.0 | `1x3x224x224`, RGB, `1/255`, two classes | SHA-256 `33b0fb4b…cd7c8a` | Device-verified copy in `data/resource/aiboxresource_cv186x/models/` | +| CV186X | Qwen 0.8B device VLM | V1.0.0 | image plus text prompt/tokenizer | SHA-256 `8d258ab0…f76f1b` | Not included; user-installed model | +| RK3576 | YOLOv8 detector | V1.0.0 | `1x3x640x640`, RGB, `1/255`, letterbox 114 | SHA-256 `26ed82e0…541e0` | Not included pending license decision | +| RK3576 | Helmet classifier | V1.0.0 | `1x3x224x224`, RGB, `1/255` | SHA-256 `471d1de3…d67ea` | Not included pending license decision | +| RK3576 | Qwen 0.8B RKLLM VLM | V1.0.0 | image plus text prompt/tokenizer | Device catalog identity only; file SHA unavailable | Not included | + +Full hashes and per-platform notes are in `bm1688.json`, `cv186x.json`, and `rk3576.json`. + +## Accuracy scope + +The present package contains capacity and stability evidence, not a business-accuracy qualification. Precision, recall, F1, fixed-recall false-positive rate, source-to-target drift, hard-case evaluation, and production dynamic-set results must be published separately before claiming model accuracy. + +## Reproduction rule + +BM1688 and CV186X used byte-identical open Sophon detector/classifier files. Each target resource set contains its own device/package copy so the build path is explicit. Other model binaries remain outside this benchmark pack. A reproducer must use the matching platform resource artifact or another licensed artifact matching the public input/output contract and record its own SHA-256. If the hash differs from this card, the run is a community reproduction and must not be presented as a byte-identical rerun of the release evidence. diff --git a/docs/benchmarks/scenario-bench/v1.1/models/rk3576.json b/docs/benchmarks/scenario-bench/v1.1/models/rk3576.json new file mode 100644 index 000000000..419473f8d --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/models/rk3576.json @@ -0,0 +1,42 @@ +{ + "schemaVersion": 1, + "platform": "RK3576", + "artifactFormat": ".rknn for CV; RKLLM-specific artifact for VLM", + "models": [ + { + "publicId": "person-detector", + "name": "YOLOv8 detector", + "version": "V1.0.0", + "input": "1x3x640x640 RGB, scale 1/255, letterbox 114", + "output": "1x84x8400 candidate tensor", + "precision": "not recorded by device catalog; do not infer INT8/FP16", + "sha256": "26ed82e076b06bf0bd757286cafd2bff7ae957366640d96559bf3215a6d541e0", + "sizeBytes": 6305107, + "verification": "hash from the frozen release resource; model code and dimensions match the tested device catalog", + "redistribution": "not included pending model-license decision" + }, + { + "publicId": "safety-helmet-classifier", + "name": "Helmet classifier", + "version": "V1.0.0", + "input": "1x3x224x224 RGB, scale 1/255", + "output": "1x2 classification tensor", + "precision": "not recorded by device catalog; do not infer INT8/FP16", + "sha256": "471d1de315fd142d696066093eaf13e9657b61789c802cfe880606e209cd67ea", + "sizeBytes": 3024125, + "verification": "hash from the frozen release resource; model code and dimensions match the tested device catalog", + "redistribution": "not included pending model-license decision" + }, + { + "publicId": "vlm-0.8b-rkllm", + "name": "Qwen 0.8B RKLLM VLM", + "version": "V1.0.0", + "input": "catalog contract 1x3x224x224 plus text prompt/tokenizer", + "output": "catalog contract 1x1; semantic text result handled by the runtime", + "precision": "not recorded by device catalog", + "sha256": null, + "verification": "device catalog identity verified; model bytes unavailable for hashing", + "redistribution": "not included" + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/release-manifest.json b/docs/benchmarks/scenario-bench/v1.1/release-manifest.json new file mode 100644 index 000000000..23f2732ad --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/release-manifest.json @@ -0,0 +1,117 @@ +{ + "schemaVersion": 1, + "manifestStatus": "frozen-publication-ready", + "doNotPublish": false, + "release": { + "version": "1.1.0", + "tag": "v1.1.0", + "publicationState": "prepared-not-published", + "frozenAt": "2026-08-13T13:02:00+08:00" + }, + "sourceBaseline": { + "repository": "https://github.com/cosmo-wander-ai/cosmo-edge", + "branch": "feat/model-guard-v2.3", + "commit": "209bc2b52849864a15bdad91beb61f5bc982c17f", + "tree": "f64a98bce05b9ee8dc64dda8e56ad50f9d15687f", + "commitTime": "2026-08-13T12:04:09+08:00", + "commitSubject": "style(cpp): format candidate sources with clang-format", + "tagAtFreeze": null + }, + "repositoryIntegration": { + "targetBranch": "feat/model-guard-v2.3", + "targetCommitAtPreparation": "209bc2b52849864a15bdad91beb61f5bc982c17f", + "targetTreeAtPreparation": "f64a98bce05b9ee8dc64dda8e56ad50f9d15687f", + "evidenceRebindingRequired": false, + "reason": "The release owner identified feat/model-guard-v2.3 at 209bc2b5 as the CosmoEdge 1.1 source baseline. Changes after the benchmarked RK3576 VLM baseline are limited to Web linkage and upgrade-cache behavior plus a formatting-only pass; they do not modify inference, media, or memory lifecycle semantics. The benchmark remains a workload report; per-device package provenance is recorded separately below." + }, + "packageArtifacts": { + "open": { + "file": "cosmo-V1.1.0-3b0f4ebafd463eadf36e0d54918626dd.tar.gz", + "profile": "public-runtime", + "md5": "3b0f4ebafd463eadf36e0d54918626dd", + "sha256": "8aee0bdb146d80647b4f517114c2920781ed6760e90e5bdf951fefd982dbecb2", + "sizeBytes": 62915457, + "engineSha256": "bc7274327896384bcf68abf7fc42ce9e133f15131f3be21cb265b8e4deb55d11", + "status": "verified-on-bm1688-and-cv186x", + "verification": "The archive MD5 matches its filename; it contains plaintext CENN preset models and no provisioning binary, identifying the Open profile. The packaged engine SHA-256 equals the running engine SHA-256 on both Sophon reference devices." + }, + "protected": { + "sha256": null, + "status": "commercial-release-artifact-not-in-public-benchmark", + "publicationImpact": "not a blocker for publishing this benchmark because no Protected package or protected model bytes are distributed here" + }, + "evidenceBinding": { + "installedVersion": "V1.1.0.0", + "sourceBaselineDeclared": true, + "sourceCommitVerifiedFromPackage": false, + "packageSha256Verified": "bm1688-and-cv186x-open-package", + "status": "benchmark-binding-recorded-with-explicit-platform-gaps", + "reason": "BM1688 and CV186X are byte-bound to the recorded Open archive through the packaged/running engine digest. The archive predates the final source freeze and does not embed a source commit. RK3576 package bytes were not recovered, so RK3576 results remain bound to the reported installed version, model identities, environment and captured evidence rather than a package SHA-256." + } + }, + "benchmarkTool": { + "name": "ScenarioBench", + "version": "0.1.0", + "nodeRequirement": ">=20", + "cliSha256": "49d462975fb536eebe9c43436d1d72d725bff9b045523bfdc719a7cabb0e9f86", + "evaluatorSha256": "d3a73a2ca784ad0db9d79a8f3b87c697210e5925ffc28eea2177fe1814185f60", + "lockfileSha256": "8da33a2d1e27df0aac4e9ba5ec279f9d85ef7be1eb398cb555a0e3b45ca1a6a7" + }, + "dataset": { + "id": "cosmoedge-safety-helmet-sample-v1", + "file": "Safety Helmet.mp4", + "sha256": "ec77182a264f3059a091b68c4973942dba3b80e93f20feaf4d7e146885caf9d2", + "sizeBytes": 20049063, + "durationSeconds": 15.018667, + "video": { + "codec": "H.264", + "width": 1920, + "height": 1080, + "pixelFormat": "yuv420p", + "sourceFps": 24 + }, + "audio": { + "codec": "AAC" + }, + "repositoryBlob": "88cfb35d0c7fc2be45ecc2ad4324e2470ab3c979", + "repositoryCommit": "daeda95ccaf0119d384ff90d5d20c3e90fde8ccb", + "licenseStatus": "not redistributed by this benchmark; hash and metadata are published for identification only" + }, + "platforms": [ + { + "id": "bm1688", + "environment": "environments/bm1688.json", + "models": "models/bm1688.json", + "results": "results/bm1688/" + }, + { + "id": "cv186x", + "environment": "environments/cv186x.json", + "models": "models/cv186x.json", + "results": "results/cv186x/" + }, + { + "id": "rk3576", + "environment": "environments/rk3576.json", + "models": "models/rk3576.json", + "results": "results/rk3576/" + } + ], + "workloads": { + "dualDetector": "scenarios/dual-detector/scenario.public.yml", + "singleDetector": "scenarios/single-detector/", + "vlmObservation": "scenarios/vlm-observation/scenario.public.yml" + }, + "qualification": { + "benchmarkPackComplete": true, + "publicAssetRedistributionSafe": true, + "benchmarkReadyToPublish": true, + "productReleaseQualificationComplete": false, + "remainingProductReleaseInputs": [ + "Protected package SHA-256 and private build provenance", + "RK3576 final package SHA-256 and source provenance", + "RK3576 VLM model file SHA-256 for a byte-identical reproduction", + "repeat, soak, customer-journey and accuracy evidence before any recommended-profile claim" + ] + } +} diff --git a/docs/benchmarks/scenario-bench/v1.1/report.html b/docs/benchmarks/scenario-bench/v1.1/report.html new file mode 100644 index 000000000..668507a63 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/report.html @@ -0,0 +1 @@ +CosmoEdge 1.1 Multi-Platform Video Analytics Benchmark

CosmoEdge 1.1 Multi-Platform Video Analytics Benchmark

BM1688 · CV186X · RK3576

Under the stated models, video, and device configurations, the BM1688 short-run dual-detector staircase completed 16 channels at 5 FPS, while CV186X and RK3576 completed 8. These are highest verified short-run points, not recommended profiles or theoretical chip limits.

Release-candidate performance material
Publication scope: this page and its sanitized attachments have completed repository-level preparation as CosmoEdge 1.1 release-candidate performance material. BM1688/CV186X evidence is bound to the Open package recorded in the manifest; Protected and RK3576 package identities remain product-release evidence and are not distributed with this public benchmark.

Recommended profiles and short-run observations

PlatformDeviceRecommended profileHighest verified pointHold / stepStatus
BM1688BM1688 reference devicePending repetition and soak≥ 16 channels × 2 detectors × 5 FPS15 sPreliminary
CV186XCV186X reference devicePending repetition and soak≥ 8 channels × 2 detectors × 5 FPS30 sPreliminary
RK3576RK3576 EVBPending repetition and soak≥ 8 channels × 2 detectors × 5 FPS15 sPreliminary
Workload envelope by platformDual-detector throughput and latency curvesResource peaks at the highest verified point

Single-detector capacity matrix

Values are last passing channels. “≥” means the highest configured point passed. “*” means the next step was blocked by task binding and is not a performance limit.

PlatformWorkload24 FPS10 FPS7 FPS5 FPSStatus
BM1688Person detector715≥16≥16Preliminary
BM1688Safety-helmet detector7≥12*≥16≥16Preliminary
CV186XPerson detector≥3*≥8*≥11*≥15*Preliminary
CV186XSafety-helmet detector≥3*≥8*≥11*≥15*Preliminary
RK3576Person detector61215≥16Preliminary
RK3576Safety-helmet detector5101215Preliminary

Experimental: VLM runtime observation

The requested rate is 0.1 FPS per channel, but analysis FPS is excluded from PASS/FAIL. Passing means non-FPS gates only and must not be interpreted as validated VLM capacity. RK3576 reports a shared task counter; this page uses the reviewed equivalent per-channel observations documented in methodology.md.

PlatformTarget FPS / chLast non-FPS passEquivalent FPS at that pointStop pointStatus
BM16880.180.04highest configured point observedExperimental
CV186X0.180.08highest configured point observedExperimental
RK35760.170.063Channel 8 non-FPS stopExperimental

Linked attachments

The primary report keeps the public conclusions concise; these sanitized attachments provide per-channel evidence and machine-readable results.

Comparability

BM1688 and CV186X use the same byte-identical Open Sophon detector/classifier artifacts. RK3576 uses platform-specific RKNN artifacts that are not proven to be equivalent conversions of the same frozen source checkpoint and precision. This report describes typical workloads and does not rank chips.

Test environment

PlatformBoardOSRuntime / mediaCosmoEdge
BM1688Sophon BM1688 reference design; commercial enclosure name withheldUbuntu 22.04.5 LTSinference: libsophon/BMRT 0.4.12; media: Sophon FFmpeg 2.0.0 / Sophon GStreamer 2.0.0; decoder: bmvpu-decoder; encoder: bmvpu-h264V1.1.0.0
CV186XSophon CV186X reference design; commercial enclosure name withheldUbuntu 22.04.5 LTSinference: libsophon/BMRT 0.4.12; media: Sophon FFmpeg 2.0.0 / Sophon GStreamer 2.0.0; decoder: bmvpu-decoder; encoder: bmvpu-h264V1.1.0.0
RK3576Rockchip RK3576 EVB1 V10 BoardLinux distribution not exposed by the read-only device APIinference: RKNN runtime version not exposed by the read-only device API; driver: RKNN driver version not exposed by the read-only device API; rga: version not exposed; runtime telemetry confirms RGA path; mpp: version not exposed; runtime telemetry confirms Rockchip MPP VPU; decoder: rockchip-mpp-vpu / copy-out I420; encoder: rockchip-mpp / copy-first stride-aligned I420V1.1.0.0

Method and reproduction

  1. Fixed input: H.264, 1920×1080, 24 FPS; SHA-256 is in release-manifest.json.
  2. Add one channel per step; sample CV about every 3 seconds and VLM about every 10 seconds; use the second half as steady state.
  3. See models/ for model identities, scenarios/ for public descriptors, and results/ for per-step data.
  4. Resolve the descriptor locally and follow methodology.md; the public pack contains no device addresses, credentials, or internal IDs.

Limitations

  • A short staircase is not a soak test and does not create a recommended profile.
  • This is the release-candidate public performance report; it does not replace full installation, upgrade, rollback, accuracy, or soak qualification.
  • VLM has no FPS gate and remains an Experimental runtime observation.
  • Model accuracy qualification is outside this capacity report.
  • The open detector/classifier files are present in the BM1688 and CV186X platform resource sets; the sample video and other model binaries are not redistributed by this benchmark.

Full contract: release-manifest.json · methodology.md · SHA256SUMS

diff --git a/docs/benchmarks/scenario-bench/v1.1/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/report.zh-CN.html new file mode 100644 index 000000000..a3d796c04 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/report.zh-CN.html @@ -0,0 +1 @@ +CosmoEdge 1.1 多平台多路视频分析性能报告

CosmoEdge 1.1 多平台多路视频分析性能报告

BM1688 · CV186X · RK3576

在本报告指定的模型、视频和设备配置下,BM1688 的双算法短时阶梯完成 16 路 × 5 FPS,CV186X 与 RK3576 完成 8 路 × 5 FPS。这些是最高已验证短时点,不是官方推荐路数或芯片理论峰值。

待发布性能材料
发布范围:本页及其脱敏附件已完成仓库级收口,可作为 CosmoEdge 1.1 待发布公开性能材料。BM1688/CV186X 实测已绑定到 manifest 所列 Open 包;Protected 与 RK3576 包身份属于产品发版证据,不随本公开 benchmark 分发。

推荐配置与短时实测边界

平台设备推荐配置最高已验证点单级时长状态
BM1688BM1688 reference device待重复与长稳确认≥ 16 路 × 双算法 × 5 FPS15 s初步结论
CV186XCV186X reference device待重复与长稳确认≥ 8 路 × 双算法 × 5 FPS30 s初步结论
RK3576RK3576 EVB待重复与长稳确认≥ 8 路 × 双算法 × 5 FPS15 s初步结论
多平台工作负载容量图双算法吞吐与延时曲线最高验证点资源峰值

单算法容量矩阵

数字为最后通过路数;“≥”表示最高配置点通过;“*”表示下一步被任务绑定错误阻断,不是性能上限。

平台工作负载24 FPS10 FPS7 FPS5 FPS状态
BM1688人员检测715≥16≥16初步结论
BM1688安全帽检测7≥12*≥16≥16初步结论
CV186X人员检测≥3*≥8*≥11*≥15*初步结论
CV186X安全帽检测≥3*≥8*≥11*≥15*初步结论
RK3576人员检测61215≥16初步结论
RK3576安全帽检测5101215初步结论

实验结果:VLM 运行观测

目标为每路 0.1 FPS,但分析 FPS 未参与通过/失败判定。表中“通过”只表示非 FPS 门禁,不得解释为 VLM 正式容量。RK3576 的原始计数器是共享任务口径,本页使用已复核的等效单路观测值;完整修正规则见 methodology.md。

平台目标 FPS/路非 FPS 门禁最后通过路数该点等效单路 FPS停止点状态
BM16880.180.04最高配置点完成观测实验性
CV186X0.180.08最高配置点完成观测实验性
RK35760.170.063第 8 路非 FPS 门禁停止实验性

关联附件

主报告只保留公开结论;下列脱敏附件提供逐路过程数据和机器可读结果。

可比性声明

BM1688 与 CV186X 使用字节一致的 Open Sophon 检测/分类模型;RK3576 使用平台专用 RKNN 产物,尚未证明来自同一冻结源模型与精度。本报告描述典型工作负载,不制作芯片性能排行榜。

测试环境

平台板卡操作系统运行时 / 媒体链路CosmoEdge
BM1688Sophon BM1688 reference design; commercial enclosure name withheldUbuntu 22.04.5 LTSinference: libsophon/BMRT 0.4.12; media: Sophon FFmpeg 2.0.0 / Sophon GStreamer 2.0.0; decoder: bmvpu-decoder; encoder: bmvpu-h264V1.1.0.0
CV186XSophon CV186X reference design; commercial enclosure name withheldUbuntu 22.04.5 LTSinference: libsophon/BMRT 0.4.12; media: Sophon FFmpeg 2.0.0 / Sophon GStreamer 2.0.0; decoder: bmvpu-decoder; encoder: bmvpu-h264V1.1.0.0
RK3576Rockchip RK3576 EVB1 V10 BoardLinux distribution not exposed by the read-only device APIinference: RKNN runtime version not exposed by the read-only device API; driver: RKNN driver version not exposed by the read-only device API; rga: version not exposed; runtime telemetry confirms RGA path; mpp: version not exposed; runtime telemetry confirms Rockchip MPP VPU; decoder: rockchip-mpp-vpu / copy-out I420; encoder: rockchip-mpp / copy-first stride-aligned I420V1.1.0.0

方法与复现

  1. 固定视频:H.264、1920×1080、24 FPS;SHA-256 见 release-manifest.json。
  2. 逐路增加;CV 每约 3 秒采样,VLM 每约 10 秒采样;后半段为稳态窗口。
  3. 模型身份见 models/,场景见 scenarios/,逐路数据见 results/。
  4. 按 methodology.md 完成本地解析后执行;公开包不包含设备地址、凭据或内部编号。

限制

  • 短时阶梯不是长稳,不形成官方推荐配置。
  • 本页是待发布公开性能报告,不代替完整产品安装、升级、回滚、精度与长稳资格报告。
  • VLM 未启用 FPS 门禁,只能作为实验性运行观测。
  • 模型准确率材料不在本容量报告范围内。
  • 开源检测和分类文件分别保存在 BM1688、CV186X 平台资源目录;样例视频和其他模型二进制不随本 benchmark 分发。

完整合同:release-manifest.json · methodology.md · SHA256SUMS

diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/command.txt new file mode 100644 index 000000000..2a030baed --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/command.txt @@ -0,0 +1 @@ +See dual-detector/, single-detector/, and vlm-observation/ for workload-specific reproduction descriptors. diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/command.txt new file mode 100644 index 000000000..997c57eff --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=bm1688 +workload=dual-detector +scenario=../../../scenarios/dual-detector/scenario.public.yml +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/metrics.json new file mode 100644 index 000000000..20c911442 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/metrics.json @@ -0,0 +1,604 @@ +{ + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.71, + "minimumFpsRatio": 1.143, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 33.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.5, + "minimumFpsRatio": 1.1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 5.5, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.34, + "minimumFpsRatio": 1.069, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 39.2 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.23, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 31.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 36.6 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 36.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 36.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.09, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 44.8 + } + ], + "minimumProcessingFps": 5.09, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 44.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 33.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.3, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 33.3, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 19, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 42 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 23, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 42 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 46.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 46.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 28, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 35.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 38.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 52.3 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 52.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 36, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 39.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 42, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 41.2 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 49.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 49.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 45.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 74 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 74, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 52, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 45.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 71.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 71.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 58, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 44.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 4.92, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 62, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 47.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 81.9 + } + ], + "minimumProcessingFps": 4.92, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 81.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 57, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 92.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.9, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 103.7 + } + ], + "minimumProcessingFps": 4.9, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 103.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/report.html b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/report.html new file mode 100644 index 000000000..bd9a5f4c9 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/report.html @@ -0,0 +1 @@ +BM1688 dual-detector attachment

BM1688 dual-detector attachment

Two concurrent detector tasks at 5 FPS per channel. Highest configured point: ≥ 16 channels. Recommended profile remains pending.

ChannelsHoldPerson min FPSHelmet min FPSCritical path msAvg discardAcceleratorCPUMemoryResult
115s5.715.539.10%4%5%43%PASS
215s5.345.24460%12%7%43%PASS
315s5.235.1636.60%12%10%44%PASS
415s5.155.0944.80%18%14%44%PASS
515s5.035.0240.90%20%19%44%PASS
615s5548.40%28%23%44%PASS
715s4.974.9746.50%30%28%44%PASS
815s4.974.9747.20%44%33%45%PASS
915s4.954.9552.30%38%36%45%PASS
1015s4.934.93480%40%42%44%PASS
1115s4.954.9549.40%44%47%45%PASS
1215s4.954.95740%58%52%46%PASS
1315s4.934.9371.80%56%58%46%PASS
1415s4.924.92650%70%62%47%PASS
1515s4.924.9281.90%58%57%46%PASS
1615s4.924.9103.70%60%61%46%PASS
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/report.zh-CN.html new file mode 100644 index 000000000..0e8aef95e --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/report.zh-CN.html @@ -0,0 +1 @@ +BM1688 双算法逐路报告

BM1688 双算法逐路报告

每路并发人员检测与安全帽检测,目标均为 5 FPS;最高已配置并通过点为 ≥ 16 路,推荐配置仍待确认。

路数保持人员检测最低 FPS安全帽最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果
115s5.715.539.10%4%5%43%通过
215s5.345.24460%12%7%43%通过
315s5.235.1636.60%12%10%44%通过
415s5.155.0944.80%18%14%44%通过
515s5.035.0240.90%20%19%44%通过
615s5548.40%28%23%44%通过
715s4.974.9746.50%30%28%44%通过
815s4.974.9747.20%44%33%45%通过
915s4.954.9552.30%38%36%45%通过
1015s4.934.93480%40%42%44%通过
1115s4.954.9549.40%44%47%45%通过
1215s4.954.95740%58%52%46%通过
1315s4.934.9371.80%56%58%46%通过
1415s4.924.92650%70%62%47%通过
1515s4.924.9281.90%58%57%46%通过
1615s4.924.9103.70%60%61%46%通过
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/summary.json new file mode 100644 index 000000000..3af139371 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/summary.json @@ -0,0 +1,626 @@ +{ + "schemaVersion": 2, + "workload": { + "publicId": "dual-detector", + "tasksPerChannel": 2, + "tasks": [ + "person-detector", + "safety-helmet-detector" + ], + "targetFpsPerTaskPerChannel": 5, + "input": "fixed local 1920x1080 H.264 24 FPS sample", + "previewLoad": false + }, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-11", + "recommendedProfile": { + "status": "pending repeat and soak validation", + "channels": null + }, + "observedBoundary": { + "highestVerifiedChannels": 16, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 15 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.71, + "minimumFpsRatio": 1.143, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 33.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.5, + "minimumFpsRatio": 1.1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 5.5, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.34, + "minimumFpsRatio": 1.069, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 39.2 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.23, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 31.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 36.6 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 36.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 36.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.09, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 44.8 + } + ], + "minimumProcessingFps": 5.09, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 44.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 33.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.3, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 33.3, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 19, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 42 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 23, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 42 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 46.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 46.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 28, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 35.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 38.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 52.3 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 52.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 36, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 39.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 42, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 41.2 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 49.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 49.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 45.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 74 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 74, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 52, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 45.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 71.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 71.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 58, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 44.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 4.92, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 62, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 47.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 81.9 + } + ], + "minimumProcessingFps": 4.92, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 81.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 57, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 92.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.9, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 103.7 + } + ], + "minimumProcessingFps": 4.9, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 103.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/test.log b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/test.log new file mode 100644 index 000000000..1b69493d9 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/dual-detector/test.log @@ -0,0 +1,21 @@ +benchmark=cosmoedge-1.1-multistream +platform=BM1688 +device=BM1688 reference device +workload=dual-detector +publication=release-evidence +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 +channels=9 hold=15s result=PASS avg_discard=0 +channels=10 hold=15s result=PASS avg_discard=0 +channels=11 hold=15s result=PASS avg_discard=0 +channels=12 hold=15s result=PASS avg_discard=0 +channels=13 hold=15s result=PASS avg_discard=0 +channels=14 hold=15s result=PASS avg_discard=0 +channels=15 hold=15s result=PASS avg_discard=0 +channels=16 hold=15s result=PASS avg_discard=0 diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/environment.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/environment.json new file mode 100644 index 000000000..3c81c429c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/environment.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "platform": "BM1688", + "deviceDescription": "BM1688 reference device", + "boardModel": "Sophon BM1688 reference design; commercial enclosure name withheld", + "memory": { + "systemBytes": 2160271360, + "acceleratorHeap0MiB": 1536, + "acceleratorHeap1MiB": 4096 + }, + "storage": { + "systemFilesystemBytes": 9260003328, + "dataFilesystemBytes": 49366970368 + }, + "os": "Ubuntu 22.04.5 LTS", + "architecture": "aarch64", + "bsp": "BSP package identity is not published in this benchmark", + "runtime": { + "inference": "libsophon/BMRT 0.4.12", + "media": "Sophon FFmpeg 2.0.0 / Sophon GStreamer 2.0.0", + "decoder": "bmvpu-decoder", + "encoder": "bmvpu-h264" + }, + "cosmoEdgeInstalledVersion": "V1.1.0.0", + "releaseSourceCommit": "209bc2b52849864a15bdad91beb61f5bc982c17f", + "releaseSourceTree": "f64a98bce05b9ee8dc64dda8e56ad50f9d15687f", + "packageProfile": "public-runtime", + "packageSha256": "8aee0bdb146d80647b4f517114c2920781ed6760e90e5bdf951fefd982dbecb2", + "runningEngineSha256": "bc7274327896384bcf68abf7fc42ce9e133f15131f3be21cb265b8e4deb55d11", + "packageBinding": "verified: packaged and running engine SHA-256 values match; package does not embed a source commit", + "capturedAt": "2026-08-12T16:10:00+08:00" +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/metrics.json new file mode 100644 index 000000000..57df42df9 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/metrics.json @@ -0,0 +1,3822 @@ +{ + "schemaVersion": 2, + "dualDetector": { + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.71, + "minimumFpsRatio": 1.143, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 33.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.5, + "minimumFpsRatio": 1.1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 5.5, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.34, + "minimumFpsRatio": 1.069, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 39.2 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.23, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 31.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 36.6 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 36.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 36.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.09, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 44.8 + } + ], + "minimumProcessingFps": 5.09, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 44.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 33.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.3, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 33.3, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 19, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 42 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 23, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 42 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 46.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 46.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 28, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 35.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 38.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 52.3 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 52.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 36, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 39.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 42, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 41.2 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 49.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 49.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 45.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 74 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 74, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 52, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 45.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 71.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 71.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 58, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 44.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 4.92, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 62, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 47.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 81.9 + } + ], + "minimumProcessingFps": 4.92, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 81.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 57, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 92.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.9, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 103.7 + } + ], + "minimumProcessingFps": 4.9, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 103.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "singleDetector": { + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.85, + "minimumFpsRatio": 1.169, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6 + } + ], + "minimumProcessingFps": 5.85, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.39, + "minimumFpsRatio": 1.079, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5 + } + ], + "minimumProcessingFps": 5.39, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 4, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.18, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2 + } + ], + "minimumProcessingFps": 5.18, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 5, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 15, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 26, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 39, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 41, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 8.31, + "minimumFpsRatio": 1.187, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 8.31, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.57, + "minimumFpsRatio": 1.082, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 7.57, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.35, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9 + } + ], + "minimumProcessingFps": 7.35, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 16, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 18, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 26, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 30, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 34, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 38, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 50, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 55, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.31, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4 + } + ], + "minimumProcessingFps": 10.31, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 4, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 11, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 14, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 20, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 23, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 28, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 31, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 35, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.95, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1 + } + ], + "minimumProcessingFps": 9.95, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 43, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 53, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 60, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.86, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 9.86, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 68, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 0.524, + "missingRate": 0, + "averageDiscardRate": 0.0086, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4, + "averageDiscardRate": 0.0086, + "maximumChannelDiscardRate": 0.0218, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 95, + "cpuPeakPercent": 73, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (52.4%)" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.24, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6 + } + ], + "minimumProcessingFps": 24.24, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 9, + "cpuPeakPercent": 7, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.03, + "minimumFpsRatio": 1.001, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 24.03, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 12, + "cpuPeakPercent": 13, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.81, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8 + } + ], + "minimumProcessingFps": 23.81, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 20, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.9, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8 + } + ], + "minimumProcessingFps": 23.9, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 28, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 36, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 45, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.86, + "minimumFpsRatio": 0.994, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1 + } + ], + "minimumProcessingFps": 23.86, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 56, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 22.31, + "minimumFpsRatio": 0.929, + "missingRate": 0, + "averageDiscardRate": 0.0538, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5 + } + ], + "minimumProcessingFps": 22.31, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5, + "averageDiscardRate": 0.0538, + "maximumChannelDiscardRate": 0.0601, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 85, + "cpuPeakPercent": 65, + "memoryPeakPercent": 40, + "failureReason": "average discard 5.38%" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.57, + "minimumFpsRatio": 1.114, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 5.57, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 11, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 19, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 28, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 34, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 40, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 45, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 49, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.87, + "minimumFpsRatio": 0.973, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7 + } + ], + "minimumProcessingFps": 4.87, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 54, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.89, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9 + } + ], + "minimumProcessingFps": 4.89, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 60, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 70, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 71, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.46, + "minimumFpsRatio": 1.066, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.46, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 0, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 25, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 29, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.95, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 6.95, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 40, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 49, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 57, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 63, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 67, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.68, + "minimumFpsRatio": 0.954, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104 + } + ], + "minimumProcessingFps": 6.68, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0016, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 73, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.64, + "minimumFpsRatio": 0.949, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7 + } + ], + "minimumProcessingFps": 6.64, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0024, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 68, + "cpuPeakPercent": 75, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.71, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8 + } + ], + "minimumProcessingFps": 10.71, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.28, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9 + } + ], + "minimumProcessingFps": 10.28, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 14, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 19, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 22, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 32, + "cpuPeakPercent": 28, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 35, + "cpuPeakPercent": 36, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.92, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9 + } + ], + "minimumProcessingFps": 9.92, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 44, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 41, + "cpuPeakPercent": 50, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 44, + "cpuPeakPercent": 63, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 47, + "cpuPeakPercent": 67, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 71, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.23, + "minimumFpsRatio": 1.093, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7 + } + ], + "minimumProcessingFps": 26.23, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 13, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.86, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.86, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 25, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.25, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7 + } + ], + "minimumProcessingFps": 24.25, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 38, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.08, + "minimumFpsRatio": 1.004, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3 + } + ], + "minimumProcessingFps": 24.08, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 53, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58 + } + ], + "minimumProcessingFps": 24, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 68, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.31, + "minimumFpsRatio": 0.971, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2 + } + ], + "minimumProcessingFps": 23.31, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 74, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22, + "minimumFpsRatio": 0.917, + "missingRate": 0, + "averageDiscardRate": 0.0024, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8 + } + ], + "minimumProcessingFps": 22, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8, + "averageDiscardRate": 0.0024, + "maximumChannelDiscardRate": 0.0055, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 78, + "cpuPeakPercent": 86, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18.07, + "minimumFpsRatio": 0.753, + "missingRate": 0, + "averageDiscardRate": 0.0535, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8 + } + ], + "minimumProcessingFps": 18.07, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8, + "averageDiscardRate": 0.0535, + "maximumChannelDiscardRate": 0.084, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 88, + "cpuPeakPercent": 90, + "memoryPeakPercent": 43, + "failureReason": "average discard 5.35%" + } + ] + } + } + } + ] + }, + "vlmObservation": { + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 64, + "cpuPeakPercent": 7, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 14, + "cpuPeakPercent": 11, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 12, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 90, + "cpuPeakPercent": 12, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 100, + "cpuPeakPercent": 14, + "memoryPeakPercent": 48, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.08, + "fpsAchievementRatioObserved": 0.8, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 98, + "cpuPeakPercent": 13, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.04, + "fpsAchievementRatioObserved": 0.4, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 16, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + } + ] + } +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/report.html b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/report.html new file mode 100644 index 000000000..e437b918a --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/report.html @@ -0,0 +1 @@ +BM1688 benchmark attachments

BM1688 benchmark attachments

BM1688 reference device · CosmoEdge 1.1 release-candidate evidence

These are sanitized short-run observations. No recommended profile is claimed.

Single-detector matrix

Workload24 FPS10 FPS7 FPS5 FPS
Person detector715≥16≥16
Safety-helmet detector7≥12*≥16≥16

Dual-detector steps

ChannelsHoldPerson min FPSHelmet min FPSCritical path msAvg discardAcceleratorCPUMemoryResult
115s5.715.539.10%4%5%43%PASS
215s5.345.24460%12%7%43%PASS
315s5.235.1636.60%12%10%44%PASS
415s5.155.0944.80%18%14%44%PASS
515s5.035.0240.90%20%19%44%PASS
615s5548.40%28%23%44%PASS
715s4.974.9746.50%30%28%44%PASS
815s4.974.9747.20%44%33%45%PASS
915s4.954.9552.30%38%36%45%PASS
1015s4.934.93480%40%42%44%PASS
1115s4.954.9549.40%44%47%45%PASS
1215s4.954.95740%58%52%46%PASS
1315s4.934.9371.80%56%58%46%PASS
1415s4.924.92650%70%62%47%PASS
1515s4.924.9281.90%58%57%46%PASS
1615s4.924.9103.70%60%61%46%PASS

Experimental VLM runtime observation

FPS is recorded but excluded from PASS/FAIL. “PASS” below means non-FPS gates only.

ChannelsHoldTarget FPS/chEquivalent FPS/chAvg discardAcceleratorCPUMemoryNon-FPS gateStop reason
1120s0.10.10%0%4%45%PASS-
2120s0.10.10%64%7%46%PASS-
3120s0.10.10%14%11%46%PASS-
4120s0.10.10%84%12%46%PASS-
5120s0.10.060%90%12%47%PASS-
6120s0.10.10%100%14%48%PASS-
7120s0.10.080%98%13%47%PASS-
8120s0.10.040%84%16%47%PASS-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/report.zh-CN.html new file mode 100644 index 000000000..12cbd46d9 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/report.zh-CN.html @@ -0,0 +1 @@ +BM1688 压测附件总览

BM1688 压测附件总览

BM1688 reference device · CosmoEdge 1.1 待发布证据

以下为脱敏后的短时阶梯观测,不形成官方推荐配置。

单算法容量矩阵

工作负载24 FPS10 FPS7 FPS5 FPS
人员检测715≥16≥16
安全帽检测7≥12*≥16≥16

双算法逐路数据

路数保持人员检测最低 FPS安全帽最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果
115s5.715.539.10%4%5%43%通过
215s5.345.24460%12%7%43%通过
315s5.235.1636.60%12%10%44%通过
415s5.155.0944.80%18%14%44%通过
515s5.035.0240.90%20%19%44%通过
615s5548.40%28%23%44%通过
715s4.974.9746.50%30%28%44%通过
815s4.974.9747.20%44%33%45%通过
915s4.954.9552.30%38%36%45%通过
1015s4.934.93480%40%42%44%通过
1115s4.954.9549.40%44%47%45%通过
1215s4.954.95740%58%52%46%通过
1315s4.934.9371.80%56%58%46%通过
1415s4.924.92650%70%62%47%通过
1515s4.924.9281.90%58%57%46%通过
1615s4.924.9103.70%60%61%46%通过

实验结果:VLM 运行观测

FPS 仅记录、不参与通过/失败判定;表中“通过”只表示非 FPS 门禁通过。

路数保持目标 FPS/路等效 FPS/路平均丢弃率加速器CPU内存非 FPS 门禁停止原因
1120s0.10.10%0%4%45%通过-
2120s0.10.10%64%7%46%通过-
3120s0.10.10%14%11%46%通过-
4120s0.10.10%84%12%46%通过-
5120s0.10.060%90%12%47%通过-
6120s0.10.10%100%14%48%通过-
7120s0.10.080%98%13%47%通过-
8120s0.10.040%84%16%47%通过-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/command.txt new file mode 100644 index 000000000..def5f87f7 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=bm1688 +workload=single-detector +scenario=../../../scenarios/single-detector/ +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/metrics.json new file mode 100644 index 000000000..11ac9c9de --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/metrics.json @@ -0,0 +1,3075 @@ +{ + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.85, + "minimumFpsRatio": 1.169, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6 + } + ], + "minimumProcessingFps": 5.85, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.39, + "minimumFpsRatio": 1.079, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5 + } + ], + "minimumProcessingFps": 5.39, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 4, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.18, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2 + } + ], + "minimumProcessingFps": 5.18, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 5, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 15, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 26, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 39, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 41, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 8.31, + "minimumFpsRatio": 1.187, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 8.31, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.57, + "minimumFpsRatio": 1.082, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 7.57, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.35, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9 + } + ], + "minimumProcessingFps": 7.35, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 16, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 18, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 26, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 30, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 34, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 38, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 50, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 55, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.31, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4 + } + ], + "minimumProcessingFps": 10.31, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 4, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 11, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 14, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 20, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 23, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 28, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 31, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 35, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.95, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1 + } + ], + "minimumProcessingFps": 9.95, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 43, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 53, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 60, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.86, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 9.86, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 68, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 0.524, + "missingRate": 0, + "averageDiscardRate": 0.0086, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4, + "averageDiscardRate": 0.0086, + "maximumChannelDiscardRate": 0.0218, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 95, + "cpuPeakPercent": 73, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (52.4%)" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.24, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6 + } + ], + "minimumProcessingFps": 24.24, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 9, + "cpuPeakPercent": 7, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.03, + "minimumFpsRatio": 1.001, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 24.03, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 12, + "cpuPeakPercent": 13, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.81, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8 + } + ], + "minimumProcessingFps": 23.81, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 20, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.9, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8 + } + ], + "minimumProcessingFps": 23.9, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 28, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 36, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 45, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.86, + "minimumFpsRatio": 0.994, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1 + } + ], + "minimumProcessingFps": 23.86, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 56, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 22.31, + "minimumFpsRatio": 0.929, + "missingRate": 0, + "averageDiscardRate": 0.0538, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5 + } + ], + "minimumProcessingFps": 22.31, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5, + "averageDiscardRate": 0.0538, + "maximumChannelDiscardRate": 0.0601, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 85, + "cpuPeakPercent": 65, + "memoryPeakPercent": 40, + "failureReason": "average discard 5.38%" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.57, + "minimumFpsRatio": 1.114, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 5.57, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 11, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 19, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 28, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 34, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 40, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 45, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 49, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.87, + "minimumFpsRatio": 0.973, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7 + } + ], + "minimumProcessingFps": 4.87, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 54, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.89, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9 + } + ], + "minimumProcessingFps": 4.89, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 60, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 70, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 71, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.46, + "minimumFpsRatio": 1.066, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.46, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 0, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 25, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 29, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.95, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 6.95, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 40, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 49, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 57, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 63, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 67, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.68, + "minimumFpsRatio": 0.954, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104 + } + ], + "minimumProcessingFps": 6.68, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0016, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 73, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.64, + "minimumFpsRatio": 0.949, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7 + } + ], + "minimumProcessingFps": 6.64, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0024, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 68, + "cpuPeakPercent": 75, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.71, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8 + } + ], + "minimumProcessingFps": 10.71, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.28, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9 + } + ], + "minimumProcessingFps": 10.28, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 14, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 19, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 22, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 32, + "cpuPeakPercent": 28, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 35, + "cpuPeakPercent": 36, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.92, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9 + } + ], + "minimumProcessingFps": 9.92, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 44, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 41, + "cpuPeakPercent": 50, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 44, + "cpuPeakPercent": 63, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 47, + "cpuPeakPercent": 67, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 71, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.23, + "minimumFpsRatio": 1.093, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7 + } + ], + "minimumProcessingFps": 26.23, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 13, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.86, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.86, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 25, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.25, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7 + } + ], + "minimumProcessingFps": 24.25, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 38, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.08, + "minimumFpsRatio": 1.004, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3 + } + ], + "minimumProcessingFps": 24.08, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 53, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58 + } + ], + "minimumProcessingFps": 24, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 68, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.31, + "minimumFpsRatio": 0.971, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2 + } + ], + "minimumProcessingFps": 23.31, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 74, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22, + "minimumFpsRatio": 0.917, + "missingRate": 0, + "averageDiscardRate": 0.0024, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8 + } + ], + "minimumProcessingFps": 22, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8, + "averageDiscardRate": 0.0024, + "maximumChannelDiscardRate": 0.0055, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 78, + "cpuPeakPercent": 86, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18.07, + "minimumFpsRatio": 0.753, + "missingRate": 0, + "averageDiscardRate": 0.0535, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8 + } + ], + "minimumProcessingFps": 18.07, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8, + "averageDiscardRate": 0.0535, + "maximumChannelDiscardRate": 0.084, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 88, + "cpuPeakPercent": 90, + "memoryPeakPercent": 43, + "failureReason": "average discard 5.35%" + } + ] + } + } + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/report.html b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/report.html new file mode 100644 index 000000000..1fa2e1fed --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/report.html @@ -0,0 +1 @@ +BM1688 single-detector attachment

BM1688 single-detector attachment

Short-run staircase evidence. A binding-blocked next step is not a performance limit.

Person detector

24 FPS · boundary 7

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
160s24.2429.60%22%7%34%PASS-
2120s24.0330.90%38%13%35%PASS-
3120s23.8131.80%44%20%36%PASS-
4120s23.933.80%54%28%37%PASS-
5120s23.8837.70%70%36%38%PASS-
6120s23.8841.40%88%45%39%PASS-
7120s23.8644.10%98%56%40%PASS-
8120s22.3149.55.38%100%65%40%FAILaverage discard 5.38%

10 FPS · boundary 15

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
160s10.3120.40%8%4%39%PASS-
2120s10.03300%20%7%39%PASS-
3120s10.0330.70%24%11%39%PASS-
4120s10.0332.20%28%14%39%PASS-
5120s10320%36%18%39%PASS-
6120s9.9832.90%40%20%39%PASS-
7120s10.0234.30%50%23%40%PASS-
8120s10.02350%50%28%40%PASS-
9120s9.9739.10%56%31%40%PASS-
10120s1038.10%70%35%41%PASS-
11120s9.9540.10%60%43%42%PASS-
12120s1050.40%78%47%42%PASS-
13120s9.8852.90%86%53%43%PASS-
14120s9.8846.60%92%60%44%PASS-
15120s9.8651.60%100%68%44%PASS-
16120s5.2465.40.86%100%73%44%FAILprocessing-FPS gate failed (52.4%)

7 FPS · boundary ≥16

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s8.31310%6%3%43%PASS-
215s7.5730.70%18%5%43%PASS-
315s7.3531.90%14%7%43%PASS-
415s7.2231.10%16%9%43%PASS-
515s7.0550.30%22%12%44%PASS-
615s7.0732.60%26%13%44%PASS-
715s742.80%32%16%44%PASS-
815s6.9752.50%32%18%44%PASS-
915s6.9848.60%30%21%45%PASS-
1015s7.07400%44%23%45%PASS-
1115s7.0743.60%46%26%45%PASS-
1215s7.0551.60%44%30%45%PASS-
1315s7.0345.90%42%34%46%PASS-
1415s7.0354.30%58%38%46%PASS-
1515s7.0246.40%62%50%46%PASS-
1615s766.30%64%55%46%PASS-

5 FPS · boundary ≥16

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s5.8530.60%4%3%44%PASS-
215s5.3931.50%8%4%44%PASS-
315s5.1831.20%12%5%44%PASS-
415s5.12310%12%7%44%PASS-
515s5.03320%10%9%44%PASS-
615s4.9732.40%16%10%44%PASS-
715s4.9549.70%14%12%44%PASS-
815s4.9837.20%12%13%44%PASS-
915s4.9738.50%26%15%44%PASS-
1015s4.95380%34%16%45%PASS-
1115s4.9543.40%32%18%45%PASS-
1215s4.9537.70%32%21%45%PASS-
1315s4.9740.90%30%23%45%PASS-
1415s4.9746.70%30%26%46%PASS-
1515s4.9340.50%58%39%46%PASS-
1615s4.9351.80%38%41%46%PASS-

Safety-helmet detector

24 FPS · boundary 7

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s26.2333.70%48%13%34%PASS-
215s24.8637.60%50%25%36%PASS-
315s24.2540.70%42%38%37%PASS-
415s24.0847.30%72%53%39%PASS-
515s24580%86%68%39%PASS-
615s23.3180.20%94%74%41%PASS-
715s2292.80.24%92%86%42%PASS-
815s18.07111.85.35%100%90%43%FAILaverage discard 5.35%

10 FPS · boundary ≥12*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s10.7134.80%12%5%41%PASS-
215s10.2835.90%22%9%41%PASS-
315s10.1437.40%26%14%41%PASS-
415s10.0746.90%30%19%41%PASS-
515s10.0348.60%44%22%41%PASS-
615s9.9841.40%48%28%41%PASS-
715s9.9748.40%50%36%42%PASS-
815s9.9248.90%66%44%42%PASS-
915s9.8857.80%68%50%42%PASS-
1015s9.8555.90%76%63%42%PASS-
1115s9.8390.60%96%67%43%PASS-
1215s9.83102.60%100%71%43%PASS-
1315s----%-%-%FAILan enabled performance or stability gate failed
1415s----%-%-%FAILan enabled performance or stability gate failed
1515s----%-%-%FAILan enabled performance or stability gate failed
1615s----%-%-%FAILan enabled performance or stability gate failed

7 FPS · boundary ≥16

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s7.46440%0%5%45%PASS-
215s7.2137.30%14%9%44%PASS-
315s7.0236.40%22%13%45%PASS-
415s740.20%26%18%45%PASS-
515s748.70%26%25%45%PASS-
615s6.9247.50%28%29%46%PASS-
715s6.9549.10%44%33%45%PASS-
815s6.9749.70%46%40%46%PASS-
915s7460%58%47%46%PASS-
1015s6.9851.50%66%49%47%PASS-
1115s6.9258.50%76%57%47%PASS-
1215s6.9273.70%70%63%47%PASS-
1315s6.8371.90%82%67%46%PASS-
1415s6.8366.70%82%61%46%PASS-
1515s6.681040.01%82%73%47%PASS-
1615s6.64102.70.01%94%75%47%PASS-

5 FPS · boundary ≥16

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s5.5752.90%4%4%45%PASS-
215s5.2435.60%8%7%45%PASS-
315s5.1643.20%16%11%45%PASS-
415s5.138.80%22%13%45%PASS-
515s541.50%22%16%45%PASS-
615s4.9846.80%34%19%45%PASS-
715s4.9852.10%30%24%46%PASS-
815s4.9852.80%40%28%45%PASS-
915s4.9556.20%38%34%45%PASS-
1015s4.9554.40%42%40%45%PASS-
1115s4.9577.60%52%45%46%PASS-
1215s4.9158.80%46%49%46%PASS-
1315s4.8763.70%60%54%46%PASS-
1415s4.8960.90%66%60%46%PASS-
1515s4.9166.90%70%70%47%PASS-
1615s4.9368.30%76%71%47%PASS-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/report.zh-CN.html new file mode 100644 index 000000000..daedf45de --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/report.zh-CN.html @@ -0,0 +1 @@ +BM1688 单算法逐路报告

BM1688 单算法逐路报告

短时逐路阶梯证据;下一路若因任务绑定失败而阻断,不视为性能上限。

人员检测

24 FPS · 边界 7

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
160s24.2429.60%22%7%34%通过-
2120s24.0330.90%38%13%35%通过-
3120s23.8131.80%44%20%36%通过-
4120s23.933.80%54%28%37%通过-
5120s23.8837.70%70%36%38%通过-
6120s23.8841.40%88%45%39%通过-
7120s23.8644.10%98%56%40%通过-
8120s22.3149.55.38%100%65%40%失败平均丢弃率 5.38%

10 FPS · 边界 15

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
160s10.3120.40%8%4%39%通过-
2120s10.03300%20%7%39%通过-
3120s10.0330.70%24%11%39%通过-
4120s10.0332.20%28%14%39%通过-
5120s10320%36%18%39%通过-
6120s9.9832.90%40%20%39%通过-
7120s10.0234.30%50%23%40%通过-
8120s10.02350%50%28%40%通过-
9120s9.9739.10%56%31%40%通过-
10120s1038.10%70%35%41%通过-
11120s9.9540.10%60%43%42%通过-
12120s1050.40%78%47%42%通过-
13120s9.8852.90%86%53%43%通过-
14120s9.8846.60%92%60%44%通过-
15120s9.8651.60%100%68%44%通过-
16120s5.2465.40.86%100%73%44%失败处理 FPS 门禁失败 (52.4%)

7 FPS · 边界 ≥16

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s8.31310%6%3%43%通过-
215s7.5730.70%18%5%43%通过-
315s7.3531.90%14%7%43%通过-
415s7.2231.10%16%9%43%通过-
515s7.0550.30%22%12%44%通过-
615s7.0732.60%26%13%44%通过-
715s742.80%32%16%44%通过-
815s6.9752.50%32%18%44%通过-
915s6.9848.60%30%21%45%通过-
1015s7.07400%44%23%45%通过-
1115s7.0743.60%46%26%45%通过-
1215s7.0551.60%44%30%45%通过-
1315s7.0345.90%42%34%46%通过-
1415s7.0354.30%58%38%46%通过-
1515s7.0246.40%62%50%46%通过-
1615s766.30%64%55%46%通过-

5 FPS · 边界 ≥16

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s5.8530.60%4%3%44%通过-
215s5.3931.50%8%4%44%通过-
315s5.1831.20%12%5%44%通过-
415s5.12310%12%7%44%通过-
515s5.03320%10%9%44%通过-
615s4.9732.40%16%10%44%通过-
715s4.9549.70%14%12%44%通过-
815s4.9837.20%12%13%44%通过-
915s4.9738.50%26%15%44%通过-
1015s4.95380%34%16%45%通过-
1115s4.9543.40%32%18%45%通过-
1215s4.9537.70%32%21%45%通过-
1315s4.9740.90%30%23%45%通过-
1415s4.9746.70%30%26%46%通过-
1515s4.9340.50%58%39%46%通过-
1615s4.9351.80%38%41%46%通过-

安全帽检测

24 FPS · 边界 7

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s26.2333.70%48%13%34%通过-
215s24.8637.60%50%25%36%通过-
315s24.2540.70%42%38%37%通过-
415s24.0847.30%72%53%39%通过-
515s24580%86%68%39%通过-
615s23.3180.20%94%74%41%通过-
715s2292.80.24%92%86%42%通过-
815s18.07111.85.35%100%90%43%失败平均丢弃率 5.35%

10 FPS · 边界 ≥12*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s10.7134.80%12%5%41%通过-
215s10.2835.90%22%9%41%通过-
315s10.1437.40%26%14%41%通过-
415s10.0746.90%30%19%41%通过-
515s10.0348.60%44%22%41%通过-
615s9.9841.40%48%28%41%通过-
715s9.9748.40%50%36%42%通过-
815s9.9248.90%66%44%42%通过-
915s9.8857.80%68%50%42%通过-
1015s9.8555.90%76%63%42%通过-
1115s9.8390.60%96%67%43%通过-
1215s9.83102.60%100%71%43%通过-
1315s----%-%-%失败an enabled performance or stability gate failed
1415s----%-%-%失败an enabled performance or stability gate failed
1515s----%-%-%失败an enabled performance or stability gate failed
1615s----%-%-%失败an enabled performance or stability gate failed

7 FPS · 边界 ≥16

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s7.46440%0%5%45%通过-
215s7.2137.30%14%9%44%通过-
315s7.0236.40%22%13%45%通过-
415s740.20%26%18%45%通过-
515s748.70%26%25%45%通过-
615s6.9247.50%28%29%46%通过-
715s6.9549.10%44%33%45%通过-
815s6.9749.70%46%40%46%通过-
915s7460%58%47%46%通过-
1015s6.9851.50%66%49%47%通过-
1115s6.9258.50%76%57%47%通过-
1215s6.9273.70%70%63%47%通过-
1315s6.8371.90%82%67%46%通过-
1415s6.8366.70%82%61%46%通过-
1515s6.681040.01%82%73%47%通过-
1615s6.64102.70.01%94%75%47%通过-

5 FPS · 边界 ≥16

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s5.5752.90%4%4%45%通过-
215s5.2435.60%8%7%45%通过-
315s5.1643.20%16%11%45%通过-
415s5.138.80%22%13%45%通过-
515s541.50%22%16%45%通过-
615s4.9846.80%34%19%45%通过-
715s4.9852.10%30%24%46%通过-
815s4.9852.80%40%28%45%通过-
915s4.9556.20%38%34%45%通过-
1015s4.9554.40%42%40%45%通过-
1115s4.9577.60%52%45%46%通过-
1215s4.9158.80%46%49%46%通过-
1315s4.8763.70%60%54%46%通过-
1415s4.8960.90%66%60%46%通过-
1515s4.9166.90%70%70%47%通过-
1615s4.9368.30%76%71%47%通过-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/summary.json new file mode 100644 index 000000000..07d1278a5 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/summary.json @@ -0,0 +1,3123 @@ +{ + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.85, + "minimumFpsRatio": 1.169, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6 + } + ], + "minimumProcessingFps": 5.85, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.39, + "minimumFpsRatio": 1.079, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5 + } + ], + "minimumProcessingFps": 5.39, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 4, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.18, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2 + } + ], + "minimumProcessingFps": 5.18, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 5, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 15, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 26, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 39, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 41, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 8.31, + "minimumFpsRatio": 1.187, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 8.31, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.57, + "minimumFpsRatio": 1.082, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 7.57, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.35, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9 + } + ], + "minimumProcessingFps": 7.35, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 16, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 18, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 26, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 30, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 34, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 38, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 50, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 55, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.31, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4 + } + ], + "minimumProcessingFps": 10.31, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 4, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 11, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 14, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 20, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 23, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 28, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 31, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 35, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.95, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1 + } + ], + "minimumProcessingFps": 9.95, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 43, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 53, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 60, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.86, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 9.86, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 68, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 0.524, + "missingRate": 0, + "averageDiscardRate": 0.0086, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4, + "averageDiscardRate": 0.0086, + "maximumChannelDiscardRate": 0.0218, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 95, + "cpuPeakPercent": 73, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (52.4%)" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 7, + "firstFailedChannels": 8, + "boundaryKind": "exact-boundary", + "display": "7", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.24, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6 + } + ], + "minimumProcessingFps": 24.24, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 9, + "cpuPeakPercent": 7, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.03, + "minimumFpsRatio": 1.001, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 24.03, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 12, + "cpuPeakPercent": 13, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.81, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8 + } + ], + "minimumProcessingFps": 23.81, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 20, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.9, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8 + } + ], + "minimumProcessingFps": 23.9, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 28, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 36, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 45, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.86, + "minimumFpsRatio": 0.994, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1 + } + ], + "minimumProcessingFps": 23.86, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 56, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 22.31, + "minimumFpsRatio": 0.929, + "missingRate": 0, + "averageDiscardRate": 0.0538, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5 + } + ], + "minimumProcessingFps": 22.31, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5, + "averageDiscardRate": 0.0538, + "maximumChannelDiscardRate": 0.0601, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 85, + "cpuPeakPercent": 65, + "memoryPeakPercent": 40, + "failureReason": "average discard 5.38%" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.57, + "minimumFpsRatio": 1.114, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 5.57, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 11, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 19, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 28, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 34, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 40, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 45, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 49, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.87, + "minimumFpsRatio": 0.973, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7 + } + ], + "minimumProcessingFps": 4.87, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 54, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.89, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9 + } + ], + "minimumProcessingFps": 4.89, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 60, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 70, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 71, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.46, + "minimumFpsRatio": 1.066, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.46, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 0, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 25, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 29, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.95, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 6.95, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 40, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 49, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 57, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 63, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 67, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.68, + "minimumFpsRatio": 0.954, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104 + } + ], + "minimumProcessingFps": 6.68, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0016, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 73, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.64, + "minimumFpsRatio": 0.949, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7 + } + ], + "minimumProcessingFps": 6.64, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0024, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 68, + "cpuPeakPercent": 75, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "binding-blocked", + "display": "≥12*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.71, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8 + } + ], + "minimumProcessingFps": 10.71, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.28, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9 + } + ], + "minimumProcessingFps": 10.28, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 14, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 19, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 22, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 32, + "cpuPeakPercent": 28, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 35, + "cpuPeakPercent": 36, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.92, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9 + } + ], + "minimumProcessingFps": 9.92, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 44, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 41, + "cpuPeakPercent": 50, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 44, + "cpuPeakPercent": 63, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 47, + "cpuPeakPercent": 67, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 71, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 7, + "firstFailedChannels": 8, + "boundaryKind": "exact-boundary", + "display": "7", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.23, + "minimumFpsRatio": 1.093, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7 + } + ], + "minimumProcessingFps": 26.23, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 13, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.86, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.86, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 25, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.25, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7 + } + ], + "minimumProcessingFps": 24.25, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 38, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.08, + "minimumFpsRatio": 1.004, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3 + } + ], + "minimumProcessingFps": 24.08, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 53, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58 + } + ], + "minimumProcessingFps": 24, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 68, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.31, + "minimumFpsRatio": 0.971, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2 + } + ], + "minimumProcessingFps": 23.31, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 74, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22, + "minimumFpsRatio": 0.917, + "missingRate": 0, + "averageDiscardRate": 0.0024, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8 + } + ], + "minimumProcessingFps": 22, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8, + "averageDiscardRate": 0.0024, + "maximumChannelDiscardRate": 0.0055, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 78, + "cpuPeakPercent": 86, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18.07, + "minimumFpsRatio": 0.753, + "missingRate": 0, + "averageDiscardRate": 0.0535, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8 + } + ], + "minimumProcessingFps": 18.07, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8, + "averageDiscardRate": 0.0535, + "maximumChannelDiscardRate": 0.084, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 88, + "cpuPeakPercent": 90, + "memoryPeakPercent": 43, + "failureReason": "average discard 5.35%" + } + ] + } + } + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/test.log b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/test.log new file mode 100644 index 000000000..8b371db19 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/single-detector/test.log @@ -0,0 +1,117 @@ +benchmark=cosmoedge-1.1-multistream +platform=BM1688 +device=BM1688 reference device +workload=single-detector +publication=release-evidence +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 +channels=9 hold=15s result=PASS avg_discard=0 +channels=10 hold=15s result=PASS avg_discard=0 +channels=11 hold=15s result=PASS avg_discard=0 +channels=12 hold=15s result=PASS avg_discard=0 +channels=13 hold=15s result=PASS avg_discard=0 +channels=14 hold=15s result=PASS avg_discard=0 +channels=15 hold=15s result=PASS avg_discard=0 +channels=16 hold=15s result=PASS avg_discard=0 +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 +channels=9 hold=15s result=PASS avg_discard=0 +channels=10 hold=15s result=PASS avg_discard=0 +channels=11 hold=15s result=PASS avg_discard=0 +channels=12 hold=15s result=PASS avg_discard=0 +channels=13 hold=15s result=PASS avg_discard=0 +channels=14 hold=15s result=PASS avg_discard=0 +channels=15 hold=15s result=PASS avg_discard=0 +channels=16 hold=15s result=PASS avg_discard=0 +channels=1 hold=60s result=PASS avg_discard=0 +channels=2 hold=120s result=PASS avg_discard=0 +channels=3 hold=120s result=PASS avg_discard=0 +channels=4 hold=120s result=PASS avg_discard=0 +channels=5 hold=120s result=PASS avg_discard=0 +channels=6 hold=120s result=PASS avg_discard=0 +channels=7 hold=120s result=PASS avg_discard=0 +channels=8 hold=120s result=PASS avg_discard=0 +channels=9 hold=120s result=PASS avg_discard=0 +channels=10 hold=120s result=PASS avg_discard=0 +channels=11 hold=120s result=PASS avg_discard=0 +channels=12 hold=120s result=PASS avg_discard=0 +channels=13 hold=120s result=PASS avg_discard=0 +channels=14 hold=120s result=PASS avg_discard=0 +channels=15 hold=120s result=PASS avg_discard=0 +channels=16 hold=120s result=FAIL avg_discard=0.0086 +channels=1 hold=60s result=PASS avg_discard=0 +channels=2 hold=120s result=PASS avg_discard=0 +channels=3 hold=120s result=PASS avg_discard=0 +channels=4 hold=120s result=PASS avg_discard=0 +channels=5 hold=120s result=PASS avg_discard=0 +channels=6 hold=120s result=PASS avg_discard=0 +channels=7 hold=120s result=PASS avg_discard=0 +channels=8 hold=120s result=FAIL avg_discard=0.0538 +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 +channels=9 hold=15s result=PASS avg_discard=0 +channels=10 hold=15s result=PASS avg_discard=0 +channels=11 hold=15s result=PASS avg_discard=0 +channels=12 hold=15s result=PASS avg_discard=0 +channels=13 hold=15s result=PASS avg_discard=0 +channels=14 hold=15s result=PASS avg_discard=0 +channels=15 hold=15s result=PASS avg_discard=0 +channels=16 hold=15s result=PASS avg_discard=0 +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 +channels=9 hold=15s result=PASS avg_discard=0 +channels=10 hold=15s result=PASS avg_discard=0 +channels=11 hold=15s result=PASS avg_discard=0 +channels=12 hold=15s result=PASS avg_discard=0 +channels=13 hold=15s result=PASS avg_discard=0 +channels=14 hold=15s result=PASS avg_discard=0 +channels=15 hold=15s result=PASS avg_discard=0.0001 +channels=16 hold=15s result=PASS avg_discard=0.0001 +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 +channels=9 hold=15s result=PASS avg_discard=0 +channels=10 hold=15s result=PASS avg_discard=0 +channels=11 hold=15s result=PASS avg_discard=0 +channels=12 hold=15s result=PASS avg_discard=0 +channels=13 hold=15s result=FAIL avg_discard=null +channels=14 hold=15s result=FAIL avg_discard=null +channels=15 hold=15s result=FAIL avg_discard=null +channels=16 hold=15s result=FAIL avg_discard=null +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0.0024 +channels=8 hold=15s result=FAIL avg_discard=0.0535 diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/summary.json new file mode 100644 index 000000000..4572a4226 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/summary.json @@ -0,0 +1,3914 @@ +{ + "schemaVersion": 2, + "platformId": "bm1688", + "platform": "BM1688", + "device": "BM1688 reference device", + "publicationStatus": "release-evidence", + "productInstalledVersion": "V1.1.0.0", + "releaseManifest": "../../release-manifest.json", + "environment": "../../environments/bm1688.json", + "models": "../../models/bm1688.json", + "dataset": "../../dataset/dataset-card.md", + "dualDetector": { + "schemaVersion": 2, + "workload": { + "publicId": "dual-detector", + "tasksPerChannel": 2, + "tasks": [ + "person-detector", + "safety-helmet-detector" + ], + "targetFpsPerTaskPerChannel": 5, + "input": "fixed local 1920x1080 H.264 24 FPS sample", + "previewLoad": false + }, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-11", + "recommendedProfile": { + "status": "pending repeat and soak validation", + "channels": null + }, + "observedBoundary": { + "highestVerifiedChannels": 16, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 15 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.71, + "minimumFpsRatio": 1.143, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 33.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.5, + "minimumFpsRatio": 1.1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 5.5, + "maximumDetectorLatencyMs": 29.9, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.34, + "minimumFpsRatio": 1.069, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 39.2 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 35.5, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.23, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 31.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 36.6 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 27.9, + "maximumCriticalPathLatencyMs": 36.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 36.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.09, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 44.8 + } + ], + "minimumProcessingFps": 5.09, + "maximumDetectorLatencyMs": 32.5, + "maximumCriticalPathLatencyMs": 44.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 33.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.3, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 33.3, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 19, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 42 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 23, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 42 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 46.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 38.2, + "maximumCriticalPathLatencyMs": 46.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 28, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 35.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 32.1, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 38.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 52.3 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 52.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 36, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 39.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 42, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 41.2 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 49.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 49.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 45.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 74 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 41.1, + "maximumCriticalPathLatencyMs": 74, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 52, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 45.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 71.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 40.7, + "maximumCriticalPathLatencyMs": 71.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 58, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 44.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 4.92, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 62, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 47.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 81.9 + } + ], + "minimumProcessingFps": 4.92, + "maximumDetectorLatencyMs": 42.8, + "maximumCriticalPathLatencyMs": 81.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 57, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.92, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 92.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.9, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 103.7 + } + ], + "minimumProcessingFps": 4.9, + "maximumDetectorLatencyMs": 42.6, + "maximumCriticalPathLatencyMs": 103.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "singleDetector": { + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.85, + "minimumFpsRatio": 1.169, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6 + } + ], + "minimumProcessingFps": 5.85, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.39, + "minimumFpsRatio": 1.079, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5 + } + ], + "minimumProcessingFps": 5.39, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 4, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.18, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2 + } + ], + "minimumProcessingFps": 5.18, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 5, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 15, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 26, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 39, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 41, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 8.31, + "minimumFpsRatio": 1.187, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 8.31, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.57, + "minimumFpsRatio": 1.082, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 7.57, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.35, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9 + } + ], + "minimumProcessingFps": 7.35, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 16, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 18, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 26, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 30, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 34, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 38, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 50, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 55, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.31, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4 + } + ], + "minimumProcessingFps": 10.31, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 4, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 11, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 14, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 20, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 23, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 28, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 31, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 35, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.95, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1 + } + ], + "minimumProcessingFps": 9.95, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 43, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 53, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 60, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.86, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 9.86, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 68, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 0.524, + "missingRate": 0, + "averageDiscardRate": 0.0086, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4, + "averageDiscardRate": 0.0086, + "maximumChannelDiscardRate": 0.0218, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 95, + "cpuPeakPercent": 73, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (52.4%)" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 7, + "firstFailedChannels": 8, + "boundaryKind": "exact-boundary", + "display": "7", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.24, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6 + } + ], + "minimumProcessingFps": 24.24, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 9, + "cpuPeakPercent": 7, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.03, + "minimumFpsRatio": 1.001, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 24.03, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 12, + "cpuPeakPercent": 13, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.81, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8 + } + ], + "minimumProcessingFps": 23.81, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 20, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.9, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8 + } + ], + "minimumProcessingFps": 23.9, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 28, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 36, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 45, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.86, + "minimumFpsRatio": 0.994, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1 + } + ], + "minimumProcessingFps": 23.86, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 56, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 22.31, + "minimumFpsRatio": 0.929, + "missingRate": 0, + "averageDiscardRate": 0.0538, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5 + } + ], + "minimumProcessingFps": 22.31, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5, + "averageDiscardRate": 0.0538, + "maximumChannelDiscardRate": 0.0601, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 85, + "cpuPeakPercent": 65, + "memoryPeakPercent": 40, + "failureReason": "average discard 5.38%" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.57, + "minimumFpsRatio": 1.114, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 5.57, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 11, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 19, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 28, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 34, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 40, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 45, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 49, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.87, + "minimumFpsRatio": 0.973, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7 + } + ], + "minimumProcessingFps": 4.87, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 54, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.89, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9 + } + ], + "minimumProcessingFps": 4.89, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 60, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 70, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 71, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.46, + "minimumFpsRatio": 1.066, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.46, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 0, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 25, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 29, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.95, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 6.95, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 40, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 49, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 57, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 63, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 67, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.68, + "minimumFpsRatio": 0.954, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104 + } + ], + "minimumProcessingFps": 6.68, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0016, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 73, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.64, + "minimumFpsRatio": 0.949, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7 + } + ], + "minimumProcessingFps": 6.64, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0024, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 68, + "cpuPeakPercent": 75, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "binding-blocked", + "display": "≥12*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.71, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8 + } + ], + "minimumProcessingFps": 10.71, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.28, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9 + } + ], + "minimumProcessingFps": 10.28, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 14, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 19, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 22, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 32, + "cpuPeakPercent": 28, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 35, + "cpuPeakPercent": 36, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.92, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9 + } + ], + "minimumProcessingFps": 9.92, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 44, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 41, + "cpuPeakPercent": 50, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 44, + "cpuPeakPercent": 63, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 47, + "cpuPeakPercent": 67, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 71, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 7, + "firstFailedChannels": 8, + "boundaryKind": "exact-boundary", + "display": "7", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.23, + "minimumFpsRatio": 1.093, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7 + } + ], + "minimumProcessingFps": 26.23, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 13, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.86, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.86, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 25, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.25, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7 + } + ], + "minimumProcessingFps": 24.25, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 38, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.08, + "minimumFpsRatio": 1.004, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3 + } + ], + "minimumProcessingFps": 24.08, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 53, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58 + } + ], + "minimumProcessingFps": 24, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 68, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.31, + "minimumFpsRatio": 0.971, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2 + } + ], + "minimumProcessingFps": 23.31, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 74, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22, + "minimumFpsRatio": 0.917, + "missingRate": 0, + "averageDiscardRate": 0.0024, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8 + } + ], + "minimumProcessingFps": 22, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8, + "averageDiscardRate": 0.0024, + "maximumChannelDiscardRate": 0.0055, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 78, + "cpuPeakPercent": 86, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18.07, + "minimumFpsRatio": 0.753, + "missingRate": 0, + "averageDiscardRate": 0.0535, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8 + } + ], + "minimumProcessingFps": 18.07, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8, + "averageDiscardRate": 0.0535, + "maximumChannelDiscardRate": 0.084, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 88, + "cpuPeakPercent": 90, + "memoryPeakPercent": 43, + "failureReason": "average discard 5.35%" + } + ] + } + } + } + ] + }, + "vlmObservation": { + "schemaVersion": 2, + "workload": { + "publicId": "vlm-observation", + "targetFpsPerChannel": 0.1, + "interpretation": "Experimental runtime observation; FPS is recorded but excluded from PASS/FAIL", + "counterSemantics": "device-per-channel" + }, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-11", + "observedBoundary": { + "highestNonFpsPassingChannels": 8, + "firstNonFpsStopChannels": null, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 64, + "cpuPeakPercent": 7, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 14, + "cpuPeakPercent": 11, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 12, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 90, + "cpuPeakPercent": 12, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 100, + "cpuPeakPercent": 14, + "memoryPeakPercent": 48, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.08, + "fpsAchievementRatioObserved": 0.8, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 98, + "cpuPeakPercent": 13, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.04, + "fpsAchievementRatioObserved": 0.4, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 16, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + } + ] + } +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/test.log b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/test.log new file mode 100644 index 000000000..8e203ecd3 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/test.log @@ -0,0 +1,4 @@ +benchmark=cosmoedge-1.1-multistream +platform=BM1688 +device=BM1688 reference device +publication=release-evidence diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/command.txt new file mode 100644 index 000000000..5e5b2ed40 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=bm1688 +workload=vlm-observation +scenario=../../../scenarios/vlm-observation/scenario.public.yml +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/metrics.json new file mode 100644 index 000000000..520577dfa --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/metrics.json @@ -0,0 +1,140 @@ +{ + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 64, + "cpuPeakPercent": 7, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 14, + "cpuPeakPercent": 11, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 12, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 90, + "cpuPeakPercent": 12, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 100, + "cpuPeakPercent": 14, + "memoryPeakPercent": 48, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.08, + "fpsAchievementRatioObserved": 0.8, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 98, + "cpuPeakPercent": 13, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.04, + "fpsAchievementRatioObserved": 0.4, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 16, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/report.html b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/report.html new file mode 100644 index 000000000..d7a38d548 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/report.html @@ -0,0 +1 @@ +BM1688 Experimental VLM runtime observation

BM1688 Experimental VLM runtime observation

Requested rate: 0.1 FPS per channel. FPS is observational only and is not a pass/fail gate; this report does not claim validated VLM capacity.

ChannelsHoldTarget FPS/chEquivalent FPS/chAvg discardAcceleratorCPUMemoryNon-FPS gateStop reason
1120s0.10.10%0%4%45%PASS-
2120s0.10.10%64%7%46%PASS-
3120s0.10.10%14%11%46%PASS-
4120s0.10.10%84%12%46%PASS-
5120s0.10.060%90%12%47%PASS-
6120s0.10.10%100%14%48%PASS-
7120s0.10.080%98%13%47%PASS-
8120s0.10.040%84%16%47%PASS-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/report.zh-CN.html new file mode 100644 index 000000000..03692d648 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/report.zh-CN.html @@ -0,0 +1 @@ +BM1688 VLM 实验运行观测

BM1688 VLM 实验运行观测

目标为每路 0.1 FPS。FPS 仅作观测、不参与通过判定;本页不形成 VLM 正式容量结论。

路数保持目标 FPS/路等效 FPS/路平均丢弃率加速器CPU内存非 FPS 门禁停止原因
1120s0.10.10%0%4%45%通过-
2120s0.10.10%64%7%46%通过-
3120s0.10.10%14%11%46%通过-
4120s0.10.10%84%12%46%通过-
5120s0.10.060%90%12%47%通过-
6120s0.10.10%100%14%48%通过-
7120s0.10.080%98%13%47%通过-
8120s0.10.040%84%16%47%通过-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/summary.json new file mode 100644 index 000000000..c3c3706d6 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/summary.json @@ -0,0 +1,153 @@ +{ + "schemaVersion": 2, + "workload": { + "publicId": "vlm-observation", + "targetFpsPerChannel": 0.1, + "interpretation": "Experimental runtime observation; FPS is recorded but excluded from PASS/FAIL", + "counterSemantics": "device-per-channel" + }, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-11", + "observedBoundary": { + "highestNonFpsPassingChannels": 8, + "firstNonFpsStopChannels": null, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 64, + "cpuPeakPercent": 7, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 14, + "cpuPeakPercent": 11, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 12, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 90, + "cpuPeakPercent": 12, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 100, + "cpuPeakPercent": 14, + "memoryPeakPercent": 48, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.08, + "fpsAchievementRatioObserved": 0.8, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 98, + "cpuPeakPercent": 13, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.04, + "fpsAchievementRatioObserved": 0.4, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 16, + "memoryPeakPercent": 47, + "nonFpsGateResult": "PASS", + "stopReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/test.log b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/test.log new file mode 100644 index 000000000..7464a1726 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/bm1688/vlm-observation/test.log @@ -0,0 +1,13 @@ +benchmark=cosmoedge-1.1-multistream +platform=BM1688 +device=BM1688 reference device +workload=vlm-observation +publication=release-evidence +channels=1 hold=120s result=PASS avg_discard=0 +channels=2 hold=120s result=PASS avg_discard=0 +channels=3 hold=120s result=PASS avg_discard=0 +channels=4 hold=120s result=PASS avg_discard=0 +channels=5 hold=120s result=PASS avg_discard=0 +channels=6 hold=120s result=PASS avg_discard=0 +channels=7 hold=120s result=PASS avg_discard=0 +channels=8 hold=120s result=PASS avg_discard=0 diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/command.txt new file mode 100644 index 000000000..2a030baed --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/command.txt @@ -0,0 +1 @@ +See dual-detector/, single-detector/, and vlm-observation/ for workload-specific reproduction descriptors. diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/command.txt new file mode 100644 index 000000000..9e82ddca5 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=cv186x +workload=dual-detector +scenario=../../../scenarios/dual-detector/scenario.public.yml +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/metrics.json new file mode 100644 index 000000000..bb29edca9 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/metrics.json @@ -0,0 +1,308 @@ +{ + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.31, + "minimumFpsRatio": 1.062, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 21.8 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.31, + "minimumFpsRatio": 1.062, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 24.9 + } + ], + "minimumProcessingFps": 5.31, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 24.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 22.3 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 25.4 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 25.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 23.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 29.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 29.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 54 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 54, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 40.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 45.2 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 45.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 11, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 38.4 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 45.2 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 45.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 12, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 59.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 67.9 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 67.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 15, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 56.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 64.3 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 64.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 19, + "memoryPeakPercent": 42, + "failureReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/report.html b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/report.html new file mode 100644 index 000000000..23ff7c759 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/report.html @@ -0,0 +1 @@ +CV186X dual-detector attachment

CV186X dual-detector attachment

Two concurrent detector tasks at 5 FPS per channel. Highest configured point: ≥ 8 channels. Recommended profile remains pending.

ChannelsHoldPerson min FPSHelmet min FPSCritical path msAvg discardAcceleratorCPUMemoryResult
130s5.315.3124.90%8%4%41%PASS
230s5.125.1225.40%10%5%41%PASS
330s5.055.0529.30%24%6%41%PASS
430s5.035.03540%26%9%41%PASS
530s5545.20%40%11%41%PASS
630s5545.20%34%12%41%PASS
730s4.954.9567.90%52%15%42%PASS
830s5564.30%60%19%42%PASS
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/report.zh-CN.html new file mode 100644 index 000000000..6c3c74b34 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/report.zh-CN.html @@ -0,0 +1 @@ +CV186X 双算法逐路报告

CV186X 双算法逐路报告

每路并发人员检测与安全帽检测,目标均为 5 FPS;最高已配置并通过点为 ≥ 8 路,推荐配置仍待确认。

路数保持人员检测最低 FPS安全帽最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果
130s5.315.3124.90%8%4%41%通过
230s5.125.1225.40%10%5%41%通过
330s5.055.0529.30%24%6%41%通过
430s5.035.03540%26%9%41%通过
530s5545.20%40%11%41%通过
630s5545.20%34%12%41%通过
730s4.954.9567.90%52%15%42%通过
830s5564.30%60%19%42%通过
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/summary.json new file mode 100644 index 000000000..0c1950a64 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/summary.json @@ -0,0 +1,330 @@ +{ + "schemaVersion": 2, + "workload": { + "publicId": "dual-detector", + "tasksPerChannel": 2, + "tasks": [ + "person-detector", + "safety-helmet-detector" + ], + "targetFpsPerTaskPerChannel": 5, + "input": "fixed local 1920x1080 H.264 24 FPS sample", + "previewLoad": false + }, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-11", + "recommendedProfile": { + "status": "pending repeat and soak validation", + "channels": null + }, + "observedBoundary": { + "highestVerifiedChannels": 8, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 30 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.31, + "minimumFpsRatio": 1.062, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 21.8 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.31, + "minimumFpsRatio": 1.062, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 24.9 + } + ], + "minimumProcessingFps": 5.31, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 24.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 22.3 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 25.4 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 25.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 23.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 29.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 29.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 54 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 54, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 40.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 45.2 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 45.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 11, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 38.4 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 45.2 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 45.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 12, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 59.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 67.9 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 67.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 15, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 56.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 64.3 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 64.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 19, + "memoryPeakPercent": 42, + "failureReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/test.log b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/test.log new file mode 100644 index 000000000..d6f322e0b --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/dual-detector/test.log @@ -0,0 +1,13 @@ +benchmark=cosmoedge-1.1-multistream +platform=CV186X +device=CV186X reference device +workload=dual-detector +publication=release-evidence +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/environment.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/environment.json new file mode 100644 index 000000000..0a8a4d74c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/environment.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "platform": "CV186X", + "deviceDescription": "CV186X reference device", + "boardModel": "Sophon CV186X reference design; commercial enclosure name withheld", + "memory": { + "systemBytes": 2160451584, + "acceleratorHeap0MiB": 1536, + "acceleratorHeap1MiB": 4096 + }, + "storage": { + "systemFilesystemBytes": 9260003328, + "dataFilesystemBytes": 49375051776 + }, + "os": "Ubuntu 22.04.5 LTS", + "architecture": "aarch64", + "bsp": "BSP package identity is not published in this benchmark", + "runtime": { + "inference": "libsophon/BMRT 0.4.12", + "media": "Sophon FFmpeg 2.0.0 / Sophon GStreamer 2.0.0", + "decoder": "bmvpu-decoder", + "encoder": "bmvpu-h264" + }, + "cosmoEdgeInstalledVersion": "V1.1.0.0", + "releaseSourceCommit": "209bc2b52849864a15bdad91beb61f5bc982c17f", + "releaseSourceTree": "f64a98bce05b9ee8dc64dda8e56ad50f9d15687f", + "packageProfile": "public-runtime", + "packageSha256": "8aee0bdb146d80647b4f517114c2920781ed6760e90e5bdf951fefd982dbecb2", + "runningEngineSha256": "bc7274327896384bcf68abf7fc42ce9e133f15131f3be21cb265b8e4deb55d11", + "packageBinding": "verified: packaged and running engine SHA-256 values match; package does not embed a source commit", + "capturedAt": "2026-08-12T16:10:00+08:00" +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/metrics.json new file mode 100644 index 000000000..efc81e0e3 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/metrics.json @@ -0,0 +1,3046 @@ +{ + "schemaVersion": 2, + "dualDetector": { + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.31, + "minimumFpsRatio": 1.062, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 21.8 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.31, + "minimumFpsRatio": 1.062, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 24.9 + } + ], + "minimumProcessingFps": 5.31, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 24.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 22.3 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 25.4 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 25.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 23.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 29.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 29.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 54 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 54, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 40.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 45.2 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 45.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 11, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 38.4 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 45.2 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 45.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 12, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 59.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 67.9 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 67.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 15, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 56.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 64.3 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 64.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 19, + "memoryPeakPercent": 42, + "failureReason": null + } + ] + }, + "singleDetector": { + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.28, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7 + } + ], + "minimumProcessingFps": 5.28, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 3, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 16, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": 45, + "cpuPeakPercent": 17, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 48, + "cpuPeakPercent": 18, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 13, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 22, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.63, + "minimumFpsRatio": 0.925, + "missingRate": 0, + "averageDiscardRate": 0.0018, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5 + } + ], + "minimumProcessingFps": 4.63, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5, + "averageDiscardRate": 0.0018, + "maximumChannelDiscardRate": 0.0048, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 67, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.19, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8 + } + ], + "minimumProcessingFps": 7.19, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 0.845, + "missingRate": 0, + "averageDiscardRate": 0.0245, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2 + } + ], + "minimumProcessingFps": 5.92, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2, + "averageDiscardRate": 0.0245, + "maximumChannelDiscardRate": 0.0519, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 13, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.55, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7 + } + ], + "minimumProcessingFps": 10.55, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.25, + "minimumFpsRatio": 1.025, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6 + } + ], + "minimumProcessingFps": 10.25, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.11, + "minimumFpsRatio": 1.011, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2 + } + ], + "minimumProcessingFps": 10.11, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.55, + "minimumFpsRatio": 0.855, + "missingRate": 0, + "averageDiscardRate": 0.0146, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3 + } + ], + "minimumProcessingFps": 8.55, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3, + "averageDiscardRate": 0.0146, + "maximumChannelDiscardRate": 0.0262, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.93, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8 + } + ], + "minimumProcessingFps": 24.93, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 3, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.15, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 24.15, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.52, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 23.52, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 7, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 18.68, + "minimumFpsRatio": 0.778, + "missingRate": 0, + "averageDiscardRate": 0.0832, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59 + } + ], + "minimumProcessingFps": 18.68, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59, + "averageDiscardRate": 0.0832, + "maximumChannelDiscardRate": 0.1384, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 10, + "memoryPeakPercent": 35, + "failureReason": "average discard 8.32%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.36, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.36, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 15, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 17, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 20, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 29, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 28, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.22, + "minimumFpsRatio": 0.844, + "missingRate": 0, + "averageDiscardRate": 0.0209, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4 + } + ], + "minimumProcessingFps": 4.22, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4, + "averageDiscardRate": 0.0209, + "maximumChannelDiscardRate": 0.0521, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 82, + "cpuPeakPercent": 44, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 18, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 21, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.85, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8 + } + ], + "minimumProcessingFps": 6.85, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 24, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.24, + "minimumFpsRatio": 0.891, + "missingRate": 0, + "averageDiscardRate": 0.0217, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2 + } + ], + "minimumProcessingFps": 6.24, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2, + "averageDiscardRate": 0.0217, + "maximumChannelDiscardRate": 0.0447, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 71, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.45, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2 + } + ], + "minimumProcessingFps": 10.45, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.2, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1 + } + ], + "minimumProcessingFps": 10.2, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.09, + "minimumFpsRatio": 1.009, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 10.09, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 10, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0346, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9, + "averageDiscardRate": 0.0346, + "maximumChannelDiscardRate": 0.0466, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 60, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.17, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7 + } + ], + "minimumProcessingFps": 24.17, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.89, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4 + } + ], + "minimumProcessingFps": 23.89, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 9, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.66, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7 + } + ], + "minimumProcessingFps": 23.66, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18, + "minimumFpsRatio": 0.75, + "missingRate": 0, + "averageDiscardRate": 0.0913, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3 + } + ], + "minimumProcessingFps": 18, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3, + "averageDiscardRate": 0.0913, + "maximumChannelDiscardRate": 0.145, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 17, + "memoryPeakPercent": 37, + "failureReason": "average discard 9.13%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + } + ] + }, + "vlmObservation": { + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.12, + "fpsAchievementRatioObserved": 1.2, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 5, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 10, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 16, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 96, + "cpuPeakPercent": 15, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 82, + "cpuPeakPercent": 19, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 98, + "cpuPeakPercent": 21, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.08, + "fpsAchievementRatioObserved": 0.8, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 21, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + } + ] + } +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/report.html b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/report.html new file mode 100644 index 000000000..f292aaa4b --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/report.html @@ -0,0 +1 @@ +CV186X benchmark attachments

CV186X benchmark attachments

CV186X reference device · CosmoEdge 1.1 release-candidate evidence

These are sanitized short-run observations. No recommended profile is claimed.

Single-detector matrix

Workload24 FPS10 FPS7 FPS5 FPS
Person detector≥3*≥8*≥11*≥15*
Safety-helmet detector≥3*≥8*≥11*≥15*

Dual-detector steps

ChannelsHoldPerson min FPSHelmet min FPSCritical path msAvg discardAcceleratorCPUMemoryResult
130s5.315.3124.90%8%4%41%PASS
230s5.125.1225.40%10%5%41%PASS
330s5.055.0529.30%24%6%41%PASS
430s5.035.03540%26%9%41%PASS
530s5545.20%40%11%41%PASS
630s5545.20%34%12%41%PASS
730s4.954.9567.90%52%15%42%PASS
830s5564.30%60%19%42%PASS

Experimental VLM runtime observation

FPS is recorded but excluded from PASS/FAIL. “PASS” below means non-FPS gates only.

ChannelsHoldTarget FPS/chEquivalent FPS/chAvg discardAcceleratorCPUMemoryNon-FPS gateStop reason
1120s0.10.120%0%5%42%PASS-
2120s0.10.10%0%10%42%PASS-
3120s0.10.10%0%14%42%PASS-
4120s0.10.10%84%16%43%PASS-
5120s0.10.060%96%15%43%PASS-
6120s0.10.060%82%19%42%PASS-
7120s0.10.060%98%21%43%PASS-
8120s0.10.080%84%21%43%PASS-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/report.zh-CN.html new file mode 100644 index 000000000..c9d7c95c2 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/report.zh-CN.html @@ -0,0 +1 @@ +CV186X 压测附件总览

CV186X 压测附件总览

CV186X reference device · CosmoEdge 1.1 待发布证据

以下为脱敏后的短时阶梯观测,不形成官方推荐配置。

单算法容量矩阵

工作负载24 FPS10 FPS7 FPS5 FPS
人员检测≥3*≥8*≥11*≥15*
安全帽检测≥3*≥8*≥11*≥15*

双算法逐路数据

路数保持人员检测最低 FPS安全帽最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果
130s5.315.3124.90%8%4%41%通过
230s5.125.1225.40%10%5%41%通过
330s5.055.0529.30%24%6%41%通过
430s5.035.03540%26%9%41%通过
530s5545.20%40%11%41%通过
630s5545.20%34%12%41%通过
730s4.954.9567.90%52%15%42%通过
830s5564.30%60%19%42%通过

实验结果:VLM 运行观测

FPS 仅记录、不参与通过/失败判定;表中“通过”只表示非 FPS 门禁通过。

路数保持目标 FPS/路等效 FPS/路平均丢弃率加速器CPU内存非 FPS 门禁停止原因
1120s0.10.120%0%5%42%通过-
2120s0.10.10%0%10%42%通过-
3120s0.10.10%0%14%42%通过-
4120s0.10.10%84%16%43%通过-
5120s0.10.060%96%15%43%通过-
6120s0.10.060%82%19%42%通过-
7120s0.10.060%98%21%43%通过-
8120s0.10.080%84%21%43%通过-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/command.txt new file mode 100644 index 000000000..ac83f3106 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=cv186x +workload=single-detector +scenario=../../../scenarios/single-detector/ +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/metrics.json new file mode 100644 index 000000000..939b3f80b --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/metrics.json @@ -0,0 +1,2595 @@ +{ + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.28, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7 + } + ], + "minimumProcessingFps": 5.28, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 3, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 16, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": 45, + "cpuPeakPercent": 17, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 48, + "cpuPeakPercent": 18, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 13, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 22, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.63, + "minimumFpsRatio": 0.925, + "missingRate": 0, + "averageDiscardRate": 0.0018, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5 + } + ], + "minimumProcessingFps": 4.63, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5, + "averageDiscardRate": 0.0018, + "maximumChannelDiscardRate": 0.0048, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 67, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.19, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8 + } + ], + "minimumProcessingFps": 7.19, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 0.845, + "missingRate": 0, + "averageDiscardRate": 0.0245, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2 + } + ], + "minimumProcessingFps": 5.92, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2, + "averageDiscardRate": 0.0245, + "maximumChannelDiscardRate": 0.0519, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 13, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.55, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7 + } + ], + "minimumProcessingFps": 10.55, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.25, + "minimumFpsRatio": 1.025, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6 + } + ], + "minimumProcessingFps": 10.25, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.11, + "minimumFpsRatio": 1.011, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2 + } + ], + "minimumProcessingFps": 10.11, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.55, + "minimumFpsRatio": 0.855, + "missingRate": 0, + "averageDiscardRate": 0.0146, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3 + } + ], + "minimumProcessingFps": 8.55, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3, + "averageDiscardRate": 0.0146, + "maximumChannelDiscardRate": 0.0262, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.93, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8 + } + ], + "minimumProcessingFps": 24.93, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 3, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.15, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 24.15, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.52, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 23.52, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 7, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 18.68, + "minimumFpsRatio": 0.778, + "missingRate": 0, + "averageDiscardRate": 0.0832, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59 + } + ], + "minimumProcessingFps": 18.68, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59, + "averageDiscardRate": 0.0832, + "maximumChannelDiscardRate": 0.1384, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 10, + "memoryPeakPercent": 35, + "failureReason": "average discard 8.32%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.36, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.36, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 15, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 17, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 20, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 29, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 28, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.22, + "minimumFpsRatio": 0.844, + "missingRate": 0, + "averageDiscardRate": 0.0209, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4 + } + ], + "minimumProcessingFps": 4.22, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4, + "averageDiscardRate": 0.0209, + "maximumChannelDiscardRate": 0.0521, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 82, + "cpuPeakPercent": 44, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 18, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 21, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.85, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8 + } + ], + "minimumProcessingFps": 6.85, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 24, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.24, + "minimumFpsRatio": 0.891, + "missingRate": 0, + "averageDiscardRate": 0.0217, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2 + } + ], + "minimumProcessingFps": 6.24, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2, + "averageDiscardRate": 0.0217, + "maximumChannelDiscardRate": 0.0447, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 71, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.45, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2 + } + ], + "minimumProcessingFps": 10.45, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.2, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1 + } + ], + "minimumProcessingFps": 10.2, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.09, + "minimumFpsRatio": 1.009, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 10.09, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 10, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0346, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9, + "averageDiscardRate": 0.0346, + "maximumChannelDiscardRate": 0.0466, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 60, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.17, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7 + } + ], + "minimumProcessingFps": 24.17, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.89, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4 + } + ], + "minimumProcessingFps": 23.89, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 9, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.66, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7 + } + ], + "minimumProcessingFps": 23.66, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18, + "minimumFpsRatio": 0.75, + "missingRate": 0, + "averageDiscardRate": 0.0913, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3 + } + ], + "minimumProcessingFps": 18, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3, + "averageDiscardRate": 0.0913, + "maximumChannelDiscardRate": 0.145, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 17, + "memoryPeakPercent": 37, + "failureReason": "average discard 9.13%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/report.html b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/report.html new file mode 100644 index 000000000..f1e87bb7a --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/report.html @@ -0,0 +1 @@ +CV186X single-detector attachment

CV186X single-detector attachment

Short-run staircase evidence. A binding-blocked next step is not a performance limit.

Person detector

24 FPS · boundary ≥3*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s24.9318.80%42%3%35%PASS-
230s24.1522.50%72%5%35%PASS-
330s23.5246.60%84%7%35%PASS-
430s18.68598.32%90%10%35%FAILaverage discard 8.32%
530s----%-%-%FAILan enabled performance or stability gate failed
630s----%-%-%FAILan enabled performance or stability gate failed
730s----%-%-%FAILan enabled performance or stability gate failed
830s----%-%-%FAILan enabled performance or stability gate failed

10 FPS · boundary ≥8*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s10.5522.70%10%2%41%PASS-
230s10.2522.60%30%4%41%PASS-
330s10.1125.20%46%6%41%PASS-
430s10.1432.10%56%8%41%PASS-
530s10.0340.80%64%7%41%PASS-
630s10.0338.20%72%8%41%PASS-
730s10.0251.50%94%8%42%PASS-
830s8.5560.31.46%84%9%42%PASS-
930s----%-%-%FAILan enabled performance or stability gate failed
1030s----%-%-%FAILan enabled performance or stability gate failed
1130s----%-%-%FAILan enabled performance or stability gate failed
1230s----%-%-%FAILan enabled performance or stability gate failed
1330s----%-%-%FAILan enabled performance or stability gate failed
1430s----%-%-%FAILan enabled performance or stability gate failed
1530s----%-%-%FAILan enabled performance or stability gate failed
1630s----%-%-%FAILan enabled performance or stability gate failed

7 FPS · boundary ≥11*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s7.4522.50%14%2%42%PASS-
230s7.1922.80%16%2%42%PASS-
330s7.1432.10%34%6%42%PASS-
430s7.1430.90%34%7%42%PASS-
530s6.9826.40%44%7%42%PASS-
630s6.9856.20%62%8%42%PASS-
730s7.0334.90%62%9%42%PASS-
830s735.30%66%9%43%PASS-
930s6.9748.60%86%11%43%PASS-
1030s6.88460%86%11%43%PASS-
1130s5.9262.22.45%88%13%43%PASS-
1230s----%-%-%FAILan enabled performance or stability gate failed
1330s----%-%-%FAILan enabled performance or stability gate failed
1430s----%-%-%FAILan enabled performance or stability gate failed
1530s----%-%-%FAILan enabled performance or stability gate failed
1630s----%-%-%FAILan enabled performance or stability gate failed

5 FPS · boundary ≥15*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s5.2820.70%6%2%37%PASS-
230s5.03230%18%4%37%PASS-
330s5.0524.60%20%3%37%PASS-
430s5.0533.50%30%5%37%PASS-
530s4.9841.60%32%5%37%PASS-
630s5.0237.70%32%5%37%PASS-
730s4.9534.50%46%6%38%PASS-
830s547.90%56%6%38%PASS-
930s554.90%58%7%39%PASS-
1030s4.97640%60%16%40%PASS-
1130s4.9379.70%74%17%40%PASS-
1230s4.9873.20%80%18%40%PASS-
1330s4.9872.70%92%13%41%PASS-
1430s4.97112.20%92%22%42%PASS-
1530s4.63100.50.18%96%23%42%PASS-
1630s----%-%-%FAILan enabled performance or stability gate failed

Safety-helmet detector

24 FPS · boundary ≥3*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s24.1724.70%52%5%37%PASS-
230s23.8947.40%66%9%37%PASS-
330s23.6659.70%88%12%37%PASS-
430s1875.39.13%94%17%37%FAILaverage discard 9.13%
530s----%-%-%FAILan enabled performance or stability gate failed
630s----%-%-%FAILan enabled performance or stability gate failed
730s----%-%-%FAILan enabled performance or stability gate failed
830s----%-%-%FAILan enabled performance or stability gate failed

10 FPS · boundary ≥8*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s10.4526.20%16%5%41%PASS-
230s10.253.10%30%7%41%PASS-
330s10.0951.80%40%10%41%PASS-
430s10.1453.60%54%12%42%PASS-
530s10.0759.10%58%12%42%PASS-
630s9.9775.60%88%16%42%PASS-
730s9.8581.10%98%23%42%PASS-
830s8.5796.93.46%98%24%42%PASS-
930s----%-%-%FAILan enabled performance or stability gate failed
1030s----%-%-%FAILan enabled performance or stability gate failed
1130s----%-%-%FAILan enabled performance or stability gate failed
1230s----%-%-%FAILan enabled performance or stability gate failed
1330s----%-%-%FAILan enabled performance or stability gate failed
1430s----%-%-%FAILan enabled performance or stability gate failed
1530s----%-%-%FAILan enabled performance or stability gate failed
1630s----%-%-%FAILan enabled performance or stability gate failed

7 FPS · boundary ≥11*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s7.4526.80%12%4%42%PASS-
230s7.2262.40%24%6%42%PASS-
330s7.12650%30%9%42%PASS-
430s7.131.10%32%12%42%PASS-
530s7.0369.60%46%14%42%PASS-
630s767.10%60%18%42%PASS-
730s766.90%68%21%42%PASS-
830s761.60%78%24%42%PASS-
930s785.40%90%23%42%PASS-
1030s6.85121.80%100%24%43%PASS-
1130s6.24133.22.17%96%35%43%PASS-
1230s----%-%-%FAILan enabled performance or stability gate failed
1330s----%-%-%FAILan enabled performance or stability gate failed
1430s----%-%-%FAILan enabled performance or stability gate failed
1530s----%-%-%FAILan enabled performance or stability gate failed
1630s----%-%-%FAILan enabled performance or stability gate failed

5 FPS · boundary ≥15*

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s5.3624.60%10%2%41%PASS-
230s5.1245.10%14%4%41%PASS-
330s5.0734.20%26%9%41%PASS-
430s5.0529.80%26%12%40%PASS-
530s4.97330%38%15%40%PASS-
630s4.9748.60%40%17%41%PASS-
730s5.0253.80%46%20%42%PASS-
830s4.97430%54%23%42%PASS-
930s551.60%62%23%42%PASS-
1030s4.9761.90%80%26%43%PASS-
1130s4.93101.40%84%26%43%PASS-
1230s4.9597.20%88%29%43%PASS-
1330s4.95125.70%90%28%43%PASS-
1430s4.78173.80%100%35%43%PASS-
1530s4.22221.42.09%100%44%43%PASS-
1630s----%-%-%FAILan enabled performance or stability gate failed
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/report.zh-CN.html new file mode 100644 index 000000000..2770d6124 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/report.zh-CN.html @@ -0,0 +1 @@ +CV186X 单算法逐路报告

CV186X 单算法逐路报告

短时逐路阶梯证据;下一路若因任务绑定失败而阻断,不视为性能上限。

人员检测

24 FPS · 边界 ≥3*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s24.9318.80%42%3%35%通过-
230s24.1522.50%72%5%35%通过-
330s23.5246.60%84%7%35%通过-
430s18.68598.32%90%10%35%失败平均丢弃率 8.32%
530s----%-%-%失败an enabled performance or stability gate failed
630s----%-%-%失败an enabled performance or stability gate failed
730s----%-%-%失败an enabled performance or stability gate failed
830s----%-%-%失败an enabled performance or stability gate failed

10 FPS · 边界 ≥8*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s10.5522.70%10%2%41%通过-
230s10.2522.60%30%4%41%通过-
330s10.1125.20%46%6%41%通过-
430s10.1432.10%56%8%41%通过-
530s10.0340.80%64%7%41%通过-
630s10.0338.20%72%8%41%通过-
730s10.0251.50%94%8%42%通过-
830s8.5560.31.46%84%9%42%通过-
930s----%-%-%失败an enabled performance or stability gate failed
1030s----%-%-%失败an enabled performance or stability gate failed
1130s----%-%-%失败an enabled performance or stability gate failed
1230s----%-%-%失败an enabled performance or stability gate failed
1330s----%-%-%失败an enabled performance or stability gate failed
1430s----%-%-%失败an enabled performance or stability gate failed
1530s----%-%-%失败an enabled performance or stability gate failed
1630s----%-%-%失败an enabled performance or stability gate failed

7 FPS · 边界 ≥11*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s7.4522.50%14%2%42%通过-
230s7.1922.80%16%2%42%通过-
330s7.1432.10%34%6%42%通过-
430s7.1430.90%34%7%42%通过-
530s6.9826.40%44%7%42%通过-
630s6.9856.20%62%8%42%通过-
730s7.0334.90%62%9%42%通过-
830s735.30%66%9%43%通过-
930s6.9748.60%86%11%43%通过-
1030s6.88460%86%11%43%通过-
1130s5.9262.22.45%88%13%43%通过-
1230s----%-%-%失败an enabled performance or stability gate failed
1330s----%-%-%失败an enabled performance or stability gate failed
1430s----%-%-%失败an enabled performance or stability gate failed
1530s----%-%-%失败an enabled performance or stability gate failed
1630s----%-%-%失败an enabled performance or stability gate failed

5 FPS · 边界 ≥15*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s5.2820.70%6%2%37%通过-
230s5.03230%18%4%37%通过-
330s5.0524.60%20%3%37%通过-
430s5.0533.50%30%5%37%通过-
530s4.9841.60%32%5%37%通过-
630s5.0237.70%32%5%37%通过-
730s4.9534.50%46%6%38%通过-
830s547.90%56%6%38%通过-
930s554.90%58%7%39%通过-
1030s4.97640%60%16%40%通过-
1130s4.9379.70%74%17%40%通过-
1230s4.9873.20%80%18%40%通过-
1330s4.9872.70%92%13%41%通过-
1430s4.97112.20%92%22%42%通过-
1530s4.63100.50.18%96%23%42%通过-
1630s----%-%-%失败an enabled performance or stability gate failed

安全帽检测

24 FPS · 边界 ≥3*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s24.1724.70%52%5%37%通过-
230s23.8947.40%66%9%37%通过-
330s23.6659.70%88%12%37%通过-
430s1875.39.13%94%17%37%失败平均丢弃率 9.13%
530s----%-%-%失败an enabled performance or stability gate failed
630s----%-%-%失败an enabled performance or stability gate failed
730s----%-%-%失败an enabled performance or stability gate failed
830s----%-%-%失败an enabled performance or stability gate failed

10 FPS · 边界 ≥8*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s10.4526.20%16%5%41%通过-
230s10.253.10%30%7%41%通过-
330s10.0951.80%40%10%41%通过-
430s10.1453.60%54%12%42%通过-
530s10.0759.10%58%12%42%通过-
630s9.9775.60%88%16%42%通过-
730s9.8581.10%98%23%42%通过-
830s8.5796.93.46%98%24%42%通过-
930s----%-%-%失败an enabled performance or stability gate failed
1030s----%-%-%失败an enabled performance or stability gate failed
1130s----%-%-%失败an enabled performance or stability gate failed
1230s----%-%-%失败an enabled performance or stability gate failed
1330s----%-%-%失败an enabled performance or stability gate failed
1430s----%-%-%失败an enabled performance or stability gate failed
1530s----%-%-%失败an enabled performance or stability gate failed
1630s----%-%-%失败an enabled performance or stability gate failed

7 FPS · 边界 ≥11*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s7.4526.80%12%4%42%通过-
230s7.2262.40%24%6%42%通过-
330s7.12650%30%9%42%通过-
430s7.131.10%32%12%42%通过-
530s7.0369.60%46%14%42%通过-
630s767.10%60%18%42%通过-
730s766.90%68%21%42%通过-
830s761.60%78%24%42%通过-
930s785.40%90%23%42%通过-
1030s6.85121.80%100%24%43%通过-
1130s6.24133.22.17%96%35%43%通过-
1230s----%-%-%失败an enabled performance or stability gate failed
1330s----%-%-%失败an enabled performance or stability gate failed
1430s----%-%-%失败an enabled performance or stability gate failed
1530s----%-%-%失败an enabled performance or stability gate failed
1630s----%-%-%失败an enabled performance or stability gate failed

5 FPS · 边界 ≥15*

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s5.3624.60%10%2%41%通过-
230s5.1245.10%14%4%41%通过-
330s5.0734.20%26%9%41%通过-
430s5.0529.80%26%12%40%通过-
530s4.97330%38%15%40%通过-
630s4.9748.60%40%17%41%通过-
730s5.0253.80%46%20%42%通过-
830s4.97430%54%23%42%通过-
930s551.60%62%23%42%通过-
1030s4.9761.90%80%26%43%通过-
1130s4.93101.40%84%26%43%通过-
1230s4.9597.20%88%29%43%通过-
1330s4.95125.70%90%28%43%通过-
1430s4.78173.80%100%35%43%通过-
1530s4.22221.42.09%100%44%43%通过-
1630s----%-%-%失败an enabled performance or stability gate failed
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/summary.json new file mode 100644 index 000000000..6695ac668 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/summary.json @@ -0,0 +1,2643 @@ +{ + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "binding-blocked", + "display": "≥15*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.28, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7 + } + ], + "minimumProcessingFps": 5.28, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 3, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 16, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": 45, + "cpuPeakPercent": 17, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 48, + "cpuPeakPercent": 18, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 13, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 22, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.63, + "minimumFpsRatio": 0.925, + "missingRate": 0, + "averageDiscardRate": 0.0018, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5 + } + ], + "minimumProcessingFps": 4.63, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5, + "averageDiscardRate": 0.0018, + "maximumChannelDiscardRate": 0.0048, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 67, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 11, + "firstFailedChannels": 12, + "boundaryKind": "binding-blocked", + "display": "≥11*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.19, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8 + } + ], + "minimumProcessingFps": 7.19, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 0.845, + "missingRate": 0, + "averageDiscardRate": 0.0245, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2 + } + ], + "minimumProcessingFps": 5.92, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2, + "averageDiscardRate": 0.0245, + "maximumChannelDiscardRate": 0.0519, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 13, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 8, + "firstFailedChannels": 9, + "boundaryKind": "binding-blocked", + "display": "≥8*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.55, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7 + } + ], + "minimumProcessingFps": 10.55, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.25, + "minimumFpsRatio": 1.025, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6 + } + ], + "minimumProcessingFps": 10.25, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.11, + "minimumFpsRatio": 1.011, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2 + } + ], + "minimumProcessingFps": 10.11, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.55, + "minimumFpsRatio": 0.855, + "missingRate": 0, + "averageDiscardRate": 0.0146, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3 + } + ], + "minimumProcessingFps": 8.55, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3, + "averageDiscardRate": 0.0146, + "maximumChannelDiscardRate": 0.0262, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 3, + "firstFailedChannels": 4, + "boundaryKind": "binding-blocked", + "display": "≥3*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.93, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8 + } + ], + "minimumProcessingFps": 24.93, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 3, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.15, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 24.15, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.52, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 23.52, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 7, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 18.68, + "minimumFpsRatio": 0.778, + "missingRate": 0, + "averageDiscardRate": 0.0832, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59 + } + ], + "minimumProcessingFps": 18.68, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59, + "averageDiscardRate": 0.0832, + "maximumChannelDiscardRate": 0.1384, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 10, + "memoryPeakPercent": 35, + "failureReason": "average discard 8.32%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "binding-blocked", + "display": "≥15*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.36, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.36, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 15, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 17, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 20, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 29, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 28, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.22, + "minimumFpsRatio": 0.844, + "missingRate": 0, + "averageDiscardRate": 0.0209, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4 + } + ], + "minimumProcessingFps": 4.22, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4, + "averageDiscardRate": 0.0209, + "maximumChannelDiscardRate": 0.0521, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 82, + "cpuPeakPercent": 44, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 11, + "firstFailedChannels": 12, + "boundaryKind": "binding-blocked", + "display": "≥11*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 18, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 21, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.85, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8 + } + ], + "minimumProcessingFps": 6.85, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 24, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.24, + "minimumFpsRatio": 0.891, + "missingRate": 0, + "averageDiscardRate": 0.0217, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2 + } + ], + "minimumProcessingFps": 6.24, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2, + "averageDiscardRate": 0.0217, + "maximumChannelDiscardRate": 0.0447, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 71, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 8, + "firstFailedChannels": 9, + "boundaryKind": "binding-blocked", + "display": "≥8*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.45, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2 + } + ], + "minimumProcessingFps": 10.45, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.2, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1 + } + ], + "minimumProcessingFps": 10.2, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.09, + "minimumFpsRatio": 1.009, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 10.09, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 10, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0346, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9, + "averageDiscardRate": 0.0346, + "maximumChannelDiscardRate": 0.0466, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 60, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 3, + "firstFailedChannels": 4, + "boundaryKind": "binding-blocked", + "display": "≥3*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.17, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7 + } + ], + "minimumProcessingFps": 24.17, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.89, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4 + } + ], + "minimumProcessingFps": 23.89, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 9, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.66, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7 + } + ], + "minimumProcessingFps": 23.66, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18, + "minimumFpsRatio": 0.75, + "missingRate": 0, + "averageDiscardRate": 0.0913, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3 + } + ], + "minimumProcessingFps": 18, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3, + "averageDiscardRate": 0.0913, + "maximumChannelDiscardRate": 0.145, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 17, + "memoryPeakPercent": 37, + "failureReason": "average discard 9.13%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/test.log b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/test.log new file mode 100644 index 000000000..829e985b6 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/single-detector/test.log @@ -0,0 +1,117 @@ +benchmark=cosmoedge-1.1-multistream +platform=CV186X +device=CV186X reference device +workload=single-detector +publication=release-evidence +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 +channels=9 hold=30s result=PASS avg_discard=0 +channels=10 hold=30s result=PASS avg_discard=0 +channels=11 hold=30s result=PASS avg_discard=0 +channels=12 hold=30s result=PASS avg_discard=0 +channels=13 hold=30s result=PASS avg_discard=0 +channels=14 hold=30s result=PASS avg_discard=0 +channels=15 hold=30s result=PASS avg_discard=0.0018 +channels=16 hold=30s result=FAIL avg_discard=null +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 +channels=9 hold=30s result=PASS avg_discard=0 +channels=10 hold=30s result=PASS avg_discard=0 +channels=11 hold=30s result=PASS avg_discard=0.0245 +channels=12 hold=30s result=FAIL avg_discard=null +channels=13 hold=30s result=FAIL avg_discard=null +channels=14 hold=30s result=FAIL avg_discard=null +channels=15 hold=30s result=FAIL avg_discard=null +channels=16 hold=30s result=FAIL avg_discard=null +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0.0146 +channels=9 hold=30s result=FAIL avg_discard=null +channels=10 hold=30s result=FAIL avg_discard=null +channels=11 hold=30s result=FAIL avg_discard=null +channels=12 hold=30s result=FAIL avg_discard=null +channels=13 hold=30s result=FAIL avg_discard=null +channels=14 hold=30s result=FAIL avg_discard=null +channels=15 hold=30s result=FAIL avg_discard=null +channels=16 hold=30s result=FAIL avg_discard=null +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=FAIL avg_discard=0.0832 +channels=5 hold=30s result=FAIL avg_discard=null +channels=6 hold=30s result=FAIL avg_discard=null +channels=7 hold=30s result=FAIL avg_discard=null +channels=8 hold=30s result=FAIL avg_discard=null +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 +channels=9 hold=30s result=PASS avg_discard=0 +channels=10 hold=30s result=PASS avg_discard=0 +channels=11 hold=30s result=PASS avg_discard=0 +channels=12 hold=30s result=PASS avg_discard=0 +channels=13 hold=30s result=PASS avg_discard=0 +channels=14 hold=30s result=PASS avg_discard=0 +channels=15 hold=30s result=PASS avg_discard=0.0209 +channels=16 hold=30s result=FAIL avg_discard=null +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 +channels=9 hold=30s result=PASS avg_discard=0 +channels=10 hold=30s result=PASS avg_discard=0 +channels=11 hold=30s result=PASS avg_discard=0.0217 +channels=12 hold=30s result=FAIL avg_discard=null +channels=13 hold=30s result=FAIL avg_discard=null +channels=14 hold=30s result=FAIL avg_discard=null +channels=15 hold=30s result=FAIL avg_discard=null +channels=16 hold=30s result=FAIL avg_discard=null +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0.0346 +channels=9 hold=30s result=FAIL avg_discard=null +channels=10 hold=30s result=FAIL avg_discard=null +channels=11 hold=30s result=FAIL avg_discard=null +channels=12 hold=30s result=FAIL avg_discard=null +channels=13 hold=30s result=FAIL avg_discard=null +channels=14 hold=30s result=FAIL avg_discard=null +channels=15 hold=30s result=FAIL avg_discard=null +channels=16 hold=30s result=FAIL avg_discard=null +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=FAIL avg_discard=0.0913 +channels=5 hold=30s result=FAIL avg_discard=null +channels=6 hold=30s result=FAIL avg_discard=null +channels=7 hold=30s result=FAIL avg_discard=null +channels=8 hold=30s result=FAIL avg_discard=null diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/summary.json new file mode 100644 index 000000000..62d6d6378 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/summary.json @@ -0,0 +1,3138 @@ +{ + "schemaVersion": 2, + "platformId": "cv186x", + "platform": "CV186X", + "device": "CV186X reference device", + "publicationStatus": "release-evidence", + "productInstalledVersion": "V1.1.0.0", + "releaseManifest": "../../release-manifest.json", + "environment": "../../environments/cv186x.json", + "models": "../../models/cv186x.json", + "dataset": "../../dataset/dataset-card.md", + "dualDetector": { + "schemaVersion": 2, + "workload": { + "publicId": "dual-detector", + "tasksPerChannel": 2, + "tasks": [ + "person-detector", + "safety-helmet-detector" + ], + "targetFpsPerTaskPerChannel": 5, + "input": "fixed local 1920x1080 H.264 24 FPS sample", + "previewLoad": false + }, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-11", + "recommendedProfile": { + "status": "pending repeat and soak validation", + "channels": null + }, + "observedBoundary": { + "highestVerifiedChannels": 8, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 30 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.31, + "minimumFpsRatio": 1.062, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 21.8 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.31, + "minimumFpsRatio": 1.062, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 24.9 + } + ], + "minimumProcessingFps": 5.31, + "maximumDetectorLatencyMs": 20.8, + "maximumCriticalPathLatencyMs": 24.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 22.3 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 25.4 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 25.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 23.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 29.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 19.6, + "maximumCriticalPathLatencyMs": 29.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 54 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 54, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 40.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 45.2 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 45.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 11, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 38.4 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 45.2 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 34.8, + "maximumCriticalPathLatencyMs": 45.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 12, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 59.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 67.9 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 55.8, + "maximumCriticalPathLatencyMs": 67.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 15, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 56.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 64.3 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 53, + "maximumCriticalPathLatencyMs": 64.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 19, + "memoryPeakPercent": 42, + "failureReason": null + } + ] + }, + "singleDetector": { + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "binding-blocked", + "display": "≥15*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.28, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7 + } + ], + "minimumProcessingFps": 5.28, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 3, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 16, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": 45, + "cpuPeakPercent": 17, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 48, + "cpuPeakPercent": 18, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 13, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 22, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.63, + "minimumFpsRatio": 0.925, + "missingRate": 0, + "averageDiscardRate": 0.0018, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5 + } + ], + "minimumProcessingFps": 4.63, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5, + "averageDiscardRate": 0.0018, + "maximumChannelDiscardRate": 0.0048, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 67, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 11, + "firstFailedChannels": 12, + "boundaryKind": "binding-blocked", + "display": "≥11*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.19, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8 + } + ], + "minimumProcessingFps": 7.19, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 0.845, + "missingRate": 0, + "averageDiscardRate": 0.0245, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2 + } + ], + "minimumProcessingFps": 5.92, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2, + "averageDiscardRate": 0.0245, + "maximumChannelDiscardRate": 0.0519, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 13, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 8, + "firstFailedChannels": 9, + "boundaryKind": "binding-blocked", + "display": "≥8*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.55, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7 + } + ], + "minimumProcessingFps": 10.55, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.25, + "minimumFpsRatio": 1.025, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6 + } + ], + "minimumProcessingFps": 10.25, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.11, + "minimumFpsRatio": 1.011, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2 + } + ], + "minimumProcessingFps": 10.11, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.55, + "minimumFpsRatio": 0.855, + "missingRate": 0, + "averageDiscardRate": 0.0146, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3 + } + ], + "minimumProcessingFps": 8.55, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3, + "averageDiscardRate": 0.0146, + "maximumChannelDiscardRate": 0.0262, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 3, + "firstFailedChannels": 4, + "boundaryKind": "binding-blocked", + "display": "≥3*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.93, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8 + } + ], + "minimumProcessingFps": 24.93, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 3, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.15, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 24.15, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.52, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 23.52, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 7, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 18.68, + "minimumFpsRatio": 0.778, + "missingRate": 0, + "averageDiscardRate": 0.0832, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59 + } + ], + "minimumProcessingFps": 18.68, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59, + "averageDiscardRate": 0.0832, + "maximumChannelDiscardRate": 0.1384, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 10, + "memoryPeakPercent": 35, + "failureReason": "average discard 8.32%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "binding-blocked", + "display": "≥15*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.36, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.36, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 15, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 17, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 20, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 29, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 28, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.22, + "minimumFpsRatio": 0.844, + "missingRate": 0, + "averageDiscardRate": 0.0209, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4 + } + ], + "minimumProcessingFps": 4.22, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4, + "averageDiscardRate": 0.0209, + "maximumChannelDiscardRate": 0.0521, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 82, + "cpuPeakPercent": 44, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 11, + "firstFailedChannels": 12, + "boundaryKind": "binding-blocked", + "display": "≥11*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 18, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 21, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.85, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8 + } + ], + "minimumProcessingFps": 6.85, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 24, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.24, + "minimumFpsRatio": 0.891, + "missingRate": 0, + "averageDiscardRate": 0.0217, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2 + } + ], + "minimumProcessingFps": 6.24, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2, + "averageDiscardRate": 0.0217, + "maximumChannelDiscardRate": 0.0447, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 71, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 8, + "firstFailedChannels": 9, + "boundaryKind": "binding-blocked", + "display": "≥8*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.45, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2 + } + ], + "minimumProcessingFps": 10.45, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.2, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1 + } + ], + "minimumProcessingFps": 10.2, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.09, + "minimumFpsRatio": 1.009, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 10.09, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 10, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0346, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9, + "averageDiscardRate": 0.0346, + "maximumChannelDiscardRate": 0.0466, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 60, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 3, + "firstFailedChannels": 4, + "boundaryKind": "binding-blocked", + "display": "≥3*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.17, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7 + } + ], + "minimumProcessingFps": 24.17, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.89, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4 + } + ], + "minimumProcessingFps": 23.89, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 9, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.66, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7 + } + ], + "minimumProcessingFps": 23.66, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18, + "minimumFpsRatio": 0.75, + "missingRate": 0, + "averageDiscardRate": 0.0913, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3 + } + ], + "minimumProcessingFps": 18, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3, + "averageDiscardRate": 0.0913, + "maximumChannelDiscardRate": 0.145, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 17, + "memoryPeakPercent": 37, + "failureReason": "average discard 9.13%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + } + ] + }, + "vlmObservation": { + "schemaVersion": 2, + "workload": { + "publicId": "vlm-observation", + "targetFpsPerChannel": 0.1, + "interpretation": "Experimental runtime observation; FPS is recorded but excluded from PASS/FAIL", + "counterSemantics": "device-per-channel" + }, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-11", + "observedBoundary": { + "highestNonFpsPassingChannels": 8, + "firstNonFpsStopChannels": null, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.12, + "fpsAchievementRatioObserved": 1.2, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 5, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 10, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 16, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 96, + "cpuPeakPercent": 15, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 82, + "cpuPeakPercent": 19, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 98, + "cpuPeakPercent": 21, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.08, + "fpsAchievementRatioObserved": 0.8, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 21, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + } + ] + } +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/test.log b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/test.log new file mode 100644 index 000000000..aac165653 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/test.log @@ -0,0 +1,4 @@ +benchmark=cosmoedge-1.1-multistream +platform=CV186X +device=CV186X reference device +publication=release-evidence diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/command.txt new file mode 100644 index 000000000..15b2cf578 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=cv186x +workload=vlm-observation +scenario=../../../scenarios/vlm-observation/scenario.public.yml +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/metrics.json new file mode 100644 index 000000000..6da55cb65 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/metrics.json @@ -0,0 +1,140 @@ +{ + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.12, + "fpsAchievementRatioObserved": 1.2, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 5, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 10, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 16, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 96, + "cpuPeakPercent": 15, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 82, + "cpuPeakPercent": 19, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 98, + "cpuPeakPercent": 21, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.08, + "fpsAchievementRatioObserved": 0.8, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 21, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/report.html b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/report.html new file mode 100644 index 000000000..b68058404 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/report.html @@ -0,0 +1 @@ +CV186X Experimental VLM runtime observation

CV186X Experimental VLM runtime observation

Requested rate: 0.1 FPS per channel. FPS is observational only and is not a pass/fail gate; this report does not claim validated VLM capacity.

ChannelsHoldTarget FPS/chEquivalent FPS/chAvg discardAcceleratorCPUMemoryNon-FPS gateStop reason
1120s0.10.120%0%5%42%PASS-
2120s0.10.10%0%10%42%PASS-
3120s0.10.10%0%14%42%PASS-
4120s0.10.10%84%16%43%PASS-
5120s0.10.060%96%15%43%PASS-
6120s0.10.060%82%19%42%PASS-
7120s0.10.060%98%21%43%PASS-
8120s0.10.080%84%21%43%PASS-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/report.zh-CN.html new file mode 100644 index 000000000..94f8154de --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/report.zh-CN.html @@ -0,0 +1 @@ +CV186X VLM 实验运行观测

CV186X VLM 实验运行观测

目标为每路 0.1 FPS。FPS 仅作观测、不参与通过判定;本页不形成 VLM 正式容量结论。

路数保持目标 FPS/路等效 FPS/路平均丢弃率加速器CPU内存非 FPS 门禁停止原因
1120s0.10.120%0%5%42%通过-
2120s0.10.10%0%10%42%通过-
3120s0.10.10%0%14%42%通过-
4120s0.10.10%84%16%43%通过-
5120s0.10.060%96%15%43%通过-
6120s0.10.060%82%19%42%通过-
7120s0.10.060%98%21%43%通过-
8120s0.10.080%84%21%43%通过-
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/summary.json new file mode 100644 index 000000000..022e6524c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/summary.json @@ -0,0 +1,153 @@ +{ + "schemaVersion": 2, + "workload": { + "publicId": "vlm-observation", + "targetFpsPerChannel": 0.1, + "interpretation": "Experimental runtime observation; FPS is recorded but excluded from PASS/FAIL", + "counterSemantics": "device-per-channel" + }, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-11", + "observedBoundary": { + "highestNonFpsPassingChannels": 8, + "firstNonFpsStopChannels": null, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.12, + "fpsAchievementRatioObserved": 1.2, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 5, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 10, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 16, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 96, + "cpuPeakPercent": 15, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 82, + "cpuPeakPercent": 19, + "memoryPeakPercent": 42, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.06, + "fpsAchievementRatioObserved": 0.6, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 98, + "cpuPeakPercent": 21, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.08, + "fpsAchievementRatioObserved": 0.8, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 84, + "cpuPeakPercent": 21, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/test.log b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/test.log new file mode 100644 index 000000000..07d2ebedf --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/cv186x/vlm-observation/test.log @@ -0,0 +1,13 @@ +benchmark=cosmoedge-1.1-multistream +platform=CV186X +device=CV186X reference device +workload=vlm-observation +publication=release-evidence +channels=1 hold=120s result=PASS avg_discard=0 +channels=2 hold=120s result=PASS avg_discard=0 +channels=3 hold=120s result=PASS avg_discard=0 +channels=4 hold=120s result=PASS avg_discard=0 +channels=5 hold=120s result=PASS avg_discard=0 +channels=6 hold=120s result=PASS avg_discard=0 +channels=7 hold=120s result=PASS avg_discard=0 +channels=8 hold=120s result=PASS avg_discard=0 diff --git a/docs/benchmarks/scenario-bench/v1.1/results/index.json b/docs/benchmarks/scenario-bench/v1.1/results/index.json new file mode 100644 index 000000000..9bf0e13d7 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/index.json @@ -0,0 +1,31 @@ +{ + "schemaVersion": 2, + "benchmark": "CosmoEdge 1.1 Multi-Platform Video Analytics Benchmark", + "publicationStatus": "release-evidence", + "manifest": "../release-manifest.json", + "generatedAt": "2026-08-13T11:57:35+08:00", + "primaryClaim": "short-run concurrent dual-detector workload; not a recommended profile", + "platforms": [ + { + "platform": "BM1688", + "overview": "bm1688/summary.json", + "dualDetector": "bm1688/dual-detector/summary.json", + "singleDetector": "bm1688/single-detector/summary.json", + "vlmObservation": "bm1688/vlm-observation/summary.json" + }, + { + "platform": "CV186X", + "overview": "cv186x/summary.json", + "dualDetector": "cv186x/dual-detector/summary.json", + "singleDetector": "cv186x/single-detector/summary.json", + "vlmObservation": "cv186x/vlm-observation/summary.json" + }, + { + "platform": "RK3576", + "overview": "rk3576/summary.json", + "dualDetector": "rk3576/dual-detector/summary.json", + "singleDetector": "rk3576/single-detector/summary.json", + "vlmObservation": "rk3576/vlm-observation/summary.json" + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/command.txt new file mode 100644 index 000000000..2a030baed --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/command.txt @@ -0,0 +1 @@ +See dual-detector/, single-detector/, and vlm-observation/ for workload-specific reproduction descriptors. diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/command.txt new file mode 100644 index 000000000..eeae17ccc --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=rk3576 +workload=dual-detector +scenario=../../../scenarios/dual-detector/scenario.public.yml +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/metrics.json new file mode 100644 index 000000000..1d2d98b4a --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/metrics.json @@ -0,0 +1,308 @@ +{ + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 1.185, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 53.4 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 138.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 138.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 15, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.48, + "minimumFpsRatio": 1.097, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 132 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.34, + "minimumFpsRatio": 1.069, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 198.3 + } + ], + "minimumProcessingFps": 5.34, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 198.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 19, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.3, + "minimumFpsRatio": 1.059, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 45.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 100.1 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 100.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.25, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 47.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.029, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 99.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 99.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.17, + "minimumFpsRatio": 1.034, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 45.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 89.6 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 89.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.17, + "minimumFpsRatio": 1.034, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 41.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 94 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 94, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 39, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 43.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 84.9 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 84.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 42.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 90.1 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 90.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 30, + "failureReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/report.html b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/report.html new file mode 100644 index 000000000..e5375c8e5 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/report.html @@ -0,0 +1 @@ +RK3576 dual-detector attachment

RK3576 dual-detector attachment

Two concurrent detector tasks at 5 FPS per channel. Highest configured point: ≥ 8 channels. Recommended profile remains pending.

ChannelsHoldPerson min FPSHelmet min FPSCritical path msAvg discardAcceleratorCPUMemoryResult
115s5.925.69138.10%14%15%23%PASS
215s5.485.34198.30%19%21%24%PASS
315s5.35.2100.10%21%23%25%PASS
415s5.255.1499.10%27%27%26%PASS
515s5.175.189.60%31%33%27%PASS
615s5.175.08940%34%39%27%PASS
715s5.155.0884.90%37%43%28%PASS
815s5.155.1190.10%41%47%30%PASS
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/report.zh-CN.html new file mode 100644 index 000000000..f62b21889 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/report.zh-CN.html @@ -0,0 +1 @@ +RK3576 双算法逐路报告

RK3576 双算法逐路报告

每路并发人员检测与安全帽检测,目标均为 5 FPS;最高已配置并通过点为 ≥ 8 路,推荐配置仍待确认。

路数保持人员检测最低 FPS安全帽最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果
115s5.925.69138.10%14%15%23%通过
215s5.485.34198.30%19%21%24%通过
315s5.35.2100.10%21%23%25%通过
415s5.255.1499.10%27%27%26%通过
515s5.175.189.60%31%33%27%通过
615s5.175.08940%34%39%27%通过
715s5.155.0884.90%37%43%28%通过
815s5.155.1190.10%41%47%30%通过
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/summary.json new file mode 100644 index 000000000..48b10cc5d --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/summary.json @@ -0,0 +1,330 @@ +{ + "schemaVersion": 2, + "workload": { + "publicId": "dual-detector", + "tasksPerChannel": 2, + "tasks": [ + "person-detector", + "safety-helmet-detector" + ], + "targetFpsPerTaskPerChannel": 5, + "input": "fixed local 1920x1080 H.264 24 FPS sample", + "previewLoad": false + }, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "evidenceDate": "2026-08-11", + "recommendedProfile": { + "status": "pending repeat and soak validation", + "channels": null + }, + "observedBoundary": { + "highestVerifiedChannels": 8, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 15 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 1.185, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 53.4 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 138.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 138.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 15, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.48, + "minimumFpsRatio": 1.097, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 132 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.34, + "minimumFpsRatio": 1.069, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 198.3 + } + ], + "minimumProcessingFps": 5.34, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 198.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 19, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.3, + "minimumFpsRatio": 1.059, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 45.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 100.1 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 100.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.25, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 47.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.029, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 99.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 99.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.17, + "minimumFpsRatio": 1.034, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 45.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 89.6 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 89.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.17, + "minimumFpsRatio": 1.034, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 41.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 94 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 94, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 39, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 43.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 84.9 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 84.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 42.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 90.1 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 90.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 30, + "failureReason": null + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/test.log b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/test.log new file mode 100644 index 000000000..22e72351c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/dual-detector/test.log @@ -0,0 +1,13 @@ +benchmark=cosmoedge-1.1-multistream +platform=RK3576 +device=RK3576 EVB +workload=dual-detector +publication=release-evidence +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/environment.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/environment.json new file mode 100644 index 000000000..2bcf51f30 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/environment.json @@ -0,0 +1,32 @@ +{ + "schemaVersion": 1, + "platform": "RK3576", + "deviceDescription": "RK3576 EVB", + "boardModel": "Rockchip RK3576 EVB1 V10 Board", + "memory": { + "sharedSystemMiB": 7917, + "memoryDomain": "shared-system" + }, + "storage": { + "usedGB": 11.56, + "availableGB": 2.13, + "note": "values are device-reported decimal GB at capture time" + }, + "os": "Linux distribution not exposed by the read-only device API", + "architecture": "aarch64 (inferred from RK3576 target; verify from the final package environment)", + "bsp": "BSP package identity is not published in this benchmark", + "runtime": { + "inference": "RKNN runtime version not exposed by the read-only device API", + "driver": "RKNN driver version not exposed by the read-only device API", + "rga": "version not exposed; runtime telemetry confirms RGA path", + "mpp": "version not exposed; runtime telemetry confirms Rockchip MPP VPU", + "decoder": "rockchip-mpp-vpu / copy-out I420", + "encoder": "rockchip-mpp / copy-first stride-aligned I420" + }, + "cosmoEdgeInstalledVersion": "V1.1.0.0", + "releaseSourceCommit": "209bc2b52849864a15bdad91beb61f5bc982c17f", + "releaseSourceTree": "f64a98bce05b9ee8dc64dda8e56ad50f9d15687f", + "packageSha256": null, + "packageBinding": "package bytes unavailable; evidence is bound to the installed V1.1.0.0 runtime, captured environment and model identities, not to a package digest", + "capturedAt": "2026-08-12T16:10:00+08:00" +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/metrics.json new file mode 100644 index 000000000..8723b1e8d --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/metrics.json @@ -0,0 +1,3586 @@ +{ + "schemaVersion": 2, + "dualDetector": { + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 1.185, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 53.4 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 138.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 138.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 15, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.48, + "minimumFpsRatio": 1.097, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 132 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.34, + "minimumFpsRatio": 1.069, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 198.3 + } + ], + "minimumProcessingFps": 5.34, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 198.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 19, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.3, + "minimumFpsRatio": 1.059, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 45.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 100.1 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 100.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.25, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 47.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.029, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 99.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 99.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.17, + "minimumFpsRatio": 1.034, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 45.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 89.6 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 89.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.17, + "minimumFpsRatio": 1.034, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 41.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 94 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 94, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 39, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 43.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 84.9 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 84.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 42.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 90.1 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 90.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 30, + "failureReason": null + } + ] + }, + "singleDetector": { + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0.0482, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1, + "averageDiscardRate": 0.0482, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 11, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.33, + "minimumFpsRatio": 1.067, + "missingRate": 0, + "averageDiscardRate": 0.0391, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6 + } + ], + "minimumProcessingFps": 5.33, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6, + "averageDiscardRate": 0.0391, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.049, + "missingRate": 0, + "averageDiscardRate": 0.0481, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9, + "averageDiscardRate": 0.0481, + "maximumChannelDiscardRate": 0.0747, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 30, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 41, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 65, + "memoryPeakPercent": 36, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.31, + "minimumFpsRatio": 1.044, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3 + } + ], + "minimumProcessingFps": 7.31, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 13, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 23, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.2, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9 + } + ], + "minimumProcessingFps": 7.2, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.17, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3 + } + ], + "minimumProcessingFps": 7.17, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 37, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 51, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 67, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 75, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.69, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0.0269, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240 + } + ], + "minimumProcessingFps": 6.69, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240, + "averageDiscardRate": 0.0269, + "maximumChannelDiscardRate": 0.2269, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 74, + "failureReason": "critical-path latency 240 ms" + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.86, + "minimumFpsRatio": 1.086, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5 + } + ], + "minimumProcessingFps": 10.86, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.41, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7 + } + ], + "minimumProcessingFps": 10.41, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 25, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 22, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.27, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2 + } + ], + "minimumProcessingFps": 10.27, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.19, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 10.19, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.18, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 10.18, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 87, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.29, + "minimumFpsRatio": 0.829, + "missingRate": 0, + "averageDiscardRate": 0.0154, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8 + } + ], + "minimumProcessingFps": 8.29, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8, + "averageDiscardRate": 0.0154, + "maximumChannelDiscardRate": 0.1849, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0604, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3, + "averageDiscardRate": 0.0604, + "maximumChannelDiscardRate": 0.246, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 63, + "failureReason": "average discard 6.04%" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.07, + "minimumFpsRatio": 0.807, + "missingRate": 0, + "averageDiscardRate": 0.1327, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1 + } + ], + "minimumProcessingFps": 8.07, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1, + "averageDiscardRate": 0.1327, + "maximumChannelDiscardRate": 0.2667, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 67, + "failureReason": "average discard 13.27%" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.4, + "minimumFpsRatio": 0.74, + "missingRate": 0, + "averageDiscardRate": 0.2054, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7 + } + ], + "minimumProcessingFps": 7.4, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7, + "averageDiscardRate": 0.2054, + "maximumChannelDiscardRate": 0.2914, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 70, + "failureReason": "average discard 20.54%" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 0.707, + "missingRate": 0, + "averageDiscardRate": 0.2669, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1, + "averageDiscardRate": 0.2669, + "maximumChannelDiscardRate": 0.3152, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 74, + "failureReason": "average discard 26.69%" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 26, + "minimumFpsRatio": 1.083, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 26, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 18, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.72, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2 + } + ], + "minimumProcessingFps": 24.72, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 19, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.48, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.48, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 53, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 36, + "memoryPeakPercent": 20, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.36, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5 + } + ], + "minimumProcessingFps": 24.36, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 51, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.34, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5 + } + ], + "minimumProcessingFps": 24.34, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 66, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 20.43, + "minimumFpsRatio": 0.851, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5 + } + ], + "minimumProcessingFps": 20.43, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 84, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 17.63, + "minimumFpsRatio": 0.734, + "missingRate": 0, + "averageDiscardRate": 0.0141, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5 + } + ], + "minimumProcessingFps": 17.63, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5, + "averageDiscardRate": 0.0141, + "maximumChannelDiscardRate": 0.0397, + "acceleratorPeakPercent": 85, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 41, + "failureReason": "processing-FPS gate failed (73.4%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0378, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6, + "averageDiscardRate": 0.0378, + "maximumChannelDiscardRate": 0.0811, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 90, + "memoryPeakPercent": 45, + "failureReason": "processing-FPS gate failed (66.7%)" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.023, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 49, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 57, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 70, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 77, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.957, + "missingRate": 0, + "averageDiscardRate": 0.0283, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2, + "averageDiscardRate": 0.0283, + "maximumChannelDiscardRate": 0.1038, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 76, + "failureReason": "critical-path latency 601.2 ms" + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.08, + "minimumFpsRatio": 1.012, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9 + } + ], + "minimumProcessingFps": 7.08, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.9, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8 + } + ], + "minimumProcessingFps": 6.9, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 29, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.06, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.06, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 68, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 71, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 73, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 93, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.39, + "minimumFpsRatio": 0.913, + "missingRate": 0, + "averageDiscardRate": 0.025, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9 + } + ], + "minimumProcessingFps": 6.39, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9, + "averageDiscardRate": 0.025, + "maximumChannelDiscardRate": 0.097, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 61, + "failureReason": "critical-path latency 329.9 ms" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.15, + "minimumFpsRatio": 0.879, + "missingRate": 0, + "averageDiscardRate": 0.1289, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8 + } + ], + "minimumProcessingFps": 6.15, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8, + "averageDiscardRate": 0.1289, + "maximumChannelDiscardRate": 0.2873, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 70, + "failureReason": "average discard 12.89%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.14, + "minimumFpsRatio": 0.877, + "missingRate": 0, + "averageDiscardRate": 0.2354, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2 + } + ], + "minimumProcessingFps": 6.14, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2, + "averageDiscardRate": 0.2354, + "maximumChannelDiscardRate": 0.3611, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 74, + "failureReason": "average discard 23.54%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 5.93, + "minimumFpsRatio": 0.847, + "missingRate": 0, + "averageDiscardRate": 0.2928, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8 + } + ], + "minimumProcessingFps": 5.93, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8, + "averageDiscardRate": 0.2928, + "maximumChannelDiscardRate": 0.3552, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 79, + "failureReason": "average discard 29.28%" + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.24, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2 + } + ], + "minimumProcessingFps": 10.24, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.08, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3 + } + ], + "minimumProcessingFps": 10.08, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 40, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 47, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 46, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.1, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4 + } + ], + "minimumProcessingFps": 10.1, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 62, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.06, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3 + } + ], + "minimumProcessingFps": 10.06, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 69, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 71, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.94, + "minimumFpsRatio": 0.894, + "missingRate": 0, + "averageDiscardRate": 0.007, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5 + } + ], + "minimumProcessingFps": 8.94, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5, + "averageDiscardRate": 0.007, + "maximumChannelDiscardRate": 0.0303, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 55, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.02, + "minimumFpsRatio": 0.902, + "missingRate": 0, + "averageDiscardRate": 0.1126, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6 + } + ], + "minimumProcessingFps": 9.02, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6, + "averageDiscardRate": 0.1126, + "maximumChannelDiscardRate": 0.1859, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": "average discard 11.26%" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.83, + "minimumFpsRatio": 0.883, + "missingRate": 0, + "averageDiscardRate": 0.2311, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5 + } + ], + "minimumProcessingFps": 8.83, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5, + "averageDiscardRate": 0.2311, + "maximumChannelDiscardRate": 0.2766, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 63, + "failureReason": "average discard 23.11%" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.14, + "minimumFpsRatio": 0.814, + "missingRate": 0, + "averageDiscardRate": 0.2846, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6 + } + ], + "minimumProcessingFps": 8.14, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6, + "averageDiscardRate": 0.2846, + "maximumChannelDiscardRate": 0.301, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 67, + "failureReason": "average discard 28.46%" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 7.41, + "minimumFpsRatio": 0.741, + "missingRate": 0, + "averageDiscardRate": 0.3041, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3 + } + ], + "minimumProcessingFps": 7.41, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3, + "averageDiscardRate": 0.3041, + "maximumChannelDiscardRate": 0.3172, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 72, + "failureReason": "average discard 30.41%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.76, + "minimumFpsRatio": 0.676, + "missingRate": 0, + "averageDiscardRate": 0.3202, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7 + } + ], + "minimumProcessingFps": 6.76, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7, + "averageDiscardRate": 0.3202, + "maximumChannelDiscardRate": 0.3321, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 75, + "failureReason": "average discard 32.02%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.3, + "minimumFpsRatio": 0.63, + "missingRate": 0, + "averageDiscardRate": 0.3395, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6 + } + ], + "minimumProcessingFps": 6.3, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6, + "averageDiscardRate": 0.3395, + "maximumChannelDiscardRate": 0.3516, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 78, + "failureReason": "average discard 33.95%" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.38, + "minimumFpsRatio": 1.099, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3 + } + ], + "minimumProcessingFps": 26.38, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 25.11, + "minimumFpsRatio": 1.046, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3 + } + ], + "minimumProcessingFps": 25.11, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 35, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.68, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1 + } + ], + "minimumProcessingFps": 24.68, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.44, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6 + } + ], + "minimumProcessingFps": 24.44, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22.43, + "minimumFpsRatio": 0.935, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2 + } + ], + "minimumProcessingFps": 22.43, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 83, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 19, + "minimumFpsRatio": 0.792, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7 + } + ], + "minimumProcessingFps": 19, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 89, + "memoryPeakPercent": 40, + "failureReason": "processing-FPS gate failed (79.2%)" + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0376, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4, + "averageDiscardRate": 0.0376, + "maximumChannelDiscardRate": 0.0679, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (66.7%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 13.79, + "minimumFpsRatio": 0.574, + "missingRate": 0, + "averageDiscardRate": 0.0754, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133 + } + ], + "minimumProcessingFps": 13.79, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133, + "averageDiscardRate": 0.0754, + "maximumChannelDiscardRate": 0.0958, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 47, + "failureReason": "average discard 7.54%" + } + ] + } + } + } + ] + }, + "vlmObservation": { + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.12, + "fpsAchievementRatioObserved": 1.2, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 22, + "memoryPeakPercent": 44, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.116, + "fpsAchievementRatioObserved": 1.16, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 7, + "cpuPeakPercent": 32, + "memoryPeakPercent": 44, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.115, + "fpsAchievementRatioObserved": 1.15, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 30, + "cpuPeakPercent": 43, + "memoryPeakPercent": 45, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.091, + "fpsAchievementRatioObserved": 0.91, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 32, + "cpuPeakPercent": 46, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.076, + "fpsAchievementRatioObserved": 0.76, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 31, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.063, + "fpsAchievementRatioObserved": 0.63, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 32, + "cpuPeakPercent": 46, + "memoryPeakPercent": 50, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.057, + "fpsAchievementRatioObserved": 0.57, + "fpsGateEnabled": false, + "averageDiscardRate": 0.2275, + "maximumChannelDiscardRate": 0.3033, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 30, + "cpuPeakPercent": 45, + "memoryPeakPercent": 52, + "nonFpsGateResult": "STOP", + "stopReason": "average discard 22.75%" + } + ] + } +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/report.html b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/report.html new file mode 100644 index 000000000..f80ad8a7f --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/report.html @@ -0,0 +1 @@ +RK3576 benchmark attachments

RK3576 benchmark attachments

RK3576 EVB · CosmoEdge 1.1 release-candidate evidence

These are sanitized short-run observations. No recommended profile is claimed.

Single-detector matrix

Workload24 FPS10 FPS7 FPS5 FPS
Person detector61215≥16
Safety-helmet detector5101215

Dual-detector steps

ChannelsHoldPerson min FPSHelmet min FPSCritical path msAvg discardAcceleratorCPUMemoryResult
115s5.925.69138.10%14%15%23%PASS
215s5.485.34198.30%19%21%24%PASS
315s5.35.2100.10%21%23%25%PASS
415s5.255.1499.10%27%27%26%PASS
515s5.175.189.60%31%33%27%PASS
615s5.175.08940%34%39%27%PASS
715s5.155.0884.90%37%43%28%PASS
815s5.155.1190.10%41%47%30%PASS

Experimental VLM runtime observation

FPS is recorded but excluded from PASS/FAIL. “PASS” below means non-FPS gates only.

ChannelsHoldTarget FPS/chEquivalent FPS/chAvg discardAcceleratorCPUMemoryNon-FPS gateStop reason
1120s0.10.10%0%3%43%PASS-
2120s0.10.120%0%22%44%PASS-
3120s0.10.1160%7%32%44%PASS-
4120s0.10.1150%30%43%45%PASS-
5120s0.10.0910%32%46%46%PASS-
6120s0.10.0760%31%47%46%PASS-
7120s0.10.0630%32%46%50%PASS-
8120s0.10.05722.75%30%45%52%STOPaverage discard 22.75%
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/report.zh-CN.html new file mode 100644 index 000000000..092db8da4 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/report.zh-CN.html @@ -0,0 +1 @@ +RK3576 压测附件总览

RK3576 压测附件总览

RK3576 EVB · CosmoEdge 1.1 待发布证据

以下为脱敏后的短时阶梯观测,不形成官方推荐配置。

单算法容量矩阵

工作负载24 FPS10 FPS7 FPS5 FPS
人员检测61215≥16
安全帽检测5101215

双算法逐路数据

路数保持人员检测最低 FPS安全帽最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果
115s5.925.69138.10%14%15%23%通过
215s5.485.34198.30%19%21%24%通过
315s5.35.2100.10%21%23%25%通过
415s5.255.1499.10%27%27%26%通过
515s5.175.189.60%31%33%27%通过
615s5.175.08940%34%39%27%通过
715s5.155.0884.90%37%43%28%通过
815s5.155.1190.10%41%47%30%通过

实验结果:VLM 运行观测

FPS 仅记录、不参与通过/失败判定;表中“通过”只表示非 FPS 门禁通过。

路数保持目标 FPS/路等效 FPS/路平均丢弃率加速器CPU内存非 FPS 门禁停止原因
1120s0.10.10%0%3%43%通过-
2120s0.10.120%0%22%44%通过-
3120s0.10.1160%7%32%44%通过-
4120s0.10.1150%30%43%45%通过-
5120s0.10.0910%32%46%46%通过-
6120s0.10.0760%31%47%46%通过-
7120s0.10.0630%32%46%50%通过-
8120s0.10.05722.75%30%45%52%停止平均丢弃率 22.75%
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/command.txt new file mode 100644 index 000000000..c8837ae17 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=rk3576 +workload=single-detector +scenario=../../../scenarios/single-detector/ +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/metrics.json new file mode 100644 index 000000000..3155654b9 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/metrics.json @@ -0,0 +1,3135 @@ +{ + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0.0482, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1, + "averageDiscardRate": 0.0482, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 11, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.33, + "minimumFpsRatio": 1.067, + "missingRate": 0, + "averageDiscardRate": 0.0391, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6 + } + ], + "minimumProcessingFps": 5.33, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6, + "averageDiscardRate": 0.0391, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.049, + "missingRate": 0, + "averageDiscardRate": 0.0481, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9, + "averageDiscardRate": 0.0481, + "maximumChannelDiscardRate": 0.0747, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 30, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 41, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 65, + "memoryPeakPercent": 36, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.31, + "minimumFpsRatio": 1.044, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3 + } + ], + "minimumProcessingFps": 7.31, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 13, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 23, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.2, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9 + } + ], + "minimumProcessingFps": 7.2, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.17, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3 + } + ], + "minimumProcessingFps": 7.17, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 37, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 51, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 67, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 75, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.69, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0.0269, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240 + } + ], + "minimumProcessingFps": 6.69, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240, + "averageDiscardRate": 0.0269, + "maximumChannelDiscardRate": 0.2269, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 74, + "failureReason": "critical-path latency 240 ms" + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.86, + "minimumFpsRatio": 1.086, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5 + } + ], + "minimumProcessingFps": 10.86, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.41, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7 + } + ], + "minimumProcessingFps": 10.41, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 25, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 22, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.27, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2 + } + ], + "minimumProcessingFps": 10.27, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.19, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 10.19, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.18, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 10.18, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 87, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.29, + "minimumFpsRatio": 0.829, + "missingRate": 0, + "averageDiscardRate": 0.0154, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8 + } + ], + "minimumProcessingFps": 8.29, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8, + "averageDiscardRate": 0.0154, + "maximumChannelDiscardRate": 0.1849, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0604, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3, + "averageDiscardRate": 0.0604, + "maximumChannelDiscardRate": 0.246, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 63, + "failureReason": "average discard 6.04%" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.07, + "minimumFpsRatio": 0.807, + "missingRate": 0, + "averageDiscardRate": 0.1327, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1 + } + ], + "minimumProcessingFps": 8.07, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1, + "averageDiscardRate": 0.1327, + "maximumChannelDiscardRate": 0.2667, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 67, + "failureReason": "average discard 13.27%" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.4, + "minimumFpsRatio": 0.74, + "missingRate": 0, + "averageDiscardRate": 0.2054, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7 + } + ], + "minimumProcessingFps": 7.4, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7, + "averageDiscardRate": 0.2054, + "maximumChannelDiscardRate": 0.2914, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 70, + "failureReason": "average discard 20.54%" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 0.707, + "missingRate": 0, + "averageDiscardRate": 0.2669, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1, + "averageDiscardRate": 0.2669, + "maximumChannelDiscardRate": 0.3152, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 74, + "failureReason": "average discard 26.69%" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 26, + "minimumFpsRatio": 1.083, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 26, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 18, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.72, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2 + } + ], + "minimumProcessingFps": 24.72, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 19, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.48, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.48, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 53, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 36, + "memoryPeakPercent": 20, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.36, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5 + } + ], + "minimumProcessingFps": 24.36, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 51, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.34, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5 + } + ], + "minimumProcessingFps": 24.34, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 66, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 20.43, + "minimumFpsRatio": 0.851, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5 + } + ], + "minimumProcessingFps": 20.43, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 84, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 17.63, + "minimumFpsRatio": 0.734, + "missingRate": 0, + "averageDiscardRate": 0.0141, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5 + } + ], + "minimumProcessingFps": 17.63, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5, + "averageDiscardRate": 0.0141, + "maximumChannelDiscardRate": 0.0397, + "acceleratorPeakPercent": 85, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 41, + "failureReason": "processing-FPS gate failed (73.4%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0378, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6, + "averageDiscardRate": 0.0378, + "maximumChannelDiscardRate": 0.0811, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 90, + "memoryPeakPercent": 45, + "failureReason": "processing-FPS gate failed (66.7%)" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.023, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 49, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 57, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 70, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 77, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.957, + "missingRate": 0, + "averageDiscardRate": 0.0283, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2, + "averageDiscardRate": 0.0283, + "maximumChannelDiscardRate": 0.1038, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 76, + "failureReason": "critical-path latency 601.2 ms" + } + ] + }, + "7": { + "targetFps": 7, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.08, + "minimumFpsRatio": 1.012, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9 + } + ], + "minimumProcessingFps": 7.08, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.9, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8 + } + ], + "minimumProcessingFps": 6.9, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 29, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.06, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.06, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 68, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 71, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 73, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 93, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.39, + "minimumFpsRatio": 0.913, + "missingRate": 0, + "averageDiscardRate": 0.025, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9 + } + ], + "minimumProcessingFps": 6.39, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9, + "averageDiscardRate": 0.025, + "maximumChannelDiscardRate": 0.097, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 61, + "failureReason": "critical-path latency 329.9 ms" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.15, + "minimumFpsRatio": 0.879, + "missingRate": 0, + "averageDiscardRate": 0.1289, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8 + } + ], + "minimumProcessingFps": 6.15, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8, + "averageDiscardRate": 0.1289, + "maximumChannelDiscardRate": 0.2873, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 70, + "failureReason": "average discard 12.89%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.14, + "minimumFpsRatio": 0.877, + "missingRate": 0, + "averageDiscardRate": 0.2354, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2 + } + ], + "minimumProcessingFps": 6.14, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2, + "averageDiscardRate": 0.2354, + "maximumChannelDiscardRate": 0.3611, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 74, + "failureReason": "average discard 23.54%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 5.93, + "minimumFpsRatio": 0.847, + "missingRate": 0, + "averageDiscardRate": 0.2928, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8 + } + ], + "minimumProcessingFps": 5.93, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8, + "averageDiscardRate": 0.2928, + "maximumChannelDiscardRate": 0.3552, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 79, + "failureReason": "average discard 29.28%" + } + ] + }, + "10": { + "targetFps": 10, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.24, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2 + } + ], + "minimumProcessingFps": 10.24, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.08, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3 + } + ], + "minimumProcessingFps": 10.08, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 40, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 47, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 46, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.1, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4 + } + ], + "minimumProcessingFps": 10.1, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 62, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.06, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3 + } + ], + "minimumProcessingFps": 10.06, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 69, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 71, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.94, + "minimumFpsRatio": 0.894, + "missingRate": 0, + "averageDiscardRate": 0.007, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5 + } + ], + "minimumProcessingFps": 8.94, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5, + "averageDiscardRate": 0.007, + "maximumChannelDiscardRate": 0.0303, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 55, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.02, + "minimumFpsRatio": 0.902, + "missingRate": 0, + "averageDiscardRate": 0.1126, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6 + } + ], + "minimumProcessingFps": 9.02, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6, + "averageDiscardRate": 0.1126, + "maximumChannelDiscardRate": 0.1859, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": "average discard 11.26%" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.83, + "minimumFpsRatio": 0.883, + "missingRate": 0, + "averageDiscardRate": 0.2311, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5 + } + ], + "minimumProcessingFps": 8.83, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5, + "averageDiscardRate": 0.2311, + "maximumChannelDiscardRate": 0.2766, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 63, + "failureReason": "average discard 23.11%" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.14, + "minimumFpsRatio": 0.814, + "missingRate": 0, + "averageDiscardRate": 0.2846, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6 + } + ], + "minimumProcessingFps": 8.14, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6, + "averageDiscardRate": 0.2846, + "maximumChannelDiscardRate": 0.301, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 67, + "failureReason": "average discard 28.46%" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 7.41, + "minimumFpsRatio": 0.741, + "missingRate": 0, + "averageDiscardRate": 0.3041, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3 + } + ], + "minimumProcessingFps": 7.41, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3, + "averageDiscardRate": 0.3041, + "maximumChannelDiscardRate": 0.3172, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 72, + "failureReason": "average discard 30.41%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.76, + "minimumFpsRatio": 0.676, + "missingRate": 0, + "averageDiscardRate": 0.3202, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7 + } + ], + "minimumProcessingFps": 6.76, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7, + "averageDiscardRate": 0.3202, + "maximumChannelDiscardRate": 0.3321, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 75, + "failureReason": "average discard 32.02%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.3, + "minimumFpsRatio": 0.63, + "missingRate": 0, + "averageDiscardRate": 0.3395, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6 + } + ], + "minimumProcessingFps": 6.3, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6, + "averageDiscardRate": 0.3395, + "maximumChannelDiscardRate": 0.3516, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 78, + "failureReason": "average discard 33.95%" + } + ] + }, + "24": { + "targetFps": 24, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.38, + "minimumFpsRatio": 1.099, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3 + } + ], + "minimumProcessingFps": 26.38, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 25.11, + "minimumFpsRatio": 1.046, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3 + } + ], + "minimumProcessingFps": 25.11, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 35, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.68, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1 + } + ], + "minimumProcessingFps": 24.68, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.44, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6 + } + ], + "minimumProcessingFps": 24.44, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22.43, + "minimumFpsRatio": 0.935, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2 + } + ], + "minimumProcessingFps": 22.43, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 83, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 19, + "minimumFpsRatio": 0.792, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7 + } + ], + "minimumProcessingFps": 19, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 89, + "memoryPeakPercent": 40, + "failureReason": "processing-FPS gate failed (79.2%)" + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0376, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4, + "averageDiscardRate": 0.0376, + "maximumChannelDiscardRate": 0.0679, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (66.7%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 13.79, + "minimumFpsRatio": 0.574, + "missingRate": 0, + "averageDiscardRate": 0.0754, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133 + } + ], + "minimumProcessingFps": 13.79, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133, + "averageDiscardRate": 0.0754, + "maximumChannelDiscardRate": 0.0958, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 47, + "failureReason": "average discard 7.54%" + } + ] + } + } + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/report.html b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/report.html new file mode 100644 index 000000000..8368ea858 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/report.html @@ -0,0 +1 @@ +RK3576 single-detector attachment

RK3576 single-detector attachment

Short-run staircase evidence. A binding-blocked next step is not a performance limit.

Person detector

24 FPS · boundary 6

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s2641.60%32%14%18%PASS-
215s24.7241.20%43%25%19%PASS-
315s24.4837.60%53%36%20%PASS-
415s24.3644.50%66%51%21%PASS-
515s24.3450.50%78%66%23%PASS-
615s20.4371.50%80%84%38%PASS-
715s17.6380.51.41%85%88%41%FAILprocessing-FPS gate failed (73.4%)
815s1698.63.78%81%90%45%FAILprocessing-FPS gate failed (66.7%)

10 FPS · boundary 12

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s10.8665.50%21%14%21%PASS-
215s10.4155.70%25%21%22%PASS-
315s10.2749.20%30%25%23%PASS-
415s10.2144.40%40%28%24%PASS-
515s10.1940.50%43%31%25%PASS-
615s10.1748.40%48%38%26%PASS-
715s10.1742.30%52%42%27%PASS-
815s10.1849.10%61%52%28%PASS-
915s10.1349.80%66%58%29%PASS-
1015s10.1391.30%76%64%30%PASS-
1115s10.1760.50%79%87%32%PASS-
1215s8.29152.81.54%77%96%59%PASS-
1315s8.57200.36.04%77%95%63%FAILaverage discard 6.04%
1415s8.07209.113.27%80%95%67%FAILaverage discard 13.27%
1515s7.4225.720.54%77%95%70%FAILaverage discard 20.54%
1615s7.07284.126.69%80%95%74%FAILaverage discard 26.69%

7 FPS · boundary 15

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s7.3172.30%16%13%25%PASS-
230s7.2160.10%23%19%25%PASS-
330s7.251.90%26%24%26%PASS-
430s7.1748.30%30%26%27%PASS-
530s7.12440%39%28%28%PASS-
630s7.1543.60%37%31%29%PASS-
730s7.1541.80%41%33%30%PASS-
830s7.1542.40%45%37%31%PASS-
930s7.15440%51%42%32%PASS-
1030s7.1547.20%56%47%32%PASS-
1130s7.1447.70%61%52%33%PASS-
1230s7.1451.30%64%58%34%PASS-
1330s7.15500%67%67%35%PASS-
1430s7.1267.10%73%75%36%PASS-
1530s7.192.30%81%98%39%PASS-
1630s6.692402.69%75%98%74%FAILcritical-path latency 240 ms

5 FPS · boundary ≥16

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s5.6978.14.82%12%11%23%PASS-
215s5.3373.63.91%18%17%24%PASS-
315s5.2462.94.81%22%21%25%PASS-
415s5.1454.30%21%23%26%PASS-
515s5.1547.10%28%27%27%PASS-
615s5.1547.70%30%28%27%PASS-
715s5.1554.10%34%30%28%PASS-
815s5.1449.30%35%32%29%PASS-
915s5.155.10%36%34%30%PASS-
1015s5.1450%45%38%30%PASS-
1115s5.1473.10%45%41%31%PASS-
1215s5.1246.60%50%45%32%PASS-
1315s5.11020%54%54%33%PASS-
1415s5.1261.10%56%54%34%PASS-
1515s5.1278.70%58%60%35%PASS-
1615s5.155.90%63%65%36%PASS-

Safety-helmet detector

24 FPS · boundary 5

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
115s26.3862.30%30%19%23%PASS-
215s25.1157.30%35%35%24%PASS-
315s24.6857.10%60%49%25%PASS-
415s24.4452.60%77%60%26%PASS-
515s22.4383.20%77%83%36%PASS-
615s19104.70%80%89%40%FAILprocessing-FPS gate failed (79.2%)
715s16109.43.76%79%92%44%FAILprocessing-FPS gate failed (66.7%)
815s13.791337.54%82%92%47%FAILaverage discard 7.54%

10 FPS · boundary 10

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
130s10.21102.50%21%17%23%PASS-
230s10.2176.50%27%24%24%PASS-
330s10.2488.20%37%32%25%PASS-
430s10.0881.30%39%40%26%PASS-
530s10.03109.80%47%46%27%PASS-
630s9.9787.90%56%54%28%PASS-
730s10.198.40%61%62%29%PASS-
830s10.0679.30%69%71%30%PASS-
930s10.0783.30%74%88%31%PASS-
1030s8.94181.50.70%77%97%55%PASS-
1130s9.02204.611.26%78%96%59%FAILaverage discard 11.26%
1230s8.83242.523.11%78%96%63%FAILaverage discard 23.11%
1330s8.14272.628.46%78%96%67%FAILaverage discard 28.46%
1430s7.41302.330.41%77%96%72%FAILaverage discard 30.41%
1530s6.76397.732.02%75%95%75%FAILaverage discard 32.02%
1630s6.3367.633.95%75%96%78%FAILaverage discard 33.95%

7 FPS · boundary 12

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
1120s7.08116.90%16%16%24%PASS-
260s6.9141.80%22%21%25%PASS-
360s6.98870%29%26%26%PASS-
430s7.15118.70%32%33%26%PASS-
530s7.0583.50%36%38%27%PASS-
630s7143.10%43%43%28%PASS-
730s7.021580%48%49%29%PASS-
830s7.0685.10%54%54%30%PASS-
930s7.185.10%60%60%31%PASS-
1030s7.02120.10%63%68%32%PASS-
1130s7.0368.90%71%73%33%PASS-
1230s6.88950%73%93%34%PASS-
1330s6.39329.92.50%76%97%61%FAILcritical-path latency 329.9 ms
1430s6.15542.812.89%76%97%70%FAILaverage discard 12.89%
1530s6.14350.223.54%74%96%74%FAILaverage discard 23.54%
1630s5.93412.829.28%74%95%79%FAILaverage discard 29.28%

5 FPS · boundary 15

ChannelsHoldMin FPSCritical path msAvg discardAcceleratorCPUMemoryResultReason
160s5.2132.70%14%16%24%PASS-
260s5.07109.80%20%19%25%PASS-
360s5.1186.50%22%24%26%PASS-
430s5.1105.50%27%28%27%PASS-
530s5.178.30%31%34%28%PASS-
630s5.0779.40%32%38%28%PASS-
730s5.1106.10%36%42%29%PASS-
830s5.0589.30%43%45%30%PASS-
930s5.071170%44%49%31%PASS-
1030s5.08116.80%49%54%32%PASS-
1130s5.02111.20%54%57%33%PASS-
1230s5.07129.50%60%64%34%PASS-
1330s5.0791.40%62%70%35%PASS-
1430s5.08109.70%66%77%36%PASS-
1530s5.081690%67%88%38%PASS-
1630s4.78601.22.83%70%96%76%FAILcritical-path latency 601.2 ms
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/report.zh-CN.html new file mode 100644 index 000000000..e6f48bd92 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/report.zh-CN.html @@ -0,0 +1 @@ +RK3576 单算法逐路报告

RK3576 单算法逐路报告

短时逐路阶梯证据;下一路若因任务绑定失败而阻断,不视为性能上限。

人员检测

24 FPS · 边界 6

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s2641.60%32%14%18%通过-
215s24.7241.20%43%25%19%通过-
315s24.4837.60%53%36%20%通过-
415s24.3644.50%66%51%21%通过-
515s24.3450.50%78%66%23%通过-
615s20.4371.50%80%84%38%通过-
715s17.6380.51.41%85%88%41%失败处理 FPS 门禁失败 (73.4%)
815s1698.63.78%81%90%45%失败处理 FPS 门禁失败 (66.7%)

10 FPS · 边界 12

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s10.8665.50%21%14%21%通过-
215s10.4155.70%25%21%22%通过-
315s10.2749.20%30%25%23%通过-
415s10.2144.40%40%28%24%通过-
515s10.1940.50%43%31%25%通过-
615s10.1748.40%48%38%26%通过-
715s10.1742.30%52%42%27%通过-
815s10.1849.10%61%52%28%通过-
915s10.1349.80%66%58%29%通过-
1015s10.1391.30%76%64%30%通过-
1115s10.1760.50%79%87%32%通过-
1215s8.29152.81.54%77%96%59%通过-
1315s8.57200.36.04%77%95%63%失败平均丢弃率 6.04%
1415s8.07209.113.27%80%95%67%失败平均丢弃率 13.27%
1515s7.4225.720.54%77%95%70%失败平均丢弃率 20.54%
1615s7.07284.126.69%80%95%74%失败平均丢弃率 26.69%

7 FPS · 边界 15

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s7.3172.30%16%13%25%通过-
230s7.2160.10%23%19%25%通过-
330s7.251.90%26%24%26%通过-
430s7.1748.30%30%26%27%通过-
530s7.12440%39%28%28%通过-
630s7.1543.60%37%31%29%通过-
730s7.1541.80%41%33%30%通过-
830s7.1542.40%45%37%31%通过-
930s7.15440%51%42%32%通过-
1030s7.1547.20%56%47%32%通过-
1130s7.1447.70%61%52%33%通过-
1230s7.1451.30%64%58%34%通过-
1330s7.15500%67%67%35%通过-
1430s7.1267.10%73%75%36%通过-
1530s7.192.30%81%98%39%通过-
1630s6.692402.69%75%98%74%失败关键路径延时 240 ms

5 FPS · 边界 ≥16

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s5.6978.14.82%12%11%23%通过-
215s5.3373.63.91%18%17%24%通过-
315s5.2462.94.81%22%21%25%通过-
415s5.1454.30%21%23%26%通过-
515s5.1547.10%28%27%27%通过-
615s5.1547.70%30%28%27%通过-
715s5.1554.10%34%30%28%通过-
815s5.1449.30%35%32%29%通过-
915s5.155.10%36%34%30%通过-
1015s5.1450%45%38%30%通过-
1115s5.1473.10%45%41%31%通过-
1215s5.1246.60%50%45%32%通过-
1315s5.11020%54%54%33%通过-
1415s5.1261.10%56%54%34%通过-
1515s5.1278.70%58%60%35%通过-
1615s5.155.90%63%65%36%通过-

安全帽检测

24 FPS · 边界 5

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
115s26.3862.30%30%19%23%通过-
215s25.1157.30%35%35%24%通过-
315s24.6857.10%60%49%25%通过-
415s24.4452.60%77%60%26%通过-
515s22.4383.20%77%83%36%通过-
615s19104.70%80%89%40%失败处理 FPS 门禁失败 (79.2%)
715s16109.43.76%79%92%44%失败处理 FPS 门禁失败 (66.7%)
815s13.791337.54%82%92%47%失败平均丢弃率 7.54%

10 FPS · 边界 10

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
130s10.21102.50%21%17%23%通过-
230s10.2176.50%27%24%24%通过-
330s10.2488.20%37%32%25%通过-
430s10.0881.30%39%40%26%通过-
530s10.03109.80%47%46%27%通过-
630s9.9787.90%56%54%28%通过-
730s10.198.40%61%62%29%通过-
830s10.0679.30%69%71%30%通过-
930s10.0783.30%74%88%31%通过-
1030s8.94181.50.70%77%97%55%通过-
1130s9.02204.611.26%78%96%59%失败平均丢弃率 11.26%
1230s8.83242.523.11%78%96%63%失败平均丢弃率 23.11%
1330s8.14272.628.46%78%96%67%失败平均丢弃率 28.46%
1430s7.41302.330.41%77%96%72%失败平均丢弃率 30.41%
1530s6.76397.732.02%75%95%75%失败平均丢弃率 32.02%
1630s6.3367.633.95%75%96%78%失败平均丢弃率 33.95%

7 FPS · 边界 12

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
1120s7.08116.90%16%16%24%通过-
260s6.9141.80%22%21%25%通过-
360s6.98870%29%26%26%通过-
430s7.15118.70%32%33%26%通过-
530s7.0583.50%36%38%27%通过-
630s7143.10%43%43%28%通过-
730s7.021580%48%49%29%通过-
830s7.0685.10%54%54%30%通过-
930s7.185.10%60%60%31%通过-
1030s7.02120.10%63%68%32%通过-
1130s7.0368.90%71%73%33%通过-
1230s6.88950%73%93%34%通过-
1330s6.39329.92.50%76%97%61%失败关键路径延时 329.9 ms
1430s6.15542.812.89%76%97%70%失败平均丢弃率 12.89%
1530s6.14350.223.54%74%96%74%失败平均丢弃率 23.54%
1630s5.93412.829.28%74%95%79%失败平均丢弃率 29.28%

5 FPS · 边界 15

路数保持最低 FPS关键路径 ms平均丢弃率加速器CPU内存结果原因
160s5.2132.70%14%16%24%通过-
260s5.07109.80%20%19%25%通过-
360s5.1186.50%22%24%26%通过-
430s5.1105.50%27%28%27%通过-
530s5.178.30%31%34%28%通过-
630s5.0779.40%32%38%28%通过-
730s5.1106.10%36%42%29%通过-
830s5.0589.30%43%45%30%通过-
930s5.071170%44%49%31%通过-
1030s5.08116.80%49%54%32%通过-
1130s5.02111.20%54%57%33%通过-
1230s5.07129.50%60%64%34%通过-
1330s5.0791.40%62%70%35%通过-
1430s5.08109.70%66%77%36%通过-
1530s5.081690%67%88%38%通过-
1630s4.78601.22.83%70%96%76%失败关键路径延时 601.2 ms
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/summary.json new file mode 100644 index 000000000..3badf4c0e --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/summary.json @@ -0,0 +1,3183 @@ +{ + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0.0482, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1, + "averageDiscardRate": 0.0482, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 11, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.33, + "minimumFpsRatio": 1.067, + "missingRate": 0, + "averageDiscardRate": 0.0391, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6 + } + ], + "minimumProcessingFps": 5.33, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6, + "averageDiscardRate": 0.0391, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.049, + "missingRate": 0, + "averageDiscardRate": 0.0481, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9, + "averageDiscardRate": 0.0481, + "maximumChannelDiscardRate": 0.0747, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 30, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 41, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 65, + "memoryPeakPercent": 36, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.31, + "minimumFpsRatio": 1.044, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3 + } + ], + "minimumProcessingFps": 7.31, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 13, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 23, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.2, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9 + } + ], + "minimumProcessingFps": 7.2, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.17, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3 + } + ], + "minimumProcessingFps": 7.17, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 37, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 51, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 67, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 75, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.69, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0.0269, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240 + } + ], + "minimumProcessingFps": 6.69, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240, + "averageDiscardRate": 0.0269, + "maximumChannelDiscardRate": 0.2269, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 74, + "failureReason": "critical-path latency 240 ms" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "exact-boundary", + "display": "12", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.86, + "minimumFpsRatio": 1.086, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5 + } + ], + "minimumProcessingFps": 10.86, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.41, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7 + } + ], + "minimumProcessingFps": 10.41, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 25, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 22, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.27, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2 + } + ], + "minimumProcessingFps": 10.27, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.19, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 10.19, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.18, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 10.18, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 87, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.29, + "minimumFpsRatio": 0.829, + "missingRate": 0, + "averageDiscardRate": 0.0154, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8 + } + ], + "minimumProcessingFps": 8.29, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8, + "averageDiscardRate": 0.0154, + "maximumChannelDiscardRate": 0.1849, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0604, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3, + "averageDiscardRate": 0.0604, + "maximumChannelDiscardRate": 0.246, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 63, + "failureReason": "average discard 6.04%" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.07, + "minimumFpsRatio": 0.807, + "missingRate": 0, + "averageDiscardRate": 0.1327, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1 + } + ], + "minimumProcessingFps": 8.07, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1, + "averageDiscardRate": 0.1327, + "maximumChannelDiscardRate": 0.2667, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 67, + "failureReason": "average discard 13.27%" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.4, + "minimumFpsRatio": 0.74, + "missingRate": 0, + "averageDiscardRate": 0.2054, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7 + } + ], + "minimumProcessingFps": 7.4, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7, + "averageDiscardRate": 0.2054, + "maximumChannelDiscardRate": 0.2914, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 70, + "failureReason": "average discard 20.54%" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 0.707, + "missingRate": 0, + "averageDiscardRate": 0.2669, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1, + "averageDiscardRate": 0.2669, + "maximumChannelDiscardRate": 0.3152, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 74, + "failureReason": "average discard 26.69%" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 6, + "firstFailedChannels": 7, + "boundaryKind": "exact-boundary", + "display": "6", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 26, + "minimumFpsRatio": 1.083, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 26, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 18, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.72, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2 + } + ], + "minimumProcessingFps": 24.72, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 19, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.48, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.48, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 53, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 36, + "memoryPeakPercent": 20, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.36, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5 + } + ], + "minimumProcessingFps": 24.36, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 51, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.34, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5 + } + ], + "minimumProcessingFps": 24.34, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 66, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 20.43, + "minimumFpsRatio": 0.851, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5 + } + ], + "minimumProcessingFps": 20.43, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 84, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 17.63, + "minimumFpsRatio": 0.734, + "missingRate": 0, + "averageDiscardRate": 0.0141, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5 + } + ], + "minimumProcessingFps": 17.63, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5, + "averageDiscardRate": 0.0141, + "maximumChannelDiscardRate": 0.0397, + "acceleratorPeakPercent": 85, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 41, + "failureReason": "processing-FPS gate failed (73.4%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0378, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6, + "averageDiscardRate": 0.0378, + "maximumChannelDiscardRate": 0.0811, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 90, + "memoryPeakPercent": 45, + "failureReason": "processing-FPS gate failed (66.7%)" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.023, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 49, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 57, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 70, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 77, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.957, + "missingRate": 0, + "averageDiscardRate": 0.0283, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2, + "averageDiscardRate": 0.0283, + "maximumChannelDiscardRate": 0.1038, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 76, + "failureReason": "critical-path latency 601.2 ms" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "exact-boundary", + "display": "12", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.08, + "minimumFpsRatio": 1.012, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9 + } + ], + "minimumProcessingFps": 7.08, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.9, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8 + } + ], + "minimumProcessingFps": 6.9, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 29, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.06, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.06, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 68, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 71, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 73, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 93, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.39, + "minimumFpsRatio": 0.913, + "missingRate": 0, + "averageDiscardRate": 0.025, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9 + } + ], + "minimumProcessingFps": 6.39, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9, + "averageDiscardRate": 0.025, + "maximumChannelDiscardRate": 0.097, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 61, + "failureReason": "critical-path latency 329.9 ms" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.15, + "minimumFpsRatio": 0.879, + "missingRate": 0, + "averageDiscardRate": 0.1289, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8 + } + ], + "minimumProcessingFps": 6.15, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8, + "averageDiscardRate": 0.1289, + "maximumChannelDiscardRate": 0.2873, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 70, + "failureReason": "average discard 12.89%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.14, + "minimumFpsRatio": 0.877, + "missingRate": 0, + "averageDiscardRate": 0.2354, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2 + } + ], + "minimumProcessingFps": 6.14, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2, + "averageDiscardRate": 0.2354, + "maximumChannelDiscardRate": 0.3611, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 74, + "failureReason": "average discard 23.54%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 5.93, + "minimumFpsRatio": 0.847, + "missingRate": 0, + "averageDiscardRate": 0.2928, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8 + } + ], + "minimumProcessingFps": 5.93, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8, + "averageDiscardRate": 0.2928, + "maximumChannelDiscardRate": 0.3552, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 79, + "failureReason": "average discard 29.28%" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 10, + "firstFailedChannels": 11, + "boundaryKind": "exact-boundary", + "display": "10", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.24, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2 + } + ], + "minimumProcessingFps": 10.24, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.08, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3 + } + ], + "minimumProcessingFps": 10.08, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 40, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 47, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 46, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.1, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4 + } + ], + "minimumProcessingFps": 10.1, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 62, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.06, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3 + } + ], + "minimumProcessingFps": 10.06, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 69, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 71, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.94, + "minimumFpsRatio": 0.894, + "missingRate": 0, + "averageDiscardRate": 0.007, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5 + } + ], + "minimumProcessingFps": 8.94, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5, + "averageDiscardRate": 0.007, + "maximumChannelDiscardRate": 0.0303, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 55, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.02, + "minimumFpsRatio": 0.902, + "missingRate": 0, + "averageDiscardRate": 0.1126, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6 + } + ], + "minimumProcessingFps": 9.02, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6, + "averageDiscardRate": 0.1126, + "maximumChannelDiscardRate": 0.1859, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": "average discard 11.26%" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.83, + "minimumFpsRatio": 0.883, + "missingRate": 0, + "averageDiscardRate": 0.2311, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5 + } + ], + "minimumProcessingFps": 8.83, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5, + "averageDiscardRate": 0.2311, + "maximumChannelDiscardRate": 0.2766, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 63, + "failureReason": "average discard 23.11%" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.14, + "minimumFpsRatio": 0.814, + "missingRate": 0, + "averageDiscardRate": 0.2846, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6 + } + ], + "minimumProcessingFps": 8.14, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6, + "averageDiscardRate": 0.2846, + "maximumChannelDiscardRate": 0.301, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 67, + "failureReason": "average discard 28.46%" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 7.41, + "minimumFpsRatio": 0.741, + "missingRate": 0, + "averageDiscardRate": 0.3041, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3 + } + ], + "minimumProcessingFps": 7.41, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3, + "averageDiscardRate": 0.3041, + "maximumChannelDiscardRate": 0.3172, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 72, + "failureReason": "average discard 30.41%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.76, + "minimumFpsRatio": 0.676, + "missingRate": 0, + "averageDiscardRate": 0.3202, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7 + } + ], + "minimumProcessingFps": 6.76, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7, + "averageDiscardRate": 0.3202, + "maximumChannelDiscardRate": 0.3321, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 75, + "failureReason": "average discard 32.02%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.3, + "minimumFpsRatio": 0.63, + "missingRate": 0, + "averageDiscardRate": 0.3395, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6 + } + ], + "minimumProcessingFps": 6.3, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6, + "averageDiscardRate": 0.3395, + "maximumChannelDiscardRate": 0.3516, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 78, + "failureReason": "average discard 33.95%" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 5, + "firstFailedChannels": 6, + "boundaryKind": "exact-boundary", + "display": "5", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.38, + "minimumFpsRatio": 1.099, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3 + } + ], + "minimumProcessingFps": 26.38, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 25.11, + "minimumFpsRatio": 1.046, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3 + } + ], + "minimumProcessingFps": 25.11, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 35, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.68, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1 + } + ], + "minimumProcessingFps": 24.68, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.44, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6 + } + ], + "minimumProcessingFps": 24.44, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22.43, + "minimumFpsRatio": 0.935, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2 + } + ], + "minimumProcessingFps": 22.43, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 83, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 19, + "minimumFpsRatio": 0.792, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7 + } + ], + "minimumProcessingFps": 19, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 89, + "memoryPeakPercent": 40, + "failureReason": "processing-FPS gate failed (79.2%)" + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0376, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4, + "averageDiscardRate": 0.0376, + "maximumChannelDiscardRate": 0.0679, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (66.7%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 13.79, + "minimumFpsRatio": 0.574, + "missingRate": 0, + "averageDiscardRate": 0.0754, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133 + } + ], + "minimumProcessingFps": 13.79, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133, + "averageDiscardRate": 0.0754, + "maximumChannelDiscardRate": 0.0958, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 47, + "failureReason": "average discard 7.54%" + } + ] + } + } + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/test.log b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/test.log new file mode 100644 index 000000000..d497f1381 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/single-detector/test.log @@ -0,0 +1,117 @@ +benchmark=cosmoedge-1.1-multistream +platform=RK3576 +device=RK3576 EVB +workload=single-detector +publication=release-evidence +channels=1 hold=15s result=PASS avg_discard=0.0482 +channels=2 hold=15s result=PASS avg_discard=0.0391 +channels=3 hold=15s result=PASS avg_discard=0.0481 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 +channels=9 hold=15s result=PASS avg_discard=0 +channels=10 hold=15s result=PASS avg_discard=0 +channels=11 hold=15s result=PASS avg_discard=0 +channels=12 hold=15s result=PASS avg_discard=0 +channels=13 hold=15s result=PASS avg_discard=0 +channels=14 hold=15s result=PASS avg_discard=0 +channels=15 hold=15s result=PASS avg_discard=0 +channels=16 hold=15s result=PASS avg_discard=0 +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 +channels=9 hold=30s result=PASS avg_discard=0 +channels=10 hold=30s result=PASS avg_discard=0 +channels=11 hold=30s result=PASS avg_discard=0 +channels=12 hold=30s result=PASS avg_discard=0 +channels=13 hold=30s result=PASS avg_discard=0 +channels=14 hold=30s result=PASS avg_discard=0 +channels=15 hold=30s result=PASS avg_discard=0 +channels=16 hold=30s result=FAIL avg_discard=0.0269 +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=PASS avg_discard=0 +channels=8 hold=15s result=PASS avg_discard=0 +channels=9 hold=15s result=PASS avg_discard=0 +channels=10 hold=15s result=PASS avg_discard=0 +channels=11 hold=15s result=PASS avg_discard=0 +channels=12 hold=15s result=PASS avg_discard=0.0154 +channels=13 hold=15s result=FAIL avg_discard=0.0604 +channels=14 hold=15s result=FAIL avg_discard=0.1327 +channels=15 hold=15s result=FAIL avg_discard=0.2054 +channels=16 hold=15s result=FAIL avg_discard=0.2669 +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=PASS avg_discard=0 +channels=7 hold=15s result=FAIL avg_discard=0.0141 +channels=8 hold=15s result=FAIL avg_discard=0.0378 +channels=1 hold=60s result=PASS avg_discard=0 +channels=2 hold=60s result=PASS avg_discard=0 +channels=3 hold=60s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 +channels=9 hold=30s result=PASS avg_discard=0 +channels=10 hold=30s result=PASS avg_discard=0 +channels=11 hold=30s result=PASS avg_discard=0 +channels=12 hold=30s result=PASS avg_discard=0 +channels=13 hold=30s result=PASS avg_discard=0 +channels=14 hold=30s result=PASS avg_discard=0 +channels=15 hold=30s result=PASS avg_discard=0 +channels=16 hold=30s result=FAIL avg_discard=0.0283 +channels=1 hold=120s result=PASS avg_discard=0 +channels=2 hold=60s result=PASS avg_discard=0 +channels=3 hold=60s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 +channels=9 hold=30s result=PASS avg_discard=0 +channels=10 hold=30s result=PASS avg_discard=0 +channels=11 hold=30s result=PASS avg_discard=0 +channels=12 hold=30s result=PASS avg_discard=0 +channels=13 hold=30s result=FAIL avg_discard=0.025 +channels=14 hold=30s result=FAIL avg_discard=0.1289 +channels=15 hold=30s result=FAIL avg_discard=0.2354 +channels=16 hold=30s result=FAIL avg_discard=0.2928 +channels=1 hold=30s result=PASS avg_discard=0 +channels=2 hold=30s result=PASS avg_discard=0 +channels=3 hold=30s result=PASS avg_discard=0 +channels=4 hold=30s result=PASS avg_discard=0 +channels=5 hold=30s result=PASS avg_discard=0 +channels=6 hold=30s result=PASS avg_discard=0 +channels=7 hold=30s result=PASS avg_discard=0 +channels=8 hold=30s result=PASS avg_discard=0 +channels=9 hold=30s result=PASS avg_discard=0 +channels=10 hold=30s result=PASS avg_discard=0.007 +channels=11 hold=30s result=FAIL avg_discard=0.1126 +channels=12 hold=30s result=FAIL avg_discard=0.2311 +channels=13 hold=30s result=FAIL avg_discard=0.2846 +channels=14 hold=30s result=FAIL avg_discard=0.3041 +channels=15 hold=30s result=FAIL avg_discard=0.3202 +channels=16 hold=30s result=FAIL avg_discard=0.3395 +channels=1 hold=15s result=PASS avg_discard=0 +channels=2 hold=15s result=PASS avg_discard=0 +channels=3 hold=15s result=PASS avg_discard=0 +channels=4 hold=15s result=PASS avg_discard=0 +channels=5 hold=15s result=PASS avg_discard=0 +channels=6 hold=15s result=FAIL avg_discard=0 +channels=7 hold=15s result=FAIL avg_discard=0.0376 +channels=8 hold=15s result=FAIL avg_discard=0.0754 diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/summary.json new file mode 100644 index 000000000..21d099e13 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/summary.json @@ -0,0 +1,3678 @@ +{ + "schemaVersion": 2, + "platformId": "rk3576", + "platform": "RK3576", + "device": "RK3576 EVB", + "publicationStatus": "release-evidence", + "productInstalledVersion": "V1.1.0.0", + "releaseManifest": "../../release-manifest.json", + "environment": "../../environments/rk3576.json", + "models": "../../models/rk3576.json", + "dataset": "../../dataset/dataset-card.md", + "dualDetector": { + "schemaVersion": 2, + "workload": { + "publicId": "dual-detector", + "tasksPerChannel": 2, + "tasks": [ + "person-detector", + "safety-helmet-detector" + ], + "targetFpsPerTaskPerChannel": 5, + "input": "fixed local 1920x1080 H.264 24 FPS sample", + "previewLoad": false + }, + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "evidenceDate": "2026-08-11", + "recommendedProfile": { + "status": "pending repeat and soak validation", + "channels": null + }, + "observedBoundary": { + "highestVerifiedChannels": 8, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 15 + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 1.185, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 53.4 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 138.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 138.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 15, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.48, + "minimumFpsRatio": 1.097, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 132 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.34, + "minimumFpsRatio": 1.069, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 198.3 + } + ], + "minimumProcessingFps": 5.34, + "maximumDetectorLatencyMs": 120.6, + "maximumCriticalPathLatencyMs": 198.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 19, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.3, + "minimumFpsRatio": 1.059, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 45.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 100.1 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 41.2, + "maximumCriticalPathLatencyMs": 100.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.25, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 47.1 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.029, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 99.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 43.8, + "maximumCriticalPathLatencyMs": 99.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.17, + "minimumFpsRatio": 1.034, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 45.5 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 89.6 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.8, + "maximumCriticalPathLatencyMs": 89.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.17, + "minimumFpsRatio": 1.034, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 41.6 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 94 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 94, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 39, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 43.7 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 84.9 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 84.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 42.9 + }, + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 90.1 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 90.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 30, + "failureReason": null + } + ] + }, + "singleDetector": { + "schemaVersion": 2, + "workloads": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0.0482, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1, + "averageDiscardRate": 0.0482, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 11, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.33, + "minimumFpsRatio": 1.067, + "missingRate": 0, + "averageDiscardRate": 0.0391, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6 + } + ], + "minimumProcessingFps": 5.33, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6, + "averageDiscardRate": 0.0391, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.049, + "missingRate": 0, + "averageDiscardRate": 0.0481, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9, + "averageDiscardRate": 0.0481, + "maximumChannelDiscardRate": 0.0747, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 30, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 41, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 65, + "memoryPeakPercent": 36, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.31, + "minimumFpsRatio": 1.044, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3 + } + ], + "minimumProcessingFps": 7.31, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 13, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 23, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.2, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9 + } + ], + "minimumProcessingFps": 7.2, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.17, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3 + } + ], + "minimumProcessingFps": 7.17, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 37, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 51, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 67, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 75, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.69, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0.0269, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240 + } + ], + "minimumProcessingFps": 6.69, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240, + "averageDiscardRate": 0.0269, + "maximumChannelDiscardRate": 0.2269, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 74, + "failureReason": "critical-path latency 240 ms" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "exact-boundary", + "display": "12", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.86, + "minimumFpsRatio": 1.086, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5 + } + ], + "minimumProcessingFps": 10.86, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.41, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7 + } + ], + "minimumProcessingFps": 10.41, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 25, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 22, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.27, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2 + } + ], + "minimumProcessingFps": 10.27, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.19, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 10.19, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.18, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 10.18, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 87, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.29, + "minimumFpsRatio": 0.829, + "missingRate": 0, + "averageDiscardRate": 0.0154, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8 + } + ], + "minimumProcessingFps": 8.29, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8, + "averageDiscardRate": 0.0154, + "maximumChannelDiscardRate": 0.1849, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0604, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3, + "averageDiscardRate": 0.0604, + "maximumChannelDiscardRate": 0.246, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 63, + "failureReason": "average discard 6.04%" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.07, + "minimumFpsRatio": 0.807, + "missingRate": 0, + "averageDiscardRate": 0.1327, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1 + } + ], + "minimumProcessingFps": 8.07, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1, + "averageDiscardRate": 0.1327, + "maximumChannelDiscardRate": 0.2667, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 67, + "failureReason": "average discard 13.27%" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.4, + "minimumFpsRatio": 0.74, + "missingRate": 0, + "averageDiscardRate": 0.2054, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7 + } + ], + "minimumProcessingFps": 7.4, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7, + "averageDiscardRate": 0.2054, + "maximumChannelDiscardRate": 0.2914, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 70, + "failureReason": "average discard 20.54%" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 0.707, + "missingRate": 0, + "averageDiscardRate": 0.2669, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1, + "averageDiscardRate": 0.2669, + "maximumChannelDiscardRate": 0.3152, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 74, + "failureReason": "average discard 26.69%" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 6, + "firstFailedChannels": 7, + "boundaryKind": "exact-boundary", + "display": "6", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 26, + "minimumFpsRatio": 1.083, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 26, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 18, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.72, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2 + } + ], + "minimumProcessingFps": 24.72, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 19, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.48, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.48, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 53, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 36, + "memoryPeakPercent": 20, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.36, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5 + } + ], + "minimumProcessingFps": 24.36, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 51, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.34, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5 + } + ], + "minimumProcessingFps": 24.34, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 66, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 20.43, + "minimumFpsRatio": 0.851, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5 + } + ], + "minimumProcessingFps": 20.43, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 84, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 17.63, + "minimumFpsRatio": 0.734, + "missingRate": 0, + "averageDiscardRate": 0.0141, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5 + } + ], + "minimumProcessingFps": 17.63, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5, + "averageDiscardRate": 0.0141, + "maximumChannelDiscardRate": 0.0397, + "acceleratorPeakPercent": 85, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 41, + "failureReason": "processing-FPS gate failed (73.4%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0378, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6, + "averageDiscardRate": 0.0378, + "maximumChannelDiscardRate": 0.0811, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 90, + "memoryPeakPercent": 45, + "failureReason": "processing-FPS gate failed (66.7%)" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.023, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 49, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 57, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 70, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 77, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.957, + "missingRate": 0, + "averageDiscardRate": 0.0283, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2, + "averageDiscardRate": 0.0283, + "maximumChannelDiscardRate": 0.1038, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 76, + "failureReason": "critical-path latency 601.2 ms" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "exact-boundary", + "display": "12", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.08, + "minimumFpsRatio": 1.012, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9 + } + ], + "minimumProcessingFps": 7.08, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.9, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8 + } + ], + "minimumProcessingFps": 6.9, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 29, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.06, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.06, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 68, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 71, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 73, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 93, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.39, + "minimumFpsRatio": 0.913, + "missingRate": 0, + "averageDiscardRate": 0.025, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9 + } + ], + "minimumProcessingFps": 6.39, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9, + "averageDiscardRate": 0.025, + "maximumChannelDiscardRate": 0.097, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 61, + "failureReason": "critical-path latency 329.9 ms" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.15, + "minimumFpsRatio": 0.879, + "missingRate": 0, + "averageDiscardRate": 0.1289, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8 + } + ], + "minimumProcessingFps": 6.15, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8, + "averageDiscardRate": 0.1289, + "maximumChannelDiscardRate": 0.2873, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 70, + "failureReason": "average discard 12.89%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.14, + "minimumFpsRatio": 0.877, + "missingRate": 0, + "averageDiscardRate": 0.2354, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2 + } + ], + "minimumProcessingFps": 6.14, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2, + "averageDiscardRate": 0.2354, + "maximumChannelDiscardRate": 0.3611, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 74, + "failureReason": "average discard 23.54%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 5.93, + "minimumFpsRatio": 0.847, + "missingRate": 0, + "averageDiscardRate": 0.2928, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8 + } + ], + "minimumProcessingFps": 5.93, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8, + "averageDiscardRate": 0.2928, + "maximumChannelDiscardRate": 0.3552, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 79, + "failureReason": "average discard 29.28%" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 10, + "firstFailedChannels": 11, + "boundaryKind": "exact-boundary", + "display": "10", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.24, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2 + } + ], + "minimumProcessingFps": 10.24, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.08, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3 + } + ], + "minimumProcessingFps": 10.08, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 40, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 47, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 46, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.1, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4 + } + ], + "minimumProcessingFps": 10.1, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 62, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.06, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3 + } + ], + "minimumProcessingFps": 10.06, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 69, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 71, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.94, + "minimumFpsRatio": 0.894, + "missingRate": 0, + "averageDiscardRate": 0.007, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5 + } + ], + "minimumProcessingFps": 8.94, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5, + "averageDiscardRate": 0.007, + "maximumChannelDiscardRate": 0.0303, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 55, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.02, + "minimumFpsRatio": 0.902, + "missingRate": 0, + "averageDiscardRate": 0.1126, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6 + } + ], + "minimumProcessingFps": 9.02, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6, + "averageDiscardRate": 0.1126, + "maximumChannelDiscardRate": 0.1859, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": "average discard 11.26%" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.83, + "minimumFpsRatio": 0.883, + "missingRate": 0, + "averageDiscardRate": 0.2311, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5 + } + ], + "minimumProcessingFps": 8.83, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5, + "averageDiscardRate": 0.2311, + "maximumChannelDiscardRate": 0.2766, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 63, + "failureReason": "average discard 23.11%" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.14, + "minimumFpsRatio": 0.814, + "missingRate": 0, + "averageDiscardRate": 0.2846, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6 + } + ], + "minimumProcessingFps": 8.14, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6, + "averageDiscardRate": 0.2846, + "maximumChannelDiscardRate": 0.301, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 67, + "failureReason": "average discard 28.46%" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 7.41, + "minimumFpsRatio": 0.741, + "missingRate": 0, + "averageDiscardRate": 0.3041, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3 + } + ], + "minimumProcessingFps": 7.41, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3, + "averageDiscardRate": 0.3041, + "maximumChannelDiscardRate": 0.3172, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 72, + "failureReason": "average discard 30.41%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.76, + "minimumFpsRatio": 0.676, + "missingRate": 0, + "averageDiscardRate": 0.3202, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7 + } + ], + "minimumProcessingFps": 6.76, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7, + "averageDiscardRate": 0.3202, + "maximumChannelDiscardRate": 0.3321, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 75, + "failureReason": "average discard 32.02%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.3, + "minimumFpsRatio": 0.63, + "missingRate": 0, + "averageDiscardRate": 0.3395, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6 + } + ], + "minimumProcessingFps": 6.3, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6, + "averageDiscardRate": 0.3395, + "maximumChannelDiscardRate": 0.3516, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 78, + "failureReason": "average discard 33.95%" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 5, + "firstFailedChannels": 6, + "boundaryKind": "exact-boundary", + "display": "5", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.38, + "minimumFpsRatio": 1.099, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3 + } + ], + "minimumProcessingFps": 26.38, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 25.11, + "minimumFpsRatio": 1.046, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3 + } + ], + "minimumProcessingFps": 25.11, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 35, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.68, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1 + } + ], + "minimumProcessingFps": 24.68, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.44, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6 + } + ], + "minimumProcessingFps": 24.44, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22.43, + "minimumFpsRatio": 0.935, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2 + } + ], + "minimumProcessingFps": 22.43, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 83, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 19, + "minimumFpsRatio": 0.792, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7 + } + ], + "minimumProcessingFps": 19, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 89, + "memoryPeakPercent": 40, + "failureReason": "processing-FPS gate failed (79.2%)" + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0376, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4, + "averageDiscardRate": 0.0376, + "maximumChannelDiscardRate": 0.0679, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (66.7%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 13.79, + "minimumFpsRatio": 0.574, + "missingRate": 0, + "averageDiscardRate": 0.0754, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133 + } + ], + "minimumProcessingFps": 13.79, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133, + "averageDiscardRate": 0.0754, + "maximumChannelDiscardRate": 0.0958, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 47, + "failureReason": "average discard 7.54%" + } + ] + } + } + } + ] + }, + "vlmObservation": { + "schemaVersion": 2, + "workload": { + "publicId": "vlm-observation", + "targetFpsPerChannel": 0.1, + "interpretation": "Experimental runtime observation; FPS is recorded but excluded from PASS/FAIL", + "counterSemantics": "shared-task-counter-corrected" + }, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-12", + "observedBoundary": { + "highestNonFpsPassingChannels": 7, + "firstNonFpsStopChannels": 8, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.12, + "fpsAchievementRatioObserved": 1.2, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 22, + "memoryPeakPercent": 44, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.116, + "fpsAchievementRatioObserved": 1.16, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 7, + "cpuPeakPercent": 32, + "memoryPeakPercent": 44, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.115, + "fpsAchievementRatioObserved": 1.15, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 30, + "cpuPeakPercent": 43, + "memoryPeakPercent": 45, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.091, + "fpsAchievementRatioObserved": 0.91, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 32, + "cpuPeakPercent": 46, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.076, + "fpsAchievementRatioObserved": 0.76, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 31, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.063, + "fpsAchievementRatioObserved": 0.63, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 32, + "cpuPeakPercent": 46, + "memoryPeakPercent": 50, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.057, + "fpsAchievementRatioObserved": 0.57, + "fpsGateEnabled": false, + "averageDiscardRate": 0.2275, + "maximumChannelDiscardRate": 0.3033, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 30, + "cpuPeakPercent": 45, + "memoryPeakPercent": 52, + "nonFpsGateResult": "STOP", + "stopReason": "average discard 22.75%" + } + ] + } +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/test.log b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/test.log new file mode 100644 index 000000000..7720b9200 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/test.log @@ -0,0 +1,4 @@ +benchmark=cosmoedge-1.1-multistream +platform=RK3576 +device=RK3576 EVB +publication=release-evidence diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/command.txt b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/command.txt new file mode 100644 index 000000000..cfebb7f76 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/command.txt @@ -0,0 +1,6 @@ +# Public reproduction descriptor +platform=rk3576 +workload=vlm-observation +scenario=../../../scenarios/vlm-observation/scenario.public.yml +# Resolve the public model reference, device-local layout, and schedule before running. +node scenario-bench/src/cli.js run --output diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/metrics.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/metrics.json new file mode 100644 index 000000000..d33fa373e --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/metrics.json @@ -0,0 +1,140 @@ +{ + "schemaVersion": 2, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.12, + "fpsAchievementRatioObserved": 1.2, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 22, + "memoryPeakPercent": 44, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.116, + "fpsAchievementRatioObserved": 1.16, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 7, + "cpuPeakPercent": 32, + "memoryPeakPercent": 44, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.115, + "fpsAchievementRatioObserved": 1.15, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 30, + "cpuPeakPercent": 43, + "memoryPeakPercent": 45, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.091, + "fpsAchievementRatioObserved": 0.91, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 32, + "cpuPeakPercent": 46, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.076, + "fpsAchievementRatioObserved": 0.76, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 31, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.063, + "fpsAchievementRatioObserved": 0.63, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 32, + "cpuPeakPercent": 46, + "memoryPeakPercent": 50, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.057, + "fpsAchievementRatioObserved": 0.57, + "fpsGateEnabled": false, + "averageDiscardRate": 0.2275, + "maximumChannelDiscardRate": 0.3033, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 30, + "cpuPeakPercent": 45, + "memoryPeakPercent": 52, + "nonFpsGateResult": "STOP", + "stopReason": "average discard 22.75%" + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/report.html b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/report.html new file mode 100644 index 000000000..1be4e62ef --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/report.html @@ -0,0 +1 @@ +RK3576 Experimental VLM runtime observation

RK3576 Experimental VLM runtime observation

Requested rate: 0.1 FPS per channel. FPS is observational only and is not a pass/fail gate; this report does not claim validated VLM capacity.

ChannelsHoldTarget FPS/chEquivalent FPS/chAvg discardAcceleratorCPUMemoryNon-FPS gateStop reason
1120s0.10.10%0%3%43%PASS-
2120s0.10.120%0%22%44%PASS-
3120s0.10.1160%7%32%44%PASS-
4120s0.10.1150%30%43%45%PASS-
5120s0.10.0910%32%46%46%PASS-
6120s0.10.0760%31%47%46%PASS-
7120s0.10.0630%32%46%50%PASS-
8120s0.10.05722.75%30%45%52%STOPaverage discard 22.75%
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/report.zh-CN.html b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/report.zh-CN.html new file mode 100644 index 000000000..0b169481a --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/report.zh-CN.html @@ -0,0 +1 @@ +RK3576 VLM 实验运行观测

RK3576 VLM 实验运行观测

目标为每路 0.1 FPS。FPS 仅作观测、不参与通过判定;本页不形成 VLM 正式容量结论。

路数保持目标 FPS/路等效 FPS/路平均丢弃率加速器CPU内存非 FPS 门禁停止原因
1120s0.10.10%0%3%43%通过-
2120s0.10.120%0%22%44%通过-
3120s0.10.1160%7%32%44%通过-
4120s0.10.1150%30%43%45%通过-
5120s0.10.0910%32%46%46%通过-
6120s0.10.0760%31%47%46%通过-
7120s0.10.0630%32%46%50%通过-
8120s0.10.05722.75%30%45%52%停止平均丢弃率 22.75%
diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/summary.json b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/summary.json new file mode 100644 index 000000000..a6f72fb9c --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/summary.json @@ -0,0 +1,153 @@ +{ + "schemaVersion": 2, + "workload": { + "publicId": "vlm-observation", + "targetFpsPerChannel": 0.1, + "interpretation": "Experimental runtime observation; FPS is recorded but excluded from PASS/FAIL", + "counterSemantics": "shared-task-counter-corrected" + }, + "gates": { + "minimumFpsRatio": null, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "evidenceDate": "2026-08-12", + "observedBoundary": { + "highestNonFpsPassingChannels": 7, + "firstNonFpsStopChannels": 8, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + }, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.1, + "fpsAchievementRatioObserved": 1, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.12, + "fpsAchievementRatioObserved": 1.2, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 0, + "cpuPeakPercent": 22, + "memoryPeakPercent": 44, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.116, + "fpsAchievementRatioObserved": 1.16, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 7, + "cpuPeakPercent": 32, + "memoryPeakPercent": 44, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.115, + "fpsAchievementRatioObserved": 1.15, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 30, + "cpuPeakPercent": 43, + "memoryPeakPercent": 45, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.091, + "fpsAchievementRatioObserved": 0.91, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 32, + "cpuPeakPercent": 46, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.076, + "fpsAchievementRatioObserved": 0.76, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 31, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.063, + "fpsAchievementRatioObserved": 0.63, + "fpsGateEnabled": false, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 32, + "cpuPeakPercent": 46, + "memoryPeakPercent": 50, + "nonFpsGateResult": "PASS", + "stopReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "targetFpsPerChannel": 0.1, + "observedEquivalentPerChannelFps": 0.057, + "fpsAchievementRatioObserved": 0.57, + "fpsGateEnabled": false, + "averageDiscardRate": 0.2275, + "maximumChannelDiscardRate": 0.3033, + "telemetryMissingRate": 0, + "acceleratorPeakPercent": 30, + "cpuPeakPercent": 45, + "memoryPeakPercent": 52, + "nonFpsGateResult": "STOP", + "stopReason": "average discard 22.75%" + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/test.log b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/test.log new file mode 100644 index 000000000..c6760b02a --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/rk3576/vlm-observation/test.log @@ -0,0 +1,13 @@ +benchmark=cosmoedge-1.1-multistream +platform=RK3576 +device=RK3576 EVB +workload=vlm-observation +publication=release-evidence +channels=1 hold=120s result=PASS avg_discard=0 +channels=2 hold=120s result=PASS avg_discard=0 +channels=3 hold=120s result=PASS avg_discard=0 +channels=4 hold=120s result=PASS avg_discard=0 +channels=5 hold=120s result=PASS avg_discard=0 +channels=6 hold=120s result=PASS avg_discard=0 +channels=7 hold=120s result=PASS avg_discard=0 +channels=8 hold=120s result=STOP avg_discard=0.2275 diff --git a/docs/benchmarks/scenario-bench/v1.1/results/workload-matrix.json b/docs/benchmarks/scenario-bench/v1.1/results/workload-matrix.json new file mode 100644 index 000000000..e96b4d794 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/results/workload-matrix.json @@ -0,0 +1,9000 @@ +{ + "schemaVersion": 2, + "publicationStatus": "release-evidence", + "interpretation": { + "singleDetector": "last passing short-run channel count under enabled CV gates", + "dualDetector": "highest configured short-run point passed; observed lower bound only", + "vlm": "Experimental runtime observation; analysis FPS is not a gate", + "bindingBlocked": "setup evidence only; not a performance limit" + }, + "platforms": [ + { + "platformId": "bm1688", + "platform": "BM1688", + "singleDetector": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.85, + "minimumFpsRatio": 1.169, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6 + } + ], + "minimumProcessingFps": 5.85, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 30.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.39, + "minimumFpsRatio": 1.079, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5 + } + ], + "minimumProcessingFps": 5.39, + "maximumDetectorLatencyMs": 28, + "maximumCriticalPathLatencyMs": 31.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 4, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.18, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2 + } + ], + "minimumProcessingFps": 5.18, + "maximumDetectorLatencyMs": 27.7, + "maximumCriticalPathLatencyMs": 31.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 5, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 28.4, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 28.5, + "maximumCriticalPathLatencyMs": 32.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 10, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 46, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 33.5, + "maximumCriticalPathLatencyMs": 37.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 34.7, + "maximumCriticalPathLatencyMs": 38.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 15, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 39.1, + "maximumCriticalPathLatencyMs": 43.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 33.6, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 40.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 36.6, + "maximumCriticalPathLatencyMs": 46.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 26, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 36, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 39, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 41, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 8.31, + "minimumFpsRatio": 1.187, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31 + } + ], + "minimumProcessingFps": 8.31, + "maximumDetectorLatencyMs": 26.6, + "maximumCriticalPathLatencyMs": 31, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 3, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.57, + "minimumFpsRatio": 1.082, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 7.57, + "maximumDetectorLatencyMs": 27.6, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 5, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.35, + "minimumFpsRatio": 1.05, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9 + } + ], + "minimumProcessingFps": 7.35, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 31.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 27.5, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 50.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 12, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 29.1, + "maximumCriticalPathLatencyMs": 32.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 13, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 42.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 16, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 48.9, + "maximumCriticalPathLatencyMs": 52.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 18, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 21, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 35, + "maximumCriticalPathLatencyMs": 40, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 23, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 39.5, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 26, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 46.6, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 30, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 45.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 34, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 38, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 41.8, + "maximumCriticalPathLatencyMs": 46.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 50, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 61.8, + "maximumCriticalPathLatencyMs": 66.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 55, + "memoryPeakPercent": 46, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.31, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4 + } + ], + "minimumProcessingFps": 10.31, + "maximumDetectorLatencyMs": 16.9, + "maximumCriticalPathLatencyMs": 20.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 4, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 30, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 27, + "maximumCriticalPathLatencyMs": 30.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 11, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 14, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 28.3, + "maximumCriticalPathLatencyMs": 32, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 32.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 20, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 30.6, + "maximumCriticalPathLatencyMs": 34.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 23, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 35, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 28, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 39.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 31, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 38.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 35, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.95, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1 + } + ], + "minimumProcessingFps": 9.95, + "maximumDetectorLatencyMs": 35.9, + "maximumCriticalPathLatencyMs": 40.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 43, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4 + } + ], + "minimumProcessingFps": 10, + "maximumDetectorLatencyMs": 46.2, + "maximumCriticalPathLatencyMs": 50.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 47, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 48.5, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 53, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 60, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 9.86, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 9.86, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 68, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 0.524, + "missingRate": 0, + "averageDiscardRate": 0.0086, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 50, + "maximumCriticalPathLatencyMs": 65.4, + "averageDiscardRate": 0.0086, + "maximumChannelDiscardRate": 0.0218, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 95, + "cpuPeakPercent": 73, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (52.4%)" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 7, + "firstFailedChannels": 8, + "boundaryKind": "exact-boundary", + "display": "7", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.24, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6 + } + ], + "minimumProcessingFps": 24.24, + "maximumDetectorLatencyMs": 26.1, + "maximumCriticalPathLatencyMs": 29.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 9, + "cpuPeakPercent": 7, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.03, + "minimumFpsRatio": 1.001, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 24.03, + "maximumDetectorLatencyMs": 27.3, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 12, + "cpuPeakPercent": 13, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.81, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8 + } + ], + "minimumProcessingFps": 23.81, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 31.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 20, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.9, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8 + } + ], + "minimumProcessingFps": 23.9, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 33.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 28, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 34, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 36, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.88, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 23.88, + "maximumDetectorLatencyMs": 37.7, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 45, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.86, + "minimumFpsRatio": 0.994, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1 + } + ], + "minimumProcessingFps": 23.86, + "maximumDetectorLatencyMs": 40, + "maximumCriticalPathLatencyMs": 44.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 56, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 120, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 22.31, + "minimumFpsRatio": 0.929, + "missingRate": 0, + "averageDiscardRate": 0.0538, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5 + } + ], + "minimumProcessingFps": 22.31, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 49.5, + "averageDiscardRate": 0.0538, + "maximumChannelDiscardRate": 0.0601, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 85, + "cpuPeakPercent": 65, + "memoryPeakPercent": 40, + "failureReason": "average discard 5.38%" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.57, + "minimumFpsRatio": 1.114, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9 + } + ], + "minimumProcessingFps": 5.57, + "maximumDetectorLatencyMs": 42.9, + "maximumCriticalPathLatencyMs": 52.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 4, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 4, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.048, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 28.8, + "maximumCriticalPathLatencyMs": 35.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 8, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 7, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.16, + "minimumFpsRatio": 1.032, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2 + } + ], + "minimumProcessingFps": 5.16, + "maximumDetectorLatencyMs": 35.6, + "maximumCriticalPathLatencyMs": 43.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 11, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 29.2, + "maximumCriticalPathLatencyMs": 38.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 41.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 46.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 19, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 52.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38.9, + "maximumCriticalPathLatencyMs": 52.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 28, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 40.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 34, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 54.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 40, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 77.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 45, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 40.4, + "maximumCriticalPathLatencyMs": 58.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 49, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.87, + "minimumFpsRatio": 0.973, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7 + } + ], + "minimumProcessingFps": 4.87, + "maximumDetectorLatencyMs": 44.2, + "maximumCriticalPathLatencyMs": 63.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 54, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.89, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9 + } + ], + "minimumProcessingFps": 4.89, + "maximumDetectorLatencyMs": 41.5, + "maximumCriticalPathLatencyMs": 60.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 60, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.91, + "minimumFpsRatio": 0.982, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 4.91, + "maximumDetectorLatencyMs": 43.4, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 70, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 43.7, + "maximumCriticalPathLatencyMs": 68.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 62, + "cpuPeakPercent": 71, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.46, + "minimumFpsRatio": 1.066, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.46, + "maximumDetectorLatencyMs": 34.4, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 0, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 5, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 37.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 44, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 36.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 13, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 28.1, + "maximumCriticalPathLatencyMs": 40.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 18, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 48.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 25, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 33.2, + "maximumCriticalPathLatencyMs": 47.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 29, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.95, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 6.95, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 33, + "memoryPeakPercent": 45, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 33.9, + "maximumCriticalPathLatencyMs": 49.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 40, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 47, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 49, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 50, + "cpuPeakPercent": 57, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.92, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7 + } + ], + "minimumProcessingFps": 6.92, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 73.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": 53, + "cpuPeakPercent": 63, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 71.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 56, + "cpuPeakPercent": 67, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.83, + "minimumFpsRatio": 0.976, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7 + } + ], + "minimumProcessingFps": 6.83, + "maximumDetectorLatencyMs": 45.5, + "maximumCriticalPathLatencyMs": 66.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 59, + "cpuPeakPercent": 61, + "memoryPeakPercent": 46, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.68, + "minimumFpsRatio": 0.954, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104 + } + ], + "minimumProcessingFps": 6.68, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 104, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0016, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 73, + "memoryPeakPercent": 47, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.64, + "minimumFpsRatio": 0.949, + "missingRate": 0, + "averageDiscardRate": 0.0001, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7 + } + ], + "minimumProcessingFps": 6.64, + "maximumDetectorLatencyMs": 51.7, + "maximumCriticalPathLatencyMs": 102.7, + "averageDiscardRate": 0.0001, + "maximumChannelDiscardRate": 0.0024, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 68, + "cpuPeakPercent": 75, + "memoryPeakPercent": 47, + "failureReason": null + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "binding-blocked", + "display": "≥12*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.71, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8 + } + ], + "minimumProcessingFps": 10.71, + "maximumDetectorLatencyMs": 26.5, + "maximumCriticalPathLatencyMs": 34.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.28, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9 + } + ], + "minimumProcessingFps": 10.28, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 35.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 27.4, + "maximumCriticalPathLatencyMs": 37.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 14, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 27.8, + "maximumCriticalPathLatencyMs": 46.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 19, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 31.1, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 22, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4 + } + ], + "minimumProcessingFps": 9.98, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 41.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 32, + "cpuPeakPercent": 28, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 32.9, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 35, + "cpuPeakPercent": 36, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.92, + "minimumFpsRatio": 0.992, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9 + } + ], + "minimumProcessingFps": 9.92, + "maximumDetectorLatencyMs": 32.3, + "maximumCriticalPathLatencyMs": 48.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 44, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.88, + "minimumFpsRatio": 0.988, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8 + } + ], + "minimumProcessingFps": 9.88, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 57.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 41, + "cpuPeakPercent": 50, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 36.8, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": 44, + "cpuPeakPercent": 63, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 90.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 47, + "cpuPeakPercent": 67, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.83, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6 + } + ], + "minimumProcessingFps": 9.83, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 102.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 71, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 7, + "firstFailedChannels": 8, + "boundaryKind": "exact-boundary", + "display": "7", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.23, + "minimumFpsRatio": 1.093, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7 + } + ], + "minimumProcessingFps": 26.23, + "maximumDetectorLatencyMs": 26.4, + "maximumCriticalPathLatencyMs": 33.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 13, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.86, + "minimumFpsRatio": 1.036, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.86, + "maximumDetectorLatencyMs": 30.2, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": 19, + "cpuPeakPercent": 25, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.25, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7 + } + ], + "minimumProcessingFps": 24.25, + "maximumDetectorLatencyMs": 30.7, + "maximumCriticalPathLatencyMs": 40.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 38, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.08, + "minimumFpsRatio": 1.004, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3 + } + ], + "minimumProcessingFps": 24.08, + "maximumDetectorLatencyMs": 33, + "maximumCriticalPathLatencyMs": 47.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 25, + "cpuPeakPercent": 53, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58 + } + ], + "minimumProcessingFps": 24, + "maximumDetectorLatencyMs": 38.6, + "maximumCriticalPathLatencyMs": 58, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 68, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.31, + "minimumFpsRatio": 0.971, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2 + } + ], + "minimumProcessingFps": 23.31, + "maximumDetectorLatencyMs": 45, + "maximumCriticalPathLatencyMs": 80.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 74, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22, + "minimumFpsRatio": 0.917, + "missingRate": 0, + "averageDiscardRate": 0.0024, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8 + } + ], + "minimumProcessingFps": 22, + "maximumDetectorLatencyMs": 55, + "maximumCriticalPathLatencyMs": 92.8, + "averageDiscardRate": 0.0024, + "maximumChannelDiscardRate": 0.0055, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 78, + "cpuPeakPercent": 86, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18.07, + "minimumFpsRatio": 0.753, + "missingRate": 0, + "averageDiscardRate": 0.0535, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8 + } + ], + "minimumProcessingFps": 18.07, + "maximumDetectorLatencyMs": 59.3, + "maximumCriticalPathLatencyMs": 111.8, + "averageDiscardRate": 0.0535, + "maximumChannelDiscardRate": 0.084, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 88, + "cpuPeakPercent": 90, + "memoryPeakPercent": 43, + "failureReason": "average discard 5.35%" + } + ] + } + } + } + ], + "dualDetector": { + "highestVerifiedChannels": 16, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 15 + }, + "vlmObservation": { + "highestNonFpsPassingChannels": 8, + "firstNonFpsStopChannels": null, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + } + }, + { + "platformId": "cv186x", + "platform": "CV186X", + "singleDetector": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "binding-blocked", + "display": "≥15*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.28, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7 + } + ], + "minimumProcessingFps": 5.28, + "maximumDetectorLatencyMs": 17.2, + "maximumCriticalPathLatencyMs": 20.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 6, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.03, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23 + } + ], + "minimumProcessingFps": 5.03, + "maximumDetectorLatencyMs": 19.5, + "maximumCriticalPathLatencyMs": 23, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 21.1, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 3, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 30, + "maximumCriticalPathLatencyMs": 33.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 38, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 34.2, + "maximumCriticalPathLatencyMs": 37.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 34.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 44.4, + "maximumCriticalPathLatencyMs": 47.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 6, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 51.2, + "maximumCriticalPathLatencyMs": 54.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 7, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 60.4, + "maximumCriticalPathLatencyMs": 64, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 16, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 75.9, + "maximumCriticalPathLatencyMs": 79.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": 45, + "cpuPeakPercent": 17, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 69.4, + "maximumCriticalPathLatencyMs": 73.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 48, + "cpuPeakPercent": 18, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.98, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7 + } + ], + "minimumProcessingFps": 4.98, + "maximumDetectorLatencyMs": 68.7, + "maximumCriticalPathLatencyMs": 72.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 13, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 108.1, + "maximumCriticalPathLatencyMs": 112.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 92, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 22, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 4.63, + "minimumFpsRatio": 0.925, + "missingRate": 0, + "averageDiscardRate": 0.0018, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5 + } + ], + "minimumProcessingFps": 4.63, + "maximumDetectorLatencyMs": 96.6, + "maximumCriticalPathLatencyMs": 100.5, + "averageDiscardRate": 0.0018, + "maximumChannelDiscardRate": 0.0048, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 67, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 11, + "firstFailedChannels": 12, + "boundaryKind": "binding-blocked", + "display": "≥11*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.19, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8 + } + ], + "minimumProcessingFps": 7.19, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 22.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 2, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 30.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 22.8, + "maximumCriticalPathLatencyMs": 26.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 7, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 52.1, + "maximumCriticalPathLatencyMs": 56.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 31.3, + "maximumCriticalPathLatencyMs": 34.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 35.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 9, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.97, + "minimumFpsRatio": 0.995, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 6.97, + "maximumDetectorLatencyMs": 44.9, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 86, + "acceleratorMemoryPeakPercent": 43, + "cpuPeakPercent": 11, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 5.92, + "minimumFpsRatio": 0.845, + "missingRate": 0, + "averageDiscardRate": 0.0245, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2 + } + ], + "minimumProcessingFps": 5.92, + "maximumDetectorLatencyMs": 58.6, + "maximumCriticalPathLatencyMs": 62.2, + "averageDiscardRate": 0.0245, + "maximumChannelDiscardRate": 0.0519, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 55, + "cpuPeakPercent": 13, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 8, + "firstFailedChannels": 9, + "boundaryKind": "binding-blocked", + "display": "≥8*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.55, + "minimumFpsRatio": 1.055, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7 + } + ], + "minimumProcessingFps": 10.55, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 22.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.25, + "minimumFpsRatio": 1.025, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6 + } + ], + "minimumProcessingFps": 10.25, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.11, + "minimumFpsRatio": 1.011, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2 + } + ], + "minimumProcessingFps": 10.11, + "maximumDetectorLatencyMs": 21.6, + "maximumCriticalPathLatencyMs": 25.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 6, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 28.6, + "maximumCriticalPathLatencyMs": 32.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 37.2, + "maximumCriticalPathLatencyMs": 40.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 34.6, + "maximumCriticalPathLatencyMs": 38.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 8, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5 + } + ], + "minimumProcessingFps": 10.02, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 51.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 8, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.55, + "minimumFpsRatio": 0.855, + "missingRate": 0, + "averageDiscardRate": 0.0146, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3 + } + ], + "minimumProcessingFps": 8.55, + "maximumDetectorLatencyMs": 56.6, + "maximumCriticalPathLatencyMs": 60.3, + "averageDiscardRate": 0.0146, + "maximumChannelDiscardRate": 0.0262, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 58, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 3, + "firstFailedChannels": 4, + "boundaryKind": "binding-blocked", + "display": "≥3*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.93, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8 + } + ], + "minimumProcessingFps": 24.93, + "maximumDetectorLatencyMs": 18.8, + "maximumCriticalPathLatencyMs": 18.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 42, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 3, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.15, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5 + } + ], + "minimumProcessingFps": 24.15, + "maximumDetectorLatencyMs": 19, + "maximumCriticalPathLatencyMs": 22.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 72, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 5, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 23.52, + "minimumFpsRatio": 0.98, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 23.52, + "maximumDetectorLatencyMs": 43, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 22, + "cpuPeakPercent": 7, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 18.68, + "minimumFpsRatio": 0.778, + "missingRate": 0, + "averageDiscardRate": 0.0832, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59 + } + ], + "minimumProcessingFps": 18.68, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 59, + "averageDiscardRate": 0.0832, + "maximumChannelDiscardRate": 0.1384, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 10, + "memoryPeakPercent": 35, + "failureReason": "average discard 8.32%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "binding-blocked", + "display": "≥15*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.36, + "minimumFpsRatio": 1.071, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6 + } + ], + "minimumProcessingFps": 5.36, + "maximumDetectorLatencyMs": 20.6, + "maximumCriticalPathLatencyMs": 24.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 10, + "acceleratorMemoryPeakPercent": 13, + "cpuPeakPercent": 2, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 38.5, + "maximumCriticalPathLatencyMs": 45.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": 16, + "cpuPeakPercent": 4, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 19.3, + "maximumCriticalPathLatencyMs": 34.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 20, + "cpuPeakPercent": 9, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 20.2, + "maximumCriticalPathLatencyMs": 29.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 22.5, + "maximumCriticalPathLatencyMs": 33, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 38, + "acceleratorMemoryPeakPercent": 26, + "cpuPeakPercent": 15, + "memoryPeakPercent": 40, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 48.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 29, + "cpuPeakPercent": 17, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 53.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 33, + "cpuPeakPercent": 20, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 29, + "maximumCriticalPathLatencyMs": 43, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 36, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6 + } + ], + "minimumProcessingFps": 5, + "maximumDetectorLatencyMs": 33.7, + "maximumCriticalPathLatencyMs": 51.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": 39, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.97, + "minimumFpsRatio": 0.993, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9 + } + ], + "minimumProcessingFps": 4.97, + "maximumDetectorLatencyMs": 43.1, + "maximumCriticalPathLatencyMs": 61.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": 42, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.93, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4 + } + ], + "minimumProcessingFps": 4.93, + "maximumDetectorLatencyMs": 48.2, + "maximumCriticalPathLatencyMs": 101.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 84, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 26, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 53.1, + "maximumCriticalPathLatencyMs": 97.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 29, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.95, + "minimumFpsRatio": 0.99, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7 + } + ], + "minimumProcessingFps": 4.95, + "maximumDetectorLatencyMs": 75.7, + "maximumCriticalPathLatencyMs": 125.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 52, + "cpuPeakPercent": 28, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 173.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 64, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.22, + "minimumFpsRatio": 0.844, + "missingRate": 0, + "averageDiscardRate": 0.0209, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4 + } + ], + "minimumProcessingFps": 4.22, + "maximumDetectorLatencyMs": 122.7, + "maximumCriticalPathLatencyMs": 221.4, + "averageDiscardRate": 0.0209, + "maximumChannelDiscardRate": 0.0521, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 82, + "cpuPeakPercent": 44, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 11, + "firstFailedChannels": 12, + "boundaryKind": "binding-blocked", + "display": "≥11*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.45, + "minimumFpsRatio": 1.064, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8 + } + ], + "minimumProcessingFps": 7.45, + "maximumDetectorLatencyMs": 20.1, + "maximumCriticalPathLatencyMs": 26.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 4, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.22, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4 + } + ], + "minimumProcessingFps": 7.22, + "maximumDetectorLatencyMs": 55.7, + "maximumCriticalPathLatencyMs": 62.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 24, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 6, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 55.4, + "maximumCriticalPathLatencyMs": 65, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 9, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 23.9, + "maximumCriticalPathLatencyMs": 31.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 56.8, + "maximumCriticalPathLatencyMs": 69.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 46, + "acceleratorMemoryPeakPercent": 27, + "cpuPeakPercent": 14, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": 30, + "cpuPeakPercent": 18, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 54, + "maximumCriticalPathLatencyMs": 66.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 68, + "acceleratorMemoryPeakPercent": 34, + "cpuPeakPercent": 21, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 61.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": 37, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 85.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 90, + "acceleratorMemoryPeakPercent": 40, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.85, + "minimumFpsRatio": 0.978, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8 + } + ], + "minimumProcessingFps": 6.85, + "maximumDetectorLatencyMs": 59.8, + "maximumCriticalPathLatencyMs": 121.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 100, + "acceleratorMemoryPeakPercent": 49, + "cpuPeakPercent": 24, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.24, + "minimumFpsRatio": 0.891, + "missingRate": 0, + "averageDiscardRate": 0.0217, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2 + } + ], + "minimumProcessingFps": 6.24, + "maximumDetectorLatencyMs": 64.2, + "maximumCriticalPathLatencyMs": 133.2, + "averageDiscardRate": 0.0217, + "maximumChannelDiscardRate": 0.0447, + "acceleratorPeakPercent": 96, + "acceleratorMemoryPeakPercent": 71, + "cpuPeakPercent": 35, + "memoryPeakPercent": 43, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 8, + "firstFailedChannels": 9, + "boundaryKind": "binding-blocked", + "display": "≥8*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.45, + "minimumFpsRatio": 1.045, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2 + } + ], + "minimumProcessingFps": 10.45, + "maximumDetectorLatencyMs": 19.8, + "maximumCriticalPathLatencyMs": 26.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": 15, + "cpuPeakPercent": 5, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.2, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1 + } + ], + "minimumProcessingFps": 10.2, + "maximumDetectorLatencyMs": 46.7, + "maximumCriticalPathLatencyMs": 53.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": 18, + "cpuPeakPercent": 7, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.09, + "minimumFpsRatio": 1.009, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8 + } + ], + "minimumProcessingFps": 10.09, + "maximumDetectorLatencyMs": 45.2, + "maximumCriticalPathLatencyMs": 51.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": 21, + "cpuPeakPercent": 10, + "memoryPeakPercent": 41, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.14, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6 + } + ], + "minimumProcessingFps": 10.14, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 53.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": 24, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 47.9, + "maximumCriticalPathLatencyMs": 59.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": 28, + "cpuPeakPercent": 12, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 58.9, + "maximumCriticalPathLatencyMs": 75.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 31, + "cpuPeakPercent": 16, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.85, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1 + } + ], + "minimumProcessingFps": 9.85, + "maximumDetectorLatencyMs": 51.3, + "maximumCriticalPathLatencyMs": 81.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 38, + "cpuPeakPercent": 23, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0346, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 56.1, + "maximumCriticalPathLatencyMs": 96.9, + "averageDiscardRate": 0.0346, + "maximumChannelDiscardRate": 0.0466, + "acceleratorPeakPercent": 98, + "acceleratorMemoryPeakPercent": 60, + "cpuPeakPercent": 24, + "memoryPeakPercent": 42, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": null, + "maximumDetectorLatencyMs": null + }, + "lastPassingChannels": 3, + "firstFailedChannels": 4, + "boundaryKind": "binding-blocked", + "display": "≥3*", + "blockedReason": "task binding error; not a measured performance limit", + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.17, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7 + } + ], + "minimumProcessingFps": 24.17, + "maximumDetectorLatencyMs": 19.2, + "maximumCriticalPathLatencyMs": 24.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": 14, + "cpuPeakPercent": 5, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.89, + "minimumFpsRatio": 0.996, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4 + } + ], + "minimumProcessingFps": 23.89, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 47.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": 17, + "cpuPeakPercent": 9, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 23.66, + "minimumFpsRatio": 0.986, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7 + } + ], + "minimumProcessingFps": 23.66, + "maximumDetectorLatencyMs": 50.9, + "maximumCriticalPathLatencyMs": 59.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 88, + "acceleratorMemoryPeakPercent": 23, + "cpuPeakPercent": 12, + "memoryPeakPercent": 37, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 18, + "minimumFpsRatio": 0.75, + "missingRate": 0, + "averageDiscardRate": 0.0913, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3 + } + ], + "minimumProcessingFps": 18, + "maximumDetectorLatencyMs": 52.8, + "maximumCriticalPathLatencyMs": 75.3, + "averageDiscardRate": 0.0913, + "maximumChannelDiscardRate": 0.145, + "acceleratorPeakPercent": 94, + "acceleratorMemoryPeakPercent": 46, + "cpuPeakPercent": 17, + "memoryPeakPercent": 37, + "failureReason": "average discard 9.13%" + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [], + "minimumProcessingFps": null, + "maximumDetectorLatencyMs": null, + "maximumCriticalPathLatencyMs": null, + "averageDiscardRate": null, + "maximumChannelDiscardRate": null, + "failureReason": "an enabled performance or stability gate failed" + } + ] + } + } + } + ], + "dualDetector": { + "highestVerifiedChannels": 8, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 30 + }, + "vlmObservation": { + "highestNonFpsPassingChannels": 8, + "firstNonFpsStopChannels": null, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + } + }, + { + "platformId": "rk3576", + "platform": "RK3576", + "singleDetector": [ + { + "workload": "person-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 16, + "firstFailedChannels": null, + "boundaryKind": "lower-bound", + "display": "≥16", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.69, + "minimumFpsRatio": 1.138, + "missingRate": 0, + "averageDiscardRate": 0.0482, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1 + } + ], + "minimumProcessingFps": 5.69, + "maximumDetectorLatencyMs": 63.6, + "maximumCriticalPathLatencyMs": 78.1, + "averageDiscardRate": 0.0482, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 12, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 11, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.33, + "minimumFpsRatio": 1.067, + "missingRate": 0, + "averageDiscardRate": 0.0391, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6 + } + ], + "minimumProcessingFps": 5.33, + "maximumDetectorLatencyMs": 68.5, + "maximumCriticalPathLatencyMs": 73.6, + "averageDiscardRate": 0.0391, + "maximumChannelDiscardRate": 0.0482, + "acceleratorPeakPercent": 18, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.24, + "minimumFpsRatio": 1.049, + "missingRate": 0, + "averageDiscardRate": 0.0481, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9 + } + ], + "minimumProcessingFps": 5.24, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 62.9, + "averageDiscardRate": 0.0481, + "maximumChannelDiscardRate": 0.0747, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 48.4, + "maximumCriticalPathLatencyMs": 54.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 23, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42, + "maximumCriticalPathLatencyMs": 47.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 28, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 27, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 42.7, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.15, + "minimumFpsRatio": 1.031, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1 + } + ], + "minimumProcessingFps": 5.15, + "maximumDetectorLatencyMs": 49.3, + "maximumCriticalPathLatencyMs": 54.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 34, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 30, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 44.1, + "maximumCriticalPathLatencyMs": 49.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 50.8, + "maximumCriticalPathLatencyMs": 55.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 45, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.14, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1 + } + ], + "minimumProcessingFps": 5.14, + "maximumDetectorLatencyMs": 68.3, + "maximumCriticalPathLatencyMs": 73.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 41, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 46.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 50, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 97.9, + "maximumCriticalPathLatencyMs": 102, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 46.1, + "maximumCriticalPathLatencyMs": 61.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.12, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7 + } + ], + "minimumProcessingFps": 5.12, + "maximumDetectorLatencyMs": 74.8, + "maximumCriticalPathLatencyMs": 78.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 58, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 51.5, + "maximumCriticalPathLatencyMs": 55.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 65, + "memoryPeakPercent": 36, + "failureReason": null + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.31, + "minimumFpsRatio": 1.044, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3 + } + ], + "minimumProcessingFps": 7.31, + "maximumDetectorLatencyMs": 64.1, + "maximumCriticalPathLatencyMs": 72.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 13, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.21, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1 + } + ], + "minimumProcessingFps": 7.21, + "maximumDetectorLatencyMs": 52.6, + "maximumCriticalPathLatencyMs": 60.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 23, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.2, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9 + } + ], + "minimumProcessingFps": 7.2, + "maximumDetectorLatencyMs": 45.1, + "maximumCriticalPathLatencyMs": 51.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 26, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.17, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3 + } + ], + "minimumProcessingFps": 7.17, + "maximumDetectorLatencyMs": 42.5, + "maximumCriticalPathLatencyMs": 48.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 43.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37, + "maximumCriticalPathLatencyMs": 41.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 41, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 37.5, + "maximumCriticalPathLatencyMs": 42.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 45, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 37, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 39.3, + "maximumCriticalPathLatencyMs": 44, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 51, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 42.3, + "maximumCriticalPathLatencyMs": 47.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 47, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 47.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.14, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3 + } + ], + "minimumProcessingFps": 7.14, + "maximumDetectorLatencyMs": 46.4, + "maximumCriticalPathLatencyMs": 51.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 64, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 45.7, + "maximumCriticalPathLatencyMs": 50, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 67, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.12, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1 + } + ], + "minimumProcessingFps": 7.12, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 67.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 75, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 83.6, + "maximumCriticalPathLatencyMs": 92.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 39, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 7, + "minimumProcessingFps": 6.69, + "minimumFpsRatio": 0.956, + "missingRate": 0, + "averageDiscardRate": 0.0269, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240 + } + ], + "minimumProcessingFps": 6.69, + "maximumDetectorLatencyMs": 179.8, + "maximumCriticalPathLatencyMs": 240, + "averageDiscardRate": 0.0269, + "maximumChannelDiscardRate": 0.2269, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 98, + "memoryPeakPercent": 74, + "failureReason": "critical-path latency 240 ms" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "exact-boundary", + "display": "12", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.86, + "minimumFpsRatio": 1.086, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5 + } + ], + "minimumProcessingFps": 10.86, + "maximumDetectorLatencyMs": 56.3, + "maximumCriticalPathLatencyMs": 65.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.41, + "minimumFpsRatio": 1.041, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7 + } + ], + "minimumProcessingFps": 10.41, + "maximumDetectorLatencyMs": 47.7, + "maximumCriticalPathLatencyMs": 55.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 25, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 22, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.27, + "minimumFpsRatio": 1.027, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2 + } + ], + "minimumProcessingFps": 10.27, + "maximumDetectorLatencyMs": 41.9, + "maximumCriticalPathLatencyMs": 49.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 44.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 40, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.19, + "minimumFpsRatio": 1.019, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5 + } + ], + "minimumProcessingFps": 10.19, + "maximumDetectorLatencyMs": 35.2, + "maximumCriticalPathLatencyMs": 40.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 31, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 43.3, + "maximumCriticalPathLatencyMs": 48.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 37.3, + "maximumCriticalPathLatencyMs": 42.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 52, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.18, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1 + } + ], + "minimumProcessingFps": 10.18, + "maximumDetectorLatencyMs": 43.9, + "maximumCriticalPathLatencyMs": 49.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 52, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 44.5, + "maximumCriticalPathLatencyMs": 49.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 58, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.13, + "minimumFpsRatio": 1.013, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3 + } + ], + "minimumProcessingFps": 10.13, + "maximumDetectorLatencyMs": 86.7, + "maximumCriticalPathLatencyMs": 91.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 10.17, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5 + } + ], + "minimumProcessingFps": 10.17, + "maximumDetectorLatencyMs": 55.2, + "maximumCriticalPathLatencyMs": 60.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 87, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.29, + "minimumFpsRatio": 0.829, + "missingRate": 0, + "averageDiscardRate": 0.0154, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8 + } + ], + "minimumProcessingFps": 8.29, + "maximumDetectorLatencyMs": 105, + "maximumCriticalPathLatencyMs": 152.8, + "averageDiscardRate": 0.0154, + "maximumChannelDiscardRate": 0.1849, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.57, + "minimumFpsRatio": 0.857, + "missingRate": 0, + "averageDiscardRate": 0.0604, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3 + } + ], + "minimumProcessingFps": 8.57, + "maximumDetectorLatencyMs": 121.7, + "maximumCriticalPathLatencyMs": 200.3, + "averageDiscardRate": 0.0604, + "maximumChannelDiscardRate": 0.246, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 63, + "failureReason": "average discard 6.04%" + }, + { + "channels": 14, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 8.07, + "minimumFpsRatio": 0.807, + "missingRate": 0, + "averageDiscardRate": 0.1327, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1 + } + ], + "minimumProcessingFps": 8.07, + "maximumDetectorLatencyMs": 143.7, + "maximumCriticalPathLatencyMs": 209.1, + "averageDiscardRate": 0.1327, + "maximumChannelDiscardRate": 0.2667, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 67, + "failureReason": "average discard 13.27%" + }, + { + "channels": 15, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.4, + "minimumFpsRatio": 0.74, + "missingRate": 0, + "averageDiscardRate": 0.2054, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7 + } + ], + "minimumProcessingFps": 7.4, + "maximumDetectorLatencyMs": 135.5, + "maximumCriticalPathLatencyMs": 225.7, + "averageDiscardRate": 0.2054, + "maximumChannelDiscardRate": 0.2914, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 70, + "failureReason": "average discard 20.54%" + }, + { + "channels": 16, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 10, + "minimumProcessingFps": 7.07, + "minimumFpsRatio": 0.707, + "missingRate": 0, + "averageDiscardRate": 0.2669, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1 + } + ], + "minimumProcessingFps": 7.07, + "maximumDetectorLatencyMs": 149.6, + "maximumCriticalPathLatencyMs": 284.1, + "averageDiscardRate": 0.2669, + "maximumChannelDiscardRate": 0.3152, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 74, + "failureReason": "average discard 26.69%" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 6, + "firstFailedChannels": 7, + "boundaryKind": "exact-boundary", + "display": "6", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 26, + "minimumFpsRatio": 1.083, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6 + } + ], + "minimumProcessingFps": 26, + "maximumDetectorLatencyMs": 31.9, + "maximumCriticalPathLatencyMs": 41.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 14, + "memoryPeakPercent": 18, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.72, + "minimumFpsRatio": 1.03, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2 + } + ], + "minimumProcessingFps": 24.72, + "maximumDetectorLatencyMs": 31.6, + "maximumCriticalPathLatencyMs": 41.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 25, + "memoryPeakPercent": 19, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.48, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6 + } + ], + "minimumProcessingFps": 24.48, + "maximumDetectorLatencyMs": 30.5, + "maximumCriticalPathLatencyMs": 37.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 53, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 36, + "memoryPeakPercent": 20, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.36, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5 + } + ], + "minimumProcessingFps": 24.36, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 44.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 51, + "memoryPeakPercent": 21, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 24.34, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5 + } + ], + "minimumProcessingFps": 24.34, + "maximumDetectorLatencyMs": 40.9, + "maximumCriticalPathLatencyMs": 50.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 66, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 20.43, + "minimumFpsRatio": 0.851, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5 + } + ], + "minimumProcessingFps": 20.43, + "maximumDetectorLatencyMs": 49.7, + "maximumCriticalPathLatencyMs": 71.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 84, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 17.63, + "minimumFpsRatio": 0.734, + "missingRate": 0, + "averageDiscardRate": 0.0141, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5 + } + ], + "minimumProcessingFps": 17.63, + "maximumDetectorLatencyMs": 57.7, + "maximumCriticalPathLatencyMs": 80.5, + "averageDiscardRate": 0.0141, + "maximumChannelDiscardRate": 0.0397, + "acceleratorPeakPercent": 85, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 41, + "failureReason": "processing-FPS gate failed (73.4%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "person-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0378, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 66.7, + "maximumCriticalPathLatencyMs": 98.6, + "averageDiscardRate": 0.0378, + "maximumChannelDiscardRate": 0.0811, + "acceleratorPeakPercent": 81, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 90, + "memoryPeakPercent": 45, + "failureReason": "processing-FPS gate failed (66.7%)" + } + ] + } + } + }, + { + "workload": "safety-helmet-detector", + "points": { + "5": { + "targetFps": 5, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 15, + "firstFailedChannels": 16, + "boundaryKind": "exact-boundary", + "display": "15", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.2, + "minimumFpsRatio": 1.039, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7 + } + ], + "minimumProcessingFps": 5.2, + "maximumDetectorLatencyMs": 58, + "maximumCriticalPathLatencyMs": 132.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 14, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 49, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 20, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.11, + "minimumFpsRatio": 1.023, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5 + } + ], + "minimumProcessingFps": 5.11, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 86.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 105.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 28, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 35.8, + "maximumCriticalPathLatencyMs": 78.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 31, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 34, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 38.1, + "maximumCriticalPathLatencyMs": 79.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.1, + "minimumFpsRatio": 1.02, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1 + } + ], + "minimumProcessingFps": 5.1, + "maximumDetectorLatencyMs": 66.8, + "maximumCriticalPathLatencyMs": 106.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 42, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.05, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3 + } + ], + "minimumProcessingFps": 5.05, + "maximumDetectorLatencyMs": 36.2, + "maximumCriticalPathLatencyMs": 89.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 45, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 69.7, + "maximumCriticalPathLatencyMs": 117, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 44, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 38.7, + "maximumCriticalPathLatencyMs": 116.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 49, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2 + } + ], + "minimumProcessingFps": 5.02, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 111.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 57, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 94.5, + "maximumCriticalPathLatencyMs": 129.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 64, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.07, + "minimumFpsRatio": 1.014, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4 + } + ], + "minimumProcessingFps": 5.07, + "maximumDetectorLatencyMs": 42.1, + "maximumCriticalPathLatencyMs": 91.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 62, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 70, + "memoryPeakPercent": 35, + "failureReason": null + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 109.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 66, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 77, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 5.08, + "minimumFpsRatio": 1.017, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169 + } + ], + "minimumProcessingFps": 5.08, + "maximumDetectorLatencyMs": 48.3, + "maximumCriticalPathLatencyMs": 169, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 67, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 38, + "failureReason": null + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 5, + "minimumProcessingFps": 4.78, + "minimumFpsRatio": 0.957, + "missingRate": 0, + "averageDiscardRate": 0.0283, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2 + } + ], + "minimumProcessingFps": 4.78, + "maximumDetectorLatencyMs": 258.1, + "maximumCriticalPathLatencyMs": 601.2, + "averageDiscardRate": 0.0283, + "maximumChannelDiscardRate": 0.1038, + "acceleratorPeakPercent": 70, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 76, + "failureReason": "critical-path latency 601.2 ms" + } + ] + }, + "7": { + "targetFps": 7, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 12, + "firstFailedChannels": 13, + "boundaryKind": "exact-boundary", + "display": "12", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 120, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.08, + "minimumFpsRatio": 1.012, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9 + } + ], + "minimumProcessingFps": 7.08, + "maximumDetectorLatencyMs": 52.9, + "maximumCriticalPathLatencyMs": 116.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 16, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 16, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.9, + "minimumFpsRatio": 0.985, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8 + } + ], + "minimumProcessingFps": 6.9, + "maximumDetectorLatencyMs": 40.5, + "maximumCriticalPathLatencyMs": 141.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 22, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 21, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 60, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.98, + "minimumFpsRatio": 0.998, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87 + } + ], + "minimumProcessingFps": 6.98, + "maximumDetectorLatencyMs": 36.9, + "maximumCriticalPathLatencyMs": 87, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 29, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 26, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.15, + "minimumFpsRatio": 1.022, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7 + } + ], + "minimumProcessingFps": 7.15, + "maximumDetectorLatencyMs": 35.4, + "maximumCriticalPathLatencyMs": 118.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 32, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 33, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.05, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5 + } + ], + "minimumProcessingFps": 7.05, + "maximumDetectorLatencyMs": 36.5, + "maximumCriticalPathLatencyMs": 83.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 36, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 38, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7, + "minimumFpsRatio": 1, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1 + } + ], + "minimumProcessingFps": 7, + "maximumDetectorLatencyMs": 48, + "maximumCriticalPathLatencyMs": 143.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 43, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 43, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.002, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 36.3, + "maximumCriticalPathLatencyMs": 158, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 48, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.06, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.06, + "maximumDetectorLatencyMs": 52.2, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 54, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.1, + "minimumFpsRatio": 1.015, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1 + } + ], + "minimumProcessingFps": 7.1, + "maximumDetectorLatencyMs": 41.7, + "maximumCriticalPathLatencyMs": 85.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.02, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1 + } + ], + "minimumProcessingFps": 7.02, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 120.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 63, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 68, + "memoryPeakPercent": 32, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 7.03, + "minimumFpsRatio": 1.005, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9 + } + ], + "minimumProcessingFps": 7.03, + "maximumDetectorLatencyMs": 39.8, + "maximumCriticalPathLatencyMs": 68.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 71, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 73, + "memoryPeakPercent": 33, + "failureReason": null + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.88, + "minimumFpsRatio": 0.983, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95 + } + ], + "minimumProcessingFps": 6.88, + "maximumDetectorLatencyMs": 51.8, + "maximumCriticalPathLatencyMs": 95, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 73, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 93, + "memoryPeakPercent": 34, + "failureReason": null + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.39, + "minimumFpsRatio": 0.913, + "missingRate": 0, + "averageDiscardRate": 0.025, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9 + } + ], + "minimumProcessingFps": 6.39, + "maximumDetectorLatencyMs": 166.2, + "maximumCriticalPathLatencyMs": 329.9, + "averageDiscardRate": 0.025, + "maximumChannelDiscardRate": 0.097, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 61, + "failureReason": "critical-path latency 329.9 ms" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.15, + "minimumFpsRatio": 0.879, + "missingRate": 0, + "averageDiscardRate": 0.1289, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8 + } + ], + "minimumProcessingFps": 6.15, + "maximumDetectorLatencyMs": 262.2, + "maximumCriticalPathLatencyMs": 542.8, + "averageDiscardRate": 0.1289, + "maximumChannelDiscardRate": 0.2873, + "acceleratorPeakPercent": 76, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 70, + "failureReason": "average discard 12.89%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 6.14, + "minimumFpsRatio": 0.877, + "missingRate": 0, + "averageDiscardRate": 0.2354, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2 + } + ], + "minimumProcessingFps": 6.14, + "maximumDetectorLatencyMs": 163.9, + "maximumCriticalPathLatencyMs": 350.2, + "averageDiscardRate": 0.2354, + "maximumChannelDiscardRate": 0.3611, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 74, + "failureReason": "average discard 23.54%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 7, + "minimumProcessingFps": 5.93, + "minimumFpsRatio": 0.847, + "missingRate": 0, + "averageDiscardRate": 0.2928, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8 + } + ], + "minimumProcessingFps": 5.93, + "maximumDetectorLatencyMs": 175.2, + "maximumCriticalPathLatencyMs": 412.8, + "averageDiscardRate": 0.2928, + "maximumChannelDiscardRate": 0.3552, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 79, + "failureReason": "average discard 29.28%" + } + ] + }, + "10": { + "targetFps": 10, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 10, + "firstFailedChannels": 11, + "boundaryKind": "exact-boundary", + "display": "10", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 49.8, + "maximumCriticalPathLatencyMs": 102.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 21, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 17, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.21, + "minimumFpsRatio": 1.021, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5 + } + ], + "minimumProcessingFps": 10.21, + "maximumDetectorLatencyMs": 37.9, + "maximumCriticalPathLatencyMs": 76.5, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 27, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 24, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.24, + "minimumFpsRatio": 1.024, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2 + } + ], + "minimumProcessingFps": 10.24, + "maximumDetectorLatencyMs": 34.5, + "maximumCriticalPathLatencyMs": 88.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 37, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 32, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.08, + "minimumFpsRatio": 1.008, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3 + } + ], + "minimumProcessingFps": 10.08, + "maximumDetectorLatencyMs": 40.2, + "maximumCriticalPathLatencyMs": 81.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 39, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 40, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.03, + "minimumFpsRatio": 1.003, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8 + } + ], + "minimumProcessingFps": 10.03, + "maximumDetectorLatencyMs": 78.8, + "maximumCriticalPathLatencyMs": 109.8, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 47, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 46, + "memoryPeakPercent": 27, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.97, + "minimumFpsRatio": 0.997, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9 + } + ], + "minimumProcessingFps": 9.97, + "maximumDetectorLatencyMs": 38.3, + "maximumCriticalPathLatencyMs": 87.9, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 56, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 54, + "memoryPeakPercent": 28, + "failureReason": null + }, + { + "channels": 7, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.1, + "minimumFpsRatio": 1.01, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4 + } + ], + "minimumProcessingFps": 10.1, + "maximumDetectorLatencyMs": 39, + "maximumCriticalPathLatencyMs": 98.4, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 61, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 62, + "memoryPeakPercent": 29, + "failureReason": null + }, + { + "channels": 8, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.06, + "minimumFpsRatio": 1.006, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3 + } + ], + "minimumProcessingFps": 10.06, + "maximumDetectorLatencyMs": 39.2, + "maximumCriticalPathLatencyMs": 79.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 69, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 71, + "memoryPeakPercent": 30, + "failureReason": null + }, + { + "channels": 9, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 10.07, + "minimumFpsRatio": 1.007, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3 + } + ], + "minimumProcessingFps": 10.07, + "maximumDetectorLatencyMs": 45.3, + "maximumCriticalPathLatencyMs": 83.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 74, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 88, + "memoryPeakPercent": 31, + "failureReason": null + }, + { + "channels": 10, + "holdSeconds": 30, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.94, + "minimumFpsRatio": 0.894, + "missingRate": 0, + "averageDiscardRate": 0.007, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5 + } + ], + "minimumProcessingFps": 8.94, + "maximumDetectorLatencyMs": 106.4, + "maximumCriticalPathLatencyMs": 181.5, + "averageDiscardRate": 0.007, + "maximumChannelDiscardRate": 0.0303, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 97, + "memoryPeakPercent": 55, + "failureReason": null + }, + { + "channels": 11, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 9.02, + "minimumFpsRatio": 0.902, + "missingRate": 0, + "averageDiscardRate": 0.1126, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6 + } + ], + "minimumProcessingFps": 9.02, + "maximumDetectorLatencyMs": 111.4, + "maximumCriticalPathLatencyMs": 204.6, + "averageDiscardRate": 0.1126, + "maximumChannelDiscardRate": 0.1859, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 59, + "failureReason": "average discard 11.26%" + }, + { + "channels": 12, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.83, + "minimumFpsRatio": 0.883, + "missingRate": 0, + "averageDiscardRate": 0.2311, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5 + } + ], + "minimumProcessingFps": 8.83, + "maximumDetectorLatencyMs": 117.7, + "maximumCriticalPathLatencyMs": 242.5, + "averageDiscardRate": 0.2311, + "maximumChannelDiscardRate": 0.2766, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 63, + "failureReason": "average discard 23.11%" + }, + { + "channels": 13, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 8.14, + "minimumFpsRatio": 0.814, + "missingRate": 0, + "averageDiscardRate": 0.2846, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6 + } + ], + "minimumProcessingFps": 8.14, + "maximumDetectorLatencyMs": 129.9, + "maximumCriticalPathLatencyMs": 272.6, + "averageDiscardRate": 0.2846, + "maximumChannelDiscardRate": 0.301, + "acceleratorPeakPercent": 78, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 67, + "failureReason": "average discard 28.46%" + }, + { + "channels": 14, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 7.41, + "minimumFpsRatio": 0.741, + "missingRate": 0, + "averageDiscardRate": 0.3041, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3 + } + ], + "minimumProcessingFps": 7.41, + "maximumDetectorLatencyMs": 145.6, + "maximumCriticalPathLatencyMs": 302.3, + "averageDiscardRate": 0.3041, + "maximumChannelDiscardRate": 0.3172, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 72, + "failureReason": "average discard 30.41%" + }, + { + "channels": 15, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.76, + "minimumFpsRatio": 0.676, + "missingRate": 0, + "averageDiscardRate": 0.3202, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7 + } + ], + "minimumProcessingFps": 6.76, + "maximumDetectorLatencyMs": 149.9, + "maximumCriticalPathLatencyMs": 397.7, + "averageDiscardRate": 0.3202, + "maximumChannelDiscardRate": 0.3321, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 95, + "memoryPeakPercent": 75, + "failureReason": "average discard 32.02%" + }, + { + "channels": 16, + "holdSeconds": 30, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 10, + "minimumProcessingFps": 6.3, + "minimumFpsRatio": 0.63, + "missingRate": 0, + "averageDiscardRate": 0.3395, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6 + } + ], + "minimumProcessingFps": 6.3, + "maximumDetectorLatencyMs": 161.5, + "maximumCriticalPathLatencyMs": 367.6, + "averageDiscardRate": 0.3395, + "maximumChannelDiscardRate": 0.3516, + "acceleratorPeakPercent": 75, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 96, + "memoryPeakPercent": 78, + "failureReason": "average discard 33.95%" + } + ] + }, + "24": { + "targetFps": 24, + "evidenceDate": "2026-08-11", + "gates": { + "minimumFpsRatio": 0.8, + "maximumMissingRate": 0, + "maximumAverageDiscardRate": 0.05, + "maximumCriticalPathLatencyMs": 200, + "maximumDetectorLatencyMs": 150 + }, + "lastPassingChannels": 5, + "firstFailedChannels": 6, + "boundaryKind": "exact-boundary", + "display": "5", + "blockedReason": null, + "steps": [ + { + "channels": 1, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 26.38, + "minimumFpsRatio": 1.099, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3 + } + ], + "minimumProcessingFps": 26.38, + "maximumDetectorLatencyMs": 30.1, + "maximumCriticalPathLatencyMs": 62.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 30, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 19, + "memoryPeakPercent": 23, + "failureReason": null + }, + { + "channels": 2, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 25.11, + "minimumFpsRatio": 1.046, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3 + } + ], + "minimumProcessingFps": 25.11, + "maximumDetectorLatencyMs": 27.2, + "maximumCriticalPathLatencyMs": 57.3, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 35, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 35, + "memoryPeakPercent": 24, + "failureReason": null + }, + { + "channels": 3, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.68, + "minimumFpsRatio": 1.028, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1 + } + ], + "minimumProcessingFps": 24.68, + "maximumDetectorLatencyMs": 31.2, + "maximumCriticalPathLatencyMs": 57.1, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 60, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 49, + "memoryPeakPercent": 25, + "failureReason": null + }, + { + "channels": 4, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 24.44, + "minimumFpsRatio": 1.018, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6 + } + ], + "minimumProcessingFps": 24.44, + "maximumDetectorLatencyMs": 30.9, + "maximumCriticalPathLatencyMs": 52.6, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 60, + "memoryPeakPercent": 26, + "failureReason": null + }, + { + "channels": 5, + "holdSeconds": 15, + "result": "PASS", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 22.43, + "minimumFpsRatio": 0.935, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2 + } + ], + "minimumProcessingFps": 22.43, + "maximumDetectorLatencyMs": 46.9, + "maximumCriticalPathLatencyMs": 83.2, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 77, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 83, + "memoryPeakPercent": 36, + "failureReason": null + }, + { + "channels": 6, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 19, + "minimumFpsRatio": 0.792, + "missingRate": 0, + "averageDiscardRate": 0, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7 + } + ], + "minimumProcessingFps": 19, + "maximumDetectorLatencyMs": 56.4, + "maximumCriticalPathLatencyMs": 104.7, + "averageDiscardRate": 0, + "maximumChannelDiscardRate": 0, + "acceleratorPeakPercent": 80, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 89, + "memoryPeakPercent": 40, + "failureReason": "processing-FPS gate failed (79.2%)" + }, + { + "channels": 7, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 16, + "minimumFpsRatio": 0.667, + "missingRate": 0, + "averageDiscardRate": 0.0376, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4 + } + ], + "minimumProcessingFps": 16, + "maximumDetectorLatencyMs": 65.8, + "maximumCriticalPathLatencyMs": 109.4, + "averageDiscardRate": 0.0376, + "maximumChannelDiscardRate": 0.0679, + "acceleratorPeakPercent": 79, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 44, + "failureReason": "processing-FPS gate failed (66.7%)" + }, + { + "channels": 8, + "holdSeconds": 15, + "result": "FAIL", + "tasks": [ + { + "name": "safety-helmet-detector", + "targetFps": 24, + "minimumProcessingFps": 13.79, + "minimumFpsRatio": 0.574, + "missingRate": 0, + "averageDiscardRate": 0.0754, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133 + } + ], + "minimumProcessingFps": 13.79, + "maximumDetectorLatencyMs": 73.9, + "maximumCriticalPathLatencyMs": 133, + "averageDiscardRate": 0.0754, + "maximumChannelDiscardRate": 0.0958, + "acceleratorPeakPercent": 82, + "acceleratorMemoryPeakPercent": null, + "cpuPeakPercent": 92, + "memoryPeakPercent": 47, + "failureReason": "average discard 7.54%" + } + ] + } + } + } + ], + "dualDetector": { + "highestVerifiedChannels": 8, + "boundaryKind": "lower-bound", + "allConfiguredStepsPassed": true, + "holdSecondsAtHighestPoint": 15 + }, + "vlmObservation": { + "highestNonFpsPassingChannels": 7, + "firstNonFpsStopChannels": 8, + "capacityClaimAllowed": false, + "reason": "analysis FPS gate disabled" + } + } + ] +} diff --git a/docs/benchmarks/scenario-bench/v1.1/scenarios/README.md b/docs/benchmarks/scenario-bench/v1.1/scenarios/README.md new file mode 100644 index 000000000..354a3ee06 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/scenarios/README.md @@ -0,0 +1,7 @@ +# Scenario package status + +`dual-detector/scenario.public.yml` is the sanitized semantic workload definition. + +It intentionally omits internal algorithm IDs, schedule IDs, action IDs, device endpoints, and orchestration templates. A directly executable per-platform scenario cannot be published until the public model identities, import process, legal sample video, and release package are frozen. The final release process must generate device-resolved scenario bundles from the public model card and release manifest. + +Do not insert internal identifiers merely to make this draft executable. diff --git a/docs/benchmarks/scenario-bench/v1.1/scenarios/dual-detector/scenario.public.yml b/docs/benchmarks/scenario-bench/v1.1/scenarios/dual-detector/scenario.public.yml new file mode 100644 index 000000000..b0e1853da --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/scenarios/dual-detector/scenario.public.yml @@ -0,0 +1,45 @@ +version: 2 +name: dual-detector-5fps-staircase +displayName: Dual-detector 5 FPS per channel staircase +sampleIntervalSec: 3 + +channels: + mode: local + repeatCount: 0 + sources: + - name: public-1080p24-sample + file: "../../dataset/Safety Helmet.mp4" + +tasks: + - id: person-detector + displayName: Person detector + type: cv + modelRef: "../../models/.json#person-detector" + targetFps: 5 + - id: safety-helmet-detector + displayName: Safety-helmet detector + type: cv + modelRef: "../../models/.json#safety-helmet-classifier" + targetFps: 5 + +bindings: + - task: person-detector + channels: all + - task: safety-helmet-detector + channels: all + +thresholds: + pass: + avgDiscardRate: 0.05 + taskTypes: + cv: + minFpsRatio: 0.8 + maxMissingRate: 0 + +loadProfile: + # Use the platform-specific step duration recorded in results/*/summary.json. + - channels: "1.." + holdSec: "" + +# This public descriptor is deliberately device-resolved at execution time. +# Internal algorithm and schedule identifiers are not part of the public identity. diff --git a/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/README.md b/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/README.md new file mode 100644 index 000000000..22b6b2248 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/README.md @@ -0,0 +1,6 @@ +# Single-detector reproduction descriptors + +- `person-detector.public.yml`: personnel detection at 24, 10, 7, and 5 FPS. +- `safety-helmet-detector.public.yml`: two-stage safety-helmet workload at the same FPS gradient. + +Each file is a public descriptor. Before execution, resolve the model reference and device-specific algorithm layout locally. Do not commit device addresses, credentials, schedule IDs, internal algorithm IDs, or channel IDs. diff --git a/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/person-detector.public.yml b/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/person-detector.public.yml new file mode 100644 index 000000000..58cf03d17 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/person-detector.public.yml @@ -0,0 +1,34 @@ +version: 2 +name: person-detector-fps-gradient +displayName: Person detector 24/10/7/5 FPS staircase +sampleIntervalSec: 3 + +channels: + mode: local + repeatCount: 0 + sources: + - name: public-1080p24-sample + file: "../../dataset/Safety Helmet.mp4" + +tasks: + - id: person-detector + displayName: Person detector + type: cv + modelRef: "../../models/.json#person-detector" + targetFps: "<24|10|7|5>" + +bindings: + - task: person-detector + channels: all + +loadProfile: + - channels: "1.." + holdSec: "" + +thresholds: + pass: + avgDiscardRate: 0.05 + taskTypes: + cv: + minFpsRatio: 0.8 + maxMissingRate: 0 diff --git a/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/safety-helmet-detector.public.yml b/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/safety-helmet-detector.public.yml new file mode 100644 index 000000000..d59f46a08 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/scenarios/single-detector/safety-helmet-detector.public.yml @@ -0,0 +1,36 @@ +version: 2 +name: safety-helmet-detector-fps-gradient +displayName: Safety-helmet detector 24/10/7/5 FPS staircase +sampleIntervalSec: 3 + +channels: + mode: local + repeatCount: 0 + sources: + - name: public-1080p24-sample + file: "../../dataset/Safety Helmet.mp4" + +tasks: + - id: safety-helmet-detector + displayName: Safety-helmet detector + type: cv + modelRefs: + - "../../models/.json#person-detector" + - "../../models/.json#safety-helmet-classifier" + targetFps: "<24|10|7|5>" + +bindings: + - task: safety-helmet-detector + channels: all + +loadProfile: + - channels: "1.." + holdSec: "" + +thresholds: + pass: + avgDiscardRate: 0.05 + taskTypes: + cv: + minFpsRatio: 0.8 + maxMissingRate: 0 diff --git a/docs/benchmarks/scenario-bench/v1.1/scenarios/vlm-observation/scenario.public.yml b/docs/benchmarks/scenario-bench/v1.1/scenarios/vlm-observation/scenario.public.yml new file mode 100644 index 000000000..7ac9b4882 --- /dev/null +++ b/docs/benchmarks/scenario-bench/v1.1/scenarios/vlm-observation/scenario.public.yml @@ -0,0 +1,52 @@ +version: 2 +name: vlm-0p1fps-runtime-observation +displayName: VLM 0.1 FPS per-channel runtime observation +sampleIntervalSec: 10 + +channels: + mode: local + repeatCount: 0 + sources: + - name: public-1080p24-sample + file: "../../dataset/Safety Helmet.mp4" + +tasks: + - id: vlm-observation + displayName: Vision-language model observation + type: vlm + modelRef: "../../models/.json#vlm" + targetFps: 0.1 + +bindings: + - task: vlm-observation + channels: all + +loadProfile: + - channels: 1 + holdSec: 120 + - channels: 2 + holdSec: 120 + - channels: 3 + holdSec: 120 + - channels: 4 + holdSec: 120 + - channels: 5 + holdSec: 120 + - channels: 6 + holdSec: 120 + - channels: 7 + holdSec: 120 + - channels: 8 + holdSec: 120 + +thresholds: + pass: + avgDiscardRate: 0.05 + taskTypes: + vlm: + minFpsRatio: null + maxMissingRate: 0 + +# Analysis FPS is observed but deliberately excluded from PASS/FAIL in this +# historical evidence. Results must be labelled Experimental runtime observation, +# never validated VLM capacity or an official supported-channel claim. diff --git a/docs/development/ci.md b/docs/development/ci.md index 2b16135b2..8ed545681 100644 --- a/docs/development/ci.md +++ b/docs/development/ci.md @@ -1,6 +1,6 @@ --- title: CI 与质量检查 -description: 面向开源协作的文档站、前端、C++ 后端、静态分析和发布构建检查入口。 +description: 面向开源协作的文档站、前端、C++ 后端、静态分析和平台发布构建检查入口。 prev: text: 后端开发 link: /development/backend @@ -23,7 +23,8 @@ next: | C++ 静态分析 | `scripts/static_analysis.sh --cppcheck`、`scripts/static_analysis.sh --clang-tidy` | 定期 / 手动 / self-hosted | | CPU 测试构建 | `scripts/build_cpu_test.sh`、`build_cpu/cosmo-tests` | Pull request / 手动 | | x86 Docker | `docker compose -f docker-compose.x86.yml up -d --build` (Windows 下为 `docker-compose.x86.windows.yml`) | 手动 / release 前 | -| Sophon 发布包 | `docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package` | 手动 / self-hosted | +| Sophon 发布包 | `./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package [--chip <型号>]`,支持 `bm1688` / `cv186x`(默认 `bm1688`) | 手动 / self-hosted | +| RK3576 发布包 | `docker compose -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package` | 每日 02:12(北京时间)/ 手动 | ## 文档站检查 @@ -172,13 +173,46 @@ x86 开发模式可用于集成级验证: Sophon/aarch64 发布包构建入口: ```bash -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package +# 省略型号时默认 bm1688 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x ``` Windows PowerShell: ```powershell +# 省略型号时默认 bm1688 .\scripts\build_sophon_package.ps1 +.\scripts\build_sophon_package.ps1 -Chip cv186x ``` -Sophon 发布包构建依赖交叉编译环境和 Sophon SDK。`build_output/` 中导出的包名格式为 `cosmo-V..-.tar.gz`。 +Sophon 发布包构建依赖交叉编译环境和 Sophon SDK。型号决定内部资源目录和芯片隔离的 +输出目录;`build_output///` 同时包含 `TARGET_CHIP`、`SHA256SUMS` 和 +`cosmo-V..-.tar.gz`。 + +## RK3576 夜间交叉编译 + +`.github/workflows/ci-build-rk3576.yml` 使用正式 RK3576 Compose 入口,每日 +北京时间 02:12(UTC 前一日 18:12)在默认分支运行,同时保留手动触发。定时工作流 +只有进入 GitHub 默认分支后才会生效。 + +CI 使用公开、固定 digest 且已包含固定 RKLLM v1.3.0 的最终构建镜像, +无需 registry 登录: + +```bash +docker compose -f docker-compose.rk3576.yml pull cosmo-rk3576-package +docker compose -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package +``` + +工作流执行以下发布候选检查: + +1. 验证 Compose 配置,并拉取固定 digest、带 RKLLM 的最终构建镜像。 +2. 从干净的 `build_rknn/` 完成交叉编译、测试程序构建和打包。 +3. 要求 `build_output/rk3576/` 中只存在一个普通文件类型的发布包,并记录 SHA-256。 +4. 确认 `cosmo-tests`、`cosmo-rknn-backend-smoke` 和 + `cosmo-rknn-fastpath-qualify` 都是 ARM aarch64 程序。 +5. 确认包内包含 `librkllmrt.so` 及其许可证,再以 `public-runtime` 配置审计内容。 +6. 上传发布包、校验和及三个验证程序,保留 7 天。 + +工作流只授予 `contents: read` 权限;同一分支出现重叠运行时取消旧任务。该任务完成 +交叉编译与产物检查,不在 GitHub 托管的 x86 runner 上执行 aarch64 程序。 diff --git a/docs/en/development/ci.md b/docs/en/development/ci.md index d7423c186..cb8fba2ad 100644 --- a/docs/en/development/ci.md +++ b/docs/en/development/ci.md @@ -1,6 +1,6 @@ --- title: CI and Quality Checks -description: Entry points for documentation site, frontend, C++ formatting, static analysis, and release build quality checks for open-source collaboration. +description: Entry points for documentation, frontend, C++, static analysis, and platform release-build checks. prev: text: Backend Development link: /en/development/backend @@ -23,7 +23,8 @@ This page collects the quality-check entry points that already exist in the repo | C++ static analysis | `scripts/static_analysis.sh --cppcheck`, `scripts/static_analysis.sh --clang-tidy` | Periodic / manual / self-hosted | | CPU test build | `scripts/build_cpu_test.sh`, `build_cpu/cosmo-tests` | Pull request / manual | | x86 Docker | `docker compose -f docker-compose.x86.yml up -d --build` (use `docker-compose.x86.windows.yml` on Windows) | Manual / before release | -| Sophon release package | `docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package` | Manual / self-hosted | +| Sophon release package | `./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package [--chip ]`; supports `bm1688` / `cv186x` (defaults to `bm1688`) | Manual / self-hosted | +| RK3576 release package | `docker compose -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package` | Daily at 02:12 Beijing Time / manual | ## Documentation Site Checks @@ -173,13 +174,53 @@ Before a release, confirm at minimum: Sophon/aarch64 release package build entry point: ```bash -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package +# Defaults to bm1688 when the chip model is omitted +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x ``` Windows PowerShell: ```powershell +# Defaults to bm1688 when the chip model is omitted .\scripts\build_sophon_package.ps1 +.\scripts\build_sophon_package.ps1 -Chip cv186x ``` -The Sophon release package build depends on the cross-compilation environment and the Sophon SDK. The package exported into `build_output/` is named in the form `cosmo-V..-.tar.gz`. +The Sophon release package build depends on the cross-compilation environment and +the Sophon SDK. The chip model selects both the internal resource directory and +the chip-scoped output. Each `build_output///` directory contains +`TARGET_CHIP`, `SHA256SUMS`, and one +`cosmo-V..-.tar.gz` archive. + +## RK3576 Nightly Cross-Build + +`.github/workflows/ci-build-rk3576.yml` uses the formal RK3576 Compose entry +every day at 02:12 Beijing Time (18:12 UTC on the previous day) and also supports +manual dispatch. A scheduled workflow becomes active only after it reaches the +GitHub default branch. + +CI uses the public digest-pinned final builder that already contains the pinned +RKLLM v1.3.0 files; no registry login is required: + +```bash +docker compose -f docker-compose.rk3576.yml pull cosmo-rk3576-package +docker compose -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package +``` + +The workflow applies these release-candidate checks: + +1. Validates Compose and builds the RKLLM-enabled image from the pinned base. +2. Cross-compiles, builds validation programs, and packages from a clean + `build_rknn/` directory. +3. Requires exactly one regular package file under `build_output/rk3576/` and + records its SHA-256. +4. Confirms that `cosmo-tests`, `cosmo-rknn-backend-smoke`, and + `cosmo-rknn-fastpath-qualify` are ARM aarch64 programs. +5. Requires `librkllmrt.so` and its license, then audits package contents with + the `public-runtime` profile inside the build container. +6. Uploads the package, checksum, and three validation programs for 7 days. + +The workflow has only `contents: read` permission and cancels an older +overlapping run on the same branch. It cross-compiles and inspects artifacts; +it does not execute aarch64 programs on the GitHub-hosted x86 runner. diff --git a/docs/en/guide/architecture.md b/docs/en/guide/architecture.md index d900f8f8d..1ce3032a1 100644 --- a/docs/en/guide/architecture.md +++ b/docs/en/guide/architecture.md @@ -109,7 +109,8 @@ Two inference backend paths currently exist in the project: Resource directories: -- `data/resource/aiboxresource` +- `data/resource/aiboxresource_bm1688` +- `data/resource/aiboxresource_cv186x` - `data/resource/aiboxresource_x86` -The current templates cover detection (YOLO v5/v8/v9/v11/v12/v26), classification, keypoints, feature, segmentation (SAM2), object localization (DINO), and vision-language models (Qwen3VL, Qwen3.5). The complete list is subject to the actual files under `data/resource/aiboxresource/model_template/` and `data/resource/aiboxresource_x86/model_template/`. +The current templates cover detection (YOLO v5/v8/v9/v11/v12/v26), classification, keypoints, feature, segmentation (SAM2), object localization (DINO), and vision-language models (Qwen3VL, Qwen3.5). The complete list is subject to the actual files under each `data/resource/aiboxresource_*/model_template/` directory. diff --git a/docs/en/guide/build.md b/docs/en/guide/build.md index a7a4f9c9c..b2c2e4fd3 100644 --- a/docs/en/guide/build.md +++ b/docs/en/guide/build.md @@ -1,12 +1,12 @@ --- title: Build Guide -description: Confirmed build paths for x86 Docker, Sophon release packages, CPU test builds, and docs. +description: Confirmed build paths for x86 Docker, Sophon, RK3576, CPU tests, and docs. prev: text: Documentation Home link: /en/ next: - text: Deployment Guide - link: /en/guide/deployment + text: RK3576 / RKNN Integration + link: /en/guide/rk3576-rknn-development --- # Build Guide @@ -15,13 +15,17 @@ This page documents build paths that are confirmed and available in the reposito > **💡 Docker Compose Version Note** > This documentation uses the latest Docker Compose V2 command format (`docker compose`). If you are using an older Docker environment, please replace `docker compose` with the hyphenated `docker-compose` in all commands. +> On Linux, `./scripts/docker-compose.sh` detects Compose V2/V1 and requests +> `sudo` once when the current account cannot access the Docker daemon. ## Build Path Overview | Target | Entry Point | Notes | | --- | --- | --- | | x86 Docker runtime | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` | Starts the containerized development/runtime environment. | -| Sophon release package | `docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package` | Creates the target-device release package. | +| macOS Docker Preview | `scripts/macos-docker-preview.sh` | Runs the one-video x86 workflow under amd64 emulation on Apple Silicon. | +| Sophon SOURCE package | `./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package` | Cross-compiles the installable source-build package. | +| RK3576 release package | `docker compose -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package` | Cross-compiles the RKNN/MPP/RGA package and aarch64 validation programs. | | CPU test build | `scripts/build_cpu_test.sh` | Builds `cosmo-tests` for x86 CPU validation. | | Documentation site | `npm ci` and `npm run docs:build` | Builds this VitePress site. | @@ -31,6 +35,7 @@ These entry points are from: - `docker-compose.x86.yml` (Linux) - `docker-compose.x86.windows.yml` (Windows) +- `docker-compose.x86.macos.yml` (Apple Silicon macOS Preview) - `Dockerfile.x86` - `scripts/build_cpu.sh` @@ -59,6 +64,18 @@ docker compose -f docker-compose.x86.windows.yml up -d --build docker compose -f docker-compose.x86.windows.yml ps ``` +Apple Silicon macOS (Preview): + +```bash +./scripts/macos-docker-preview.sh doctor +./scripts/macos-docker-preview.sh up +``` + +The Mac path explicitly runs `linux/amd64`, uses isolated volumes, and publishes +only on loopback. It does not enable Model Guard and is not native arm64 or NPU +performance evidence. See [macOS Docker Preview](./macos-docker-preview.md) for +the complete setup and acceptance boundary. + After build: - Web console available at `http://127.0.0.1:8080`. @@ -66,30 +83,142 @@ After build: - Runtime data stored in Docker volume `cosmo-x86-data`. - Resource directory mounted to Docker volume `cosmo-x86-app-resource`. -## Sophon Release Package +## Sophon Artifacts + +The public entry point defaults to +`COSMO_MODEL_GUARD_BUILD_PROFILE=public-runtime`: ```bash -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package +# Defaults to bm1688 when the chip model is omitted +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package + +# Select a chip model explicitly +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip bm1688 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x ``` Windows PowerShell: ```powershell +# Defaults to bm1688 when the chip model is omitted .\scripts\build_sophon_package.ps1 + +# Select a chip model explicitly +.\scripts\build_sophon_package.ps1 -Chip bm1688 +.\scripts\build_sophon_package.ps1 -Chip cv186x +``` + +The two supported profiles are deliberately isolated: + +| Profile | Intended use | Output directory | Deployment status | +| --- | --- | --- | --- | +| Open (`public-runtime`, default) | Public aarch64 compile, link, package, and test validation using the tracked runtime SDK | `build_output/public-runtime//` | Plain models; no device authorization required | +| Protected (`production-release`) | Controlled build with the complete production SDK and provisioning tool | `build_output/production-release//` | Encrypted models; device authorization required | + +Every chip directory also contains `TARGET_CHIP` and `SHA256SUMS`, while the +archive contains `share/cosmo/target-chip.txt`. Even when the selected public +model bytes match, complete packages for different chips must have different +hashes. Always take the archive from its chip-scoped directory. + +On the first build, Compose fills the npm cache serially from `package-lock.json` +and then installs fully offline. BM1688, CV186X, and RK3576 builds in the same +working directory share that cache. This avoids an npm 10.2 failure mode where +many CDN sockets remain open indefinitely. Removing the Compose volume refills it. + +Both profiles produce `cosmo-V-<32-char-md5>.tar.gz`. The same format +can be uploaded through the management page on a main-branch installation and +on every later version. Application archives are not signed. The profiles differ +only in model protection and availability of `cosmo-model-provision`. + +### Hand a Sophon Build to the Deployment Workflow + +After the build, verify the target marker and SHA-256 in the chip-scoped output +directory: + +```bash +chip=bm1688 # or cv186x +cat "build_output/public-runtime/${chip}/TARGET_CHIP" +(cd "build_output/public-runtime/${chip}" && sha256sum -c SHA256SUMS) +``` + +Use the [Deployment Guide](./deployment.md#ssh-installation-path) as the single +reference for SSH installation, web upgrade, recovery boundaries, and +post-reboot version acceptance. This guide does not duplicate device installation +commands, so the build entry point and deployment workflow cannot drift apart. + +Maintainers use one command in a controlled environment containing the complete +Guard SDK and provisioning tool: + +```bash +COSMO_MODEL_GUARD_BUILD_PROFILE=production-release \ + ./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x ``` +This example builds a CV186X Protected package. Use `bm1688`, or omit the chip +model, for BM1688. + +The Protected build fails immediately if the controlled SDK does not contain +`cosmo-model-provision`. +Stage the controlled production SDK under the host path +`build_output/model-guard-sdk-production/`. The existing Compose volume exposes +that ignored directory to the container, and Protected builds select it +automatically. Open builds remain unchanged. + +The Protected CPack artifact is itself the upgrade archive accepted by the web +management page. No offline application-signing step is required. Guard device +certificates and model-encryption secrets remain controlled inputs and must never +be placed in the public repository. + This path is from: +- `scripts/docker-compose.sh` (Linux/macOS: selects Compose V2 or V1 and handles Docker access) - `docker-compose.sophon.yml` +- `scripts/build_sophon_package.sh` - `scripts/build_sophon_package.ps1` (Windows: restores `.so` symlinks before building) - `scripts/build.sh` Confirmed behavior: - Base image uses the pre-built GHCR image: `ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_sophon:v1` (unified build environment, speeding up local start time). -- Builds with `scripts/build.sh -m data/resource/aiboxresource`. -- Exports the release package only (does not start services). -- Package output under `build_output/`. +- Docker Compose accepts a chip model argument: `cosmo-sophon-package --chip bm1688` + or `cosmo-sophon-package --chip cv186x`. Omitting `--chip` defaults to `bm1688`. +- `scripts/build_sophon_package.sh` passes the chip model to + `scripts/build.sh -T -c `. `build.sh` then selects the matching resource + directory; users do not provide a model path. +- Exports build artifacts only (does not start services). +- The chip model does not change CPack or MD5 renaming. Profile outputs remain + under `build_output///`, with package names in the existing + `cosmo-V..-.tar.gz` format. + +## RK3576 Artifacts + +The public RK3576 entry uses a digest-pinned final GHCR builder with RKLLM +Runtime v1.3.0 from a pinned official Rockchip commit. The environment +contains the aarch64 toolchain, RKNN Runtime, RKLLM Runtime, MPP, and RGA files: + +```bash +./scripts/docker-compose.sh -f docker-compose.rk3576.yml pull cosmo-rk3576-package +./scripts/docker-compose.sh -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package +sha256sum build_output/rk3576/cosmo-*.tar.gz +``` + +Confirmed behavior: + +- Runs the aarch64 cross-build in a `linux/amd64` build container. +- Removes `build_rknn/` before calling `scripts/build_rknn.sh -T`, preventing a + partial cache from being reused. +- Fails when the RKLLM header, runtime, or license is missing; a package without + Qwen3.5 support is not a valid release candidate. +- Packages both `lib/librkllmrt.so` and `share/licenses/rkllm/LICENSE`. +- Exports the single release package to `build_output/rk3576/` without starting + application services. +- Also builds the aarch64 `build_rknn/cosmo-tests`, + `cosmo-rknn-backend-smoke`, and `cosmo-rknn-fastpath-qualify` programs. +- Uses host networking to resolve build dependencies but publishes no + application ports. + +See [RK3576 / RKNN Integration](./rk3576-rknn-development.md) for the supported +release profile, runtime selection, model contract, and device-evidence boundary. ## CPU Test Build diff --git a/docs/en/guide/configuration.md b/docs/en/guide/configuration.md index a771e2382..974a77e8c 100644 --- a/docs/en/guide/configuration.md +++ b/docs/en/guide/configuration.md @@ -19,6 +19,7 @@ x86 development runtime: - Linux: `docker-compose.x86.yml` - Windows: `docker-compose.x86.windows.yml` +- Apple Silicon macOS Preview: `docker-compose.x86.macos.yml` Sophon release package build: @@ -58,6 +59,10 @@ When both variables are absent, signed manager requests remain disabled. A parti `docker-compose.sophon.yml` supports the following build arguments: +Pass the chip model as `--chip ` after the Compose service name. +Supported values are `bm1688` and `cv186x`; omitting `--chip` defaults to +`bm1688`. The build script automatically selects the matching resource directory. + | Variable | Default | Description | | --- | --- | --- | | `SOPHON_APT_MIRROR` | `https://mirrors.aliyun.com/ubuntu` | apt mirror | @@ -71,7 +76,8 @@ When both variables are absent, signed manager requests remain disabled. A parti | Build Path | Resource Directory | | --- | --- | | x86 Docker | `data/resource/aiboxresource_x86` | -| Sophon package | `data/resource/aiboxresource` | +| Sophon BM1688 package | `data/resource/aiboxresource_bm1688` | +| Sophon CV186X package | `data/resource/aiboxresource_cv186x` | CMake installs resources via `RESOURCE_DIR`. diff --git a/docs/en/guide/cv186x-quick-start.md b/docs/en/guide/cv186x-quick-start.md new file mode 100644 index 000000000..54a90a545 --- /dev/null +++ b/docs/en/guide/cv186x-quick-start.md @@ -0,0 +1,121 @@ +--- +title: CV186X Quick Start +description: Install CosmoEdge 1.1 on a prepared CV186X Linux device and produce the first detection event. +prev: + text: Build Guide + link: /en/guide/build +next: + text: RK3576 / RKNN Integration + link: /en/guide/rk3576-rknn-development +--- + +# CV186X Quick Start + +This guide targets a CV186X Linux device with Sophon runtime dependencies and networking already +prepared. CosmoEdge 1.1 uses BMRT and `.nn` artifacts validated on CV186X. The two open Sophon +models used by this release benchmark are byte-identical to the BM1688 workload artifacts; other +models still require contract-by-contract compatibility validation. + +Verify hardware identity before installation; an IP address or old model directory +is not platform evidence: + +```bash +tr -d '\0' -.tar.gz` format and must be qualified together with the +adjacent `TARGET_CHIP` and `SHA256SUMS` files. + +Alternatively, download a CosmoEdge 1.1 Sophon Open package explicitly marked +for CV186X and its published SHA-256 from the +[GitHub Release](https://github.com/cosmo-wander-ai/cosmo-edge/releases), then verify it on the build host: + +```bash +sha256sum cosmo-V1.1.0-*.tar.gz +scp cosmo-V1.1.0-*.tar.gz root@:/tmp/ +``` + +## 2. Install and start + +```bash +ssh root@ +install_dir=$(mktemp -d /tmp/cosmo-install.XXXXXX) +tar -xzf /tmp/cosmo-V1.1.0-*.tar.gz -C "$install_dir" +cd "$install_dir"/cosmo-V*/ +./scripts/install.sh +reboot +``` + +After the device returns, confirm that `cosmo.service` is active and verify version 1.1 in the +device console. An existing CosmoEdge device can upload the same archive through **System +Management → System Maintenance → Software Upgrade**. + +## 3. Create the first event with the bundled open models + +For a `cv186x` build, the build script automatically selects the matching resource +directory. Users do not provide that path. The package includes the two models +used by the public CV186X benchmark: + +- `YOLOV8n V1.0.0`: person detector, `1x3x640x640`, 7,023,600-byte model file; +- `helmet V1.0.0`: safety-helmet classifier, `1x3x224x224`, 6,001,416-byte model file. + +Their repository directories, input/output contracts, and SHA-256 identities are recorded in the +[ScenarioBench v1.1 model identity record](/benchmarks/scenario-bench/v1.1/models/cv186x.json). +The model subdirectories retain the legacy `prod_BM1688_` compatibility prefix because the files +were copied from the CV186X benchmark device without modification. Neither that directory prefix +nor a `BM1688` device-tree string determines the complete product platform by itself. CV186X +qualification binds controlled platform mapping, an exact SHA-256 match between device-loaded +files and the CV186X resource set, and successful device inference. It does not imply that other +BM1688 artifacts are interchangeable. + +1. Sign in to the Web console, open **Model Repository**, and confirm that both models are present. +2. Add one test stream under **Video Input**, then create and bind a task with the person detector. + Add the helmet classifier to the orchestration when validating the complete helmet workflow. +3. Open algorithm preview, confirm OSD and an event, then verify that task state and service logs + show no continuing error. Record the model SHA-256, literal device-tree string, and inference + result together in the qualification evidence. + +When importing a custom model, its directory must contain a matching `config.json` and model file. +Input dimensions, quantization, preprocessing, postprocessing, and output tensors must match the +configuration. See the [Model Porting Guide](/en/tutorials/05-model-porting/model-porting) for the +full contract. + +## Upgrade, recovery, and evidence boundary + +- Installation and Web upgrade use the same `cosmo-V-.tar.gz` lifecycle. Keep power + connected and verify both service state and software version after recovery. +- If the service does not recover, inspect `systemctl status cosmo.service` and service logs before + attempting another upload. +- See the [Deployment Guide](/en/guide/deployment) for directories, ports, persistence, failure + recovery, and rollback boundaries. +- Public workload results are in [ScenarioBench v1.1](/benchmarks/scenario-bench/v1.1/report.html). + A highest short-run point is not an official recommended profile; size production deployments + with the actual models, streams, and accuracy requirements. diff --git a/docs/en/guide/deployment.md b/docs/en/guide/deployment.md index 27ad284cf..5cbcf337a 100644 --- a/docs/en/guide/deployment.md +++ b/docs/en/guide/deployment.md @@ -2,8 +2,8 @@ title: Deployment Guide description: Runtime directories, service processes, ports, upgrade packages, and systemd behavior. prev: - text: Build Guide - link: /en/guide/build + text: macOS Docker Preview + link: /en/guide/macos-docker-preview next: text: Runtime Configuration link: /en/guide/configuration @@ -30,6 +30,10 @@ Start: ```powershell docker compose -f docker-compose.x86.windows.yml up -d --build ``` +- **Apple Silicon macOS (Preview)**: + ```bash + ./scripts/macos-docker-preview.sh up + ``` Stop: @@ -41,6 +45,10 @@ Stop: ```powershell docker compose -f docker-compose.x86.windows.yml down ``` +- **Apple Silicon macOS (Preview)**: + ```bash + ./scripts/macos-docker-preview.sh down + ``` View logs: @@ -52,6 +60,10 @@ View logs: ```powershell docker compose -f docker-compose.x86.windows.yml logs -f ``` +- **Apple Silicon macOS (Preview)**: + ```bash + ./scripts/macos-docker-preview.sh logs --follow + ``` ## Runtime Directories @@ -86,7 +98,7 @@ ${INSTALLPATH}/bin/cosmo-engine | Port | Source | Purpose | | --- | --- | --- | -| `8080 -> 80` | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` | x86 Docker web console | +| `8080 -> 80` | x86 Compose files; the Mac Preview binds only to `127.0.0.1` | x86 Docker web console | | `1936` | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` / SRS | RTMP | | `1985` | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` / SRS | SRS API | | `18088` | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` / SRS | HTTP stream | @@ -121,7 +133,7 @@ Optional or handled by presence: - `lib` - `resource` -Upgrade package filename pattern: +The upgrade package filename must match this pattern: ```text cosmo-V..-<32-char-md5>.tar.gz @@ -132,26 +144,45 @@ The web console performs a local upgrade as follows: 1. Query device status and record the current Linux `bootId`. 2. Transfer the package in chunks according to live device capabilities while showing actual upload progress. 3. Validate the filename, MD5, archive safety, package layout, and live disk budget. -4. After a Sophon reboot, validate the MD5 again, install the release package, and start the services. +4. After a Sophon reboot, the startup script revalidates the MD5 and installs the package. Open and Protected packages permanently use this same upgrade flow. 5. Return to login after observing a new `bootId`. If reboot invalidates the login session, first observe the device offline and then require an authentication response from the recovered service before returning to login. The 15-minute recovery wait is a UI timeout; it does not cancel an upgrade already running on the device. Keep power connected and inspect device networking and systemd logs if it expires. After signing in again, verify the software version against the release package; UI recovery proves reboot and service recovery, not version acceptance. -## systemd Service +## SSH Installation Path -`scripts/install.sh` creates: +In addition to web upgrade, packaged `scripts/install.sh` is the SSH entry point +for migration from main and later compatible installations. It installs the +application, replaces and enables `cosmo.service`, and relies on reboot to start +the service: -```text -/etc/systemd/system/cosmo.service +```bash +scp build_output/public-runtime//.tar.gz root@:/tmp/ +ssh root@ +cd /tmp +install_dir=$(mktemp -d /tmp/cosmo-install.XXXXXX) +tar -xzf .tar.gz -C "$install_dir" +cd "$install_dir"/cosmo-V*/ +sudo ./scripts/install.sh +sudo reboot ``` -Service start command: +This path assumes that the Sophon Linux base system and runtime dependencies are +already prepared. It is not an OS-image installation procedure for arbitrary +blank hardware. Record the current version and recovery plan first; the +installer replaces the active application tree. + +## systemd Service + +The configured device uses this service start command: ```text -ExecStart=${INSTALLPATH}/scripts/inte_run_start.sh +ExecStart=/appfs/cosmo_wander/cwai_data/scripts/inte_run_start.sh ``` -The service runs as `root` with `Restart=on-failure`. A fatal initialization exception returns a non-zero status so systemd retries it instead of treating the process as a clean stop. +`scripts/install.sh` implements the upgrade transaction; it does not create the +systemd unit for a blank device. The service runs as `root` with +`Restart=on-failure`. Some Sophon images restore the persistent data tree to the appliance administrator at boot. The upload staging service therefore allows `sessions` to inherit the owner of an immediate parent that is not writable by group/other, while still requiring: diff --git a/docs/en/guide/macos-docker-preview.md b/docs/en/guide/macos-docker-preview.md new file mode 100644 index 000000000..f3625e444 --- /dev/null +++ b/docs/en/guide/macos-docker-preview.md @@ -0,0 +1,190 @@ +--- +title: macOS Docker Preview +description: Run the CosmoEdge x86 workflow on Apple Silicon through an isolated linux/amd64 Docker environment. +prev: + text: RK3576 / RKNN Integration + link: /en/guide/rk3576-rknn-development +next: + text: Deployment Guide + link: /en/guide/deployment +--- + +# macOS Docker Preview + +> **Status: Preview.** This path targets local development and one offline-video +> workflow. It is not a native arm64 build, a Sophon device emulator, or a +> production deployment. Apple Silicon runs a `linux/amd64` image through Docker +> Desktop, so the first build and inference are slower than native x86 Linux. + +## What It Covers + +The Mac Preview reuses the x86 CPU/ONNX Runtime backend. Its target experience is: + +- sign in to the web console; +- upload local video and retain the channel; +- use the bundled x86 ONNX models to create a task, set an ROI, and start or stop analysis; +- inspect live OSD, alarm snapshots, and event history; +- export a non-empty alarm CSV; and +- stop and restart the container without losing configuration or uploaded data. + +It does not provide NPU performance parity, USB-camera passthrough, LAN device +discovery, multi-channel capacity evidence, or local VLM support. See +[Acceptance and Boundaries](#acceptance-and-boundaries) for the complete scope. + +## Prepare the Environment + +The current admission target is an Apple Silicon Mac with Docker Compose V2. +Recommended capacity is: + +- at least 20 GiB of free disk space; +- at least 8 GiB assigned to the Docker virtual machine; and +- Rosetta 2 for a better amd64 emulation experience. + +Before installing or first starting Docker Desktop, review and accept its separate +[Docker Subscription Service Agreement](https://docs.docker.com/subscription/). +The current operating-system, memory, and Rosetta requirements are in Docker's +[Mac installation guide](https://docs.docker.com/desktop/setup/install/mac-install/). + +For this amd64 workload, Docker Desktop is generally faster with Apple +Virtualization Framework and Rosetta enabled. Docker's current +[settings reference](https://docs.docker.com/desktop/settings-and-maintenance/settings/) +states that the Rosetta option is available only with Apple Virtualization +Framework; Docker VMM does not currently accelerate amd64 emulation through +Rosetta. This is a performance recommendation, not a system setting changed by +the CosmoEdge scripts. + +## Start the Preview + +Run the read-only admission check from the repository root: + +```bash +./scripts/macos-docker-preview.sh doctor +``` + +It checks Apple Silicon, Docker Desktop, Compose configuration, Docker memory, +disk, Rosetta, and local ports. It does not install components or change Docker +settings. When it passes, start the Preview: + +```bash +./scripts/macos-docker-preview.sh up +``` + +The script builds `docker-compose.x86.macos.yml` only when its image is missing, +otherwise reuses the existing image. It then waits until nginx, SRS, +`cosmo-engine`, and the web response are all healthy, then prints: + +```text +http://127.0.0.1:8080 +``` + +The first run downloads the amd64 builder and dependencies and compiles under +emulation. It can be substantially slower than later starts. +The Mac Compose file pins the validated amd64 builder and Debian runtime base by +digest so a tag update cannot silently change the base environment for the same candidate. +The Mac Compose file defaults to one build job to avoid nested GNU Make jobserver +descriptor failures under amd64 emulation. `COSMO_X86_BUILD_JOBS` can override +that value, but higher parallelism is experimental and requires repeating both +acceptance runs on this page. + +Rebuild explicitly after changing source, the Dockerfile, or build resources: + +```bash +./scripts/macos-docker-preview.sh up --build +``` + +A normal `up` reuses the existing image and does not turn unrelated workspace +changes into another long emulated build. + +If host port `8080` is occupied, override only the web port: + +```bash +COSMO_X86_WEB_PORT=8280 ./scripts/macos-docker-preview.sh up +``` + +Then open `http://127.0.0.1:8280`. Media ports `1936`, `1985`, and `18088` remain +fixed and cannot be reused as the web port because the current frontend preview +path relies on the SRS port contract. + +The Mac Preview plays SRS HTTP-FLV directly through loopback port `18088` and +does not try WebRTC first. The media port remains `18088` even when +`COSMO_X86_WEB_PORT` moves the web console to another port. This avoids the long +WebRTC media-timeout and fallback window that can occur through Docker Desktop. +It is a deterministic local Preview setting and does not change the WebRTC +default used by other deployment paths. + +## Lifecycle and Isolation + +```bash +# Show container and health state. +./scripts/macos-docker-preview.sh status + +# Print recent logs, or follow until interrupted. +./scripts/macos-docker-preview.sh logs +./scripts/macos-docker-preview.sh logs --follow + +# Stop services while preserving settings, uploads, and model resources. +./scripts/macos-docker-preview.sh down +``` + +The Preview has its own Compose project, container, image, volumes, and build output: + +| Object | Name or path | +| --- | --- | +| Compose project | `cosmo-x86-macos-preview` | +| Container | `cosmo-x86-macos-preview` | +| Runtime data volume | `cosmo-x86-macos-preview-data` | +| Model resource volume | `cosmo-x86-macos-preview-app-resource` | +| Package output | `build_output/macos-x86/` | + +The default `down` command does not delete named volumes, so an ordinary stop +does not erase Preview data. + +## Acceptance and Boundaries + +Before community promotion, run the following workflow two consecutive times on +an Apple Silicon Mac, with one `down` / `up` cycle between the runs: + +1. The container becomes healthy and the web console accepts a sign-in. +2. Upload `data/test-video/Safety Helmet.mp4`; the channel remains after refresh. +3. Create a task with the bundled No Safety Helmet ONNX model and set an ROI. +4. Start the task and confirm that Live Display shows video and OSD; one enabled + task should open its OSD directly without first creating a raw stream. +5. Confirm that Event Center receives an alarm with a snapshot. +6. Export a non-empty alarm CSV. +7. After restart, the configuration, video, and task still work, without a crash or abnormal restart. + +Conclusions are limited to the layer actually tested: + +| Capability | Mac Preview conclusion | +| --- | --- | +| Web console, upload, task, ROI, OSD, alarms, CSV | Preview target; report the result of the consecutive acceptance runs | +| x86 ONNX Runtime CPU inference | Runs under `linux/amd64` emulation; not native performance evidence | +| Sophon / Rockchip NPU, USB cameras, LAN discovery | Not covered | +| Multi-channel performance, soak testing, production deployment | Not covered and cannot be inferred from one local-video run | +| Model Guard, Sophon Protected packages, CEMC models, device provisioning | Disabled and unverified | + +`scripts/build_cpu.sh` explicitly disables the Sophon backend and enables the CPU +backend, so CMake disables Model Guard. Building this Preview from the Model Guard +development branch does not run Model Guard on the Mac. CEMC protected models +remain part of the Sophon Protected runtime path. + +## Local Security Defaults + +`docker-compose.x86.macos.yml` binds the web, RTMP, SRS API, and HTTP stream +ports to `127.0.0.1`. It does not publish UDP discovery, request `NET_ADMIN`, or +expose `/dev/video*` devices. These defaults fit single-machine development and +prevent direct access from other LAN hosts. Remote access requires a separate +review of authentication, TLS, firewall rules, video data, and port exposure. Do +not remove the loopback bindings and treat this Preview as a production configuration. + +## Troubleshooting + +- `Docker Desktop is not ready`: open Docker Desktop, finish first-run setup and + agreement acceptance, wait for Running, and rerun `doctor`. +- Slow builds: inspect Docker's VMM and Rosetta settings and assign at least 8 GiB + of memory. amd64 emulation remains a best-effort Preview. +- The service never becomes healthy: run `./scripts/macos-docker-preview.sh logs` + and inspect the first failing process among nginx, SRS, and `cosmo-engine`. +- Web-port conflict: set `COSMO_X86_WEB_PORT`; stop the owner of any conflicting fixed media port. +- Rebuild while preserving data: run `./scripts/macos-docker-preview.sh up --build` + and do not delete the two Preview named volumes. Use normal `up` for a restart. diff --git a/docs/en/guide/rk3576-rknn-development.md b/docs/en/guide/rk3576-rknn-development.md new file mode 100644 index 000000000..42d4198f5 --- /dev/null +++ b/docs/en/guide/rk3576-rknn-development.md @@ -0,0 +1,249 @@ +--- +title: RK3576 / RKNN Integration +description: Stable-release build, runtime, model, and validation boundaries for Rockchip RK3576. +prev: + text: Build Guide + link: /en/guide/build +next: + text: macOS Docker Preview + link: /en/guide/macos-docker-preview +--- + +# RK3576 / RKNN Integration Guide + +## Scope + +The RK3576 integration adds a production-oriented CV backend without changing +the behavior of the CPU, CUDA, or Sophon backends: + +- RKNN Runtime 2.3.2 executes static-batch detector and classifier models. +- RKLLM Runtime 1.3.0 works with an RKNN vision encoder to execute Qwen3.5 + multimodal models. +- Rockchip MPP performs H.264/H.265 decode and encode. +- The decoder uses delayed Copy-out: frames are sampled or discarded before a + host I420 copy is requested. +- RGA performs the Rockchip frame-processing operations required by preview and + OSD paths. +- Full DMA-BUF zero-copy is outside the supported release boundary. + +The recommended deployment starting point is the single-detector profile that completed a +12-hour run at four channels and 5 FPS per channel. The latest short staircases reached 16 +channels at 5 FPS for a single detector and 8 channels at 5 FPS per task for two detectors. +These are measured boundaries for the stated models and gates, not replacements for a recommended +profile. See [ScenarioBench v1.1](/benchmarks/scenario-bench/v1.1/report.html). + +## Repository and Evidence Boundary + +The repository owns product code, build definitions, unit tests, reproducible +model tooling, deployable RKNN resources, and two reusable acceptance scenarios: + +- `tools/scenario-bench/scenarios/rk3576-no-helmet-customer-journey` +- `tools/scenario-bench/scenarios/rk3576-no-helmet-longrun-4x5fps` + +Raw device logs, metrics streams, screenshots, exported events, and generated +HTML/XML/JSON reports are external validation artifacts and must not be added to +the source tree. A release evidence manifest binds results to the source commit +and tree, final package SHA-256, device/firmware/runtime versions, model and +dataset hashes, thresholds, cleanup status, and measured values. + +Device addresses, account data, local backup paths, and reusable credentials do +not belong in source-controlled configuration or evidence. + +## Frozen Toolchain Identities + +The machine-readable toolchain and model-input lock is +`config/rknn/toolchain-lock.json`. The supported integration is based on: + +- RKNN-Toolkit2 2.3.2 +- RKNN Model Zoo 2.3.2 +- Ubuntu 22.04 x86_64 conversion host with Python 3.10 +- RK3576 Ubuntu 22.04 aarch64 target with kernel 6.1.118 and RKNPU driver 0.9.8 + +Changing a locked SDK, runtime, input model, or preprocessing contract requires +new conversion and device evidence. + +## Runtime Safety Boundary + +Keep the board's system RKNN runtime as the rollback baseline. Package RKNN +Runtime 2.3.2 beside CosmoEdge and select it with executable RPATH or a +task-local `LD_LIBRARY_PATH`; do not overwrite `/usr/lib/librknnrt.so`. +Production inference uses the native C API and does not depend on `rknn_server`. + +## Model and Preprocessing Contract + +The first supported models are: + +1. Helmet classification: `1x3x224x224`, ONNX opset 19. +2. YOLOv8 detection: `1x3x640x640`, converted to ONNX opset 19 / IR 9. + +Qwen3.5 multimodal deployment is a separate model contract. An importable +directory contains at least: + +- `model.rkllm`: a language model targeting RK3576; +- `vision.rknn`: a vision encoder whose image-token count and embedding width + match the language model; +- `tokenizer.json`: the tokenizer from the exact conversion source model; +- `config.json`: `model_type` is `qwen3_5` and `runtime_backend` is `rkllm`. + +Record SHA-256 for the four files as one set. The presence of `librkllmrt.so`, +a text-only model load, or an isolated `vision.rknn` run does not prove +multimodal capability. + +CosmoEdge owns resize, channel order, and normalization. Conversion must not +bake in a second mean/std transform. CosmoEdge supplies float32 NCHW tensors; +the RKNN boundary performs one explicit NCHW-to-NHWC copy because Runtime 2.3.2 +rejects NCHW on this input-conversion path. Outputs are requested as float32 so +the existing postprocessors remain authoritative. + +The production YOLO model exposes three box/class head pairs. The +`yolov8_dfl_v1` host adapter applies DFL and sigmoid, then reconstructs the +logical `[1,84,8400]` contract. A single quantized output is not supported +because its shared scale collapses confidence precision. + +## Reproducible Conversion + +Prepare the verified offline bundle at an operator-selected path: + +```bash +./scripts/rknn/prepare_offline_env.sh "$RKNN_OFFLINE_BUNDLE" +``` + +The locked YOLO conversion sequence is: + +```bash +python tools/rknn/convert_onnx_opset.py \ + --input model-opset22.onnx --output yolov8-opset19-ir9.onnx \ + --opset 19 --ir-version 9 + +python tools/rknn/extract_yolov8_heads.py \ + --input yolov8-opset19-ir9.onnx --output yolov8-heads.onnx + +python tools/rknn/prepare_validation_data.py \ + --spec config/rknn/models/yolov8.json --video "$VALIDATION_VIDEO" \ + --output-dir yolov8-calibration --samples 32 + +python tools/rknn/convert_model.py \ + --spec config/rknn/models/yolov8.json --model yolov8-heads.onnx \ + --output yolov8-heads-int8.rknn --quantize \ + --dataset yolov8-calibration/dataset.txt +``` + +Calibration and numerical-parity samples are unlabeled. They do not replace a +labeled precision/recall/F1 acceptance set. + +## Build and Deployment + +The public build uses a digest-pinned final image with RKLLM Runtime v1.3.0 +from a pinned official Rockchip commit. The environment contains the +aarch64 toolchain, RKNN Runtime, RKLLM Runtime, MPP, and RGA development files. +The base resource directory supplies common actions, layouts, and fonts; the +RKNN resource directory supplies the RK3576 algorithms and models. + +```bash +./scripts/docker-compose.sh -f docker-compose.rk3576.yml pull cosmo-rk3576-package +./scripts/docker-compose.sh -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package +sha256sum build_output/rk3576/cosmo-*.tar.gz +``` + +The base image and pinned official RKLLM files are public and require no +`docker login`; the helper selects Compose V2/V1. This command builds a +Release package with the Rockchip media backend and leaves the aarch64 test +binary at `build_rknn/cosmo-tests`; it does not enable `COSMO_DEV_MODE`. + +RKLLM is mandatory for a formal RK3576 package. A missing header, +`librkllmrt.so`, or license fails configuration instead of silently producing a +package without Qwen3.5 support. + +The package distributes RKLLM Runtime, but the Open package does not distribute +Qwen3.5 model files. The deployer must provide a licensed conversion artifact +that matches RK3576 and Runtime 1.3.0 and import it as the four-file set above. + +The formal entry removes the previous `build_rknn` directory before building so +a partial cross-compilation cache cannot be reused as release evidence. It uses +host networking for build-time dependency resolution; the one-shot build +service does not publish or listen on application ports. + +Board networking on RK3576 is managed by system NetworkManager, not by the +Sophon netplan path in CosmoEdge. Clearing `/data/cwaiuserdata` recreates the +default JSON but does not change an existing NetworkManager connection to +`192.168.100.1`; use `ip -4 addr`/`nmcli` as the deployment source of truth. + +Keep mutable and packaged roots separate at runtime: + +```bash +export COSMO_DATA_DIR=/data/cwaiuserdata +export COSMO_APP_DATA_DIR=/appfs/cosmo_wander/cwai_data +export LD_LIBRARY_PATH="$COSMO_APP_DATA_DIR/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" +``` + +`COSMO_DATA_DIR` contains configuration, databases, uploads, and events. +`COSMO_APP_DATA_DIR` contains packaged resources, models, libraries, and +binaries. Use the packaged launcher so transitive shared-library dependencies +resolve from the artifact being validated. + +## Reusable Acceptance Scenarios + +The customer-journey scenario runs one channel at 5 FPS for a bounded window. +Acceptance includes login, model/task/channel visibility, real raw and +algorithm HTTP-FLV playback, OSD difference, events, reconnect, stop/start +recovery, and cleanup. + +The long-run scenario holds four channels at 5 FPS for 12 hours. Run it with +algorithm-preview clients enabled and audit it with `--gate-hours 12`. The +runner stops when the configured disk fuse is reached. Use `--password-stdin` +so credentials do not enter process arguments. + +Preview validation requires real `ffmpeg` and `ffprobe` executables. The tool +preflights them before mutating device configuration. + +## Qwen3.5 Multimodal Device Acceptance + +Formal acceptance supplies a fixed test image on a real RK3576 device and +requires non-empty text related to that image. A text-only prompt proves only +the RKLLM language path and does not replace this gate. Use the CosmoEdge +**Image Analysis** flow, or cross-compile Rockchip's official +[`multimodal_model_demo`](https://github.com/airockchip/rknn-llm/tree/878f9361fd3afa7e167b7079918918f78d2c1c2a/examples/multimodal_model_demo) +with the same aarch64 toolchain as the build image and run it on the device: + +```bash +MODEL_DIR=/data/cwaiuserdata/resource/models/ +export LD_LIBRARY_PATH=./lib +./demo smoke.jpg "$MODEL_DIR/vision.rknn" "$MODEL_DIR/model.rkllm" \ + 64 4096 2 rk3576 \ + '<|vision_start|>' '<|vision_end|>' '<|image_pad|>' +``` + +Record the package and four model-file SHA-256 values, RKLLM/Toolkit/driver +versions, target platform, quantization type, vision input/output shapes, test +image hash, returned text, and exit status. The gate passes only when both +models load, vision encoding runs successfully, and non-empty image-related +text is returned. After the test, restore `cosmo.service`, confirm it is +`active`, verify a successful management-page response, and recheck the +device's actual IP address. + +## Validated Release Boundary + +- Four channels at 5 FPS completed the 12-hour gate with zero media + failure/fallback deltas and stable memory-pool accounting; the corresponding + CPU measurements remain in that historical evidence record. +- Real raw and algorithm playback, hardware decode/encode, OSD, reconnect, and + task restart recovery passed on the tested build. +- Delayed Copy-out discarded frames before host copies and is the selected + optimization for this release. +- The v1.1 public report records a 16-channel, 5 FPS single-detector staircase and an 8-channel, + 5 FPS-per-task dual-detector staircase. Both are short-run measured boundaries and have not been + promoted to official recommended profiles. +- RK3576 NPU telemetry uses the vendor busy-time counter from + `/sys/kernel/debug/rknpu/load`, reports the busiest core on the health card, + and retains every core in the accelerator payload. The startup script exposes + only this read-only file at `/run/cosmo-edge/metrics/rknpu-load`; the devfreq + governor signal is never treated as NPU load. +- RK3576 NPU and media allocations share system DDR. Accelerator telemetry + marks this as `memoryDomain=shared-system`; the dashboard emits one system + memory capacity instead of adding the same pool again as dedicated VRAM. + +These observations are artifact-bound and must be rerun after source, model, +runtime, or package changes. The accepted release record preserves the immutable +package SHA-256, business-accuracy result, credential-safe logs, +event-retention result, cleanup status, and measured values. Raw validation +artifacts remain outside the source tree. diff --git a/docs/en/guide/troubleshooting.md b/docs/en/guide/troubleshooting.md index f55453b6e..6edbc5c98 100644 --- a/docs/en/guide/troubleshooting.md +++ b/docs/en/guide/troubleshooting.md @@ -35,6 +35,12 @@ Check container status: docker compose -f docker-compose.x86.windows.yml ps ``` +- **Apple Silicon macOS (Preview)**: + + ```bash + ./scripts/macos-docker-preview.sh status + ``` + View logs: - **Linux**: @@ -49,6 +55,12 @@ View logs: docker compose -f docker-compose.x86.windows.yml logs -f ``` +- **Apple Silicon macOS (Preview)**: + + ```bash + ./scripts/macos-docker-preview.sh logs --follow + ``` + ## Port Conflicts The x86 Compose file publishes: @@ -76,6 +88,15 @@ docker compose -f docker-compose.x86.windows.yml up -d --build Then open `http://127.0.0.1:8280`. The default remains `8080` when the variable is unset. +The Mac Preview accepts the same web-port variable while retaining its host-only binding: + +```bash +COSMO_X86_WEB_PORT=8280 ./scripts/macos-docker-preview.sh up +``` + +If Mac builds are unexpectedly slow, inspect Docker Desktop's VMM and Rosetta +settings. See [macOS Docker Preview](./macos-docker-preview.md) for the full boundary. + ## Windows Build Scripts Report `No such file or directory` If a Docker build reports that an existing `configure`, `config`, or `Configure` file cannot be executed, Git for Windows may have checked out the extensionless script with CRLF endings. The container then cannot parse its shebang. @@ -88,7 +109,7 @@ git check-attr text eol -- 3rd/mp4v2-2.0.0/configure 3rd/openssl-3.5.3/config 3r All three files should report `text: auto` and `eol: lf`. -## No Release Package in `build_output/` +## No Build Artifact in `build_output/` Use the full run command: @@ -104,28 +125,82 @@ Use the full run command: docker compose -f docker-compose.x86.windows.yml up -d --build ``` -For the Sophon path, use: +The [Build Guide](./build.md#sophon-artifacts) is the authoritative reference for +the Sophon entry point, profiles, and output contract. For example, after the +default BM1688 Open build, inspect the chip-scoped directory directly: ```bash -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package +cat build_output/public-runtime/bm1688/TARGET_CHIP +(cd build_output/public-runtime/bm1688 && sha256sum -c SHA256SUMS) ``` -Note: `docker compose build` only builds the image and does not necessarily execute the container command that exports the release package. +Sophon output is not written directly to `build_output/`. Each +`build_output///` directory should contain `TARGET_CHIP`, +`SHA256SUMS`, and exactly one `cosmo-V-<32-char-md5>.tar.gz`. First check +that the selected profile and chip match the directory being inspected. + +Do not substitute `docker compose build` for the `run` entry point above; it does +not execute the container command that exports the artifact. ## Sophon Build Failure -The Sophon build uses a self-contained `Dockerfile.sophon` (based on `ubuntu:22.04`) and does not require an external base image. +The `cosmo-sophon-package` service directly uses the pre-built GHCR image +configured in `docker-compose.sophon.yml`; there is no local `Dockerfile.sophon` +build path. The [Build Guide](./build.md#sophon-artifacts) is the single reference +for the current image and build chain. -If the build fails, check the Docker build logs: +If the build fails, rerun the same entry point and inspect the final log lines: ```bash -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package 2>&1 | tail -50 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x 2>&1 | tail -50 ``` +For BM1688, replace the final argument with `bm1688` or omit it. + Common causes: - Network issues preventing apt/npm/cargo mirror downloads — check `SOPHON_APT_MIRROR` and related environment variables. - Insufficient disk space — the build requires approximately 3GB. +- An unsupported `COSMO_MODEL_GUARD_BUILD_PROFILE` value — only + `public-runtime` and `production-release` are accepted. +- An unsupported chip model — only `bm1688` and `cv186x` are accepted; omitting + it defaults to `bm1688`. +- Selecting `production-release` outside the controlled release environment — + missing production SDK, provisioning, release-public-key, or bootstrap inputs is + rejected by design. Use SOURCE for ordinary source-code builds; do not bypass + the formal release checks. + +## Protected Presets Do Not Load + +The device needs exactly one Guard state file: + +```text +/data/cwaiuserdata/model-guard/device-certificate.bin +``` + +Check certificate status and service logs first: + +```bash +sudo test -f /data/cwaiuserdata/model-guard/device-certificate.bin +sudo journalctl -u cosmo.service -b --no-pager -n 200 +``` + +If the controlled provisioner is still present in its temporary device +directory, run `sudo /temporary-directory/cosmo-model-provision status` to +validate the certificate against the live device. The SOURCE package does not +provide that tool. + +- `-2001` (`CMG_V2_CERTIFICATE_UNAVAILABLE`) means the certificate is missing + or unreadable. +- `-2002` (`CMG_V2_CERTIFICATE_REJECTED`) means the certificate is malformed, + has an invalid signature, or was issued for another device. + +Do not create per-model licenses or copy another device's certificate. Create +a fresh request on this device, issue its certificate in the controlled +offline environment, and run +`cosmo-model-provision install --certificate `. +The SOURCE installer does not create, delete, or repair this certificate. ## nginx / SRS / cosmo-engine Not Started @@ -157,10 +232,10 @@ On a Sophon device, inspect: ```bash systemctl status cosmo --no-pager -l journalctl -u cosmo -b --no-pager -n 200 -stat -c '%F %a %U:%G %n' /data/cwaiuserdata/upload/sessions ``` -Normally `cosmo.service` is `active (running)` and the staging root is a real directory with mode `0700`. A fatal initialization exception exits non-zero so `Restart=on-failure` can retry. Do not bypass the checks by recursively widening permissions on all of `/data/cwaiuserdata`. +Normally `cosmo.service` is `active (running)`. A fatal initialization +exception exits non-zero so `Restart=on-failure` can retry. ## Documentation Site Build Fails diff --git a/docs/en/reference/api.md b/docs/en/reference/api.md index 83d8dd5bd..f0c1eee21 100644 --- a/docs/en/reference/api.md +++ b/docs/en/reference/api.md @@ -146,6 +146,13 @@ Control-plane JSON requests are limited to 1 MB by default. A regular single mul ### Upgrade Recovery Status +The upgrade request accepts an `uploadId` whose original filename matches +`cosmo-V..-<32-char-md5>.tar.gz`. Before reboot, the backend +validates the filename, MD5, archive safety, and package layout. After reboot, +the common startup script revalidates the MD5 and installs the package. Open and +Protected packages use the same application-upgrade protocol; model authorization +is independent. + `POST /gtw/cwai/System/QueryDeviceStatus` returns these fields on success: | Field | Meaning | diff --git a/docs/en/reference/models.md b/docs/en/reference/models.md index a465ab14f..259c9171d 100644 --- a/docs/en/reference/models.md +++ b/docs/en/reference/models.md @@ -17,7 +17,8 @@ This document describes the model and resource organization that can be confirme | Directory | Purpose | | --- | --- | -| `data/resource/aiboxresource` | Resources for the Sophon release package. | +| `data/resource/aiboxresource_bm1688` | Resources for the Sophon BM1688 release package. | +| `data/resource/aiboxresource_cv186x` | Resources for the Sophon CV186X release package. | | `data/resource/aiboxresource_x86` | Resources for the x86 Docker / CPU backend. | The resource directory is selected through `RESOURCE_DIR` at build time. @@ -92,7 +93,8 @@ data/resource/aiboxresource_x86 Sophon path: ```text -data/resource/aiboxresource +data/resource/aiboxresource_bm1688 +data/resource/aiboxresource_cv186x ``` The code shows the differences between handling x86 ONNX files and Sophon model packages. The full model porting workflow should be re-validated against the currently releasable model packages. diff --git a/docs/en/tutorials/01-quickstart/quickstart.md b/docs/en/tutorials/01-quickstart/quickstart.md index 6770eb282..6b627a1a6 100644 --- a/docs/en/tutorials/01-quickstart/quickstart.md +++ b/docs/en/tutorials/01-quickstart/quickstart.md @@ -15,14 +15,14 @@ next: | --- | --- | | Who this is for | First-time CosmoEdge users, deployment engineers, and developers | | What you will accomplish | Deploy or connect to the system, configure device network and time, add video, assign an algorithm, and verify its output | -| Prerequisites | Docker is installed on an x86 host, or a CosmoEdge edge device is already provisioned | -| Estimated time | About 15–30 minutes for the first x86 build; about 15–25 minutes for a provisioned device | -| Device required | Choose either an x86 Docker host or a provisioned edge device; a camera is not required for the first test | +| Prerequisites | Docker is installed on an x86 host, an Apple Silicon Mac has the Docker Desktop Preview environment, or a CosmoEdge edge device is provisioned | +| Estimated time | About 15–30 minutes for a native x86 first build; Mac amd64 emulation can take longer; about 15–25 minutes for a provisioned device | +| Device required | Choose an x86 Docker host, an Apple Silicon Mac Preview, or a provisioned edge device; a camera is not required for the first test | | Final acceptance result | The channel is running, Live Display shows the algorithm overlay, and Event Center contains a matching event or count result | The goal is not merely to open the UI. It is to complete a **verifiable first detection**: -1. Make CosmoEdge reachable through either the x86 Docker path or the edge-device path. +1. Make CosmoEdge reachable through the x86 Docker, macOS Preview, or edge-device path. 2. For an edge device at its default static address, configure the computer first, then sign in and set the device network and time. 3. Add an offline test video. 4. Assign a scenario task and start analysis. @@ -35,7 +35,8 @@ Changing the default password, setting the device network, and correcting device ### 1.1 Path A: Docker on an x86 Host Use this path on a Linux x86_64 host. On Windows, use -`docker-compose.x86.windows.yml`; the acceptance workflow is otherwise the same. +`docker-compose.x86.windows.yml`. Apple Silicon Macs use the separate Preview +path in the next section. An earlier validated setup used Ubuntu 22.04.2, an Intel Core i9-13900F, 64 GB of memory, Docker 29.1.3, and Docker Compose v5.1.4. This is a recorded validation environment, not a minimum requirement. Use the root README, the current Compose files, and the resource requirements of your selected models as the current source of truth. @@ -73,13 +74,61 @@ Success conditions: - `docker compose ... ps` reports the services as `Up` or `running`; - `http://127.0.0.1:8080` opens on the host; -- for remote access, replace `127.0.0.1` with the host IP and allow TCP 8080 through the host firewall. +- for remote access, replace `127.0.0.1` with the x86 host IP and allow TCP 8080 through the host firewall. ![CosmoEdge containers in the running state](images/container.webp) -### 1.2 Path B: A Provisioned Edge Device +### 1.2 Path B: Apple Silicon macOS Preview -CosmoEdge currently supports the Sophon BM1688 platform. The following images show the BM1688 dual-Ethernet device used in the earlier walkthrough. Enclosures, labels, and specifications can differ by shipment; use the label and delivery manifest for the actual unit. +The Mac path uses an isolated `linux/amd64` Docker Preview. Read its +[admission, licensing, and capability boundaries](/en/guide/macos-docker-preview), +then run: + +```bash +./scripts/macos-docker-preview.sh doctor +./scripts/macos-docker-preview.sh up +./scripts/macos-docker-preview.sh status +``` + +When healthy, open `http://127.0.0.1:8080` on the same Mac. This path is for +single-video local evaluation; it is not a native macOS binary, a Sophon or +Rockchip NPU deployment, or production performance evidence. + +### 1.3 Path C: A Provisioned Edge Device + +CosmoEdge currently supports two Sophon chips: BM1688 and CV186X. The following images show the BM1688 dual-Ethernet device used in the earlier walkthrough. Enclosures, labels, and specifications can differ by shipment; use the label and delivery manifest for the actual unit. + +To build an upgrade package from source, select the target chip with the +`--chip ` option at the repository root: + +```bash +# BM1688 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip bm1688 + +# CV186X +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x + +find build_output/public-runtime -mindepth 2 -maxdepth 2 -type f -print +``` + +Omitting the chip argument defaults to `bm1688`. The build script selects the +matching model resource directory; you do not need to provide a model path. + +The model resources in the package must match the target chip. BM1688 and +CV186X artifacts are not interchangeable. + +Use the one package name reported by the build for installation. To install it +over SSH on a prepared Sophon Linux device, follow the +[Deployment Guide: SSH Installation Path](/en/guide/deployment#ssh-installation-path). +That section is the single source of truth for transfer, extraction, installation, +reboot, base-system prerequisites, and recovery boundaries. + +When CosmoEdge is already running, you can instead open **System Management → +System Maintenance → Software Upgrade** and upload the same package. Keep power +connected during installation. After reboot and sign-in, verify that **Software +Version** matches the package version. The SSH installer targets a Sophon device +with its base Linux system already prepared; it is not an OS-image installer for +arbitrary blank hardware. ![Example BM1688 edge-device connector panel](images/img_01.webp) diff --git a/docs/guide/architecture.md b/docs/guide/architecture.md index bb40ed29b..3ad31e590 100644 --- a/docs/guide/architecture.md +++ b/docs/guide/architecture.md @@ -109,8 +109,8 @@ src/web 资源目录: -- `data/resource/aiboxresource` +- `data/resource/aiboxresource_bm1688` +- `data/resource/aiboxresource_cv186x` - `data/resource/aiboxresource_x86` -当前模板覆盖检测(YOLO v5/v8/v9/v11/v12/26)、分类、关键点、特征、分割(SAM2)、目标定位(DINO)以及视觉语言模型(Qwen3VL、Qwen3.5)。完整清单以 `data/resource/aiboxresource/model_template/` 与 `data/resource/aiboxresource_x86/model_template/` 目录下的实际模板文件为准。 - +当前模板覆盖检测(YOLO v5/v8/v9/v11/v12/26)、分类、关键点、特征、分割(SAM2)、目标定位(DINO)以及视觉语言模型(Qwen3VL、Qwen3.5)。完整清单以各 `data/resource/aiboxresource_*/model_template/` 目录下的实际文件为准。 diff --git a/docs/guide/build.md b/docs/guide/build.md index 0a0fcccb4..32ace9703 100644 --- a/docs/guide/build.md +++ b/docs/guide/build.md @@ -1,12 +1,12 @@ --- title: 构建指南 -description: x86 Docker、Sophon 发布包和 CPU 测试构建路径。 +description: x86 Docker、Sophon、RK3576 和 CPU 测试构建路径。 prev: text: 文档首页 link: / next: - text: 部署指南 - link: /guide/deployment + text: RK3576 / RKNN 集成 + link: /guide/rk3576-rknn-development --- # 构建指南 @@ -15,13 +15,18 @@ next: > **💡 Docker Compose 版本提示** > 本文档统一使用最新的 Docker Compose V2 命令格式 (`docker compose`)。如果你使用的是旧版 Docker 环境(如自带独立的 V1 插件),请将文中的 `docker compose` 替换为带横杠的 `docker-compose`。 +> Linux 上也可以直接使用 `./scripts/docker-compose.sh`;它会检测 Compose V2/V1, +> 并在当前账号无权访问 Docker daemon 时明确请求一次 `sudo`。若不希望使用 sudo, +> 请先按 Docker 官方方式授予当前账号 daemon 访问权限并重新登录。 ## 构建路径总览 | 路径 | 用途 | 是否启动服务 | 输出 | | --- | --- | --- | --- | | x86 Docker 开发运行环境 | 首次体验、开发评估、生成 x86 发布包 | 是 | `build_output/` | -| Sophon 发布包构建 | 生成 aarch64/Sophon 部署包 | 否 | `build_output/` | +| macOS Docker Preview | Apple Silicon 上体验单路 x86 工作流 | 是 | `build_output/macos-x86/` | +| Sophon SOURCE 构建 | 交叉编译可安装的源码构建包 | 否 | `build_output/public-runtime//` | +| RK3576 稳定版构建 | 使用 RKNN、MPP 和 RGA 交叉编译发布包与测试程序 | 否 | `build_output/rk3576/` | | CPU 测试构建 | 构建 `cosmo-tests` | 否 | `build_cpu/cosmo-tests` | ## x86 Docker 开发运行环境 @@ -38,10 +43,22 @@ Windows (PowerShell/CMD): docker compose -f docker-compose.x86.windows.yml up -d --build ``` +Apple Silicon macOS (Preview): + +```bash +./scripts/macos-docker-preview.sh doctor +./scripts/macos-docker-preview.sh up +``` + +Mac 路径显式运行 `linux/amd64`,使用独立卷并只绑定回环地址。它不启用 +Model Guard,也不构成原生 arm64 或 NPU 性能证据。完整说明和验收范围见 +[macOS Docker Preview](./macos-docker-preview.md)。 + 该路径来自: - `docker-compose.x86.yml` (Linux) - `docker-compose.x86.windows.yml` (Windows) +- `docker-compose.x86.macos.yml` (Apple Silicon macOS Preview) - `Dockerfile.x86` - `scripts/build_cpu.sh` @@ -63,32 +80,127 @@ docker compose -f docker-compose.x86.windows.yml up -d --build - 运行数据保存在 Docker volume `cosmo-x86-data`。 - 资源目录挂载到 Docker volume `cosmo-x86-app-resource`。 -## Sophon 发布包构建 +## Sophon 构建产物 + +公开构建入口默认使用 +`COSMO_MODEL_GUARD_BUILD_PROFILE=public-runtime`: Linux / Bash: ```bash -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package +# 省略型号时默认 bm1688 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package + +# 显式选择型号 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip bm1688 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x ``` Windows PowerShell: ```powershell +# 省略型号时默认 bm1688 .\scripts\build_sophon_package.ps1 + +# 显式选择型号 +.\scripts\build_sophon_package.ps1 -Chip bm1688 +.\scripts\build_sophon_package.ps1 -Chip cv186x ``` +两个支持的配置使用相互隔离的输出目录: + +| 配置 | 用途 | 输出目录 | 部署状态 | +| --- | --- | --- | --- | +| Open(内部配置 `public-runtime`,默认) | 使用仓库内运行时 SDK 完成公开的 aarch64 编译、链接、打包和测试验证 | `build_output/public-runtime//` | 明文模型,无需设备授权 | +| Protected(内部配置 `production-release`) | 在受控环境中使用完整正式 SDK 和设备授权工具构建 | `build_output/production-release//` | 加密模型,需要设备授权 | + +每个芯片目录同时包含 `TARGET_CHIP` 和 `SHA256SUMS`,压缩包内部还包含 +`share/cosmo/target-chip.txt`。即使两个芯片当前选择的公开模型字节一致,完整安装包也 +必须具有不同哈希;必须从各自目录取包,不能用相同包名推断芯片兼容性。 + +Compose 会在首次构建时按 `package-lock.json` 串行填充 npm 缓存,随后完全离线安装; +同一工作目录中的 BM1688、CV186X 与 RK3576 构建共享该缓存。这样可规避 npm 10.2 +在部分网络上建立大量 CDN 连接后无法退出的问题。删除 Compose 卷会触发重新填充。 + +两种配置都生成 `cosmo-V<版本号>-<32位md5>.tar.gz`。同一格式既可以在 main +分支部署的管理页面升级,也可以在后续任意版本继续升级。应用包不签名;两种配置 +只在模型是否加密以及是否包含 `cosmo-model-provision` 上有区别。 + +### 将 Sophon 构建包交给部署流程 + +构建完成后,先在对应芯片目录核对目标标记和 SHA-256: + +```bash +chip=bm1688 # 或 cv186x +cat "build_output/public-runtime/${chip}/TARGET_CHIP" +(cd "build_output/public-runtime/${chip}" && sha256sum -c SHA256SUMS) +``` + +SSH 安装、Web 升级、恢复边界和重启后的版本验收统一见[部署指南](./deployment.md#ssh安装路径)。 +构建指南不重复维护设备安装命令,避免构建入口和部署流程独立演进后出现两套口径。 + +维护人员在包含完整 Guard SDK 和授权工具的受控环境中使用一条命令构建: + +```bash +COSMO_MODEL_GUARD_BUILD_PROFILE=production-release \ + ./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x +``` + +上例构建 CV186X Protected 包;构建 BM1688 时把末尾型号改为 `bm1688`,或省略型号。 + +如果受控 SDK 中缺少 `cosmo-model-provision`,Protected 构建会直接失败。 +受控生产 SDK 应放在宿主机的 +`build_output/model-guard-sdk-production/`,该目录通过现有 Compose 挂载进入 +容器且不会提交到 Git。Protected 构建会自动优先使用它;Open 构建不受影响。 + +Protected 的 CPack 产物本身就是管理页面接受的升级包,不再需要离线应用签名步骤。 +Guard 设备证书和模型加密秘密仍属于受控输入,不得写入公开仓库。 + 该路径来自: +- `scripts/docker-compose.sh`(Linux/macOS:选择 Compose V2 或 V1,并处理 Docker 权限) - `docker-compose.sophon.yml` +- `scripts/build_sophon_package.sh` - `scripts/build_sophon_package.ps1`(Windows:构建前自动修复 `.so` 软链接) - `scripts/build.sh` 已确认行为: - 基础镜像使用预先构建的 GHCR 镜像:`ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_sophon:v1`(统一的编译环境,加速了本地启动时间)。 -- 使用 `scripts/build.sh -m data/resource/aiboxresource` 构建(生产包不启用 dev mode,故不传 `-t`)。 -- 只导出发布包,不启动服务。 -- 发布包导出到 `build_output/`。 +- Docker Compose 接受芯片型号参数:`cosmo-sophon-package --chip bm1688` 或 + `cosmo-sophon-package --chip cv186x`。省略 `--chip` 时默认使用 `bm1688`。 +- `scripts/build_sophon_package.sh` 把芯片型号传给 `scripts/build.sh -T -c <型号>`; + `build.sh` 再选择对应资源目录,用户无需传入模型路径。 +- 只导出构建产物,不启动服务。 +- 芯片型号不会改变 CPack 或 MD5 重命名逻辑;输出隔离到 + `build_output///`,包名仍为 `cosmo-V..-.tar.gz`, + 旁边的 `TARGET_CHIP` 与 `SHA256SUMS` 用于阻止同名产物混用。 + +## RK3576 构建产物 + +RK3576 公开构建入口使用固定 digest 的 GHCR 最终构建镜像,其中 RKLLM Runtime v1.3.0 +固定到官方 commit。该镜像包含 aarch64 工具链、RKNN Runtime、RKLLM Runtime、 +MPP 和 RGA 开发文件: + +```bash +./scripts/docker-compose.sh -f docker-compose.rk3576.yml pull cosmo-rk3576-package +./scripts/docker-compose.sh -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package +sha256sum build_output/rk3576/cosmo-*.tar.gz +``` + +该入口已确认: + +- 在 `linux/amd64` 构建容器中执行 aarch64 交叉编译。 +- 构建前清理 `build_rknn/`,再调用 `scripts/build_rknn.sh -T`,避免复用部分缓存。 +- RKLLM 头文件、运行库或许可证缺少时立即失败,不再静默生成缺少 Qwen3.5 的包。 +- 发布包必须包含 `lib/librkllmrt.so` 和 `share/licenses/rkllm/LICENSE`。 +- 将唯一发布包导出到 `build_output/rk3576/`,不启动应用服务。 +- 同时生成 `build_rknn/cosmo-tests`、`cosmo-rknn-backend-smoke` 和 + `cosmo-rknn-fastpath-qualify` 三个 aarch64 验证程序。 +- 使用宿主机网络解析构建依赖,但不发布应用端口。 + +稳定版支持范围、运行时选择、模型约定和板端证据边界见 +[RK3576 / RKNN 集成指南](./rk3576-rknn-development.md)。 ## CPU 测试构建 diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 74776bea3..732ea9261 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -19,6 +19,7 @@ x86 开发运行环境: - Linux: `docker-compose.x86.yml` - Windows: `docker-compose.x86.windows.yml` +- Apple Silicon macOS Preview: `docker-compose.x86.macos.yml` Sophon 发布包构建: @@ -58,6 +59,9 @@ ${INSTALLPATH}/scripts/run_start.sh start ${DATADIR}/log/logs/INTE_RUN_container `docker-compose.sophon.yml` 支持以下构建参数: +芯片型号通过 Compose 服务后的 `--chip <型号>` 参数传入,支持 `bm1688` 和 `cv186x`; +省略 `--chip` 时默认为 `bm1688`。构建脚本会自动选择匹配的资源目录。 + | 变量 | 默认值 | 说明 | | --- | --- | --- | | `SOPHON_APT_MIRROR` | `https://mirrors.aliyun.com/ubuntu` | apt 镜像 | @@ -71,7 +75,8 @@ ${INSTALLPATH}/scripts/run_start.sh start ${DATADIR}/log/logs/INTE_RUN_container | 构建路径 | 资源目录 | | --- | --- | | x86 Docker | `data/resource/aiboxresource_x86` | -| Sophon package | `data/resource/aiboxresource` | +| Sophon BM1688 包 | `data/resource/aiboxresource_bm1688` | +| Sophon CV186X 包 | `data/resource/aiboxresource_cv186x` | CMake 通过 `RESOURCE_DIR` 安装资源。 diff --git a/docs/guide/cv186x-quick-start.md b/docs/guide/cv186x-quick-start.md new file mode 100644 index 000000000..ea281888d --- /dev/null +++ b/docs/guide/cv186x-quick-start.md @@ -0,0 +1,104 @@ +--- +title: CV186X 快速开始 +description: 在已准备好的 CV186X Linux 设备上安装 CosmoEdge 1.1,并完成首次检测。 +prev: + text: 构建指南 + link: /guide/build +next: + text: RK3576 / RKNN 集成 + link: /guide/rk3576-rknn-development +--- + +# CV186X 快速开始 + +本指南适用于已经配置好 Sophon 运行依赖和网络的 CV186X Linux 设备。CosmoEdge 1.1 +的 CV186X 路径使用 BMRT 与已在 CV186X 上验证的 `.nn` 模型。本版本公开压测使用的两份 +Sophon 模型与 BM1688 压测产物字节一致;其他模型是否可复用仍须按模型合同逐项验证。 + +安装前必须先核对硬件身份,不能用设备 IP 或旧模型目录名代替平台证据: + +```bash +tr -d '\0' -.tar.gz` 命名, +但必须连同同目录的 `TARGET_CHIP` 与 `SHA256SUMS` 一起验收。 + +也可以从 [GitHub Release](https://github.com/cosmo-wander-ai/cosmo-edge/releases) 获取明确标注 +适用于 CV186X 的 CosmoEdge 1.1 Sophon Open 包和发布页列出的 SHA-256,然后在构建机上核对: + +```bash +sha256sum cosmo-V1.1.0-*.tar.gz +scp cosmo-V1.1.0-*.tar.gz root@:/tmp/ +``` + +## 2. 安装并启动 + +```bash +ssh root@ +install_dir=$(mktemp -d /tmp/cosmo-install.XXXXXX) +tar -xzf /tmp/cosmo-V1.1.0-*.tar.gz -C "$install_dir" +cd "$install_dir"/cosmo-V*/ +./scripts/install.sh +reboot +``` + +设备恢复后确认 `cosmo.service` 为 active,并从设备管理页面核对软件版本为 1.1。 +已有 CosmoEdge 的设备也可以在 **系统管理 → 系统维护 → 软件升级** 上传同一安装包。 + +## 3. 使用内置开源模型创建首个事件 + +CV186X Sophon Open 包由构建脚本根据 `cv186x` 型号自动选择对应资源目录,已包含本次公开压测 +使用的两份模型;用户无需传入资源路径: + +- `YOLOV8n V1.0.0`:人员检测,`1x3x640x640`,模型文件 7,023,600 B; +- `helmet V1.0.0`:安全帽分类,`1x3x224x224`,模型文件 6,001,416 B。 + +它们的模型目录、输入输出合同与 SHA-256 记录在 +[ScenarioBench v1.1 模型身份表](/benchmarks/scenario-bench/v1.1/models/cv186x.json)。 +模型子目录仍保留 `prod_BM1688_` 历史兼容前缀,这是为了完整保留 CV186X 压测设备中的 +原始文件。目录名和设备树中的 `BM1688` 都不单独决定产品平台。CV186X 资格依据是受控的 +整机平台映射、设备实际加载文件与 CV186X 资源目录副本的 SHA-256 完全一致,以及真机 +推理成功;不能据此推断其他 BM1688 模型也可直接复用。 + +1. 登录 Web 控制台并进入 **模型仓库**,确认上述两份模型可见。 +2. 在 **视频接入** 添加一路测试视频,再在 **场景任务** 使用人员检测模型创建任务并绑定 + 该视频;需要安全帽完整链路时,在编排中增加安全帽分类模型。 +3. 打开算法预览,确认 OSD 和事件;随后检查任务状态与服务日志无持续报错。将模型 + SHA-256、实际设备树字符串和该次推理结果一起写入验收记录。 + +导入自有模型时,目录至少应包含匹配的 `config.json` 和模型文件。输入尺寸、量化方式、 +前后处理和输出张量必须与配置一致;详细合同见[模型适配指南](/tutorials/05-model-porting/model-porting)。 + +## 升级、恢复与证据边界 + +- 安装和 Web 升级共用 `cosmo-V-.tar.gz` 生命周期;保持供电,恢复后同时 + 核对服务状态和软件版本。 +- 若服务未恢复,先检查 `systemctl status cosmo.service` 与服务日志;不要重复上传同一 + 包掩盖首次失败。 +- 完整目录、端口、持久化、失败恢复和回滚边界见[部署指南](/guide/deployment)。 +- 当前公开容量结果见 [ScenarioBench v1.1](/benchmarks/scenario-bench/v1.1/report.zh-CN.html);短时最高点 + 不是官方推荐配置,生产容量需按实际模型、视频和精度要求复验。 diff --git a/docs/guide/deployment.md b/docs/guide/deployment.md index 1748ed2da..67abcf2cc 100644 --- a/docs/guide/deployment.md +++ b/docs/guide/deployment.md @@ -2,8 +2,8 @@ title: 部署指南 description: 当前运行目录、服务进程、端口、升级包和 systemd 行为。 prev: - text: 构建指南 - link: /guide/build + text: macOS Docker Preview + link: /guide/macos-docker-preview next: text: 架构概览 link: /guide/architecture @@ -30,6 +30,10 @@ next: ```powershell docker compose -f docker-compose.x86.windows.yml up -d --build ``` +- **Apple Silicon macOS (Preview)**: + ```bash + ./scripts/macos-docker-preview.sh up + ``` 停止: @@ -41,6 +45,10 @@ next: ```powershell docker compose -f docker-compose.x86.windows.yml down ``` +- **Apple Silicon macOS (Preview)**: + ```bash + ./scripts/macos-docker-preview.sh down + ``` 查看日志: @@ -52,6 +60,10 @@ next: ```powershell docker compose -f docker-compose.x86.windows.yml logs -f ``` +- **Apple Silicon macOS (Preview)**: + ```bash + ./scripts/macos-docker-preview.sh logs --follow + ``` ## 运行目录 @@ -86,7 +98,7 @@ ${INSTALLPATH}/bin/cosmo-engine | 端口 | 来源 | 用途 | | --- | --- | --- | -| `8080 -> 80` | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` | x86 Docker Web 控制台 | +| `8080 -> 80` | x86 Compose 文件;Mac Preview 仅绑定 `127.0.0.1` | x86 Docker Web 控制台 | | `1936` | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` / SRS | RTMP | | `1985` | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` / SRS | SRS API | | `18088` | `docker-compose.x86.yml` / `docker-compose.x86.windows.yml` / SRS | HTTP stream | @@ -121,7 +133,7 @@ COSMO_STREAM_HTTP_PORT=18088 - `lib` - `resource` -升级包文件名匹配: +升级包文件名必须匹配以下格式: ```text cosmo-V..-<32-char-md5>.tar.gz @@ -132,26 +144,40 @@ Web 控制台的本地升级流程如下: 1. 查询设备状态并记录当前 Linux `bootId`。 2. 按设备返回的上传能力分片传输安装包,界面显示实际上传百分比。 3. 后端校验文件名、MD5、归档安全、目录结构和实时磁盘预算。 -4. Sophon 设备重启后,启动脚本再次校验 MD5、安装发布包并启动服务。 +4. Sophon 设备重启后,启动脚本再次校验 MD5 并安装。Open 与 Protected 包永久使用同一升级流程。 5. 页面在看到新的 `bootId` 后返回登录页。如果重启使登录会话失效,则必须先观察到设备离线,再收到新服务的鉴权响应,才能判定服务已恢复并返回登录页。 页面等待恢复的 15 分钟是交互超时,不会中止设备端已经开始的升级。超时后应保持供电,并通过设备网络和 systemd 日志确认状态。重新登录后还应核对软件版本与本次发布包;页面恢复只证明重启与服务恢复,不替代版本验收。 -## systemd 服务 +## SSH安装路径 -`scripts/install.sh` 会创建: +除了Web升级,包内`scripts/install.sh`还提供从main版本迁移及后续兼容安装的SSH入口。 +它会安装应用、替换并启用`cosmo.service`,然后由重启启动服务: -```text -/etc/systemd/system/cosmo.service +```bash +scp build_output/public-runtime//<安装包>.tar.gz root@<设备IP>:/tmp/ +ssh root@<设备IP> +cd /tmp +install_dir=$(mktemp -d /tmp/cosmo-install.XXXXXX) +tar -xzf <安装包>.tar.gz -C "$install_dir" +cd "$install_dir"/cosmo-V*/ +sudo ./scripts/install.sh +sudo reboot ``` -服务启动命令: +该路径假设Sophon Linux基础系统和运行依赖已经准备好,不是任意空白硬件的操作系统 +镜像安装流程。安装前记录当前版本和恢复方案;安装器会替换当前应用树。 + +## systemd 服务 + +已配置设备的服务启动命令为: ```text -ExecStart=${INSTALLPATH}/scripts/inte_run_start.sh +ExecStart=/appfs/cosmo_wander/cwai_data/scripts/inte_run_start.sh ``` -服务以 `root` 运行并使用 `Restart=on-failure`。致命初始化异常会返回非零状态,使 systemd 能够重试,而不会把异常退出误判为正常停止。 +`scripts/install.sh`负责升级事务,不创建空白设备的systemd unit。服务以`root` +运行并使用`Restart=on-failure`。 部分 Sophon 系统会在启动时把持久化数据树的属主恢复为设备管理账户。上传暂存服务允许 `sessions` 目录继承一个不可被 group/other 写入的直接父目录属主,同时继续要求: diff --git a/docs/guide/macos-docker-preview.md b/docs/guide/macos-docker-preview.md new file mode 100644 index 000000000..4bb1fa6fd --- /dev/null +++ b/docs/guide/macos-docker-preview.md @@ -0,0 +1,174 @@ +--- +title: macOS Docker Preview +description: 在 Apple Silicon Mac 上通过隔离的 linux/amd64 Docker 环境体验 CosmoEdge x86 工作流。 +prev: + text: RK3576 / RKNN 集成 + link: /guide/rk3576-rknn-development +next: + text: 部署指南 + link: /guide/deployment +--- + +# macOS Docker Preview + +> **状态:Preview。** 这条路径面向本地开发和单路离线视频体验,不是原生 +> arm64 构建、Sophon 设备仿真或生产部署方案。Apple Silicon 通过 Docker +> Desktop 运行 `linux/amd64` 镜像,因此首次构建和推理速度都低于原生 x86 Linux。 + +## 能做什么 + +Mac Preview 复用 x86 CPU/ONNX Runtime 后端,目标是让开发者在没有边缘设备时完成: + +- 登录 Web 控制台; +- 上传本地视频和查看持久化通道; +- 使用随仓库提供的 x86 ONNX 模型创建任务、设置 ROI 和启停分析; +- 查看实时 OSD、告警截图和事件记录; +- 导出非空告警 CSV; +- 停止并重新启动容器后继续使用原有配置和上传数据。 + +它不提供 NPU 性能等价、USB 摄像头直通、局域网设备发现、多路容量结论或本地 +VLM 能力。更完整的能力边界见[验收与边界](#验收与边界)。 + +## 准备环境 + +当前 Preview 的准入环境是 Apple Silicon Mac 和 Docker Compose V2。建议预留: + +- 至少 20 GiB 可用磁盘空间; +- 至少 8 GiB Docker 虚拟机内存; +- Rosetta 2,用于改善 amd64 仿真体验。 + +安装和首次启动 Docker Desktop 前,请自行确认并接受其独立的 +[Docker Subscription Service Agreement](https://docs.docker.com/subscription/)。 +[Docker 的 Mac 安装说明](https://docs.docker.com/desktop/setup/install/mac-install/) +列出了当前支持的 macOS、内存和 Rosetta 要求。 + +对于这个 amd64 工作负载,Docker Desktop 当前使用 Apple Virtualization +Framework 并开启 Rosetta 时通常更快。Docker 的 +[设置说明](https://docs.docker.com/desktop/settings-and-maintenance/settings/) +指出 Rosetta 选项只在 Apple Virtualization Framework 下可用;Docker VMM +目前不通过 Rosetta 加速 amd64 仿真。这个设置是性能建议,不是 CosmoEdge +脚本自动修改的系统配置。 + +## 启动 + +在仓库根目录运行只读准入检查: + +```bash +./scripts/macos-docker-preview.sh doctor +``` + +检查会确认 Apple Silicon、Docker Desktop、Compose 配置、Docker 内存、磁盘、 +Rosetta 和本地端口,但不会安装组件或修改 Docker 设置。通过后启动: + +```bash +./scripts/macos-docker-preview.sh up +``` + +脚本会在镜像缺失时构建 `docker-compose.x86.macos.yml`,已有镜像时则直接复用, +随后等待 nginx、SRS、`cosmo-engine` 和 Web 响应全部健康,然后输出: + +```text +http://127.0.0.1:8080 +``` + +首次构建需要下载 amd64 构建镜像和依赖,并在仿真环境内编译,可能明显慢于后续启动。 +Mac Compose 通过摘要固定已验证的 amd64 builder 和 Debian 运行基础镜像,避免标签 +更新让同一候选使用不同基础环境。 +Mac Compose 默认使用一个编译 job,以避开 amd64 仿真下嵌套 GNU Make jobserver 的 +文件描述符兼容问题。`COSMO_X86_BUILD_JOBS` 可以覆盖该值,但提高并行度属于实验性 +调优,应重新完成本页的两轮验收。 + +源代码、Dockerfile 或构建资源变化后,显式重建: + +```bash +./scripts/macos-docker-preview.sh up --build +``` + +普通 `up` 会复用现有镜像,不会因工作区中无关文件变化再次触发耗时构建。 + +如果 Web 端口 `8080` 已被占用,可以只覆盖 Web 端口: + +```bash +COSMO_X86_WEB_PORT=8280 ./scripts/macos-docker-preview.sh up +``` + +随后访问 `http://127.0.0.1:8280`。流媒体端口 `1936`、`1985` 和 `18088` 保持固定, +不能用作 Web 端口,因为前端预览链路依赖当前 SRS 端口契约。 + +Mac Preview 默认直接通过本机回环端口 `18088` 播放 SRS HTTP-FLV,不先尝试 WebRTC。 +Web 控制台端口即使通过 `COSMO_X86_WEB_PORT` 改为其他值,流媒体端口仍保持 `18088`。 +这样可以避开 Docker Desktop 本地 WebRTC 建连失败后最长十余秒的媒体超时与回退窗口; +这只是本机 Preview 的确定性设置,不改变其他部署默认采用的 WebRTC 模式。 + +## 日常命令和数据隔离 + +```bash +# 查看容器和健康状态 +./scripts/macos-docker-preview.sh status + +# 查看最近日志;加 --follow 持续跟踪 +./scripts/macos-docker-preview.sh logs +./scripts/macos-docker-preview.sh logs --follow + +# 停止服务,但保留配置、上传文件和模型资源 +./scripts/macos-docker-preview.sh down +``` + +Mac Preview 使用独立的 Compose 项目、容器、镜像、卷和构建输出: + +| 对象 | 名称或路径 | +| --- | --- | +| Compose 项目 | `cosmo-x86-macos-preview` | +| 容器 | `cosmo-x86-macos-preview` | +| 运行数据卷 | `cosmo-x86-macos-preview-data` | +| 模型资源卷 | `cosmo-x86-macos-preview-app-resource` | +| 发布包输出 | `build_output/macos-x86/` | + +默认 `down` 不删除命名卷,因此不会因为一次普通停止而清空数据。 + +## 验收与边界 + +发布为社区 Preview 前,至少应在 Apple Silicon Mac 上连续完成两次以下流程,且 +两次之间执行一次 `down` / `up`: + +1. 容器健康,Web 控制台可以登录; +2. 上传仓库内 `data/test-video/Safety Helmet.mp4`,刷新后通道仍存在; +3. 使用随仓库提供的未戴安全帽 ONNX 模型创建任务并设置 ROI; +4. 启动任务,实时展示出现视频和 OSD;单个已启用任务应直接进入 OSD,不先建立原始流; +5. 事件中心生成带截图的告警; +6. 导出的告警 CSV 非空; +7. 重启后配置、视频和任务仍可使用,容器没有崩溃或异常重启。 + +验收结论只覆盖实际测试的这一层: + +| 能力 | Mac Preview 结论 | +| --- | --- | +| Web 控制台、视频上传、任务、ROI、OSD、告警、CSV | Preview 目标范围,按上面的连续验收记录结论 | +| x86 ONNX Runtime CPU 推理 | 运行于 `linux/amd64` 仿真,不能代表原生性能 | +| Sophon / Rockchip NPU、USB 摄像头、局域网发现 | 未覆盖 | +| 多路性能、长稳、生产部署 | 未覆盖,不能从单路本地视频外推 | +| Model Guard、Sophon Protected 包、CEMC 模型和设备授权 | 未启用、未验证 | + +`scripts/build_cpu.sh` 明确关闭 Sophon 后端并启用 CPU 后端,CMake 因此关闭 +Model Guard。Mac Preview 基于 Model Guard 开发分支并不等于在 Mac 上运行了 +Model Guard;CEMC 受保护模型仍属于 Sophon Protected 运行路径。 + +## 本地安全默认值 + +`docker-compose.x86.macos.yml` 将 Web、RTMP、SRS API 和 HTTP stream 端口 +全部绑定到 `127.0.0.1`,不发布 UDP 设备发现端口、不请求 `NET_ADMIN`,也不映射 +`/dev/video*`。这适合单机开发,但不会让同一局域网的其他主机直接访问。若要开放 +远程访问,需要另行评估身份验证、TLS、防火墙、视频数据和端口暴露;不要直接删除 +回环地址绑定并把 Preview 当成生产配置。 + +## 常见问题 + +- `Docker Desktop is not ready`:打开 Docker Desktop,完成首次启动和协议确认, + 等状态为 Running 后重新执行 `doctor`。 +- 构建很慢:确认 Docker 使用的 VMM 和 Rosetta 设置,并给 Docker 至少 8 GiB + 内存。amd64 仿真仍然只属于 best-effort Preview。 +- 服务没有变为 healthy:运行 `./scripts/macos-docker-preview.sh logs`,先检查 + nginx、SRS、`cosmo-engine` 中第一个失败的进程。 +- Web 端口冲突:设置 `COSMO_X86_WEB_PORT`;其他固定端口冲突需要先停止占用者。 +- 修改源码后需要保留数据并重建:运行 `./scripts/macos-docker-preview.sh up --build`; + 不要删除两个 Preview 命名卷。仅重启时使用普通 `up`。 diff --git a/docs/guide/rk3576-rknn-development.md b/docs/guide/rk3576-rknn-development.md new file mode 100644 index 000000000..329260155 --- /dev/null +++ b/docs/guide/rk3576-rknn-development.md @@ -0,0 +1,208 @@ +--- +title: RK3576 / RKNN 集成指南 +description: Rockchip RK3576 稳定版的构建、运行时、模型和验证边界。 +prev: + text: 构建指南 + link: /guide/build +next: + text: macOS Docker Preview + link: /guide/macos-docker-preview +--- + +# RK3576 / RKNN 集成指南 + +## 能力范围 + +RK3576 集成增加了面向生产的 CV 后端,不改变 CPU、CUDA 或 Sophon 后端的行为: + +- RKNN Runtime 2.3.2 执行静态 batch 的检测和分类模型。 +- RKLLM Runtime 1.3.0 配合 RKNN 视觉编码器执行 Qwen3.5 多模态模型。 +- Rockchip MPP 执行 H.264/H.265 解码与编码。 +- 解码器使用延迟 Copy-out:先对帧进行采样或丢弃,再按需复制宿主机 I420 数据。 +- RGA 执行预览与 OSD 路径所需的 Rockchip 图像处理操作。 +- 完整 DMA-BUF 零拷贝不属于当前稳定版支持边界。 + +推荐部署起点为已完成 12 小时验证的 4 路 × 5 FPS 单算法配置。最新短时阶梯中, +单算法覆盖到 16 路 × 5 FPS,双算法覆盖到 8 路 × 每任务 5 FPS;这些是指定模型与 +门禁下的实测边界,不直接替代推荐配置。详见 [ScenarioBench v1.1](/benchmarks/scenario-bench/v1.1/report.zh-CN.html)。 + +## 仓库与证据边界 + +仓库负责产品代码、构建定义、单元测试、可复现模型工具、可部署 RKNN 资源以及 +两个可复用验收场景: + +- `tools/scenario-bench/scenarios/rk3576-no-helmet-customer-journey` +- `tools/scenario-bench/scenarios/rk3576-no-helmet-longrun-4x5fps` + +板端原始日志、指标流、截图、导出事件以及生成的 HTML/XML/JSON 报告属于外部 +验证产物,不应加入源码树。发布证据 manifest 应绑定源码 commit 与 tree、最终 +安装包 SHA-256、设备/固件/运行时版本、模型与数据集哈希、阈值、清理状态和实测值。 + +设备地址、账号数据、本地备份路径和可复用凭据不得进入版本控制配置或证据。 + +## 固定工具链标识 + +机器可读的工具链与模型输入锁文件为 `config/rknn/toolchain-lock.json`。当前支持 +的集成基于: + +- RKNN-Toolkit2 2.3.2 +- RKNN Model Zoo 2.3.2 +- Ubuntu 22.04 x86_64 转换主机与 Python 3.10 +- RK3576 Ubuntu 22.04 aarch64 目标机、内核 6.1.118、RKNPU 驱动 0.9.8 + +修改已锁定的 SDK、运行时、输入模型或预处理约定后,必须重新生成转换和板端证据。 + +## 运行时安全边界 + +保留板端系统 RKNN 运行时作为回滚基线。将 RKNN Runtime 2.3.2 与 CosmoEdge 一起 +打包,通过可执行文件 RPATH 或任务局部 `LD_LIBRARY_PATH` 选择它;不要覆盖 +`/usr/lib/librknnrt.so`。生产推理使用原生 C API,不依赖 `rknn_server`。 + +## 模型与预处理约定 + +首批支持的模型为: + +1. 安全帽分类:`1x3x224x224`,ONNX opset 19。 +2. YOLOv8 检测:`1x3x640x640`,转换为 ONNX opset 19 / IR 9。 + +Qwen3.5 多模态模型属于另一份模型合同。一个可导入目录至少包含: + +- `model.rkllm`:目标平台为 RK3576 的语言模型; +- `vision.rknn`:与语言模型的图像 token 数、embedding 宽度匹配的视觉编码器; +- `tokenizer.json`:与转换源模型完全一致的分词器; +- `config.json`:`model_type` 为 `qwen3_5`,并声明 `runtime_backend: rkllm`。 + +四个文件必须作为一组记录 SHA-256。仅有 `librkllmrt.so`、仅能加载文本模型,或仅能 +运行 `vision.rknn`,都不能证明多模态能力。 + +CosmoEdge 负责 resize、通道顺序和归一化。转换过程不得再次固化 mean/std 变换。 +CosmoEdge 提供 float32 NCHW 张量;由于 Runtime 2.3.2 在该输入转换路径拒绝 NCHW, +RKNN 边界执行一次显式 NCHW 到 NHWC 拷贝。输出请求为 float32,以现有后处理器 +为最终行为基准。 + +生产 YOLO 模型提供三组 box/class head。`yolov8_dfl_v1` 宿主适配器执行 DFL 和 +sigmoid,再重建逻辑 `[1,84,8400]` 约定。不支持单个量化输出,因为共享 scale +会压缩置信度精度。 + +## 可复现转换 + +在操作人员选定的路径准备已验证离线包: + +```bash +./scripts/rknn/prepare_offline_env.sh "$RKNN_OFFLINE_BUNDLE" +``` + +锁定的 YOLO 转换顺序为: + +```bash +python tools/rknn/convert_onnx_opset.py \ + --input model-opset22.onnx --output yolov8-opset19-ir9.onnx \ + --opset 19 --ir-version 9 + +python tools/rknn/extract_yolov8_heads.py \ + --input yolov8-opset19-ir9.onnx --output yolov8-heads.onnx + +python tools/rknn/prepare_validation_data.py \ + --spec config/rknn/models/yolov8.json --video "$VALIDATION_VIDEO" \ + --output-dir yolov8-calibration --samples 32 + +python tools/rknn/convert_model.py \ + --spec config/rknn/models/yolov8.json --model yolov8-heads.onnx \ + --output yolov8-heads-int8.rknn --quantize \ + --dataset yolov8-calibration/dataset.txt +``` + +校准样本和数值一致性样本没有标签,不能替代带标签的 precision/recall/F1 验收集。 + +## 构建与部署 + +公开构建使用 digest 固定的最终镜像,其中 RKLLM Runtime v1.3.0 来自 Rockchip 官方仓库 +的固定 commit;最终环境包含 aarch64 工具链、RKNN Runtime、RKLLM Runtime、 +MPP 和 RGA 开发文件。基础资源目录提供通用动作、布局和字体;RKNN 资源目录提供 +RK3576 算法与模型。 + +```bash +./scripts/docker-compose.sh -f docker-compose.rk3576.yml pull cosmo-rk3576-package +./scripts/docker-compose.sh -f docker-compose.rk3576.yml run --rm cosmo-rk3576-package +sha256sum build_output/rk3576/cosmo-*.tar.gz +``` + +基础镜像和 RKLLM 官方文件均可公开获取,无需 `docker login`。辅助脚本会自动选择 +Docker Compose V2/V1。该命令使用 Rockchip 媒体后端构建 Release 包,并在 +`build_rknn/cosmo-tests` 保留 aarch64 测试程序;不会启用 `COSMO_DEV_MODE`。 + +RKLLM 是正式 RK3576 包的强制依赖:头文件、`librkllmrt.so` 或许可证任一缺失都会让 +配置阶段失败,不能用缺少 Qwen3.5 的降级包作为发布候选。 + +RKLLM Runtime 会随安装包发布,但 Qwen3.5 模型文件不随 Open 包分发。部署人员必须使用 +有权使用、与 RK3576 和 Runtime 1.3.0 匹配的转换产物,并按上一节的四文件合同导入。 + +正式入口在构建前删除旧的 `build_rknn`,避免将部分交叉编译缓存误作发布证据。 +构建时依赖解析使用宿主机网络;一次性构建服务不发布或监听应用端口。 + +RK3576 的板端网络由系统 NetworkManager 管理,不由 CosmoEdge 的 Sophon netplan 路径 +接管。清空 `/data/cwaiuserdata` 会重新生成默认 JSON,但不会把现有 NetworkManager +连接改成 `192.168.100.1`;部署和恢复时应以 `ip -4 addr`/`nmcli` 的实际地址为准。 + +运行时应隔离可变数据目录和包内应用目录: + +```bash +export COSMO_DATA_DIR=/data/cwaiuserdata +export COSMO_APP_DATA_DIR=/appfs/cosmo_wander/cwai_data +export LD_LIBRARY_PATH="$COSMO_APP_DATA_DIR/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" +``` + +`COSMO_DATA_DIR` 保存配置、数据库、上传内容和事件;`COSMO_APP_DATA_DIR` 保存包内 +资源、模型、库和可执行文件。使用包内启动器,确保传递依赖从正在验证的产物解析。 + +## 可复用验收场景 + +客户旅程场景在有界时间内运行 1 路 × 5 FPS。验收范围包括登录、模型/任务/通道 +可见性、真实原始与算法 HTTP-FLV 播放、OSD 差异、事件、重连、停止/启动恢复和清理。 + +长稳场景保持 4 路 × 5 FPS 运行 12 小时。运行时启用算法预览客户端,并使用 +`--gate-hours 12` 审计。达到配置的磁盘熔断线后 runner 会停止。使用 +`--password-stdin`,避免凭据进入进程参数。 + +预览验证需要真实的 `ffmpeg` 和 `ffprobe` 可执行文件。工具会在修改设备配置前 +完成环境预检。 + +## Qwen3.5 多模态真机验收 + +正式验收必须在 RK3576 真机上输入一张固定测试图,并得到非空、与画面相关的文本结果。 +纯文本问答只证明 RKLLM 语言侧,不能代替本项。可以使用 CosmoEdge 的**图片分析**流程; +也可以用与构建镜像相同的 aarch64 工具链编译 Rockchip 官方 +[`multimodal_model_demo`](https://github.com/airockchip/rknn-llm/tree/878f9361fd3afa7e167b7079918918f78d2c1c2a/examples/multimodal_model_demo), +再在设备上运行: + +```bash +MODEL_DIR=/data/cwaiuserdata/resource/models/ +export LD_LIBRARY_PATH=./lib +./demo smoke.jpg "$MODEL_DIR/vision.rknn" "$MODEL_DIR/model.rkllm" \ + 64 4096 2 rk3576 \ + '<|vision_start|>' '<|vision_end|>' '<|image_pad|>' +``` + +验收记录至少包含:安装包和四个模型文件的 SHA-256、RKLLM/Toolkit/驱动版本、目标平台、 +量化类型、视觉模型输入输出形状、测试图哈希、返回文本和退出状态。通过条件为语言模型与 +视觉模型均成功加载,视觉编码推理成功,并返回与测试图相关的非空文本。测试结束后还要 +恢复 `cosmo.service`,确认服务为 `active`、管理页返回成功,并再次核对设备实际 IP。 + +## 已验证发布边界 + +- 4 路 × 5 FPS 完成 12 小时门禁,媒体失败/fallback 增量为 0,内存池统计稳定; + 对应 CPU 实测值保留在该次历史证据记录中。 +- 真实原始与算法播放、硬件解码/编码、OSD、重连和任务重启恢复在被测产物上通过。 +- 延迟 Copy-out 会在宿主拷贝前丢弃无需处理的帧,是本版本选定的优化方案。 +- v1.1 公开报告记录了单算法 5 FPS 的 16 路阶梯和双算法 5 FPS 的 8 路阶梯;两者 + 均为短时实测边界,尚未升级为官方推荐配置。 +- RK3576 NPU 指标使用 `/sys/kernel/debug/rknpu/load` 的厂商忙碌时间计数器;健康卡片 + 展示最忙核心,加速器 payload 保留所有核心。启动脚本仅将该只读文件暴露到 + `/run/cosmo-edge/metrics/rknpu-load`;devfreq governor 信号不会被当作 NPU 负载。 +- RK3576 NPU 和媒体分配共享系统 DDR。加速器指标标记为 + `memoryDomain=shared-system`;面板只显示一次系统内存容量,不再将同一内存池重复 + 计为独立显存。 + +这些结论与产物绑定;源码、模型、运行时或安装包变化后必须重新验证。已接受的发布 +记录应保留不可变安装包 SHA-256、业务精度结果、凭据安全日志、事件留存结果、清理 +状态和实测值。原始验证产物继续保留在源码树之外。 diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md index 6556c7ae7..929f6560b 100644 --- a/docs/guide/troubleshooting.md +++ b/docs/guide/troubleshooting.md @@ -35,6 +35,12 @@ http://127.0.0.1:8080 docker compose -f docker-compose.x86.windows.yml ps ``` +- **Apple Silicon macOS (Preview)**: + + ```bash + ./scripts/macos-docker-preview.sh status + ``` + 查看日志: - **Linux**: @@ -49,6 +55,12 @@ http://127.0.0.1:8080 docker compose -f docker-compose.x86.windows.yml logs -f ``` +- **Apple Silicon macOS (Preview)**: + + ```bash + ./scripts/macos-docker-preview.sh logs --follow + ``` + ## 端口冲突 x86 Compose 会发布: @@ -76,6 +88,15 @@ docker compose -f docker-compose.x86.windows.yml up -d --build 随后访问 `http://127.0.0.1:8280`。不设置该变量时仍默认使用 `8080`。 +Mac Preview 使用相同的 Web 端口变量,但仍只绑定本机: + +```bash +COSMO_X86_WEB_PORT=8280 ./scripts/macos-docker-preview.sh up +``` + +Mac 上若构建速度异常慢,请同时检查 Docker Desktop 的 VMM 与 Rosetta 设置; +完整边界见 [macOS Docker Preview](./macos-docker-preview.md)。 + ## Windows 构建脚本提示 `No such file or directory` 如果 Docker 构建在执行 `configure`、`config` 或 `Configure` 时报告文件存在但无法执行,通常是 Git for Windows 将无扩展名脚本检出为 CRLF,导致容器无法识别 shebang。 @@ -88,7 +109,7 @@ git check-attr text eol -- 3rd/mp4v2-2.0.0/configure 3rd/openssl-3.5.3/config 3r 三个文件都应显示 `text: auto` 和 `eol: lf`。 -## `build_output/` 没有发布包 +## `build_output/` 没有构建产物 使用完整运行命令: @@ -104,28 +125,74 @@ git check-attr text eol -- 3rd/mp4v2-2.0.0/configure 3rd/openssl-3.5.3/config 3r docker compose -f docker-compose.x86.windows.yml up -d --build ``` -Sophon 路径使用: +Sophon 的完整构建入口、profile 和输出约定以[构建指南](./build.md#sophon-构建产物)为准。 +例如,默认 BM1688 Open 构建完成后可直接检查芯片目录: ```bash -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package +cat build_output/public-runtime/bm1688/TARGET_CHIP +(cd build_output/public-runtime/bm1688 && sha256sum -c SHA256SUMS) ``` -注意:`docker compose build` 只构建镜像,不一定执行导出发布包的容器命令。 +Sophon 产物不会直接写在 `build_output/` 根目录。每个 +`build_output///` 目录应包含 `TARGET_CHIP`、`SHA256SUMS` 和唯一的 +`cosmo-V-<32位md5>.tar.gz`。先确认检查的是本次选择的 profile 和芯片目录。 + +注意:不要使用 `docker compose build` 代替上述 `run` 入口;前者不会执行导出产物的 +容器命令。 ## Sophon 构建失败 -Sophon 构建使用自包含的 `Dockerfile.sophon`(基于 `ubuntu:22.04`),无需外部基础镜像。 +`cosmo-sophon-package` 服务直接使用 `docker-compose.sophon.yml` 中配置的预构建 GHCR +镜像,仓库没有 `Dockerfile.sophon` 本地构建路径。镜像和构建链路的当前事实统一见 +[构建指南](./build.md#sophon-构建产物)。 -如果构建失败,请检查 Docker 构建日志: +如果构建失败,请重新运行同一入口并检查末尾日志: ```bash -docker compose -f docker-compose.sophon.yml run --rm cosmo-sophon-package 2>&1 | tail -50 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x 2>&1 | tail -50 ``` +检查 BM1688 构建时把末尾型号改为 `bm1688`,或省略型号。 + 常见问题: - 网络问题导致 apt/npm/cargo 镜像下载失败 — 检查 `SOPHON_APT_MIRROR` 等环境变量。 - 磁盘空间不足 — 构建过程需要约 3GB 空间。 +- `COSMO_MODEL_GUARD_BUILD_PROFILE` 取值不受支持——只接受 + `public-runtime` 和 `production-release`。 +- 芯片型号不受支持——只接受 `bm1688` 和 `cv186x`;省略时默认 `bm1688`。 +- 在非受控发布环境选择 `production-release`——缺少正式 SDK、设备初始化、 + 信任身份、签发者或发布引导输入时按设计拒绝构建。普通源码修改应使用 + SOURCE,不要绕过正式发布检查。 + +## 受保护 preset 无法加载 + +设备只需要以下一个 Guard 状态文件: + +```text +/data/cwaiuserdata/model-guard/device-certificate.bin +``` + +先检查证书状态和服务日志: + +```bash +sudo test -f /data/cwaiuserdata/model-guard/device-certificate.bin +sudo journalctl -u cosmo.service -b --no-pager -n 200 +``` + +如果受控 provisioner 仍在设备的临时目录,还可以运行 +`sudo /临时目录/cosmo-model-provision status` 直接校验证书和本机绑定;SOURCE +包本身不提供该工具。 + +- `-2001`(`CMG_V2_CERTIFICATE_UNAVAILABLE`):证书文件不存在或无法读取。 +- `-2002`(`CMG_V2_CERTIFICATE_REJECTED`):证书损坏、签名无效,或证书不是 + 为本机签发。 + +不要生成逐模型 license,也不要复制另一台设备的证书。使用本机生成的新请求在 +受控离线环境重新签发证书,再执行 +`cosmo-model-provision install --certificate <证书绝对路径>`。SOURCE 安装器 +不会创建、删除或修复该证书。 ## nginx / SRS / cosmo-engine 未启动 diff --git a/docs/reference/api.md b/docs/reference/api.md index f380740b4..b43536037 100644 --- a/docs/reference/api.md +++ b/docs/reference/api.md @@ -146,6 +146,11 @@ QueryLogs ### 升级恢复状态 +升级请求接受 `uploadId`,其原始文件名必须匹配 +`cosmo-V..-<32-char-md5>.tar.gz`。后端在重启前校验 +文件名、MD5、归档安全和目录结构;重启后由统一启动脚本再次校验 MD5 并安装。 +Open 与 Protected 包使用相同升级协议,模型授权不参与应用包校验。 + `POST /gtw/cwai/System/QueryDeviceStatus` 成功时返回: | 字段 | 语义 | diff --git a/docs/reference/models.md b/docs/reference/models.md index 5c5668c52..c6fe8eef5 100644 --- a/docs/reference/models.md +++ b/docs/reference/models.md @@ -17,7 +17,8 @@ next: | 目录 | 用途 | | --- | --- | -| `data/resource/aiboxresource` | Sophon 发布包资源 | +| `data/resource/aiboxresource_bm1688` | Sophon BM1688 发布包资源 | +| `data/resource/aiboxresource_cv186x` | Sophon CV186X 发布包资源 | | `data/resource/aiboxresource_x86` | x86 Docker/CPU 后端资源 | 构建时通过 `RESOURCE_DIR` 选择资源目录。 @@ -41,7 +42,7 @@ data/resource/*/model_template - 视觉语言模型:`qwen3vl`、`qwen3_5` - 文字识别:`ocr` -> 完整清单以 `data/resource/aiboxresource/model_template/` 与 `data/resource/aiboxresource_x86/model_template/` 目录下的实际文件为准。 +> 完整清单以各 `data/resource/aiboxresource_*/model_template/` 目录下的实际文件为准。 ## 车牌 OCR 模型包 @@ -94,7 +95,8 @@ data/resource/aiboxresource_x86 Sophon 路径: ```text -data/resource/aiboxresource +data/resource/aiboxresource_bm1688 +data/resource/aiboxresource_cv186x ``` 代码中可见 x86 ONNX 文件和 Sophon model package 的处理差异。完整模型移植流程应结合当前可发布模型包重新验证。 diff --git a/docs/tutorials/01-quickstart/quickstart.md b/docs/tutorials/01-quickstart/quickstart.md index 3c514fb33..ae29c427f 100644 --- a/docs/tutorials/01-quickstart/quickstart.md +++ b/docs/tutorials/01-quickstart/quickstart.md @@ -15,14 +15,14 @@ next: | --- | --- | | 适合谁 | 第一次部署或使用 CosmoEdge 的用户、实施人员和开发者 | | 完成后能做什么 | 部署或连接系统,完成设备网络与时间设置,接入视频,分配算法并验证结果 | -| 使用前提 | x86 主机已安装 Docker,或已有预装 CosmoEdge 的边缘设备 | -| 预计时间 | x86 首次构建约 15–30 分钟;预装设备约 15–25 分钟 | -| 是否需要设备 | 二选一:x86 Docker 主机,或预装 CosmoEdge 的边缘设备;首次检测不要求摄像机 | +| 使用前提 | x86 主机已安装 Docker,Apple Silicon Mac 已准备 Docker Desktop Preview 环境,或已有预装 CosmoEdge 的边缘设备 | +| 预计时间 | 原生 x86 首次构建约 15–30 分钟;Mac amd64 仿真可能更久;预装设备约 15–25 分钟 | +| 是否需要设备 | 三选一:x86 Docker 主机、Apple Silicon Mac Preview,或预装 CosmoEdge 的边缘设备;首次检测不要求摄像机 | | 最终验收结果 | 通道处于运行状态,实时展示出现算法叠加结果,事件中心可查询到符合规则的事件或统计结果 | 本页目标不是“把页面打开”,而是完成一次**可验证的首次检测**。完整路径是: -1. 选择 x86 Docker 或边缘设备路径并让系统可访问。 +1. 选择 x86 Docker、macOS Preview 或边缘设备路径并让系统可访问。 2. 如果使用默认静态 IP 的边缘设备,先配置电脑 IP,再登录并调整设备网络与时间。 3. 接入一段离线测试视频。 4. 为视频分配一个场景任务并启动分析。 @@ -35,7 +35,7 @@ next: ### 1.1 路径 A:x86 主机使用 Docker 适用于 Linux x86_64 主机。Windows 用户使用仓库中的 -`docker-compose.x86.windows.yml`,其余验证路径相同。 +`docker-compose.x86.windows.yml`。Apple Silicon Mac 使用下一节的独立 Preview 路径。 旧版教程记录过一套已验证环境:Ubuntu 22.04.2、Intel Core i9-13900F、64 GB 内存、 Docker 29.1.3 和 Docker Compose v5.1.4。它只是一次验证快照,不是最低配置要求;实际支持情况以仓库根目录的 README、当前 Compose 文件和目标模型资源占用为准。 @@ -78,11 +78,51 @@ docker compose -f docker-compose.x86.windows.yml ps ![CosmoEdge 容器处于运行状态](images/container.webp) -### 1.2 路径 B:预装 CosmoEdge 的边缘设备 +### 1.2 路径 B:Apple Silicon macOS Preview -CosmoEdge 当前支持 Sophon BM1688 平台。下图是旧版教程使用的 BM1688 双网口边缘设备示例; +Mac 使用隔离的 `linux/amd64` Docker Preview。先阅读 +[Mac 准入、许可和能力边界](/guide/macos-docker-preview),再运行: + +```bash +./scripts/macos-docker-preview.sh doctor +./scripts/macos-docker-preview.sh up +./scripts/macos-docker-preview.sh status +``` + +成功后只从本机打开 `http://127.0.0.1:8080`。这条路径面向单路离线视频体验, +不是原生 macOS 二进制、Sophon/Rockchip NPU 部署或生产性能证据。 + +### 1.3 路径 C:预装 CosmoEdge 的边缘设备 + +CosmoEdge 当前支持 Sophon BM1688 和 CV186X 两种芯片。下图是旧版教程使用的 BM1688 双网口边缘设备示例; 不同批次的外壳、接口标识和硬件参数可能不同,应以设备标签与交付清单为准。 +如果需要从源码构建升级包,在仓库根目录通过 `--chip <型号>` 选项指定目标芯片: + +```bash +# BM1688 +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip bm1688 + +# CV186X +./scripts/docker-compose.sh -f docker-compose.sophon.yml run --rm cosmo-sophon-package --chip cv186x + +find build_output/public-runtime -mindepth 2 -maxdepth 2 -type f -print +``` + +省略芯片型号参数时默认使用 `bm1688`。构建脚本会根据型号选择对应的模型资源目录, +无需手动填写模型路径。 + +构建包中的模型资源必须与目标芯片匹配;BM1688 与 CV186X 的产物不可互换。 + +把构建日志列出的唯一包名用于安装。需要通过 SSH 安装到已准备好的 Sophon Linux +设备时,请按[部署指南:SSH 安装路径](/guide/deployment#ssh安装路径)操作。文件传输、 +解压、安装、重启、基础系统前提和恢复边界统一在该章节维护。 + +已有 CosmoEdge 正常运行时,也可以登录管理页面,进入 +**系统管理 → 系统维护 → 软件升级**,选择同一个安装包并确认。升级期间保持供电;设备重启并 +重新登录后,在设备信息中核对 **软件版本** 与安装包版本一致。SSH安装器面向已经准备好基础 +系统的Sophon设备,并不是任意空白硬件的操作系统镜像安装器。 + ![BM1688 边缘设备接口面板示例](images/img_01.webp) ![BM1688 边缘设备指示灯和扩展接口示例](images/img_02.webp) diff --git a/nginx/conf/conf.d/default.conf b/nginx/conf/conf.d/default.conf index 7a87b1cb9..0d3d204c5 100644 --- a/nginx/conf/conf.d/default.conf +++ b/nginx/conf/conf.d/default.conf @@ -17,10 +17,30 @@ server { # try_files $uri $uri/ /index.html last; #} + # Vite emits content-hashed files below /assets. A missing file belongs to + # an older frontend build and must stay a 404; returning index.html here + # makes browsers reject the JavaScript module as text/html. + location ^~ /assets/ { + root /appfs/cosmo_wander/cwai_data/web/; + try_files $uri =404; + add_header Cache-Control "public, max-age=31536000, immutable"; + add_header Access-Control-Allow-Origin *; + } + + # index.html binds one exact set of hashed assets. Never retain it across + # an upgrade, otherwise an old entry page requests deleted chunks. + location = /index.html { + root /appfs/cosmo_wander/cwai_data/web/; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + add_header Pragma "no-cache" always; + add_header Expires "0" always; + add_header Access-Control-Allow-Origin *; + } + location / { root /appfs/cosmo_wander/cwai_data/web/; try_files $uri $uri/ /index.html; - add_header Cache-Control no-cache; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Methods 'GET,POST, OPTIONS'; add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; diff --git a/package.json b/package.json index be6074e8b..4abb5cb05 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,15 @@ "type": "module", "scripts": { "docs:dev": "vitepress dev docs", - "docs:build": "vitepress build docs", + "docs:build": "vitepress build docs && node scripts/copy-static-benchmark-assets.mjs", "docs:preview": "vitepress preview docs", + "macos:check": "node scripts/check-macos-docker-preview.mjs", "docs:check": "node scripts/check-tutorial-docs.mjs", "docs:smoke": "node scripts/smoke-tutorial-pages.mjs", - "docs:verify": "npm run docs:check && npm run docs:build && npm run docs:smoke" + "benchmarks:v1.1:smoke": "node scripts/smoke-benchmark-pages.mjs", + "models:sophon:verify": "node scripts/run-python.mjs scripts/verify_sophon_open_benchmark_models.py", + "benchmarks:v1.1:validate": "node scripts/validate-public-v1.1-multistream-benchmark.mjs", + "docs:verify": "npm run models:sophon:verify && npm run benchmarks:v1.1:validate && npm run macos:check && npm run docs:check && npm run docs:build && npm run docs:smoke && npm run benchmarks:v1.1:smoke" }, "devDependencies": { "vitepress": "^1.6.4" diff --git a/prebuild/model-guard-v2/README.md b/prebuild/model-guard-v2/README.md new file mode 100644 index 000000000..7577e048c --- /dev/null +++ b/prebuild/model-guard-v2/README.md @@ -0,0 +1,44 @@ +# Cosmo Model Guard v2 SDK + +This directory exposes the public, consumer-facing portion of the formally +built Model Guard v2 SDK used by CosmoEdge: + +- `include/cosmo_model_guard_v2.h` +- `lib/libcosmo_model_guard.so*` + +The checked-in AArch64 shared library has the `v2-only` runtime compatibility +profile. It does not expose the legacy Model Guard ABI. + +The default CosmoEdge build profile remains `public-runtime` for automation +compatibility; its user-facing artifact is the SOURCE package. The public SDK +and SOURCE package contain the runtime library and public header, but no +`bin/cosmo-model-provision` or private signing material. A configured device +needs only +`/data/cwaiuserdata/model-guard/device-certificate.bin` to authorize all +current and future preset models published under the product model key. There +are no per-model licenses. SOURCE cannot commission a blank device or construct +or sign a formal production release. + +`bin/cosmo-model-provision` is an offline device-initialization tool and is not +part of the public runtime SDK. It remains ignored by Git and must not be +force-added. Selecting `production-release` does not create or recover any +signing key. + +This public repository does not contain the private Model Guard source, +production signing keys, device secrets, or the complete controlled inputs +required to reconstruct, sign, or deploy a production package. This README +does not grant or alter artifact licensing or redistribution rights; those +require separately approved terms from the artifact owner. + +## Verification + +The canonical public Sophon build invokes +`scripts/verify_model_guard_v2_sdk.py` for the checked-in runtime SDK: + +```bash +/usr/bin/python3 -I -B scripts/verify_model_guard_v2_sdk.py \ + --admission-profile public-runtime \ + --sdk-root "$MODEL_GUARD_SDK_ROOT" \ + --readelf "$AARCH64_READELF" \ + --nm "$AARCH64_NM" +``` diff --git a/prebuild/model-guard-v2/include/cosmo_model_guard_v2.h b/prebuild/model-guard-v2/include/cosmo_model_guard_v2.h new file mode 100644 index 000000000..f7a438c66 --- /dev/null +++ b/prebuild/model-guard-v2/include/cosmo_model_guard_v2.h @@ -0,0 +1,169 @@ +#ifndef COSMO_MODEL_GUARD_V2_H_ +#define COSMO_MODEL_GUARD_V2_H_ + +#include +#include + +#include + +#ifndef CMG_V2_API +#if defined(__GNUC__) || defined(__clang__) +#define CMG_V2_API __attribute__((visibility("default"))) +#else +#define CMG_V2_API +#endif +#endif + +#define CMG_V2_ABI_MAJOR UINT32_C(2) + +typedef struct CmgV2Artifact CmgV2Artifact; + +typedef int32_t CmgV2Status; + +#define CMG_V2_OK ((CmgV2Status)0) + +#define CMG_V2_FORMAT_INVALID ((CmgV2Status) - 1001) +#define CMG_V2_FORMAT_UNSUPPORTED ((CmgV2Status) - 1002) +#define CMG_V2_FORMAT_SOURCE_MISMATCH ((CmgV2Status) - 1003) +#define CMG_V2_FORMAT_LIMIT ((CmgV2Status) - 1004) + +#define CMG_V2_LICENSE_UNAVAILABLE ((CmgV2Status) - 2001) +#define CMG_V2_LICENSE_REJECTED ((CmgV2Status) - 2002) +/* v2.3 names for the same frozen ABI status values. */ +#define CMG_V2_CERTIFICATE_UNAVAILABLE CMG_V2_LICENSE_UNAVAILABLE +#define CMG_V2_CERTIFICATE_REJECTED CMG_V2_LICENSE_REJECTED + +#define CMG_V2_CRYPTO_FAILED ((CmgV2Status) - 3001) + +#define CMG_V2_RESOURCE_INVALID_ARGUMENT ((CmgV2Status) - 4001) +#define CMG_V2_RESOURCE_INVALID_STATE ((CmgV2Status) - 4002) +#define CMG_V2_RESOURCE_IO ((CmgV2Status) - 4003) +#define CMG_V2_RESOURCE_NO_MEMORY ((CmgV2Status) - 4004) +#define CMG_V2_RESOURCE_BUSY ((CmgV2Status) - 4005) +#define CMG_V2_RESOURCE_INTERNAL ((CmgV2Status) - 4006) +#define CMG_V2_RESOURCE_ABI_MISMATCH ((CmgV2Status) - 4007) + +#define CMG_V2_BACKEND_FAILED ((CmgV2Status) - 5001) + +typedef uint32_t CmgV2SourceFormat; + +#define CMG_V2_SOURCE_COSMO_NN_V1 ((CmgV2SourceFormat)UINT32_C(1)) +#define CMG_V2_SOURCE_RAW_BMODEL ((CmgV2SourceFormat)UINT32_C(2)) + +typedef uint32_t CmgV2SophonLoadFlags; + +#define CMG_V2_SOPHON_SHARE_MEM ((CmgV2SophonLoadFlags)UINT32_C(0x00000001)) + +#define CMG_V2_ARTIFACT_INFO_SIZE UINT32_C(72) +#define CMG_V2_SOPHON_LOAD_OPTIONS_SIZE UINT32_C(16) + +typedef struct CmgV2ArtifactInfo { + /* In: caller capacity. Out: bytes defined and written by the guard. */ + uint32_t struct_size; + uint32_t source_format; + uint32_t segment_count; + uint32_t reserved; + uint8_t artifact_id[16]; + uint64_t generation; + uint8_t model_identity_sha256[32]; +} CmgV2ArtifactInfo; + +typedef struct CmgV2SophonLoadOptions { + /* In: at least CMG_V2_SOPHON_LOAD_OPTIONS_SIZE; v2 reads only this prefix. */ + uint32_t struct_size; + uint32_t flags; + uint32_t reserved[2]; +} CmgV2SophonLoadOptions; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * On every failure, *out_artifact is NULL. A successful open has already + * authenticated the core and the device preset certificate, checked the live + * device binding, and derived the preset-model content key. + */ +CMG_V2_API CmgV2Status CmgV2OpenArtifact( + const char *installed_model_path, CmgV2SourceFormat expected_source_format, + CmgV2Artifact **out_artifact); + +/* + * The caller zero-initializes out_info and sets struct_size to its capacity. + * This ABI version requires at least CMG_V2_ARTIFACT_INFO_SIZE bytes, writes + * only the known 72-byte prefix, and returns struct_size == 72 on success. + */ +CMG_V2_API CmgV2Status CmgV2GetArtifactInfo(const CmgV2Artifact *artifact, + CmgV2ArtifactInfo *out_info); + +/* + * options may be NULL for defaults. Otherwise struct_size must be at least + * CMG_V2_SOPHON_LOAD_OPTIONS_SIZE; larger structures are accepted but v2 reads + * only the known 16-byte prefix. Known reserved fields must be zero and unknown + * flags are rejected. On every failure, *out_bmrt is NULL. On success, + * ownership of the bmrt handle transfers to the caller. bm_handle is borrowed + * and must outlive the transferred bmrt handle. + */ +CMG_V2_API CmgV2Status CmgV2LoadSophonSegment( + CmgV2Artifact *artifact, bm_handle_t bm_handle, uint32_t segment_index, + const CmgV2SophonLoadOptions *options, void **out_bmrt); + +/* NULL is accepted. A non-NULL artifact must be closed exactly once. */ +CMG_V2_API void CmgV2CloseArtifact(CmgV2Artifact *artifact); + +#ifdef __cplusplus +} +#endif + +#if defined(__cplusplus) +#define CMG_V2_STATIC_ASSERT(condition, message) \ + static_assert((condition), message) +#define CMG_V2_ALIGNOF(type) alignof(type) +#else +#define CMG_V2_STATIC_ASSERT(condition, message) \ + _Static_assert((condition), message) +#define CMG_V2_ALIGNOF(type) _Alignof(type) +#endif + +CMG_V2_STATIC_ASSERT(sizeof(CmgV2Status) == 4, "CmgV2Status must be 32 bits"); +CMG_V2_STATIC_ASSERT(sizeof(CmgV2SourceFormat) == 4, + "CmgV2SourceFormat must be 32 bits"); +CMG_V2_STATIC_ASSERT(sizeof(CmgV2SophonLoadFlags) == 4, + "CmgV2SophonLoadFlags must be 32 bits"); + +CMG_V2_STATIC_ASSERT(sizeof(CmgV2ArtifactInfo) == CMG_V2_ARTIFACT_INFO_SIZE, + "CmgV2ArtifactInfo ABI size mismatch"); +CMG_V2_STATIC_ASSERT(CMG_V2_ALIGNOF(CmgV2ArtifactInfo) == 8, + "CmgV2ArtifactInfo ABI alignment mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2ArtifactInfo, struct_size) == 0, + "CmgV2ArtifactInfo.struct_size ABI offset mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2ArtifactInfo, source_format) == 4, + "CmgV2ArtifactInfo.source_format ABI offset mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2ArtifactInfo, segment_count) == 8, + "CmgV2ArtifactInfo.segment_count ABI offset mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2ArtifactInfo, reserved) == 12, + "CmgV2ArtifactInfo.reserved ABI offset mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2ArtifactInfo, artifact_id) == 16, + "CmgV2ArtifactInfo.artifact_id ABI offset mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2ArtifactInfo, generation) == 32, + "CmgV2ArtifactInfo.generation ABI offset mismatch"); +CMG_V2_STATIC_ASSERT( + offsetof(CmgV2ArtifactInfo, model_identity_sha256) == 40, + "CmgV2ArtifactInfo.model_identity_sha256 ABI offset mismatch"); + +CMG_V2_STATIC_ASSERT(sizeof(CmgV2SophonLoadOptions) == + CMG_V2_SOPHON_LOAD_OPTIONS_SIZE, + "CmgV2SophonLoadOptions ABI size mismatch"); +CMG_V2_STATIC_ASSERT(CMG_V2_ALIGNOF(CmgV2SophonLoadOptions) == 4, + "CmgV2SophonLoadOptions ABI alignment mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2SophonLoadOptions, struct_size) == 0, + "CmgV2SophonLoadOptions.struct_size ABI offset mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2SophonLoadOptions, flags) == 4, + "CmgV2SophonLoadOptions.flags ABI offset mismatch"); +CMG_V2_STATIC_ASSERT(offsetof(CmgV2SophonLoadOptions, reserved) == 8, + "CmgV2SophonLoadOptions.reserved ABI offset mismatch"); + +#undef CMG_V2_ALIGNOF +#undef CMG_V2_STATIC_ASSERT + +#endif /* COSMO_MODEL_GUARD_V2_H_ */ diff --git a/prebuild/model-guard-v2/lib/libcosmo_model_guard.so b/prebuild/model-guard-v2/lib/libcosmo_model_guard.so new file mode 120000 index 000000000..17fca575c --- /dev/null +++ b/prebuild/model-guard-v2/lib/libcosmo_model_guard.so @@ -0,0 +1 @@ +libcosmo_model_guard.so.2 \ No newline at end of file diff --git a/prebuild/model-guard-v2/lib/libcosmo_model_guard.so.2 b/prebuild/model-guard-v2/lib/libcosmo_model_guard.so.2 new file mode 120000 index 000000000..0017e842e --- /dev/null +++ b/prebuild/model-guard-v2/lib/libcosmo_model_guard.so.2 @@ -0,0 +1 @@ +libcosmo_model_guard.so.2.0.0 \ No newline at end of file diff --git a/prebuild/model-guard-v2/lib/libcosmo_model_guard.so.2.0.0 b/prebuild/model-guard-v2/lib/libcosmo_model_guard.so.2.0.0 new file mode 100644 index 000000000..a4cf07abc Binary files /dev/null and b/prebuild/model-guard-v2/lib/libcosmo_model_guard.so.2.0.0 differ diff --git a/scripts/build.sh b/scripts/build.sh index 448667c3b..60691c69b 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -1,27 +1,59 @@ #!/bin/bash +set -euo pipefail + export LC_ALL=C.UTF-8 +COSMO_MODEL_GUARD_BUILD_PROFILE="${COSMO_MODEL_GUARD_BUILD_PROFILE:-public-runtime}" +case "${COSMO_MODEL_GUARD_BUILD_PROFILE}" in + public-runtime) + PACKAGE_VARIANT="Open" + ;; + production-release) + PACKAGE_VARIANT="Protected" + ;; + *) + echo "ERROR: COSMO_MODEL_GUARD_BUILD_PROFILE must be public-runtime or production-release" >&2 + exit 1 + ;; +esac + # ── Parse options ── +# -c = Sophon chip model; -m = explicit resource directory (internal/compatibility use); # -t = dev mode (disable watchdog); -T = also build cosmo-tests in this pass. +CHIP_MODEL="" RESOURCE_DIR="" DEV_MODE=OFF BUILD_TESTS_FLAG=OFF -while getopts "m:tT" opt; do +while getopts "c:m:tT" opt; do case $opt in + c) CHIP_MODEL="${OPTARG,,}" ;; m) RESOURCE_DIR="$OPTARG" ;; t) DEV_MODE=ON ;; T) BUILD_TESTS_FLAG=ON ;; - *) echo "Usage: $0 [-m ] [-t (enable dev mode)] [-T (also build cosmo-tests)]"; exit 1 ;; + *) echo "Usage: $0 [-c | -m ] [-t] [-T]"; exit 1 ;; esac done -if [ -z "${PROJECT_ROOT_PATH:-}" ] -then - PROJECT_ROOT_PATH=$(cd `dirname $0`; pwd)/.. +if [ -z "${PROJECT_ROOT_PATH:-}" ]; then + PROJECT_ROOT_PATH="$(cd "$(dirname "$0")/.." && pwd -P)" +fi + +if [ -n "${CHIP_MODEL}" ] && [ -n "${RESOURCE_DIR}" ]; then + echo "ERROR: -c and -m cannot be used together" >&2 + exit 1 fi if [ -z "${RESOURCE_DIR}" ]; then - RESOURCE_DIR="${PROJECT_ROOT_PATH}/data/resource/aiboxresource" + CHIP_MODEL="${CHIP_MODEL:-bm1688}" + case "${CHIP_MODEL}" in + bm1688|cv186x) + RESOURCE_DIR="${PROJECT_ROOT_PATH}/data/resource/aiboxresource_${CHIP_MODEL}" + ;; + *) + echo "ERROR: unsupported Sophon chip '${CHIP_MODEL}'; expected bm1688 or cv186x" >&2 + exit 1 + ;; + esac elif [ "${RESOURCE_DIR#/}" = "${RESOURCE_DIR}" ]; then RESOURCE_DIR="${PROJECT_ROOT_PATH}/${RESOURCE_DIR}" fi @@ -31,25 +63,42 @@ if [ ! -d "${RESOURCE_DIR}" ]; then exit 1 fi -BUILD_DIR=${PROJECT_ROOT_PATH}/build -INSTALL_DIR=${BUILD_DIR}/install - -if [ -d ${INSTALL_DIR} ] -then - rm -rf ${INSTALL_DIR} +BUILD_DIR="${PROJECT_ROOT_PATH}/build" +INSTALL_DIR="${BUILD_DIR}/install" +PACKAGE_DIR="${BUILD_DIR}/packages" +DEFAULT_COSMO_GUARD_SDK_DIR="${PROJECT_ROOT_PATH}/prebuild/model-guard-v2" +if [ "${COSMO_MODEL_GUARD_BUILD_PROFILE}" = "production-release" ] && + [ -d /build_output/model-guard-sdk-production ]; then + DEFAULT_COSMO_GUARD_SDK_DIR=/build_output/model-guard-sdk-production +fi +COSMO_GUARD_SDK_DIR="${COSMO_MODEL_GUARD_SDK_ROOT:-${DEFAULT_COSMO_GUARD_SDK_DIR}}" +MODEL_GUARD_PROFILE_ARGS=( + -DCOSMO_MODEL_GUARD_BUILD_PROFILE="${COSMO_MODEL_GUARD_BUILD_PROFILE}" + -DCOSMO_PACKAGE_MODELS="${COSMO_PACKAGE_MODELS:-include}" +) +if [ -d "${INSTALL_DIR}" ]; then + rm -rf -- "${INSTALL_DIR}" fi -mkdir -p ${BUILD_DIR} -cd ${BUILD_DIR} +mkdir -p "${BUILD_DIR}" +cd "${BUILD_DIR}" echo "Dev mode: ${DEV_MODE}" +if [ -n "${CHIP_MODEL}" ]; then + echo "Sophon chip: ${CHIP_MODEL}" +fi echo "Resource dir: ${RESOURCE_DIR}" -echo "Configuring..." +echo "Package variant: ${PACKAGE_VARIANT}" +echo "Internal Model Guard build profile: ${COSMO_MODEL_GUARD_BUILD_PROFILE}" +echo "Configuring protected build..." cmake -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \ - -DBUILD_TESTS=${BUILD_TESTS_FLAG} \ - -DCOSMO_DEV_MODE=${DEV_MODE} \ + -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ + -DBUILD_TESTS="${BUILD_TESTS_FLAG}" \ + -DCOSMO_DEV_MODE="${DEV_MODE}" \ + -DCOSMO_TARGET_CHIP="${CHIP_MODEL:-unspecified}" \ + -DCOSMO_MODEL_GUARD_SDK_ROOT="${COSMO_GUARD_SDK_DIR}" \ -DRESOURCE_DIR="${RESOURCE_DIR}" \ + "${MODEL_GUARD_PROFILE_ARGS[@]}" \ .. # Symlink compile_commands.json to project root for IDE and static analysis tools @@ -61,7 +110,61 @@ if [ "${BUILD_TESTS_FLAG}" = "ON" ]; then echo "Also building cosmo-tests in this pass..." build_targets+=(--target cosmo-tests) fi -cmake --build . "${build_targets[@]}" -j$(nproc) +cmake --build . "${build_targets[@]}" -j"$(nproc)" + +echo "Auditing installed AArch64 ELF paths..." +unsafe_elf_path=0 +while IFS= read -r -d '' installed_file; do + if aarch64-linux-gnu-readelf -hW "${installed_file}" >/dev/null 2>&1; then + dynamic_metadata=$(aarch64-linux-gnu-readelf -dW "${installed_file}") + if grep -Eq '/workspace|thirdparty_install|3rd/libsophon' \ + <<<"${dynamic_metadata}" + then + echo "ERROR: installed ELF dynamic metadata leaks a build-only path: ${installed_file}" >&2 + unsafe_elf_path=1 + fi + fi +done < <(find "${INSTALL_DIR}" -type f -print0) +if [ "${unsafe_elf_path}" -ne 0 ]; then + exit 1 +fi + +if [ "${BUILD_TESTS_FLAG}" = "ON" ]; then + echo "Running package regression suites..." + /usr/bin/python3 -I -B "${PROJECT_ROOT_PATH}/test/test_package_profile.py" + /usr/bin/python3 -I -B "${PROJECT_ROOT_PATH}/test/test_verify_model_guard_v2_sdk.py" +fi + +installed_python_cache="$( + find "${INSTALL_DIR}" \ + \( -name __pycache__ -o -name '*.pyc' -o -name '*.pyo' \) \ + -print -quit +)" +if [ -n "${installed_python_cache}" ]; then + printf 'ERROR: installed payload contains Python bytecode cache: %q\n' \ + "${installed_python_cache}" >&2 + exit 1 +fi echo "Packaging..." cmake --build . --target package_all + +shopt -s nullglob +package_artifacts=("${PACKAGE_DIR}"/*.tar.gz) +shopt -u nullglob +if [ "${#package_artifacts[@]}" -ne 1 ] || + [ ! -f "${package_artifacts[0]:-}" ] || + [ -L "${package_artifacts[0]:-}" ]; then + echo "ERROR: packaging must produce exactly one regular archive" >&2 + exit 1 +fi + +/usr/bin/python3 -I -B \ + "${PROJECT_ROOT_PATH}/scripts/verify_package_contents.py" \ + --archive "${package_artifacts[0]}" \ + --build-profile "${COSMO_MODEL_GUARD_BUILD_PROFILE}" + +package_sha256="$(sha256sum -- "${package_artifacts[0]}")" +package_sha256="${package_sha256%% *}" +echo "Verified ${PACKAGE_VARIANT} package: ${package_artifacts[0]}" +echo "Package SHA-256: ${package_sha256}" diff --git a/scripts/build_cpu.sh b/scripts/build_cpu.sh index 218cf1ed5..76361b1c3 100644 --- a/scripts/build_cpu.sh +++ b/scripts/build_cpu.sh @@ -33,6 +33,12 @@ fi BUILD_DIR=${PROJECT_ROOT_PATH}/build_cpu INSTALL_DIR=${BUILD_DIR}/install +BUILD_JOBS="${COSMO_BUILD_JOBS:-$(nproc)}" + +if [[ ! "${BUILD_JOBS}" =~ ^[1-9][0-9]*$ ]]; then + echo "ERROR: COSMO_BUILD_JOBS must be a positive integer; got '${BUILD_JOBS}'" >&2 + exit 1 +fi clean_external_project() { local name="$1" @@ -73,6 +79,7 @@ cd ${BUILD_DIR} echo "Dev mode: ${DEV_MODE}" echo "Backend: CPU (ONNX Runtime)" echo "Resource dir: ${RESOURCE_DIR}" +echo "Parallel build jobs: ${BUILD_JOBS}" echo "Requires: pkg-config and openh264 development package (for x86 realtime OSD H264 encoding)" echo "Configuring..." cmake -DCMAKE_BUILD_TYPE=Release \ @@ -94,7 +101,7 @@ cmake -DCMAKE_BUILD_TYPE=Release \ ln -sf "${BUILD_DIR}/compile_commands.json" "${PROJECT_ROOT_PATH}/compile_commands.json" 2>/dev/null || true echo "Building Cosmo (CPU backend) ..." -cmake --build . --target install -j$(nproc) +cmake --build . --target install -j"${BUILD_JOBS}" echo "Packaging..." cmake --build . --target package_all diff --git a/scripts/build_cpu_test.sh b/scripts/build_cpu_test.sh index f26342a96..553fd3525 100644 --- a/scripts/build_cpu_test.sh +++ b/scripts/build_cpu_test.sh @@ -9,6 +9,12 @@ then fi BUILD_DIR=${PROJECT_ROOT_PATH}/build_cpu +BUILD_JOBS="${COSMO_BUILD_JOBS:-$(nproc)}" + +if [[ ! "${BUILD_JOBS}" =~ ^[1-9][0-9]*$ ]]; then + echo "ERROR: COSMO_BUILD_JOBS must be a positive integer; got '${BUILD_JOBS}'" >&2 + exit 1 +fi clean_external_project() { local name="$1" @@ -43,6 +49,7 @@ cd ${BUILD_DIR} echo "Configuring with tests enabled (CPU backend)..." echo "Requires: pkg-config and openh264 development package (for x86 realtime OSD H264 encoding)" +echo "Parallel build jobs: ${BUILD_JOBS}" cmake -DCMAKE_BUILD_TYPE=Release \ -U CMAKE_TOOLCHAIN_FILE \ -DCOSMO_TARGET_ARCH=x86_64 \ @@ -59,7 +66,7 @@ cmake -DCMAKE_BUILD_TYPE=Release \ ln -sf "${BUILD_DIR}/compile_commands.json" "${PROJECT_ROOT_PATH}/compile_commands.json" 2>/dev/null || true echo "Building cosmo-tests (CPU backend)..." -cmake --build . --target cosmo-tests -j$(nproc) +cmake --build . --target cosmo-tests -j"${BUILD_JOBS}" echo "" echo "Build complete: ${BUILD_DIR}/cosmo-tests" diff --git a/scripts/build_npm_dependencies.sh b/scripts/build_npm_dependencies.sh new file mode 100755 index 000000000..ffe694d76 --- /dev/null +++ b/scripts/build_npm_dependencies.sh @@ -0,0 +1,63 @@ +#!/bin/bash +set -euo pipefail + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " >&2 + exit 2 +fi + +web_workspace="$1" +if [ ! -f "${web_workspace}/package-lock.json" ]; then + echo "ERROR: package-lock.json not found in ${web_workspace}" >&2 + exit 1 +fi + +cd "${web_workspace}" +npm_ci_args=(ci --offline --include=dev --loglevel=error --no-audit --no-fund) + +if npm "${npm_ci_args[@]}" >/dev/null 2>&1; then + echo "npm dependencies installed from the persistent offline cache." + exit 0 +fi + +package_url_output="$(node <<'NODE' +const lock = require('./package-lock.json'); +const urls = []; +const incomplete = []; + +for (const [path, metadata] of Object.entries(lock.packages || {})) { + if (!path.includes('node_modules/') || metadata.link) continue; + if (!metadata.resolved || !metadata.integrity) { + incomplete.push(path); + continue; + } + if (!metadata.resolved.startsWith('https://cdn.npmmirror.com/packages/')) { + throw new Error(`unsupported package URL for ${path}: ${metadata.resolved}`); + } + urls.push(metadata.resolved); +} + +if (incomplete.length) { + throw new Error(`package-lock.json has incomplete entries: ${incomplete.join(', ')}`); +} +if (!urls.length) throw new Error('package-lock.json has no cacheable packages'); +process.stdout.write([...new Set(urls)].join('\n')); +NODE +)" + +mapfile -t package_urls <<<"${package_url_output}" +package_count="${#package_urls[@]}" +echo "npm cache is incomplete; fetching ${package_count} locked packages serially." + +for index in "${!package_urls[@]}"; do + npm --loglevel=error --no-audit --no-fund cache add "${package_urls[$index]}" + completed=$((index + 1)) + if (( completed % 10 == 0 || completed == package_count )); then + echo "npm cache ${completed}/${package_count}" + fi +done + +# The online phase only populates the content-addressed cache. Installation is +# always offline and still verifies every package against package-lock.json. +npm "${npm_ci_args[@]}" +echo "npm dependencies installed from the newly populated offline cache." diff --git a/scripts/build_rknn.sh b/scripts/build_rknn.sh new file mode 100755 index 000000000..845a3aaa0 --- /dev/null +++ b/scripts/build_rknn.sh @@ -0,0 +1,87 @@ +#!/bin/bash +set -euo pipefail +export LC_ALL=C.UTF-8 + +RESOURCE_DIR="" +RKNN_ROOT_PATH="${RKNN_ROOT:-}" +ROCKCHIP_MEDIA_ROOT_PATH="${ROCKCHIP_MEDIA_ROOT:-}" +RKLLM_ROOT_PATH="${RKLLM_ROOT:-}" +RKLLM_REQUIRED="${COSMO_RKLLM_REQUIRED:-OFF}" +DEV_MODE=OFF +BUILD_TESTS_FLAG=OFF +while getopts "m:r:p:tT" opt; do + case ${opt} in + m) RESOURCE_DIR="${OPTARG}" ;; + r) RKNN_ROOT_PATH="${OPTARG}" ;; + p) ROCKCHIP_MEDIA_ROOT_PATH="${OPTARG}" ;; + t) DEV_MODE=ON ;; + T) BUILD_TESTS_FLAG=ON ;; + *) echo "Usage: $0 -r [-p ] [-m ] [-t] [-T]"; exit 1 ;; + esac +done + +if [ -z "${PROJECT_ROOT_PATH:-}" ]; then + PROJECT_ROOT_PATH=$(cd "$(dirname "$0")/.." && pwd) +fi + +MEDIA_CPU_BACKEND=ON +MEDIA_ROCKCHIP_BACKEND=OFF +if [ -n "${ROCKCHIP_MEDIA_ROOT_PATH}" ]; then + MEDIA_CPU_BACKEND=OFF + MEDIA_ROCKCHIP_BACKEND=ON +fi +if [ -z "${RKNN_ROOT_PATH}" ]; then + echo "ERROR: pass -r or set RKNN_ROOT" >&2 + exit 1 +fi +if [ -z "${RKLLM_ROOT_PATH}" ]; then + RKLLM_ROOT_PATH="${RKNN_ROOT_PATH}" +fi +if [ "${RKLLM_REQUIRED}" = "ON" ]; then + for required_file in include/rkllm.h lib/librkllmrt.so LICENSE; do + if [ ! -f "${RKLLM_ROOT_PATH}/${required_file}" ]; then + echo "ERROR: RKLLM is required, but ${RKLLM_ROOT_PATH}/${required_file} is missing" >&2 + exit 1 + fi + done +fi +if [ -z "${RESOURCE_DIR}" ]; then + RESOURCE_DIR="${PROJECT_ROOT_PATH}/data/resource/aiboxresource_x86" +elif [ "${RESOURCE_DIR#/}" = "${RESOURCE_DIR}" ]; then + RESOURCE_DIR="${PROJECT_ROOT_PATH}/${RESOURCE_DIR}" +fi + +RESOURCE_MODELS_DIR="${PROJECT_ROOT_PATH}/data/resource/aiboxresource_rknn/models" +RESOURCE_OVERLAY_DIR="${PROJECT_ROOT_PATH}/data/resource/aiboxresource_rknn" +BUILD_DIR="${PROJECT_ROOT_PATH}/build_rknn" +INSTALL_DIR="${BUILD_DIR}/install" +mkdir -p "${BUILD_DIR}" +rm -rf "${INSTALL_DIR}" + +cmake -S "${PROJECT_ROOT_PATH}" -B "${BUILD_DIR}" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ + -DCOSMO_TARGET_ARCH=aarch64 \ + -DCOSMO_TARGET_CHIP=rk3576 \ + -DCOSMO_NN_USE_SOPHON_BACKEND=OFF \ + -DCOSMO_NN_USE_CPU_BACKEND=OFF \ + -DCOSMO_NN_USE_RKNN_BACKEND=ON \ + -DCOSMO_MEDIA_USE_SOPHON_BACKEND=OFF \ + -DCOSMO_MEDIA_USE_CPU_BACKEND="${MEDIA_CPU_BACKEND}" \ + -DCOSMO_MEDIA_USE_ROCKCHIP_BACKEND="${MEDIA_ROCKCHIP_BACKEND}" \ + -DCOSMO_RKNN_ROOT="${RKNN_ROOT_PATH}" \ + -DCOSMO_RKLLM_ROOT="${RKLLM_ROOT_PATH}" \ + -DCOSMO_RKLLM_REQUIRED="${RKLLM_REQUIRED}" \ + -DCOSMO_ROCKCHIP_MEDIA_ROOT="${ROCKCHIP_MEDIA_ROOT_PATH}" \ + -DCOSMO_DEV_MODE="${DEV_MODE}" \ + -DBUILD_TESTS="${BUILD_TESTS_FLAG}" \ + -DRESOURCE_DIR="${RESOURCE_DIR}" \ + -DRESOURCE_OVERLAY_DIR="${RESOURCE_OVERLAY_DIR}" \ + -DRESOURCE_MODELS_DIR="${RESOURCE_MODELS_DIR}" + +ln -sf "${BUILD_DIR}/compile_commands.json" "${PROJECT_ROOT_PATH}/compile_commands.json" 2>/dev/null || true +cmake --build "${BUILD_DIR}" --target install -j"$(nproc)" +if [ "${BUILD_TESTS_FLAG}" = "ON" ]; then + cmake --build "${BUILD_DIR}" --target cosmo-tests -j"$(nproc)" +fi +cmake --build "${BUILD_DIR}" --target package_all diff --git a/scripts/build_sophon_package.ps1 b/scripts/build_sophon_package.ps1 index 7994012d2..e9471a215 100644 --- a/scripts/build_sophon_package.ps1 +++ b/scripts/build_sophon_package.ps1 @@ -1,3 +1,9 @@ +[CmdletBinding()] +param( + [ValidateSet("bm1688", "cv186x")] + [string]$Chip = "bm1688" +) + $ErrorActionPreference = "Stop" # ============================================================================= @@ -15,12 +21,21 @@ $ErrorActionPreference = "Stop" # Subsequent builds copy only changed files. # # Prerequisites: Docker Desktop -# Output: build_output/cosmo-*.tar.gz +# Output: build_output///cosmo-*.tar.gz # ============================================================================= $VolumeName = "cosmo-sophon-source" $ComposeFile = "docker-compose.sophon.yml" $OverrideFile = "docker-compose.sophon.override.yml" +$BuildProfile = $env:COSMO_MODEL_GUARD_BUILD_PROFILE +if ([string]::IsNullOrWhiteSpace($BuildProfile)) { + $BuildProfile = "public-runtime" +} +if ($BuildProfile -notin @("public-runtime", "production-release")) { + throw "COSMO_MODEL_GUARD_BUILD_PROFILE must be public-runtime or production-release" +} +$env:COSMO_MODEL_GUARD_BUILD_PROFILE = $BuildProfile +$PackageVariant = if ($BuildProfile -eq "public-runtime") { "Open" } else { "Protected" } # ── Helpers ────────────────────────────────────────────────────────────────── @@ -87,7 +102,7 @@ Invoke-Docker run --rm ` alpine ` sh /workspace/scripts/restore-symlinks.sh -Write-Step "Step 4/5 - Running Sophon cross-compilation" +Write-Step "Step 4/5 - Running Sophon $Chip cross-compilation ($PackageVariant)" # Generate a compose override that swaps the bind mount for our named volume. # The override REPLACES the volumes list; we keep ./build_output as a bind @@ -106,7 +121,7 @@ volumes: Push-Location $projectRoot try { - cmd /c "docker compose -f $ComposeFile -f $OverrideFile run --rm cosmo-sophon-package" + cmd /c "docker compose -f $ComposeFile -f $OverrideFile run --rm cosmo-sophon-package --chip $Chip" if ($LASTEXITCODE -ne 0) { Write-Error "Docker build failed with exit code $LASTEXITCODE." exit $LASTEXITCODE @@ -117,7 +132,7 @@ try { } Write-Step "Step 5/5 - Build output" -$outputDir = Join-Path $projectRoot "build_output" +$outputDir = Join-Path (Join-Path (Join-Path $projectRoot "build_output") $BuildProfile) $Chip if (Test-Path $outputDir) { $packages = Get-ChildItem $outputDir -Filter "*.tar.gz" if ($packages) { @@ -125,10 +140,16 @@ if (Test-Path $outputDir) { Write-Host " $($pkg.Name) ($('{0:N0}' -f $pkg.Length) bytes)" -ForegroundColor Green } } else { - Write-Warning "No .tar.gz found in build_output/" + Write-Warning "No .tar.gz found in build_output/$BuildProfile/$Chip/" } } else { - Write-Warning "build_output/ directory not found" + Write-Warning "build_output/$BuildProfile/$Chip/ directory not found" +} + +if ($BuildProfile -eq "public-runtime") { + Write-Host "Open MD5 upgrade package created." +} else { + Write-Host "Protected MD5 upgrade package created. Model use requires device authorization." } Write-Host "`n=== Sophon build completed ===" -ForegroundColor Green diff --git a/scripts/build_sophon_package.sh b/scripts/build_sophon_package.sh new file mode 100644 index 000000000..dcd50b97e --- /dev/null +++ b/scripts/build_sophon_package.sh @@ -0,0 +1,56 @@ +#!/bin/bash +set -euo pipefail + +COSMO_MODEL_GUARD_BUILD_PROFILE="${COSMO_MODEL_GUARD_BUILD_PROFILE:-public-runtime}" +case "${COSMO_MODEL_GUARD_BUILD_PROFILE}" in + public-runtime|production-release) ;; + *) + echo "ERROR: COSMO_MODEL_GUARD_BUILD_PROFILE must be public-runtime or production-release" >&2 + exit 1 + ;; +esac + +chip="bm1688" +if [ "$#" -gt 0 ]; then + if [ "$#" -ne 2 ] || [ "$1" != "--chip" ]; then + echo "Usage: $0 [--chip ]" >&2 + exit 1 + fi + chip="$2" +fi +chip="${chip,,}" +case "${chip}" in + bm1688|cv186x) ;; + *) + echo "ERROR: unsupported Sophon chip '${chip}'; expected bm1688 or cv186x" >&2 + exit 1 + ;; +esac + +if [ "${COSMO_MODEL_GUARD_BUILD_PROFILE}" = "public-runtime" ]; then + package_variant="Open" +else + package_variant="Protected" +fi + +echo "Starting ${package_variant} cross-compilation for ${chip}..." +./scripts/build.sh -T -c "${chip}" + +output_dir="/build_output/${COSMO_MODEL_GUARD_BUILD_PROFILE}/${chip}" +rm -rf -- "${output_dir}" +mkdir -p "${output_dir}" + +shopt -s nullglob +package_artifacts=(build/packages/*.tar.gz) +shopt -u nullglob +if [ "${#package_artifacts[@]}" -ne 1 ] || [ ! -f "${package_artifacts[0]:-}" ]; then + echo "ERROR: expected exactly one package artifact" >&2 + exit 1 +fi + +package_name="${package_artifacts[0]##*/}" +cp -f -- "${package_artifacts[0]}" "${output_dir}/${package_name}" +printf '%s\n' "${chip}" > "${output_dir}/TARGET_CHIP" +(cd "${output_dir}" && sha256sum -- "${package_name}" > SHA256SUMS) +ls -lh "${output_dir}" +echo "Build finished." diff --git a/scripts/build_test.sh b/scripts/build_test.sh index 14ba41434..5389f11d5 100755 --- a/scripts/build_test.sh +++ b/scripts/build_test.sh @@ -1,26 +1,8 @@ #!/bin/bash +set -euo pipefail -if [ -z $PROJECT_ROOT_PATH ] -then - PROJECT_ROOT_PATH=$(cd `dirname $0`; pwd)/.. -fi - -BUILD_DIR=${PROJECT_ROOT_PATH}/build - -mkdir -p ${BUILD_DIR} -cd ${BUILD_DIR} - -echo "Configuring with tests enabled..." -cmake -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTS=ON \ - .. - -# Symlink compile_commands.json to project root for IDE and static analysis tools -ln -sf "${BUILD_DIR}/compile_commands.json" "${PROJECT_ROOT_PATH}/compile_commands.json" 2>/dev/null || true - -echo "Building cosmo-tests..." -cmake --build . --target cosmo-tests -j$(nproc) - -echo "" -echo "Build complete: ${BUILD_DIR}/cosmo-tests" - +# Keep one authoritative Sophon build path. A clean test build uses the same +# configure-time Guard SDK admission and packaging profile as the final build. +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" +export COSMO_MODEL_GUARD_BUILD_PROFILE="${COSMO_MODEL_GUARD_BUILD_PROFILE:-public-runtime}" +exec "${SCRIPT_DIR}/build.sh" -T "$@" diff --git a/scripts/check-macos-docker-preview.mjs b/scripts/check-macos-docker-preview.mjs new file mode 100644 index 000000000..1ddd4b265 --- /dev/null +++ b/scripts/check-macos-docker-preview.mjs @@ -0,0 +1,143 @@ +import { readFileSync, statSync } from 'node:fs' +import { dirname, join, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' + +const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..') +const paths = { + compose: 'docker-compose.x86.macos.yml', + dockerfile: 'Dockerfile.x86', + cpuBuild: 'scripts/build_cpu.sh', + runtimeStartup: 'scripts/run_start.sh', + healthcheck: 'scripts/docker-healthcheck.x86.sh', + launcher: 'scripts/macos-docker-preview.sh', + dockerignore: '.dockerignore', + docsZh: 'docs/guide/macos-docker-preview.md', + docsEn: 'docs/en/guide/macos-docker-preview.md', + readmeZh: 'README.zh-CN.md', + readmeEn: 'README.md' +} + +const failures = [] + +function read(relativePath) { + return readFileSync(join(repositoryRoot, relativePath), 'utf8') +} + +function requireText(relativePath, source, expected, label = expected) { + if (!source.includes(expected)) failures.push(`${relativePath}: missing ${label}`) +} + +function requireExecutable(relativePath) { + if (process.platform === 'win32') return + const mode = statSync(join(repositoryRoot, relativePath)).mode + if ((mode & 0o111) === 0) failures.push(`${relativePath}: script must be executable`) +} + +const compose = read(paths.compose) +const dockerfile = read(paths.dockerfile) +const cpuBuild = read(paths.cpuBuild) +const runtimeStartup = read(paths.runtimeStartup) +const healthcheck = read(paths.healthcheck) +const launcher = read(paths.launcher) +const dockerignore = read(paths.dockerignore) +const docsZh = read(paths.docsZh) +const docsEn = read(paths.docsEn) +const readmeZh = read(paths.readmeZh) +const readmeEn = read(paths.readmeEn) + +for (const [expected, label] of [ + ['name: cosmo-x86-macos-preview', 'isolated Compose project name'], + ['platform: linux/amd64', 'explicit linux/amd64 platform'], + ['cosmo-x86-macos-data:/data/cwaiuserdata', 'isolated persistent data volume'], + ['cosmo-x86-macos-app-resource:/appfs/cosmo_wander/cwai_data/resource', 'isolated resource volume'], + ['./build_output/macos-x86:/build_output', 'isolated build output'], + ['BUILD_ENV_IMAGE: "ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_x86:v1@sha256:3345825c9255b9b73369af7ab6346c2cc7079786eb23309258acf7212ca03c1d"', 'pinned amd64 build environment'], + ['RUNTIME_BASE_IMAGE: "debian:12-slim@sha256:a7ffa3fd2ba09498788cd398575f4340599626c37610af57cc368e70fd564d75"', 'pinned Debian runtime base'], + ['COSMO_BUILD_JOBS: "${COSMO_X86_BUILD_JOBS:-1}"', 'serial emulation build default'], + ['COSMO_STREAM_PLAY_MODE: httpflv-srs', 'deterministic loopback HTTP-FLV playback'], + ['COSMO_STREAM_HTTP_PORT: "18088"', 'published SRS HTTP-FLV port'], + ['name: cosmo-x86-macos-preview-data', 'stable Preview data volume name'], + ['name: cosmo-x86-macos-preview-app-resource', 'stable Preview resource volume name'], + ['test: ["CMD", "/usr/local/bin/cosmo-x86-healthcheck"]', 'container health check'] +]) { + requireText(paths.compose, compose, expected, label) +} + +const publishedPorts = [...compose.matchAll(/^\s+-\s+"([^"\n]+:[0-9]+(?:\/udp)?)"\s*$/gmu)].map((match) => match[1]) +if (publishedPorts.length !== 4) { + failures.push(`${paths.compose}: expected 4 published ports, found ${publishedPorts.length}`) +} +for (const port of publishedPorts) { + if (!port.startsWith('127.0.0.1:')) { + failures.push(`${paths.compose}: host port is not loopback-only: ${port}`) + } +} +if (/^\s+devices:/mu.test(compose) || compose.includes('/dev/video')) { + failures.push(`${paths.compose}: USB or video devices must not be exposed by the Mac Preview`) +} +if (/^\s+cap_add:/mu.test(compose) || /^\s+sysctls:/mu.test(compose)) { + failures.push(`${paths.compose}: the local-video Preview must not request network administration privileges`) +} +if (publishedPorts.some((port) => port.endsWith('/udp'))) { + failures.push(`${paths.compose}: LAN discovery UDP must not be published by the Mac Preview`) +} + +requireText(paths.dockerfile, dockerfile, 'FROM ${BUILD_ENV_IMAGE} AS builder', 'overridable x86 build environment') +requireText(paths.dockerfile, dockerfile, 'FROM ${RUNTIME_BASE_IMAGE} AS runtime', 'overridable x86 runtime base') +requireText(paths.dockerfile, dockerfile, 'COPY scripts/docker-healthcheck.x86.sh /usr/local/bin/cosmo-x86-healthcheck') +requireText(paths.dockerfile, dockerfile, 'ARG COSMO_BUILD_JOBS', 'configurable CPU build parallelism') +requireText(paths.dockerfile, dockerfile, 'chmod +x /usr/local/bin/cosmo-x86-entrypoint /usr/local/bin/cosmo-x86-healthcheck') +requireText(paths.cpuBuild, cpuBuild, 'BUILD_JOBS="${COSMO_BUILD_JOBS:-$(nproc)}"', 'CPU build parallelism default') +requireText(paths.cpuBuild, cpuBuild, 'cmake --build . --target install -j"${BUILD_JOBS}"', 'CPU install build parallelism') +requireText(paths.cpuBuild, cpuBuild, 'cmake --build . --target package_all', 'existing CPU package build behavior') +requireText(paths.runtimeStartup, runtimeStartup, + 'export COSMO_STREAM_PLAY_MODE="${COSMO_STREAM_PLAY_MODE:-srs}"', + 'deployment stream mode must override the runtime default') +requireText(paths.runtimeStartup, runtimeStartup, + 'export COSMO_STREAM_HTTP_PORT="${COSMO_STREAM_HTTP_PORT:-18088}"', + 'deployment stream port must override the runtime default') + +for (const processName of ['nginx', 'srs', 'cosmo-engine']) { + requireText(paths.healthcheck, healthcheck, processName, `process check for ${processName}`) +} +requireText(paths.healthcheck, healthcheck, '/dev/tcp/127.0.0.1/80', 'web response check') +requireText(paths.dockerignore, dockerignore, '/output', 'private agent-run output exclusion') + +for (const command of ['doctor)', 'up)', 'status)', 'logs)', 'down)', 'url)']) { + requireText(paths.launcher, launcher, command, `launcher action ${command.slice(0, -1)}`) +} +requireText(paths.launcher, launcher, '/Applications/Docker.app/Contents/Resources/bin', 'Docker Desktop CLI and credential-helper fallback') +requireText(paths.launcher, launcher, 'COSMO_X86_BUILD_JOBS', 'Mac build-parallelism override') +requireText(paths.launcher, launcher, 'reserved for Preview media services', 'reserved media-port rejection') +requireText(paths.launcher, launcher, 'docker_cmd port "${CONTAINER_NAME}" 80/tcp', 'running-container web-port comparison') +requireText(paths.launcher, launcher, "'{{.Os}}/{{.Architecture}}'", 'existing image platform check') +requireText(paths.launcher, launcher, '"linux/amd64"', 'required reusable image platform') +requireText(paths.launcher, launcher, 'compose up -d --no-build "${SERVICE_NAME}"', 'restart without an implicit rebuild') +requireText(paths.launcher, launcher, "use 'up --build'", 'explicit rebuild guidance') +requireText(paths.launcher, launcher, 'compose down', 'non-destructive default shutdown') +if (launcher.includes('down -v') || launcher.includes('volume rm')) { + failures.push(`${paths.launcher}: default lifecycle must not remove persistent volumes`) +} + +for (const [relativePath, source, languageChecks] of [ + [paths.docsZh, docsZh, ['Preview', 'linux/amd64', '127.0.0.1', 'Model Guard', 'CEMC', '两次']], + [paths.docsEn, docsEn, ['Preview', 'linux/amd64', '127.0.0.1', 'Model Guard', 'CEMC', 'two consecutive']] +]) { + for (const expected of languageChecks) requireText(relativePath, source, expected) +} + +requireText(paths.readmeZh, readmeZh, 'scripts/macos-docker-preview.sh', 'macOS Preview entry point') +requireText(paths.readmeEn, readmeEn, 'scripts/macos-docker-preview.sh', 'macOS Preview entry point') + +requireExecutable(paths.healthcheck) +requireExecutable(paths.launcher) + +if (failures.length > 0) { + console.error(`macOS Docker Preview check failed with ${failures.length} issue(s):`) + for (const failure of failures) console.error(`- ${failure}`) + process.exit(1) +} + +console.log( + `macOS Docker Preview check passed: isolated amd64 Compose, ${publishedPorts.length} loopback-only ports, health/lifecycle contracts, persistence, and bilingual boundaries.` +) diff --git a/scripts/common.sh b/scripts/common.sh index 8639ff8e9..ccfe9ea38 100644 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -3,27 +3,136 @@ # Sourced by: inte_run_start.sh, start.sh, run_start.sh, install.sh # ── Path constants ── -COSMO_DATA_DIR="/data/cwaiuserdata" +COSMO_DATA_DIR="${COSMO_DATA_DIR:-/data/cwaiuserdata}" COSMO_LOG_DIR="${COSMO_DATA_DIR}/log/logs" -COSMO_INSTALL_DIR="/appfs/cosmo_wander/cwai_data" +COSMO_INSTALL_DIR="${COSMO_INSTALL_DIR:-/appfs/cosmo_wander/cwai_data}" COSMO_UPGRADE_DIR="${COSMO_DATA_DIR}/upgrade" COSMO_NGINX_TMP_DIR="${COSMO_DATA_DIR}/tmp" # Upgrade signal files -COSMO_HW_UPGRADE_SIGN="${COSMO_DATA_DIR}/mqttHWUpgradeApp" COSMO_UPGRADE_SIGN="${COSMO_DATA_DIR}/mqttUpgradeApp" # ── Log helpers ── +# Rotate launcher/script logs independently from the application's internal +# rotating logger. This protects redirected stdout/stderr and early-start logs. +# Usage: rotate_external_log +rotate_external_log() { + local file="$1" + local max_bytes="${COSMO_SCRIPT_LOG_MAX_BYTES:-20971520}" + local keep_files="${COSMO_SCRIPT_LOG_KEEP_FILES:-5}" + local current_bytes index + + [ -n "$file" ] || return 0 + [ -f "$file" ] || return 0 + + case "$max_bytes" in + ''|*[!0-9]*) max_bytes=20971520 ;; + esac + case "$keep_files" in + ''|*[!0-9]*) keep_files=5 ;; + esac + if [ "$max_bytes" -lt 1 ]; then + max_bytes=20971520 + fi + if [ "$keep_files" -lt 1 ]; then + keep_files=5 + fi + + current_bytes="$(wc -c < "$file" 2>/dev/null | tr -d '[:space:]' || echo 0)" + case "$current_bytes" in + ''|*[!0-9]*) current_bytes=0 ;; + esac + if [ "$current_bytes" -lt "$max_bytes" ]; then + return 0 + fi + + index=$((keep_files - 1)) + while [ "$index" -ge 1 ]; do + if [ -e "${file}.${index}" ]; then + mv -f "${file}.${index}" "${file}.$((index + 1))" + fi + index=$((index - 1)) + done + mv -f "$file" "${file}.1" +} + # Usage: cosmo_log [logFile] cosmo_log() { local tag="$1" msg="$2" file="${3:-}" local line="[${tag}] $(date '+%Y-%m-%d %H:%M:%S') ${msg}" echo "$line" if [ -n "$file" ]; then + rotate_external_log "$file" echo "$line" >> "$file" fi } +# ── Network contract helpers ── +is_valid_tcp_port() { + local port="$1" + case "$port" in + ''|*[!0-9]*) return 1 ;; + esac + [ "$port" -ge 1 ] && [ "$port" -le 65535 ] +} + +nginx_upstream_port() { + local config_file="$1" upstream_name="$2" + awk -v target="$upstream_name" ' + $1 == "upstream" && $2 == target { in_target = 1; next } + in_target && $1 == "server" { + endpoint = $2 + sub(/;$/, "", endpoint) + sub(/^.*:/, "", endpoint) + print endpoint + exit + } + in_target && /}/ { in_target = 0 } + ' "$config_file" +} + +# Refuse startup before stopping the current service when the engine ports and +# packaged Nginx upstreams drift apart. +# Usage: verify_nginx_engine_port_contract +verify_nginx_engine_port_contract() { + local config_file="$1" http_port="$2" websocket_port="$3" + local nginx_http_port nginx_websocket_port + + if [ ! -f "$config_file" ]; then + echo "Nginx upstream config is missing: ${config_file}" >&2 + return 1 + fi + if ! is_valid_tcp_port "$http_port"; then + echo "Invalid COSMO_HTTP_PORT: ${http_port}" >&2 + return 1 + fi + if ! is_valid_tcp_port "$websocket_port"; then + echo "Invalid COSMO_WEBSOCKET_PORT: ${websocket_port}" >&2 + return 1 + fi + + nginx_http_port="$(nginx_upstream_port "$config_file" mvit)" + nginx_websocket_port="$(nginx_upstream_port "$config_file" mvws)" + if ! is_valid_tcp_port "$nginx_http_port"; then + echo "Nginx upstream mvit has no valid TCP port in ${config_file}" >&2 + return 1 + fi + if ! is_valid_tcp_port "$nginx_websocket_port"; then + echo "Nginx upstream mvws has no valid TCP port in ${config_file}" >&2 + return 1 + fi + if [ "$nginx_http_port" != "$http_port" ]; then + echo "HTTP port mismatch: engine=${http_port}, nginx mvit=${nginx_http_port}" >&2 + return 1 + fi + if [ "$nginx_websocket_port" != "$websocket_port" ]; then + echo "WebSocket port mismatch: engine=${websocket_port}, nginx mvws=${nginx_websocket_port}" >&2 + return 1 + fi + + echo "HTTP=${http_port}, WebSocket=${websocket_port}" +} + # ── Directory setup ── # Create all runtime directories needed before services start ensure_runtime_dirs() { @@ -36,7 +145,9 @@ ensure_runtime_dirs() { mkdir -p "${COSMO_NGINX_TMP_DIR}/nginx_scgi" mkdir -p "${COSMO_UPGRADE_DIR}" - mkdir -p "${COSMO_INSTALL_DIR}/bin/nginx_conf/logs" + if [ -d "${COSMO_INSTALL_DIR}/bin/nginx_conf" ]; then + mkdir -p "${COSMO_INSTALL_DIR}/bin/nginx_conf/logs" + fi } # ── Process helpers ── diff --git a/scripts/copy-static-benchmark-assets.mjs b/scripts/copy-static-benchmark-assets.mjs new file mode 100644 index 000000000..ba5bb1738 --- /dev/null +++ b/scripts/copy-static-benchmark-assets.mjs @@ -0,0 +1,34 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const sourceRoot = path.join(repositoryRoot, 'docs', 'benchmarks', 'scenario-bench'); +const outputRoot = path.join(repositoryRoot, 'docs', '.vitepress', 'dist', 'benchmarks', 'scenario-bench'); +const copied = []; + +for (const version of ['v1.0', 'current', 'v1.1']) { + const source = path.join(sourceRoot, version); + if (!fs.existsSync(source)) continue; + for (const file of walk(source)) { + if (!staticBenchmarkAsset(file)) continue; + const relative = path.relative(sourceRoot, file); + const target = path.join(outputRoot, relative); + fs.mkdirSync(path.dirname(target), { recursive: true }); + fs.copyFileSync(file, target); + copied.push(relative.replaceAll('\\', '/')); + } +} + +console.log(`Copied ${copied.length} static benchmark assets into the VitePress output.`); + +function staticBenchmarkAsset(file) { + return !/\.md$/i.test(file); +} + +function walk(directory) { + return fs.readdirSync(directory, { withFileTypes: true }).flatMap((entry) => { + const full = path.join(directory, entry.name); + return entry.isDirectory() ? walk(full) : [full]; + }); +} diff --git a/scripts/cosmo-performance.service b/scripts/cosmo-performance.service new file mode 100644 index 000000000..94a7bb0d3 --- /dev/null +++ b/scripts/cosmo-performance.service @@ -0,0 +1,11 @@ +[Unit] +Description=Cosmo RK3576 performance profile +Before=cosmo.service + +[Service] +Type=oneshot +ExecStart=/usr/local/sbin/rk3576-performance.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/scripts/docker-compose.sh b/scripts/docker-compose.sh new file mode 100755 index 000000000..46428ceff --- /dev/null +++ b/scripts/docker-compose.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +set -euo pipefail + +if ! command -v docker >/dev/null 2>&1; then + echo "ERROR: Docker is not installed or is not on PATH." >&2 + exit 1 +fi + +run_compose() { + local privilege_prefix="$1" + shift + if ${privilege_prefix} docker compose version >/dev/null 2>&1; then + exec ${privilege_prefix} docker compose "$@" + fi + if command -v docker-compose >/dev/null 2>&1 && + ${privilege_prefix} docker-compose version >/dev/null 2>&1; then + exec ${privilege_prefix} docker-compose "$@" + fi + return 1 +} + +if docker info >/dev/null 2>&1; then + run_compose "" "$@" || true + echo "ERROR: Docker is reachable, but neither Compose V2 nor Compose V1 is installed." >&2 + exit 1 +fi + +if ! command -v sudo >/dev/null 2>&1; then + echo "ERROR: Docker is not accessible to this user and sudo is unavailable." >&2 + exit 1 +fi +if [ ! -t 0 ]; then + echo "ERROR: Docker requires elevated access. Re-run interactively or grant this user Docker access." >&2 + exit 1 +fi + +echo "Docker requires elevated access; requesting sudo once." >&2 +sudo -v +if ! sudo docker info >/dev/null 2>&1; then + echo "ERROR: Docker is unavailable even with sudo." >&2 + exit 1 +fi +run_compose "sudo" "$@" || true +echo "ERROR: neither 'sudo docker compose' nor 'sudo docker-compose' is available." >&2 +exit 1 diff --git a/scripts/docker-healthcheck.x86.sh b/scripts/docker-healthcheck.x86.sh new file mode 100755 index 000000000..e48e9fc4d --- /dev/null +++ b/scripts/docker-healthcheck.x86.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +for process_name in nginx srs cosmo-engine; do + if ! pgrep -x "${process_name}" >/dev/null; then + echo "process is not running: ${process_name}" >&2 + exit 1 + fi +done + +exec 3<>/dev/tcp/127.0.0.1/80 +printf 'GET / HTTP/1.0\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n' >&3 +IFS= read -r status_line <&3 +exec 3>&- +exec 3<&- + +if [[ ! "${status_line}" =~ ^HTTP/[0-9.]+[[:space:]]+(2|3)[0-9][0-9][[:space:]] ]]; then + echo "unexpected web response: ${status_line}" >&2 + exit 1 +fi diff --git a/scripts/format_check.sh b/scripts/format_check.sh index 9b3dc5d62..d82bce154 100755 --- a/scripts/format_check.sh +++ b/scripts/format_check.sh @@ -63,7 +63,7 @@ collect_files() { if [[ "$STAGED_ONLY" == true ]]; then git -C "$PROJECT_ROOT" diff --cached --name-only --diff-filter=ACMR \ | grep -E '\.(h|cc)$' \ - | grep -vE '(^|/)3rd/' \ + | grep -vE '(^|/)(3rd|prebuild)/' \ | while read -r f; do echo "$PROJECT_ROOT/$f"; done else find "$PROJECT_ROOT/src" "$PROJECT_ROOT/test" \ diff --git a/scripts/install.sh b/scripts/install.sh deleted file mode 100644 index cd76ef264..000000000 --- a/scripts/install.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/bash -set -e - -# Enter the directory where the install script is located (before calling stop.sh) -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -cd "$SCRIPT_DIR" - -# shellcheck source=common.sh -. "${SCRIPT_DIR}/common.sh" - -# Stop running processes first -./stop.sh - -# WARNING: Do not modify INSTALLPATH - it is the production deployment root -INSTALLPATH="${COSMO_INSTALL_DIR}" - -INSTALL_SUCCESS_SIGN="${COSMO_UPGRADE_SIGN}" - -logFile="${1:-/dev/null}" -logTag="[INSTALL]" - -echo "${logTag} Install Start" >> "$logFile" -echo "${logTag} script=$0, logFile=$1" >> "$logFile" -echo "${logTag} script dir: $SCRIPT_DIR" >> "$logFile" - -echo "Install path is ${INSTALLPATH}" - -echo "${logTag} Installing files..." >> "$logFile" -echo "Installing files..." - -# Ensure install path exists and is non-empty -if [ -z "${INSTALLPATH}" ]; then - echo "${logTag} ERROR: INSTALLPATH is empty, aborting!" >> "$logFile" - exit 1 -fi - -mkdir -p "${INSTALLPATH}" - -# Remove old directories -PACKAGE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" -for dir in bin lib scripts web font files; do - if [ -d "${INSTALLPATH}/${dir}" ]; then - rm -rf "${INSTALLPATH:?}/${dir}" - fi -done - -# Install new files (skip missing directories) -for dir in bin lib scripts web font files resource; do - if [ -d "${PACKAGE_DIR}/${dir}" ]; then - if [ "$dir" = "resource" ]; then - echo "${logTag} Overwriting ${dir}..." >> "$logFile" - if [ "${CLEAN_RESOURCE:-0}" = "1" ] && [ -d "${INSTALLPATH}/resource" ]; then - echo "${logTag} CLEAN_RESOURCE=1, removing ${INSTALLPATH}/resource before install" >> "$logFile" - rm -rf "${INSTALLPATH:?}/resource" - fi - mkdir -p "${INSTALLPATH}/resource" - cp -rf "${PACKAGE_DIR}/resource/." "${INSTALLPATH}/resource/" - else - mv -f "${PACKAGE_DIR}/${dir}" "${INSTALLPATH}/" - fi - else - echo "${logTag} WARNING: ${dir} not found in package, skipping" >> "$logFile" - fi -done - -# Setup static file symlinks -mkdir -p "${INSTALLPATH}/web/staticfile" -rm -f "${INSTALLPATH}/web/staticfile/httpInterface.html" -rm -f "${INSTALLPATH}/web/staticfile/mqttInterface.html" -ln -sf "${INSTALLPATH}/files/Interface/ai-box-interface_v1.0.html" "${INSTALLPATH}/web/staticfile/httpInterface.html" -ln -sf "${INSTALLPATH}/files/Interface/mqtt_v1.0.html" "${INSTALLPATH}/web/staticfile/mqttInterface.html" - -mkdir -p "${INSTALLPATH}/bin/nginx_conf/logs" - -# Remove install script from deployed location (self-cleanup) -rm -f "${INSTALLPATH}/scripts/install.sh" - -echo "Install files Done." -echo "${logTag} Install files Done." >> "$logFile" - -# Setup systemd auto-start service -SERVICE_FILE="/etc/systemd/system/cosmo.service" -SERVICE_LINK="/etc/systemd/system/multi-user.target.wants/cosmo.service" - -echo "${logTag} Setting up systemd auto-start service..." >> "$logFile" - -cat > "$SERVICE_FILE" <> "$logFile" -echo "systemd service [cosmo] installed and enabled." - -# Upgrade completion marker for MQTT reporting -mkdir -p "$(dirname "$INSTALL_SUCCESS_SIGN")" -touch "$INSTALL_SUCCESS_SIGN" -sync - -echo "${logTag} Install End." -echo "${logTag} Install End." >> "$logFile" diff --git a/scripts/install_rkllm_sdk.py b/scripts/install_rkllm_sdk.py new file mode 100644 index 000000000..aba6b44a3 --- /dev/null +++ b/scripts/install_rkllm_sdk.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +"""Install the pinned Rockchip RKLLM runtime used by the RK3576 builder.""" + +from __future__ import annotations + +import argparse +import hashlib +import os +import pathlib +import time +import urllib.error +import urllib.request + + +VERSION = "1.3.0" +COMMIT = "878f9361fd3afa7e167b7079918918f78d2c1c2a" +SOURCE_BASE = f"https://raw.githubusercontent.com/airockchip/rknn-llm/{COMMIT}" +FILES = { + "include/rkllm.h": ( + "rkllm-runtime/Linux/librkllm_api/include/rkllm.h", + "80596a578f7f8e70df6eda1c2cbead3bfced14623a190258f2bd009a3d1f72cf", + 0o644, + ), + "lib/librkllmrt.so": ( + "rkllm-runtime/Linux/librkllm_api/aarch64/librkllmrt.so", + "6a9e4fc5324c68921c3a900340361e107af7599fe34dc8fa7759b2c5ae22a6e6", + 0o755, + ), + "LICENSE": ( + "LICENSE", + "8d670a646eb8cf28fb7c63a5c9126c224a3a3f8124b00a3b9184df9a2ed298b8", + 0o644, + ), +} + + +def download(url: str) -> bytes: + request = urllib.request.Request(url, headers={"User-Agent": "cosmo-edge-rk3576-builder"}) + last_error: Exception | None = None + for attempt in range(1, 4): + try: + with urllib.request.urlopen(request, timeout=120) as response: + return response.read() + except (OSError, urllib.error.URLError) as error: + last_error = error + if attempt < 3: + time.sleep(attempt * 2) + raise RuntimeError(f"download failed after 3 attempts: {url}: {last_error}") + + +def install(root: pathlib.Path) -> None: + root.mkdir(parents=True, exist_ok=True) + for destination_name, (source_name, expected_sha256, mode) in FILES.items(): + url = f"{SOURCE_BASE}/{source_name}" + data = download(url) + actual_sha256 = hashlib.sha256(data).hexdigest() + if actual_sha256 != expected_sha256: + raise RuntimeError( + f"SHA-256 mismatch for {source_name}: expected {expected_sha256}, got {actual_sha256}" + ) + destination = root / destination_name + destination.parent.mkdir(parents=True, exist_ok=True) + temporary = destination.with_name(f".{destination.name}.tmp") + temporary.write_bytes(data) + os.chmod(temporary, mode) + os.replace(temporary, destination) + print(f"Installed {destination_name} ({len(data)} bytes, sha256={actual_sha256})") + + (root / "VERSION").write_text( + f"RKLLM Runtime v{VERSION}\nsource_commit={COMMIT}\n", encoding="utf-8" + ) + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--root", required=True, type=pathlib.Path) + arguments = parser.parse_args() + install(arguments.root.resolve()) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/inte_run_start.sh b/scripts/inte_run_start.sh old mode 100644 new mode 100755 index 07238cfc8..c98b970a5 --- a/scripts/inte_run_start.sh +++ b/scripts/inte_run_start.sh @@ -15,4 +15,4 @@ ensure_runtime_dirs cosmo_log "BOOT" "Starting Cosmo services..." cd "$SCRIPT_DIR" || exit 1 -"$SCRIPT_DIR/start.sh" start +exec "$SCRIPT_DIR/start.sh" start diff --git a/scripts/legacy_migration_install.sh b/scripts/legacy_migration_install.sh new file mode 100644 index 000000000..bd8fefc28 --- /dev/null +++ b/scripts/legacy_migration_install.sh @@ -0,0 +1,134 @@ +#!/bin/sh +set -eu + +IFS="$(printf ' \t\n_')" +IFS="${IFS%_}" +PATH='/usr/sbin:/usr/bin:/sbin:/bin' +export IFS PATH + +fail() { + echo "[MIGRATION] ERROR: $*" >&2 + exit 1 +} + +[ "$#" -le 1 ] || fail "legacy entry accepts only the optional log file" +log_file="${1:-/dev/null}" + +log() { + printf '[INSTALL] %s\n' "$*" | tee -a "$log_file" +} + +script_path="$(readlink -f "$0")" +[ -n "$script_path" ] || fail "cannot resolve installer path" +payload_root="${script_path%/scripts/install.sh}" +[ "$payload_root" != "$script_path" ] || fail "installer is outside the package scripts directory" + +if [ -n "${COSMO_MIGRATION_TEST_ROOT:-}" ]; then + case "$COSMO_MIGRATION_TEST_ROOT" in /*) ;; *) fail "test root must be absolute" ;; esac + [ "$COSMO_MIGRATION_TEST_ROOT" != / ] || fail "test root is invalid" + active_root="${COSMO_MIGRATION_TEST_ROOT}/appfs/cosmo_wander/cwai_data" + systemd_root="${COSMO_MIGRATION_TEST_ROOT}/etc/systemd/system" + upgrade_sign="${COSMO_MIGRATION_TEST_ROOT}/data/cwaiuserdata/mqttUpgradeApp" +else + active_root='/appfs/cosmo_wander/cwai_data' + systemd_root='/etc/systemd/system' + upgrade_sign='/data/cwaiuserdata/mqttUpgradeApp' +fi +active_parent="${active_root%/*}" +staging_root="${active_parent}/.cosmo-migration-staging.$$" +backup_root="${active_parent}/.cosmo-migration-backup" + +[ -f "${payload_root}/bin/cosmo-engine" ] || fail "package is missing bin/cosmo-engine" +for required_script in stop.sh start.sh inte_run_start.sh; do + [ -x "${payload_root}/scripts/${required_script}" ] || + fail "package script is missing or not executable: ${required_script}" +done + +log "Install Start" +log "script=${script_path}, logFile=${log_file}" +log "Stopping active Cosmo processes" +"${payload_root}/scripts/stop.sh" + +mkdir -p -- "$active_parent" +[ ! -e "$staging_root" ] && [ ! -L "$staging_root" ] || fail "staging path already exists" +mkdir -- "$staging_root" +trap 'rm -rf -- "$staging_root"' EXIT + +# Match the historical installer: preserve the installed resource tree by +# default, then overlay packaged resources. Copying the installed tree first +# avoids keeping a second packaged-resource copy on space-constrained /appfs. +# CLEAN_RESOURCE=1 makes the package resource tree authoritative. +if [ "${CLEAN_RESOURCE:-0}" != 1 ] && [ -d "${active_root}/resource" ]; then + mkdir -- "${staging_root}/resource" + cp -a -- "${active_root}/resource/." "${staging_root}/resource/" +fi +cp -a -- "${payload_root}/." "$staging_root/" + +[ ! -e "$backup_root" ] && [ ! -L "$backup_root" ] || fail "stale migration backup exists" +if [ -e "$active_root" ] || [ -L "$active_root" ]; then + mv -- "$active_root" "$backup_root" +fi +if ! mv -- "$staging_root" "$active_root"; then + [ ! -e "$backup_root" ] || mv -- "$backup_root" "$active_root" + fail "cannot activate migrated application" +fi +trap - EXIT +rm -rf -- "$backup_root" + +# Preserve the historical post-install filesystem contract. +mkdir -p -- "${active_root}/web/staticfile" "${active_root}/bin/nginx_conf/logs" +rm -f -- \ + "${active_root}/web/staticfile/httpInterface.html" \ + "${active_root}/web/staticfile/mqttInterface.html" +ln -s -- \ + "${active_root}/files/Interface/ai-box-interface_v1.0.html" \ + "${active_root}/web/staticfile/httpInterface.html" +ln -s -- \ + "${active_root}/files/Interface/mqtt_v1.0.html" \ + "${active_root}/web/staticfile/mqttInterface.html" +rm -f -- "${active_root}/scripts/install.sh" + +# Always replace the unit. Existing main installations may still point to the +# former /appfs/minivision/mv_data tree, while a deleted unit must be recreated. +mkdir -p -- "$systemd_root" +service_file="${systemd_root}/cosmo.service" +service_temp="${service_file}.tmp.$$" +trap 'rm -f -- "$service_temp"' EXIT +umask 022 +{ + printf '%s\n' \ + '[Unit]' \ + 'Description=Cosmo Edge AI Engine' \ + 'Wants=network-online.target' \ + 'After=network-online.target docker.service' \ + '' \ + '[Service]' \ + 'Type=simple' \ + 'User=root' \ + 'ExecStart=/appfs/cosmo_wander/cwai_data/scripts/inte_run_start.sh' \ + 'Restart=on-failure' \ + 'RestartSec=10' \ + '' \ + '[Install]' \ + 'WantedBy=multi-user.target' +} >"$service_temp" +chmod 0644 "$service_temp" +mv -f -- "$service_temp" "$service_file" +trap - EXIT + +if [ -n "${COSMO_MIGRATION_TEST_ROOT:-}" ]; then + wants_dir="${systemd_root}/multi-user.target.wants" + mkdir -p -- "$wants_dir" + ln -sfn ../cosmo.service "${wants_dir}/cosmo.service" +else + systemctl daemon-reload + systemctl enable cosmo.service +fi + +mkdir -p -- "${upgrade_sign%/*}" +: >"$upgrade_sign" +sync +log "Install files Done" +log "systemd service [cosmo] installed and enabled" +log "installed legacy-compatible bridge at ${active_root}" +log "Install End" diff --git a/scripts/macos-docker-preview.sh b/scripts/macos-docker-preview.sh new file mode 100755 index 000000000..2bfbf8e0d --- /dev/null +++ b/scripts/macos-docker-preview.sh @@ -0,0 +1,310 @@ +#!/usr/bin/env bash +set -euo pipefail + +PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +COMPOSE_FILE="${PROJECT_ROOT}/docker-compose.x86.macos.yml" +SERVICE_NAME="cosmo-x86-macos" +CONTAINER_NAME="cosmo-x86-macos-preview" +IMAGE_NAME="cosmo:x86-macos-preview" +WEB_PORT="${COSMO_X86_WEB_PORT:-8080}" +BUILD_JOBS="${COSMO_X86_BUILD_JOBS:-1}" +DOCKER_BIN="" + +usage() { + cat <<'USAGE' +Usage: ./scripts/macos-docker-preview.sh + +Commands: + doctor Check the Mac, Docker Desktop, Compose, capacity, and ports. + up Start the Preview, building only when the image is missing. + up --build Rebuild the image, start the Preview, and wait for health. + status Show the Compose service and health state. + logs Print the most recent service logs. + logs --follow Follow service logs until interrupted. + down Stop the Preview while preserving its named volumes. + url Print the local web-console URL. + help Show this help. + +Environment: + COSMO_X86_WEB_PORT Host web port (default: 8080, range: 1024-65535; + media ports 1936, 1985, and 18088 are reserved). + COSMO_X86_BUILD_JOBS Build parallelism (default: 1 for reliable emulation). +USAGE +} + +info() { + printf '[INFO] %s\n' "$*" +} + +pass() { + printf '[PASS] %s\n' "$*" +} + +warn() { + printf '[WARN] %s\n' "$*" >&2 +} + +fail() { + printf '[FAIL] %s\n' "$*" >&2 + exit 1 +} + +find_docker() { + local app_bin_dir="/Applications/Docker.app/Contents/Resources/bin" + if [[ -d "${app_bin_dir}" ]]; then + # A first-run or per-user Docker Desktop install may not create global + # CLI and credential-helper symlinks. Keep the adjustment process-local. + export PATH="${app_bin_dir}:${PATH}" + fi + + if command -v docker >/dev/null 2>&1; then + DOCKER_BIN="$(command -v docker)" + return 0 + fi + + local app_cli="${app_bin_dir}/docker" + if [[ -x "${app_cli}" ]]; then + DOCKER_BIN="${app_cli}" + return 0 + fi + + fail "Docker CLI was not found. Install and finish starting Docker Desktop." +} + +docker_cmd() { + "${DOCKER_BIN}" "$@" +} + +compose() { + docker_cmd compose -f "${COMPOSE_FILE}" "$@" +} + +validate_web_port() { + if [[ ! "${WEB_PORT}" =~ ^[0-9]+$ ]] || ((WEB_PORT < 1024 || WEB_PORT > 65535)); then + fail "COSMO_X86_WEB_PORT must be an integer from 1024 through 65535; got '${WEB_PORT}'." + fi + case "${WEB_PORT}" in + 1936|1985|18088) + fail "COSMO_X86_WEB_PORT ${WEB_PORT} is reserved for Preview media services." + ;; + esac +} + +validate_build_jobs() { + if [[ ! "${BUILD_JOBS}" =~ ^[1-9][0-9]*$ ]]; then + fail "COSMO_X86_BUILD_JOBS must be a positive integer; got '${BUILD_JOBS}'." + fi +} + +require_apple_silicon_mac() { + local host_os host_arch + host_os="$(uname -s)" + host_arch="$(uname -m)" + if [[ "${host_os}" != "Darwin" || "${host_arch}" != "arm64" ]]; then + fail "This Preview is currently admitted only on Apple Silicon macOS; found ${host_os}/${host_arch}." + fi + pass "Apple Silicon macOS detected (${host_arch})." +} + +check_docker() { + find_docker + pass "Docker CLI: $(docker_cmd --version)" + + if ! docker_cmd compose version >/dev/null 2>&1; then + fail "Docker Compose V2 is unavailable. Finish Docker Desktop setup and retry." + fi + pass "Docker Compose: $(docker_cmd compose version --short 2>/dev/null || docker_cmd compose version)" + + if ! docker_cmd info >/dev/null 2>&1; then + fail "Docker Desktop is not ready. Open Docker Desktop, finish its first-run setup, and retry." + fi + + local server_platform + server_platform="$(docker_cmd version --format '{{.Server.Os}}/{{.Server.Arch}}' 2>/dev/null || true)" + if [[ "${server_platform}" != linux/* ]]; then + fail "The active Docker server must run Linux containers; found '${server_platform:-unknown}'." + fi + pass "Docker server is ready (${server_platform})." + + if ! compose config --quiet; then + fail "${COMPOSE_FILE} is not valid for the active Compose version." + fi + pass "macOS Compose configuration is valid." +} + +check_rosetta() { + if /usr/sbin/pkgutil --pkg-info com.apple.pkg.RosettaUpdateAuto >/dev/null 2>&1 || + /usr/bin/pgrep -q oahd 2>/dev/null; then + pass "Rosetta 2 is installed." + else + warn "Rosetta 2 was not detected. amd64 emulation may be significantly slower." + fi +} + +check_capacity() { + local disk_kb disk_gib docker_bytes docker_mib + disk_kb="$(df -Pk "${PROJECT_ROOT}" | awk 'NR == 2 {print $4}')" + disk_gib=$((disk_kb / 1024 / 1024)) + if ((disk_gib < 20)); then + warn "Only ${disk_gib} GiB is free. The first amd64 build can need substantial temporary space." + else + pass "Free host disk: ${disk_gib} GiB." + fi + + docker_bytes="$(docker_cmd info --format '{{.MemTotal}}' 2>/dev/null || printf '0')" + if [[ "${docker_bytes}" =~ ^[0-9]+$ ]]; then + docker_mib=$((docker_bytes / 1024 / 1024)) + # Docker reports usable guest memory, which is slightly below the value + # selected in Desktop. A nominal 8 GiB allocation is about 7.7 GiB here. + if ((docker_mib < 7168)); then + warn "Docker exposes ${docker_mib} MiB RAM. Allocate at least 8 GiB in Docker Desktop for this emulated build." + else + pass "Docker usable memory: ${docker_mib} MiB (compatible with the recommended 8 GiB allocation)." + fi + fi +} + +container_is_running() { + [[ "$(docker_cmd inspect --format '{{.State.Running}}' "${CONTAINER_NAME}" 2>/dev/null || true)" == "true" ]] +} + +tcp_port_in_use() { + /usr/sbin/lsof -nP -iTCP:"$1" -sTCP:LISTEN -t 2>/dev/null | grep -q . +} + +check_ports() { + if container_is_running; then + local current_web_port + current_web_port="$(docker_cmd port "${CONTAINER_NAME}" 80/tcp 2>/dev/null | awk -F: 'NR == 1 {print $NF}')" + if [[ "${current_web_port}" == "${WEB_PORT}" ]]; then + pass "Preview container is already running with the requested web port ${WEB_PORT}." + return 0 + fi + if tcp_port_in_use "${WEB_PORT}"; then + fail "Requested web port ${WEB_PORT} is already in use; the running Preview currently uses ${current_web_port:-an unknown port}." + fi + pass "Requested web port ${WEB_PORT} is available; Compose will replace the current ${current_web_port:-unknown} binding." + return 0 + fi + + local port + for port in "${WEB_PORT}" 1936 1985 18088; do + if tcp_port_in_use "${port}"; then + fail "TCP port ${port} is already in use. Stop that service or set COSMO_X86_WEB_PORT for a web-port conflict." + fi + done + pass "Required localhost ports are available." +} + +doctor() { + require_apple_silicon_mac + validate_web_port + validate_build_jobs + check_docker + check_rosetta + check_capacity + check_ports + pass "Build parallelism: ${BUILD_JOBS} job(s)." + pass "macOS Docker Preview admission passed." +} + +wait_until_healthy() { + local deadline=$((SECONDS + 240)) + local state="" + while ((SECONDS < deadline)); do + state="$(docker_cmd inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "${CONTAINER_NAME}" 2>/dev/null || true)" + case "${state}" in + healthy) + pass "CosmoEdge is healthy." + return 0 + ;; + unhealthy|exited|dead) + compose logs --tail=200 "${SERVICE_NAME}" >&2 || true + fail "CosmoEdge entered state '${state}'." + ;; + esac + sleep 5 + done + + compose logs --tail=200 "${SERVICE_NAME}" >&2 || true + fail "CosmoEdge did not become healthy within 240 seconds (last state: ${state:-unknown})." +} + +preview_image_ready() { + local image_platform + image_platform="$(docker_cmd image inspect --format '{{.Os}}/{{.Architecture}}' "${IMAGE_NAME}" 2>/dev/null || true)" + if [[ -z "${image_platform}" ]]; then + return 1 + fi + if [[ "${image_platform}" != "linux/amd64" ]]; then + warn "Existing ${IMAGE_NAME} is ${image_platform}; rebuilding the required linux/amd64 image." + return 1 + fi + return 0 +} + +start_preview() { + local force_build="${1:-}" + doctor + mkdir -p "${PROJECT_ROOT}/build_output/macos-x86" + + if [[ "${force_build}" == "--build" ]] || ! preview_image_ready; then + info "Building linux/amd64 on Apple Silicon. The first build can take considerably longer than x86 Linux." + compose up -d --build "${SERVICE_NAME}" + else + info "Reusing existing ${IMAGE_NAME}; use 'up --build' after source or build-input changes." + compose up -d --no-build "${SERVICE_NAME}" + fi + wait_until_healthy + printf 'Web console: http://127.0.0.1:%s\n' "${WEB_PORT}" +} + +require_ready_docker() { + find_docker + if ! docker_cmd info >/dev/null 2>&1; then + fail "Docker Desktop is not ready." + fi +} + +command="${1:-help}" +case "${command}" in + doctor) + doctor + ;; + up) + if [[ -n "${2:-}" && "${2}" != "--build" ]]; then + fail "Unknown up option '${2}'. Use --build or no option." + fi + start_preview "${2:-}" + ;; + status) + require_ready_docker + compose ps + ;; + logs) + require_ready_docker + if [[ "${2:-}" == "--follow" ]]; then + compose logs --tail=200 --follow "${SERVICE_NAME}" + elif [[ -n "${2:-}" ]]; then + fail "Unknown logs option '${2}'. Use --follow or no option." + else + compose logs --tail=200 "${SERVICE_NAME}" + fi + ;; + down) + require_ready_docker + compose down + pass "Preview stopped. Named volumes and uploaded data were preserved." + ;; + url) + validate_web_port + printf 'http://127.0.0.1:%s\n' "${WEB_PORT}" + ;; + help|-h|--help) + usage + ;; + *) + usage >&2 + fail "Unknown command '${command}'." + ;; +esac diff --git a/scripts/package_md5_rename.sh b/scripts/package_md5_rename.sh index 62cd8167f..6ca664616 100755 --- a/scripts/package_md5_rename.sh +++ b/scripts/package_md5_rename.sh @@ -1,21 +1,56 @@ #!/bin/bash -# 打包后计算 MD5 并嵌入文件名 -# 用法: package_md5_rename.sh -set -e +# Normalize CPack output and publish the permanent upgrade filename accepted by +# main and all later Open/Protected releases. +set -euo pipefail -PACKAGES_DIR="$1" -PACKAGE_NAME="$2" -ORIG="${PACKAGES_DIR}/${PACKAGE_NAME}.tar.gz" +if [ "$#" -ne 4 ]; then + echo "Usage: $0 " >&2 + exit 2 +fi + +packages_dir="$1" +package_name="$2" +build_profile="$3" +build_epoch="$4" +original="${packages_dir}/${package_name}.tar.gz" -if [ ! -f "$ORIG" ]; then - echo "Error: $ORIG not found" +case "$build_profile" in + public-runtime | production-release) ;; + *) echo "Unsupported build profile: $build_profile" >&2; exit 2 ;; +esac +case "$build_epoch" in + "" | *[!0-9]*) echo "Build epoch must be a non-negative integer" >&2; exit 2 ;; +esac +if [ ! -f "$original" ] || [ -L "$original" ]; then + echo "CPack artifact not found or has an unsafe type: $original" >&2 + exit 1 +fi +if ! tar -tzf "$original" | awk -v root="$package_name" ' + BEGIN { count = 0 } + { + count++ + if (substr($0, 1, 1) == "/" || $0 ~ /(^|\/)\.\.(\/|$)/ || + ($0 != root && index($0, root "/") != 1)) exit 1 + } + END { if (count == 0) exit 1 } +'; then + echo "CPack artifact has an unexpected archive layout" >&2 exit 1 fi -# 清理旧包,只保留当前构建的 -find "$PACKAGES_DIR" -name "*.tar.gz" ! -name "$(basename "$ORIG")" -delete 2>/dev/null || true +normalization_root="$(mktemp -d "${packages_dir}/.cosmo-package-normalize.XXXXXX")" +trap 'rm -rf -- "$normalization_root"' EXIT +extract_root="${normalization_root}/extract" +normalized="${normalization_root}/${package_name}.tar.gz" +mkdir -p -- "$extract_root" +tar -xzf "$original" -C "$extract_root" +test -d "${extract_root}/${package_name}" && test ! -L "${extract_root}/${package_name}" +tar --sort=name --format=gnu --mtime="@${build_epoch}" --owner=0 --group=0 \ + --numeric-owner -C "$extract_root" -cf - -- "$package_name" | gzip -n >"$normalized" +mv -- "$normalized" "$original" -MD5=$(md5sum "$ORIG" | cut -d' ' -f1) -NEW="${PACKAGES_DIR}/${PACKAGE_NAME}-${MD5}.tar.gz" -mv "$ORIG" "$NEW" -echo "Package: $(basename "$NEW")" +digest="$(md5sum -- "$original")" +digest="${digest%% *}" +labeled="${packages_dir}/${package_name}-${digest}.tar.gz" +mv -- "$original" "$labeled" +echo "Upgrade package: $(basename "$labeled")" diff --git a/scripts/prepare_rknpu_metrics.sh b/scripts/prepare_rknpu_metrics.sh new file mode 100755 index 000000000..5672225b4 --- /dev/null +++ b/scripts/prepare_rknpu_metrics.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -eu + +# Expose only the vendor's read-only NPU load counter outside debugfs. This +# lets an unprivileged cosmo-engine read it without access to the rest of debugfs. +SOURCE_PATH="/sys/kernel/debug/rknpu/load" +TARGET_DIR="/run/cosmo-edge/metrics" +TARGET_PATH="${TARGET_DIR}/rknpu-load" + +if [ ! -r "${SOURCE_PATH}" ]; then + exit 0 +fi + +if [ "$(id -u)" -ne 0 ]; then + echo "RKNN metrics bridge skipped: root is required" >&2 + exit 0 +fi + +install -d -o root -g root -m 0755 "${TARGET_DIR}" + +mounted_target="$(findmnt -rn -o TARGET --target "${TARGET_PATH}" 2>/dev/null || true)" +if [ "${mounted_target}" = "${TARGET_PATH}" ]; then + exit 0 +fi + +install -o root -g root -m 0444 /dev/null "${TARGET_PATH}" +if ! mount --bind "${SOURCE_PATH}" "${TARGET_PATH}"; then + rm -f "${TARGET_PATH}" + echo "RKNN metrics bridge failed: cannot bind ${SOURCE_PATH}" >&2 + exit 1 +fi + +if ! mount -o remount,bind,ro "${TARGET_PATH}"; then + umount "${TARGET_PATH}" || true + rm -f "${TARGET_PATH}" + echo "RKNN metrics bridge failed: cannot make target read-only" >&2 + exit 1 +fi + +echo "RKNN metrics bridge ready: ${TARGET_PATH}" diff --git a/scripts/rk3576-performance.sh b/scripts/rk3576-performance.sh new file mode 100755 index 000000000..8d504f580 --- /dev/null +++ b/scripts/rk3576-performance.sh @@ -0,0 +1,17 @@ +#!/bin/sh +set -eu + +set_governor() { + path="$1" + governor="$2" + if [ -w "$path" ]; then + printf '%s\n' "$governor" > "$path" + fi +} + +set_governor /sys/class/devfreq/27700000.npu/governor performance +set_governor /sys/class/devfreq/dmc/governor performance + +for policy in /sys/devices/system/cpu/cpufreq/policy*; do + set_governor "$policy/scaling_governor" performance +done diff --git a/scripts/rknn/build_model_runner.sh b/scripts/rknn/build_model_runner.sh new file mode 100755 index 000000000..5b47e00bb --- /dev/null +++ b/scripts/rknn/build_model_runner.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [[ $# -lt 1 || $# -gt 2 ]]; then + echo "Usage: $0 [output-dir]" >&2 + exit 2 +fi + +runtime_root="$(cd "$1" && pwd)" +output_dir="${2:-$PWD/build/rknn-model-runner}" +cxx="${CXX:-aarch64-linux-gnu-g++}" +repo_root="$(cd "$(dirname "$0")/../.." && pwd)" +source_file="$repo_root/tools/rknn/rknn_model_runner.cc" + +for required in "$runtime_root/include/rknn_api.h" "$runtime_root/lib/librknnrt.so" "$source_file"; do + if [[ ! -f "$required" ]]; then + echo "Missing build input: $required" >&2 + exit 1 + fi +done +if ! command -v "$cxx" >/dev/null 2>&1; then + echo "Cross compiler not found: $cxx" >&2 + exit 1 +fi + +install -d "$output_dir/bin" "$output_dir/lib" +"$cxx" -std=c++17 -O2 -Wall -Wextra -Werror \ + -I"$runtime_root/include" \ + "$source_file" \ + -L"$runtime_root/lib" -lrknnrt \ + -Wl,-rpath,'$ORIGIN/../lib' \ + -o "$output_dir/bin/rknn-model-runner" +cp -p "$runtime_root/lib/librknnrt.so" "$output_dir/lib/librknnrt.so" + +file "$output_dir/bin/rknn-model-runner" "$output_dir/lib/librknnrt.so" +sha256sum "$output_dir/bin/rknn-model-runner" "$output_dir/lib/librknnrt.so" diff --git a/scripts/rknn/build_runtime_probe.sh b/scripts/rknn/build_runtime_probe.sh new file mode 100755 index 000000000..33a222192 --- /dev/null +++ b/scripts/rknn/build_runtime_probe.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + echo "Usage: $0 [output-dir]" >&2 +} + +if [[ $# -lt 1 || $# -gt 2 ]]; then + usage + exit 2 +fi + +runtime_root="$(cd "$1" && pwd)" +output_dir="${2:-$PWD/build/rknn-runtime-probe}" +cxx="${CXX:-aarch64-linux-gnu-g++}" + +header="$runtime_root/include/rknn_api.h" +library="$runtime_root/lib/librknnrt.so" +source_file="$(cd "$(dirname "$0")/../.." && pwd)/tools/rknn/rknn_runtime_probe.cc" + +for required in "$header" "$library" "$source_file"; do + if [[ ! -f "$required" ]]; then + echo "Missing build input: $required" >&2 + exit 1 + fi +done + +if ! command -v "$cxx" >/dev/null 2>&1; then + echo "Cross compiler not found: $cxx" >&2 + exit 1 +fi + +install -d "$output_dir/bin" "$output_dir/lib" +"$cxx" -std=c++17 -O2 -Wall -Wextra -Werror \ + -I"$runtime_root/include" \ + "$source_file" \ + -L"$runtime_root/lib" -lrknnrt \ + -Wl,-rpath,'$ORIGIN/../lib' \ + -o "$output_dir/bin/rknn-runtime-probe" +cp -p "$library" "$output_dir/lib/librknnrt.so" + +file "$output_dir/bin/rknn-runtime-probe" "$output_dir/lib/librknnrt.so" +sha256sum "$output_dir/bin/rknn-runtime-probe" "$output_dir/lib/librknnrt.so" diff --git a/scripts/rknn/prepare_offline_env.sh b/scripts/rknn/prepare_offline_env.sh new file mode 100755 index 000000000..36c65d467 --- /dev/null +++ b/scripts/rknn/prepare_offline_env.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + echo "Usage: $0 [venv-dir]" >&2 +} + +if [[ $# -lt 1 || $# -gt 2 ]]; then + usage + exit 2 +fi + +bundle_dir="$(cd "$1" && pwd)" +venv_dir="${2:-$PWD/.venv-rknn-2.3.2}" +wheels_dir="$bundle_dir/wheels-cp310-linux-x86_64" +toolkit_wheel="$bundle_dir/toolkit/rknn_toolkit2-2.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl" + +if [[ "$(uname -m)" != "x86_64" ]]; then + echo "RKNN conversion environment requires an x86_64 Linux host" >&2 + exit 1 +fi + +if [[ "$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')" != "3.10" ]]; then + echo "Python 3.10 is required by this locked environment" >&2 + exit 1 +fi + +for required in "$wheels_dir" "$toolkit_wheel" "$bundle_dir/SHA256SUMS"; do + if [[ ! -e "$required" ]]; then + echo "Missing offline artifact: $required" >&2 + exit 1 + fi +done + +( + cd "$bundle_dir" + sha256sum --check SHA256SUMS +) + +python3 -m venv "$venv_dir" +# shellcheck disable=SC1091 +source "$venv_dir/bin/activate" + +python -m pip install --no-index --find-links "$wheels_dir" \ + "$wheels_dir/torch-2.0.1+cpu-cp310-cp310-linux_x86_64.whl" +python -m pip install --no-index --find-links "$wheels_dir" "$toolkit_wheel" + +python - <<'PY' +import numpy +import onnx +import onnxruntime +import torch +from rknn.api import RKNN + +print("RKNN environment ready") +print("numpy", numpy.__version__) +print("onnx", onnx.__version__) +print("onnxruntime", onnxruntime.__version__) +print("torch", torch.__version__) +print("rknn", RKNN) +PY diff --git a/scripts/rknn/verify_device.sh b/scripts/rknn/verify_device.sh new file mode 100755 index 000000000..19691af46 --- /dev/null +++ b/scripts/rknn/verify_device.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [[ "$(uname -m)" != "aarch64" ]]; then + echo "Expected aarch64 target, got $(uname -m)" >&2 + exit 1 +fi + +echo "kernel=$(uname -r)" +echo "model=$(tr -d '\0' /dev/null || echo unknown)" + +driver_line="$(dmesg 2>/dev/null | grep -i 'Initialized rknpu' | tail -1 || true)" +echo "driver=${driver_line:-unavailable}" + +if [[ -r /usr/lib/librknnrt.so ]]; then + system_runtime="$(strings /usr/lib/librknnrt.so | grep -m1 'librknnrt version' || true)" + echo "system_runtime=${system_runtime:-unknown}" + echo "system_runtime_sha256=$(sha256sum /usr/lib/librknnrt.so | awk '{print $1}')" +else + echo "system_runtime=missing" +fi + +for load_path in /sys/kernel/debug/rknpu/load /sys/kernel/debug/rknpu/load_balance; do + if [[ -r "$load_path" ]]; then + echo "npu_load[$load_path]=$(tr '\n' ' ' <"$load_path")" + fi +done + +for freq_path in /sys/class/devfreq/*npu*/cur_freq /sys/class/devfreq/*npu*/max_freq; do + if [[ -r "$freq_path" ]]; then + echo "$(basename "$freq_path")[$freq_path]=$(cat "$freq_path")" + fi +done diff --git a/scripts/run-python.mjs b/scripts/run-python.mjs new file mode 100644 index 000000000..691f0f202 --- /dev/null +++ b/scripts/run-python.mjs @@ -0,0 +1,45 @@ +#!/usr/bin/env node + +import { spawnSync } from 'node:child_process'; + +const scriptArgs = process.argv.slice(2); +if (scriptArgs.length === 0) { + console.error('Usage: node scripts/run-python.mjs [args...]'); + process.exit(2); +} + +const configuredPython = process.env.PYTHON?.trim(); +const candidates = configuredPython + ? [[configuredPython, []]] + : process.platform === 'win32' + ? [['py', ['-3']], ['python', []], ['python3', []]] + : [['python3', []], ['python', []]]; + +for (const [executable, prefixArgs] of candidates) { + const probe = spawnSync(executable, [...prefixArgs, '--version'], { + encoding: 'utf8', + windowsHide: true, + }); + if (probe.status !== 0) continue; + + const result = spawnSync(executable, [...prefixArgs, ...scriptArgs], { + stdio: 'inherit', + windowsHide: true, + }); + if (result.error) { + console.error(`Failed to run ${executable}: ${result.error.message}`); + process.exit(1); + } + if (result.signal) { + console.error(`${executable} terminated by signal ${result.signal}`); + process.exit(1); + } + process.exit(result.status ?? 1); +} + +console.error( + configuredPython + ? `PYTHON does not name a working Python 3 interpreter: ${configuredPython}` + : 'Python 3 was not found. Install Python 3 or set PYTHON to its executable path.', +); +process.exit(1); diff --git a/scripts/run_start.sh b/scripts/run_start.sh index a30e2156a..c6f12a317 100644 --- a/scripts/run_start.sh +++ b/scripts/run_start.sh @@ -26,6 +26,13 @@ if [ -z "${INSTALLPATH}" ]; then cosmo_log "$logTag" "INSTALLPATH=${INSTALLPATH}" "$logFile" fi +# Keep mutable runtime data separate from packaged, read-only resources. The +# application root must follow the actual installation path, including +# side-by-side validation installs, instead of silently falling back to the +# production default when INSTALLPATH is overridden. +export COSMO_DATA_DIR +export COSMO_APP_DATA_DIR="${COSMO_APP_DATA_DIR:-${INSTALLPATH}}" + if [ "$1" != "start" ]; then cosmo_log "$logTag" "Unsupported action: [$1], use 'start'" "$logFile" exit 1 @@ -42,6 +49,19 @@ case "${PLTFORM_TYPE}" in esac cosmo_log "$logTag" "Install path=${INSTALLPATH}, platform=${PLTFORM_TYPE}" "$logFile" +# On Rockchip kernels debugfs itself is root-only even though the NPU load file +# is read-only. Prepare a narrow bind mount when startup has sufficient rights; +# metric failure must not prevent the inference service from starting. +if [ -x "${SCRIPT_DIR}/prepare_rknpu_metrics.sh" ]; then + if rknpu_metrics_status="$("${SCRIPT_DIR}/prepare_rknpu_metrics.sh" 2>&1)"; then + if [ -n "${rknpu_metrics_status}" ]; then + cosmo_log "$logTag" "${rknpu_metrics_status}" "$logFile" + fi + else + cosmo_log "$logTag" "WARNING: ${rknpu_metrics_status}" "$logFile" + fi +fi + # Set multicast options sysctl -w net.ipv4.igmp_max_memberships=20 2>/dev/null || true @@ -53,10 +73,28 @@ export LD_LIBRARY_PATH="${IED_LIB}:${LD_LIBRARY_PATH:-}:/usr/lib" BINPATH="${INSTALLPATH}/bin" NGINX_PREFIX="${BINPATH}/nginx_conf" NGINX_CONF="${NGINX_PREFIX}/conf/nginx.conf" +NGINX_UPSTREAM_CONF="${NGINX_PREFIX}/conf/conf.d/default.conf" + +export COSMO_HTTP_PORT="${COSMO_HTTP_PORT:-8000}" +export COSMO_WEBSOCKET_PORT="${COSMO_WEBSOCKET_PORT:-9000}" + +# Validate the reverse-proxy/backend contract before stopping the currently +# running service. A bad override or stale Nginx config must fail closed. +if ! port_contract="$(verify_nginx_engine_port_contract "$NGINX_UPSTREAM_CONF" \ + "$COSMO_HTTP_PORT" "$COSMO_WEBSOCKET_PORT" 2>&1)"; then + cosmo_log "$logTag" "Port contract check failed: ${port_contract}" "$logFile" + exit 1 +fi +cosmo_log "$logTag" "Port contract OK: ${port_contract}" "$logFile" # Stop all running processes before starting (including nginx) cosmo_log "$logTag" "Stopping all running processes before start..." "$logFile" -"${INSTALLPATH}/scripts/stop.sh" +TRUSTED_STOP_SCRIPT="${COSMO_TRUSTED_STOP_SCRIPT:-${INSTALLPATH}/scripts/stop.sh}" +if [ ! -f "${TRUSTED_STOP_SCRIPT}" ] || [ ! -x "${TRUSTED_STOP_SCRIPT}" ]; then + cosmo_log "$logTag" "Stop script is unavailable" "$logFile" + exit 1 +fi +"${TRUSTED_STOP_SCRIPT}" # Add iptables rule (idempotent - skips if already exists) if hash iptables 2>/dev/null; then @@ -74,11 +112,13 @@ fi cd "${BINPATH}" || exit 1 -# SRS streaming environment -export COSMO_STREAM_PLAY_MODE=srs -export COSMO_STREAM_RTMP_BASE=rtmp://127.0.0.1:1936/live -export COSMO_STREAM_RTC_API_PORT=1985 -export COSMO_STREAM_HTTP_PORT=18088 +# SRS streaming environment. Deployment-specific values (for example the +# deterministic HTTP-FLV path used by the macOS Preview) take precedence over +# these defaults. +export COSMO_STREAM_PLAY_MODE="${COSMO_STREAM_PLAY_MODE:-srs}" +export COSMO_STREAM_RTMP_BASE="${COSMO_STREAM_RTMP_BASE:-rtmp://127.0.0.1:1936/live}" +export COSMO_STREAM_RTC_API_PORT="${COSMO_STREAM_RTC_API_PORT:-1985}" +export COSMO_STREAM_HTTP_PORT="${COSMO_STREAM_HTTP_PORT:-18088}" # Start nginx cosmo_log "$logTag" "Starting nginx..." "$logFile" diff --git a/scripts/smoke-benchmark-pages.mjs b/scripts/smoke-benchmark-pages.mjs new file mode 100644 index 000000000..b6d22549d --- /dev/null +++ b/scripts/smoke-benchmark-pages.mjs @@ -0,0 +1,79 @@ +import { existsSync, readFileSync } from 'node:fs'; +import { dirname, join, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const repositoryRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +const distRoot = resolve(repositoryRoot, process.argv[2] ?? 'docs/.vitepress/dist'); +const benchmarkRoot = join(distRoot, 'benchmarks', 'scenario-bench', 'v1.1'); +const platforms = ['bm1688', 'cv186x', 'rk3576']; +const workloads = ['single-detector', 'dual-detector', 'vlm-observation']; +const failures = []; +const expectedReports = ['report.html', 'report.zh-CN.html']; + +for (const platform of platforms) { + expectedReports.push(`results/${platform}/report.html`, `results/${platform}/report.zh-CN.html`); + for (const workload of workloads) { + expectedReports.push( + `results/${platform}/${workload}/report.html`, + `results/${platform}/${workload}/report.zh-CN.html`, + ); + } +} + +for (const relative of expectedReports) { + const file = join(benchmarkRoot, ...relative.split('/')); + if (!existsSync(file)) { + failures.push(`${relative}: generated report is missing`); + continue; + } + const html = readFileSync(file, 'utf8'); + if (!/]*>/iu.test(html) || !/[^<]+<\/title>/iu.test(html)) { + failures.push(`${relative}: generated file is not a complete HTML report`); + } +} + +for (const main of ['report.html', 'report.zh-CN.html']) { + const file = join(benchmarkRoot, main); + if (!existsSync(file)) continue; + const html = readFileSync(file, 'utf8'); + const reportName = main === 'report.zh-CN.html' ? 'report.zh-CN.html' : 'report.html'; + for (const platform of platforms) { + for (const workload of workloads) { + const target = `results/${platform}/${workload}/${reportName}`; + if (!html.includes(`href="${target}"`)) { + failures.push(`${main}: missing standalone-report link ${target}`); + } else if (!existsSync(join(benchmarkRoot, ...target.split('/')))) { + failures.push(`${main}: standalone-report target is missing ${target}`); + } + } + } +} + +for (const platform of platforms) { + for (const reportName of ['report.html', 'report.zh-CN.html']) { + const relative = `results/${platform}/${reportName}`; + const html = readFileSync(join(benchmarkRoot, ...relative.split('/')), 'utf8'); + for (const workload of workloads) { + const target = `${workload}/${reportName}`; + if (!html.includes(`href="${target}"`)) { + failures.push(`${relative}: missing workload-report link ${target}`); + } + } + } +} + +for (const relative of expectedReports) { + const html = readFileSync(join(benchmarkRoot, ...relative.split('/')), 'utf8'); + const tables = html.match(/<table\b/giu)?.length ?? 0; + const wrappers = html.match(/<div class="table"/giu)?.length ?? 0; + if (tables !== wrappers) failures.push(`${relative}: ${tables} table(s) but ${wrappers} responsive wrapper(s)`); + if (!html.includes('class="report-nav"')) failures.push(`${relative}: report navigation is missing`); +} + +if (failures.length > 0) { + console.error(`Benchmark page smoke test failed with ${failures.length} issue(s):`); + for (const failure of failures) console.error(`- ${failure}`); + process.exit(1); +} + +console.log(`Benchmark page smoke test passed: ${expectedReports.length} bilingual rendered reports, responsive tables, and cross-report navigation.`); diff --git a/scripts/start.sh b/scripts/start.sh old mode 100644 new mode 100755 index e7e21873a..4fa8854f7 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -1,214 +1,98 @@ #!/bin/bash -set -e +set -euo pipefail -# Upgrade orchestrator - log rotation, OTA upgrade detection, MD5 verify, install, start. -# Called by inte_run_start.sh at system boot. +IFS=$' \t\n' +PATH='/usr/sbin:/usr/bin:/sbin:/bin' +export IFS PATH -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +# Permanent MD5-package upgrade orchestrator. Open and Protected editions use +# this same lifecycle on every upgrade; model authorization is independent. +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" # shellcheck source=common.sh . "${SCRIPT_DIR}/common.sh" -if [ -z "${INSTALLPATH}" ]; then - INSTALLPATH="$(cd "${SCRIPT_DIR}/../" && pwd)" - echo "INSTALLPATH=${INSTALLPATH}" -fi - -# Ensure all runtime directories exist ensure_runtime_dirs +action="${1:-}" +log_file="${COSMO_LOG_DIR}/INTE_RUN_now.1" +log_tag='INTE_RUN' -# Rotate nginx logs -mv -f "${COSMO_LOG_DIR}/nginx_access.log" "${COSMO_LOG_DIR}/nginx_access_last.log" 2>/dev/null || true -mv -f "${COSMO_LOG_DIR}/nginx_error.log" "${COSMO_LOG_DIR}/nginx_error_last.log" 2>/dev/null || true - -# ── Log rotation ── -# Maintains up to 10 rotated log files: INTE_RUN.1 .. INTE_RUN.10 -# The current active log is always named INTE_RUN_now.<N> -nowLogFileDefault="${COSMO_LOG_DIR}/INTE_RUN_now.1" -nowLogFile="$nowLogFileDefault" - -getNowFile() { - local latest="" - for f in "${COSMO_LOG_DIR}"/INTE_RUN_now.*; do - [ -f "$f" ] && latest="$f" - done - if [ -n "$latest" ]; then - nowLogFile="$latest" - return 0 - fi - return 1 -} - -getNowFile || true -nowFileIndex="${nowLogFile##*.}" -nextFileIndex=$((nowFileIndex + 1)) - -if [ "$nextFileIndex" -gt 10 ]; then - nextFileIndex=1 -fi - -if [ -f "${nowLogFile}" ]; then - mv -f "$nowLogFile" "${COSMO_LOG_DIR}/INTE_RUN.$nowFileIndex" - nowLogFile="${COSMO_LOG_DIR}/INTE_RUN_now.$nextFileIndex" -fi - -echo "Log file: $nowLogFile" - -logTag="INTE_RUN" -logFile="$nowLogFile" - -action="$1" - -cosmo_log "$logTag" "In start.sh, action=${action}" "$logFile" - -# Clean previous upgrade sign, convert HW upgrade sign if present -rm -f "$COSMO_UPGRADE_SIGN" -if [ -f "${COSMO_HW_UPGRADE_SIGN}" ]; then - # Convert HW upgrade marker to upgrade-success marker for MQTT reporting - mv -f "$COSMO_HW_UPGRADE_SIGN" "$COSMO_UPGRADE_SIGN" - cosmo_log "$logTag" "HW upgrade detected, marker converted." "$logFile" -fi - -# Handle stop action -if [ "$action" = "stop" ]; then - "${INSTALLPATH}/scripts/stop.sh" - cosmo_log "$logTag" "Stop action completed." "$logFile" +if [ "$action" = stop ]; then + "${SCRIPT_DIR}/stop.sh" exit 0 fi +if [ "$action" != start ]; then + cosmo_log "$log_tag" "Unsupported action: ${action}" "$log_file" + exit 2 +fi -# ── OTA upgrade detection ── -TARGZ_SUFFIX="tar.gz" -INSTALL_TYPE="" -EXIST_IF="unexists" -DIRECTORY_STATIC="${COSMO_UPGRADE_DIR}" -DIRECTORY_SHELL="${INSTALLPATH}/scripts/" -START_SHELL_PATH="${INSTALLPATH}/scripts/run_start.sh" - -# Regex pattern for full package name -# Example: cosmo-V1.1.0-52d08574819464a735d4b0a90f26c924.tar.gz -TARGZ_PATTERN='^cosmo-[Vv][0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}-[0-9a-fA-F]{32}\.tar\.gz$' - -# Execute run_start.sh and exit -RUN() { - cosmo_log "$logTag" "[RUN] Before starting run_start.sh" "$logFile" - rm -rf "${DIRECTORY_STATIC:?}"/* - if [ "$action" = "start" ]; then - cd "$DIRECTORY_SHELL" || exit 1 - cosmo_log "$logTag" "[RUN] Executing $START_SHELL_PATH" "$logFile" - sh "$START_SHELL_PATH" start "$logFile" - fi - cosmo_log "$logTag" "Script ended." "$logFile" - exit 0 -} - -# Check the legality of package name -# $1: filename string, $2: regex pattern -checkFileName() { - cosmo_log "$logTag" "Checking filename legality: $1" "$logFile" - local regex_ret - regex_ret=$(echo "$1" | grep -E "$2") || true - if [ -n "${regex_ret}" ]; then - cosmo_log "$logTag" "Valid filename." "$logFile" - return 0 - else - cosmo_log "$logTag" "$1 file format error!" "$logFile" - return 1 - fi +run_active() { + rm -rf -- "${COSMO_UPGRADE_DIR:?}/"* + cd "${COSMO_INSTALL_DIR}/scripts" + INSTALLPATH="$COSMO_INSTALL_DIR" exec "${COSMO_INSTALL_DIR}/scripts/run_start.sh" start "$log_file" } -# Validate that extracted directory has the expected package layout -hasUpgradePackageLayout() { - local root="$1" - for dir in bin files font scripts web; do - if [ ! -d "$root/$dir" ]; then - cosmo_log "$logTag" "Missing required package directory: $root/$dir" "$logFile" - return 1 - fi - done - return 0 +is_compatible_archive_name() { + printf '%s\n' "$1" | + grep -Eq '^cosmo-[Vv][0-9]+\.[0-9]+\.[0-9]+-[0-9a-fA-F]{32}\.tar\.gz$' } -if [ ! -d "$DIRECTORY_STATIC" ]; then - RUN - # NOTE: RUN() calls exit, code below is unreachable -fi - -# Scan for upgrade package -cosmo_log "$logTag" "Checking for upgrade package..." "$logFile" -for FILENAME_WHOLE in "$DIRECTORY_STATIC"/*; do - FILE_NAME_WITHOUT_PATH=$(basename "${FILENAME_WHOLE}") - if [ "${FILE_NAME_WITHOUT_PATH}" != "*" ] && echo "$FILE_NAME_WITHOUT_PATH" | grep -q "\.${TARGZ_SUFFIX}$"; then - if checkFileName "$FILE_NAME_WITHOUT_PATH" "$TARGZ_PATTERN"; then - INSTALL_TYPE="install" - EXIST_IF="exists" - break - fi +archive='' +archive_count=0 +for candidate in "${COSMO_UPGRADE_DIR}"/*.tar.gz; do + [ -f "$candidate" ] || continue + if is_compatible_archive_name "$(basename "$candidate")"; then + archive="$candidate" + archive_count=$((archive_count + 1)) fi done -cosmo_log "$logTag" "INSTALL_TYPE: ${INSTALL_TYPE}" "$logFile" - -if [ "$EXIST_IF" = "exists" ]; then - cosmo_log "$logTag" "Upgrade package found: $FILENAME_WHOLE" "$logFile" -else - cosmo_log "$logTag" "No upgrade package found, starting normally." "$logFile" - RUN +if [ "$archive_count" -eq 0 ]; then + run_active fi - -# ── MD5 verification ── -cosmo_log "$logTag" "Verifying MD5 checksum..." "$logFile" -MD5_VALUE_IN_FILENAME="${FILENAME_WHOLE%.tar.gz}" -MD5_VALUE_IN_FILENAME="${MD5_VALUE_IN_FILENAME##*-}" -MD5_VALUE_IN_FILENAME=$(echo "$MD5_VALUE_IN_FILENAME" | tr 'A-F' 'a-f') -cosmo_log "$logTag" "MD5 from filename: $MD5_VALUE_IN_FILENAME" "$logFile" - -REAL_MD5_VALUE=$(/usr/bin/md5sum "${FILENAME_WHOLE}") -REAL_MD5_VALUE="${REAL_MD5_VALUE:0:${#MD5_VALUE_IN_FILENAME}}" -cosmo_log "$logTag" "MD5 computed: $REAL_MD5_VALUE" "$logFile" - -if [ "$MD5_VALUE_IN_FILENAME" = "$REAL_MD5_VALUE" ]; then - cosmo_log "$logTag" "MD5 verified. Proceeding with upgrade..." "$logFile" -else - cosmo_log "$logTag" "MD5 mismatch! Discarding package." "$logFile" - RUN +if [ "$archive_count" -ne 1 ]; then + cosmo_log "$log_tag" "Upgrade directory must contain exactly one compatible archive" "$log_file" + run_active fi -# Stop all processes before upgrade -cosmo_log "$logTag" "Stopping processes for upgrade..." "$logFile" -"${INSTALLPATH}/scripts/stop.sh" - -# Extract upgrade package -cosmo_log "$logTag" "Extracting upgrade package..." "$logFile" -tar -zxf "$FILENAME_WHOLE" -C "$DIRECTORY_STATIC" +expected_md5="${archive%.tar.gz}" +expected_md5="${expected_md5##*-}" +expected_md5="$(printf '%s' "$expected_md5" | tr 'A-F' 'a-f')" +actual_md5="$(md5sum -- "$archive")" +actual_md5="${actual_md5%% *}" +if [ "$actual_md5" != "$expected_md5" ]; then + cosmo_log "$log_tag" "Upgrade archive MD5 mismatch" "$log_file" + run_active +fi -# Detect package layout (flat or nested directory) -if hasUpgradePackageLayout "$DIRECTORY_STATIC"; then - PACKAGE_ROOT="$DIRECTORY_STATIC" -else - # Find the top-level directory extracted by tar - UNZIP_DIRNAME="" - for d in "$DIRECTORY_STATIC"/*/; do - if [ -d "$d" ]; then - UNZIP_DIRNAME="$(basename "$d")" +package_root='' +for candidate in "${COSMO_UPGRADE_DIR}"/*; do + [ -d "$candidate" ] || continue + valid=yes + for directory in bin files font lib scripts web; do + if [ ! -d "${candidate}/${directory}" ]; then + valid=no break fi done - PACKAGE_ROOT="$DIRECTORY_STATIC/$UNZIP_DIRNAME" - if ! hasUpgradePackageLayout "$PACKAGE_ROOT"; then - cosmo_log "$logTag" "Upgrade package layout error, discarding." "$logFile" - RUN + if [ "$valid" = yes ]; then + if [ -n "$package_root" ]; then + cosmo_log "$log_tag" "Upgrade directory contains multiple package roots" "$log_file" + run_active + fi + package_root="$candidate" fi -fi -cosmo_log "$logTag" "PACKAGE_ROOT: $PACKAGE_ROOT" "$logFile" -cd "$PACKAGE_ROOT" || exit 1 - -cosmo_log "$logTag" "Extraction complete." "$logFile" +done -# Run install script from the upgrade package -cosmo_log "$logTag" "Running install.sh from upgrade package..." "$logFile" -cd "$PACKAGE_ROOT/scripts/" || exit 1 -sh "$PACKAGE_ROOT/scripts/install.sh" "$logFile" -cosmo_log "$logTag" "install.sh completed." "$logFile" +if [ -z "$package_root" ] || [ ! -x "${package_root}/scripts/install.sh" ]; then + cosmo_log "$log_tag" "Compatible package root or installer is missing" "$log_file" + run_active +fi -# Start services -RUN +cosmo_log "$log_tag" "Installing compatible package $(basename "$archive")" "$log_file" +"${COSMO_INSTALL_DIR}/scripts/stop.sh" +"${package_root}/scripts/install.sh" "$log_file" +mkdir -p -- "$(dirname "$COSMO_UPGRADE_SIGN")" +: >"$COSMO_UPGRADE_SIGN" +sync +run_active diff --git a/scripts/stop.sh b/scripts/stop.sh index a8fea4fc3..527809f26 100644 --- a/scripts/stop.sh +++ b/scripts/stop.sh @@ -1,4 +1,8 @@ #!/bin/bash +set -eu +IFS=$' \t\n' +PATH='/usr/sbin:/usr/bin:/sbin:/bin' +export IFS PATH # Stop managed processes gracefully (SIGTERM first, then SIGKILL) PROC_LIST="cosmo-engine srs nginx" @@ -17,6 +21,9 @@ graceful_timeout="${COSMO_STOP_TIMEOUT_SECONDS:-15}" case "$graceful_timeout" in ''|*[!0-9]*) graceful_timeout=15 ;; esac +if [ "$graceful_timeout" -lt 1 ] || [ "$graceful_timeout" -gt 60 ]; then + graceful_timeout=15 +fi elapsed=0 while [ "$elapsed" -lt "$graceful_timeout" ]; do @@ -42,3 +49,25 @@ for proc in $PROC_LIST; do kill -9 $pids 2>/dev/null || true fi done + +# A successful stop result is a migration security boundary. Do not let the +# release transaction move any facade while a managed process can still be +# executing through the legacy tree. +force_elapsed=0 +while [ "$force_elapsed" -lt 5 ]; do + any_running=0 + for proc in $PROC_LIST; do + if pidof "$proc" >/dev/null 2>&1; then + any_running=1 + break + fi + done + if [ "$any_running" -eq 0 ]; then + exit 0 + fi + sleep 1 + force_elapsed=$((force_elapsed + 1)) +done + +echo "Managed processes remain after forced shutdown; refusing release migration" >&2 +exit 1 diff --git a/scripts/validate-public-v1.1-multistream-benchmark.mjs b/scripts/validate-public-v1.1-multistream-benchmark.mjs new file mode 100644 index 000000000..d07b2be15 --- /dev/null +++ b/scripts/validate-public-v1.1-multistream-benchmark.mjs @@ -0,0 +1,191 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import crypto from 'node:crypto'; +import { fileURLToPath } from 'node:url'; + +const here = path.dirname(fileURLToPath(import.meta.url)); +const workspace = path.resolve(here, '..'); +const root = path.join(workspace, 'docs', 'benchmarks', 'scenario-bench', 'v1.1'); +const staticAssetCopier = path.join(workspace, 'scripts', 'copy-static-benchmark-assets.mjs'); +const repositoryModelRoots = { + bm1688: path.join(workspace, 'data', 'resource', 'aiboxresource_bm1688', 'models'), + cv186x: path.join(workspace, 'data', 'resource', 'aiboxresource_cv186x', 'models'), +}; + +const errors = []; +const required = [ + 'README.md', 'README.zh-CN.md', 'RELEASE-CHECKLIST.md', 'release-manifest.json', + 'methodology.md', 'LICENSES.md', 'SHA256SUMS', 'report.html', 'report.zh-CN.html', + 'assets/capacity-overview.svg', 'assets/throughput-curves.svg', 'assets/resource-peaks.svg', + 'assets/capacity-overview.zh-CN.svg', 'assets/throughput-curves.zh-CN.svg', 'assets/resource-peaks.zh-CN.svg', + 'dataset/dataset-card.md', 'models/model-card.md', 'results/index.json', 'results/workload-matrix.json', +]; + +for (const platform of ['bm1688', 'cv186x', 'rk3576']) { + required.push( + `environments/${platform}.json`, + `models/${platform}.json`, + `results/${platform}/summary.json`, + `results/${platform}/report.html`, + `results/${platform}/report.zh-CN.html`, + ); + for (const workload of ['single-detector', 'dual-detector', 'vlm-observation']) { + for (const file of ['summary.json', 'metrics.json', 'command.txt', 'test.log', 'report.html', 'report.zh-CN.html']) { + required.push(`results/${platform}/${workload}/${file}`); + } + } +} + +for (const relative of required) { + if (!fs.existsSync(path.join(root, relative))) errors.push(`missing required file: ${relative}`); +} + +const manifest = readJson(path.join(root, 'release-manifest.json')); +if (manifest.manifestStatus !== 'frozen-publication-ready') errors.push('manifest status must be frozen-publication-ready'); +if (manifest.doNotPublish !== false) errors.push('doNotPublish must be false for the final public benchmark'); +if (manifest.release?.publicationState !== 'prepared-not-published') errors.push('manifest publicationState must be prepared-not-published before external publication'); +if (manifest.qualification?.benchmarkReadyToPublish !== true) errors.push('benchmarkReadyToPublish must be true'); +if (manifest.qualification?.productReleaseQualificationComplete !== false) errors.push('productReleaseQualificationComplete must remain false while declared product evidence is outstanding'); +if (!/^[0-9a-f]{40}$/.test(manifest.sourceBaseline?.commit ?? '')) errors.push('source commit is not frozen'); +if (!/^[0-9a-f]{40}$/.test(manifest.sourceBaseline?.tree ?? '')) errors.push('source tree is not frozen'); +if (manifest.repositoryIntegration?.targetCommitAtPreparation !== manifest.sourceBaseline?.commit) errors.push('release-branch preparation commit does not match source baseline'); +if (manifest.repositoryIntegration?.targetTreeAtPreparation !== manifest.sourceBaseline?.tree) errors.push('release-branch preparation tree does not match source baseline'); +if (!/^[0-9a-f]{64}$/.test(manifest.dataset?.sha256 ?? '')) errors.push('dataset SHA-256 is missing'); +if (!/^[0-9a-f]{64}$/.test(manifest.packageArtifacts?.open?.sha256 ?? '')) errors.push('BM1688/CV186X Open package SHA-256 is missing'); +if (!/^[0-9a-f]{64}$/.test(manifest.packageArtifacts?.open?.engineSha256 ?? '')) errors.push('BM1688/CV186X running engine SHA-256 is missing'); +if (manifest.packageArtifacts?.open?.profile !== 'public-runtime') errors.push('Open package profile is not public-runtime'); + +for (const file of walk(root).filter((entry) => entry.endsWith('.json'))) { + try { readJson(file); } catch (error) { errors.push(`invalid JSON: ${relative(file)} (${error.message})`); } +} + +for (const platform of ['bm1688', 'cv186x']) { + const identities = readJson(path.join(root, 'models', `${platform}.json`)).models; + for (const publicId of ['person-detector', 'safety-helmet-classifier']) { + const identity = identities.find((model) => model.publicId === publicId); + if (!identity) { errors.push(`${platform} model identity is missing: ${publicId}`); continue; } + const repositoryPath = identity.repositoryPath ?? ''; + const modelPath = path.resolve(workspace, ...repositoryPath.split('/'), 'model.nn'); + const expectedRepositoryPrefix = `data/resource/aiboxresource_${platform}/models/`; + const modelPrefix = `${path.resolve(repositoryModelRoots[platform])}${path.sep}`; + if (!repositoryPath.startsWith(expectedRepositoryPrefix) || !modelPath.startsWith(modelPrefix)) { + errors.push(`${platform} repository model path is invalid: ${publicId}`); + continue; + } + if (!fs.existsSync(modelPath)) { errors.push(`${platform} repository model is missing: ${publicId}`); continue; } + const bytes = fs.readFileSync(modelPath); + const actual = crypto.createHash('sha256').update(bytes).digest('hex'); + if (actual !== identity.sha256) errors.push(`${platform} repository model hash mismatch: ${publicId}`); + if (bytes.length !== identity.sizeBytes) errors.push(`${platform} repository model size mismatch: ${publicId}`); + } +} + +const forbidden = [ + [/\bhost(?:33|55|101)\b/gi, 'internal host alias'], + [/\b(?:16064|11099|41773|7463|67093|78510)\b/g, 'internal algorithm ID'], + [/\bLX\d{8,}\b/g, 'internal channel ID'], + [/\b192\.168\.\d{1,3}\.\d{1,3}\b/g, 'private device address'], + [/[A-Za-z]:[\\/](?:WorkSpace|Users)[\\/]/g, 'local absolute path'], + [/\b(?:admin|root|linaro)\s+(?:password|密码|passwd)\s*[:=]\s*[^\s<]+/gi, 'credential-like text'], + [/\b20230808003\b/g, 'device serial number'], + [/\b(?:5\.10\.4(?:-[a-z0-9-]+)?|6\.1\.118)\b/gi, 'non-public kernel identity'], + [/"kernel(?:Build)?"\s*:/gi, 'public kernel field'], + [/<th>Kernel<\/th>|OS\s*\/\s*Kernel/gi, 'public kernel column'], +]; + +for (const file of walk(root)) { + if (path.basename(file) === 'SHA256SUMS') continue; + if (!textFile(file)) continue; + const text = fs.readFileSync(file, 'utf8'); + for (const [pattern, label] of forbidden) { + pattern.lastIndex = 0; + if (pattern.test(text)) errors.push(`${label} found in ${relative(file)}`); + } +} + +const redistributedBinaryExtensions = new Set(['.mp4', '.mov', '.mkv', '.avi', '.nn', '.bmodel', '.rknn', '.rkllm', '.onnx']); +for (const file of walk(root)) { + if (redistributedBinaryExtensions.has(path.extname(file).toLowerCase())) errors.push(`model or video binary must not be redistributed: ${relative(file)}`); +} + +const checksumPath = path.join(root, 'SHA256SUMS'); +if (fs.existsSync(checksumPath)) { + for (const line of fs.readFileSync(checksumPath, 'utf8').split(/\r?\n/).filter(Boolean)) { + const match = line.match(/^([0-9a-f]{64}) (.+)$/); + if (!match) { errors.push(`invalid SHA256SUMS line: ${line}`); continue; } + const checksumTarget = match[2].replaceAll('\\', '/'); + const targetParts = checksumTarget.split('/'); + if (path.isAbsolute(checksumTarget) || targetParts.some((part) => part === '..' || part === '')) { + errors.push(`unsafe checksum target: ${match[2]}`); + continue; + } + const file = path.join(root, ...targetParts); + if (!fs.existsSync(file)) { errors.push(`checksum target missing: ${checksumTarget}`); continue; } + const actual = crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex'); + if (actual !== match[1]) errors.push(`checksum mismatch: ${checksumTarget}`); + } +} + +for (const file of walk(root).filter((entry) => entry.endsWith('.html'))) { + const text = fs.readFileSync(file, 'utf8'); + for (const match of text.matchAll(/(?:href|src)="([^"]+)"/g)) { + const target = match[1]; + if (/^(?:https?:|data:|#)/.test(target)) continue; + const resolved = path.resolve(path.dirname(file), target.split('#')[0]); + if (!fs.existsSync(resolved)) errors.push(`broken HTML asset/link in ${relative(file)}: ${target}`); + } +} + +const zh = fs.readFileSync(path.join(root, 'report.zh-CN.html'), 'utf8'); +for (const marker of ['方法与复现', '测试环境', '单算法容量矩阵', '实验结果:VLM 运行观测', '关联附件', 'assets/capacity-overview.zh-CN.svg', 'assets/throughput-curves.zh-CN.svg', 'assets/resource-peaks.zh-CN.svg']) { + if (!zh.includes(marker)) errors.push(`Chinese report missing marker: ${marker}`); +} +if (!zh.includes('<html lang="zh-CN">')) errors.push('Chinese report lang attribute is incorrect'); +for (const marker of ['results/bm1688/single-detector/report.zh-CN.html', 'results/cv186x/dual-detector/report.zh-CN.html', 'results/rk3576/vlm-observation/report.zh-CN.html', '<th>平台</th><th>板卡</th><th>操作系统</th><th>运行时 / 媒体链路</th>']) { + if (!zh.includes(marker)) errors.push(`Chinese report missing localized marker: ${marker}`); +} + +for (const file of walk(root).filter((entry) => entry.endsWith('.html'))) { + const html = fs.readFileSync(file, 'utf8'); + const tables = html.match(/<table\b/giu)?.length ?? 0; + const wrappers = html.match(/<div class="table"/giu)?.length ?? 0; + if (tables !== wrappers) errors.push(`responsive table wrapper mismatch in ${relative(file)}: ${tables} table(s), ${wrappers} wrapper(s)`); + if (!html.includes('class="report-nav"')) errors.push(`report navigation is missing in ${relative(file)}`); + if (!html.includes('td[data-status="PASS"]')) errors.push(`status styling is missing in ${relative(file)}`); +} + +for (const file of walk(root).filter((entry) => entry.endsWith('.zh-CN.html'))) { + const html = fs.readFileSync(file, 'utf8'); + if (!html.includes('<html lang="zh-CN">')) errors.push(`Chinese attachment lang attribute is incorrect in ${relative(file)}`); +} + +const packageJson = readJson(path.join(workspace, 'package.json')); +if (!fs.existsSync(staticAssetCopier)) errors.push('static benchmark asset copier is missing'); +if (!packageJson.scripts?.['docs:build']?.includes('copy-static-benchmark-assets.mjs')) errors.push('docs:build does not publish static benchmark assets'); +const gitignore = fs.readFileSync(path.join(workspace, '.gitignore'), 'utf8'); +if (!gitignore.includes('!docs/benchmarks/scenario-bench/v1.1/**/*.log')) errors.push('sanitized benchmark logs are not explicitly included by .gitignore'); + +const rkVlm = readJson(path.join(root, 'results', 'rk3576', 'vlm-observation', 'summary.json')); +const expectedRkVlm = [0.100, 0.120, 0.116, 0.115, 0.091, 0.076, 0.063, 0.057]; +const actualRkVlm = rkVlm.steps.map((step) => step.observedEquivalentPerChannelFps); +if (JSON.stringify(actualRkVlm) !== JSON.stringify(expectedRkVlm)) errors.push('RK3576 reviewed equivalent VLM FPS series changed'); +if (rkVlm.steps.some((step) => step.targetFpsPerChannel !== 0.1 || step.fpsGateEnabled !== false)) errors.push('VLM target/gate wording is inconsistent'); + +if (errors.length) { + console.error(`Validation failed (${errors.length}):`); + for (const error of errors) console.error(`- ${error}`); + process.exit(1); +} + +console.log(`Validation passed: ${walk(root).length} files, publication-ready benchmark, checksums, binary-distribution, and public-scrub rules verified.`); + +function walk(dir) { + return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => { + const full = path.join(dir, entry.name); + return entry.isDirectory() ? walk(full) : [full]; + }); +} + +function readJson(file) { return JSON.parse(fs.readFileSync(file, 'utf8')); } +function relative(file) { return path.relative(workspace, file).replaceAll('\\', '/'); } +function textFile(file) { return /\.(?:md|html|json|txt|log|yml|yaml|svg|sh|mjs)$/i.test(file); } diff --git a/scripts/verify_model_guard_v2_sdk.py b/scripts/verify_model_guard_v2_sdk.py new file mode 100644 index 000000000..21c7cd2b2 --- /dev/null +++ b/scripts/verify_model_guard_v2_sdk.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python3 +"""Check that the Model Guard SDK contains the interface CosmoEdge uses.""" + +from __future__ import annotations + +import argparse +import hashlib +import os +import pathlib +import re +import subprocess +import sys +from typing import NoReturn + + +EXPECTED_V2_EXPORTS = { + "CmgV2CloseArtifact@@CMG_2.0", + "CmgV2GetArtifactInfo@@CMG_2.0", + "CmgV2LoadSophonSegment@@CMG_2.0", + "CmgV2OpenArtifact@@CMG_2.0", +} +REQUIRED_HEADER_LINES = { + "#define CMG_V2_ABI_MAJOR UINT32_C(2)", + "#define CMG_V2_ARTIFACT_INFO_SIZE UINT32_C(72)", + "#define CMG_V2_SOPHON_LOAD_OPTIONS_SIZE UINT32_C(16)", +} +REQUIRED_HEADER_FUNCTIONS = ( + "CmgV2OpenArtifact", + "CmgV2GetArtifactInfo", + "CmgV2LoadSophonSegment", + "CmgV2CloseArtifact", +) +ADMISSION_PUBLIC_RUNTIME = "public-runtime" +ADMISSION_PRODUCTION_RELEASE = "production-release" +ADMISSION_TEST_FIXTURE = "test-fixture" +ADMISSION_PROFILES = ( + ADMISSION_PUBLIC_RUNTIME, + ADMISSION_PRODUCTION_RELEASE, + ADMISSION_TEST_FIXTURE, +) +TEST_FIXTURE_MARKER_NAME = "TEST_FIXTURE_DO_NOT_DEPLOY" +TEST_FIXTURE_MARKER_CONTENT = b"COSMO_MODEL_GUARD_V2_TEST_FIXTURE_DO_NOT_DEPLOY\n" + + +def fail(message: str) -> NoReturn: + raise RuntimeError(message) + + +def checked_directory(path: pathlib.Path) -> None: + if not path.is_dir(): + fail(f"SDK directory is missing: {path}") + + +def checked_file( + path: pathlib.Path, + maximum_size: int, + *, + allow_empty: bool = False, +) -> bytes: + try: + data = path.read_bytes() + except OSError as error: + fail(f"cannot read SDK file {path}: {error}") + if (not allow_empty and not data) or len(data) > maximum_size: + fail(f"SDK file size is invalid: {path}") + return data + + +def checked_symlink(path: pathlib.Path, expected_target: str) -> None: + if not path.is_symlink() or os.readlink(path) != expected_target: + fail(f"SDK linker alias is invalid: {path}") + + +def run_tool(tool: pathlib.Path, arguments: list[str]) -> str: + if not tool.is_absolute() or not tool.is_file(): + fail(f"inspection tool is missing: {tool}") + environment = dict(os.environ) + environment["LC_ALL"] = "C" + completed = subprocess.run( + [str(tool), *arguments], + check=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + env=environment, + ) + if completed.returncode != 0: + fail(f"inspection tool failed: {tool.name}") + return completed.stdout + + +def verify_header(header: bytes) -> None: + if not header or len(header) > 128 * 1024 or b"\x00" in header: + fail("Model Guard v2 header size/content rejected") + try: + text = header.decode("utf-8", "strict") + except UnicodeError as error: + raise RuntimeError("Model Guard v2 header is not UTF-8") from error + if not REQUIRED_HEADER_LINES.issubset(set(text.splitlines())): + fail("Model Guard v2 header constants are incompatible") + for function in REQUIRED_HEADER_FUNCTIONS: + if len(re.findall(rf"\b{re.escape(function)}\s*\(", text)) != 1: + fail(f"Model Guard v2 header declaration rejected: {function}") + + +def verify_elf( + library: pathlib.Path, + readelf: pathlib.Path, + nm: pathlib.Path, +) -> None: + header = run_tool(readelf, ["-h", str(library)]) + if re.search(r"^\s*Type:\s+DYN\b", header, re.MULTILINE) is None: + fail("model guard SDK library is not a shared ELF image") + + dynamic = run_tool(readelf, ["-d", str(library)]) + runpaths = re.findall(r"\(RUNPATH\).*\[([^]]+)\]", dynamic) + if runpaths != ["$ORIGIN"]: + fail("model guard SDK RUNPATH must be exactly $ORIGIN") + + symbols = run_tool(nm, ["-D", "--defined-only", str(library)]) + exports = { + fields[2] + for line in symbols.splitlines() + if len(fields := line.split()) == 3 and fields[1] in {"T", "W"} + } + if exports != EXPECTED_V2_EXPORTS: + fail(f"model guard SDK exports are incompatible: {sorted(exports)}") + + +def verify_provision_tool(tool: pathlib.Path, readelf: pathlib.Path) -> None: + header = run_tool(readelf, ["-h", str(tool)]) + if re.search(r"^\s*Type:\s+(?:DYN|EXEC)\b", header, re.MULTILINE) is None: + fail("cosmo-model-provision is not an ELF executable") + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument( + "--admission-profile", choices=ADMISSION_PROFILES, required=True + ) + parser.add_argument("--sdk-root", required=True) + parser.add_argument("--readelf", required=True) + parser.add_argument("--nm", required=True) + arguments = parser.parse_args() + public_runtime = arguments.admission_profile == ADMISSION_PUBLIC_RUNTIME + test_fixture = arguments.admission_profile == ADMISSION_TEST_FIXTURE + + root = pathlib.Path(arguments.sdk_root) + if not root.is_absolute(): + fail("SDK root must be absolute") + include_directory = root / "include" + library_directory = root / "lib" + share_directory = root / "share/cosmo-model-guard" + for directory in (root, include_directory, library_directory): + checked_directory(directory) + + header_path = include_directory / "cosmo_model_guard_v2.h" + library_path = library_directory / "libcosmo_model_guard.so.2.0.0" + header = checked_file(header_path, 128 * 1024) + library = checked_file(library_path, 32 * 1024 * 1024) + checked_symlink( + library_directory / "libcosmo_model_guard.so.2", library_path.name + ) + checked_symlink( + library_directory / "libcosmo_model_guard.so", + "libcosmo_model_guard.so.2", + ) + + marker_path = share_directory / TEST_FIXTURE_MARKER_NAME + marker: bytes | None = None + if marker_path.exists(): + marker = checked_file(marker_path, len(TEST_FIXTURE_MARKER_CONTENT)) + if marker != TEST_FIXTURE_MARKER_CONTENT: + fail("Model Guard SDK test-fixture marker content is invalid") + if test_fixture and marker is None: + fail("test-fixture admission requires the exact non-production SDK marker") + if not test_fixture and marker is not None: + fail( + "Model Guard test fixtures are forbidden for public-runtime and " + "production-release admission" + ) + + provision_path: pathlib.Path | None = None + provision: bytes | None = None + if not public_runtime: + provision_path = root / "bin/cosmo-model-provision" + provision = checked_file(provision_path, 32 * 1024 * 1024) + + verify_header(header) + verify_elf( + library_path, + pathlib.Path(arguments.readelf), + pathlib.Path(arguments.nm), + ) + if provision_path is not None: + verify_provision_tool(provision_path, pathlib.Path(arguments.readelf)) + + print(f"admission_profile={arguments.admission_profile}") + print(f"verified_sdk_root={root}") + print(f"header_sha256={hashlib.sha256(header).hexdigest()}") + print(f"library_sha256={hashlib.sha256(library).hexdigest()}") + if provision is not None: + print(f"provision_tool_sha256={hashlib.sha256(provision).hexdigest()}") + if public_runtime: + print("sdk_profile=public-runtime") + elif test_fixture: + print("sdk_profile=TEST-FIXTURE-DO-NOT-DEPLOY") + else: + print("sdk_profile=production") + return 0 + + +if __name__ == "__main__": + try: + raise SystemExit(main()) + except (OSError, RuntimeError) as error: + print(f"model guard v2 SDK verification failed: {error}", file=sys.stderr) + raise SystemExit(1) diff --git a/scripts/verify_package_contents.py b/scripts/verify_package_contents.py new file mode 100644 index 000000000..b632d11a4 --- /dev/null +++ b/scripts/verify_package_contents.py @@ -0,0 +1,143 @@ +#!/usr/bin/python3 +"""Audit permanent MD5 upgrade packages for the Open and Protected editions.""" + +from __future__ import annotations + +import argparse +import hashlib +import pathlib +import re +import stat +import tarfile + + +class PackageAuditError(RuntimeError): + pass + + +PROFILES = ("public-runtime", "production-release") +REQUIRED_DIRS = {"bin", "files", "font", "lib", "resource", "scripts", "web"} +REQUIRED_EXECUTABLES = { + "bin/cosmo-engine", + "scripts/install.sh", + "scripts/inte_run_start.sh", + "scripts/run_start.sh", + "scripts/start.sh", + "scripts/stop.sh", +} +REQUIRED_FILES = {"bin/version.txt", "scripts/common.sh"} +PRIVATE_MARKERS = ( + b"-----BEGIN PRIVATE KEY-----", + b"-----BEGIN ENCRYPTED PRIVATE KEY-----", + b"-----BEGIN RSA PRIVATE KEY-----", + b"-----BEGIN EC PRIVATE KEY-----", + b"-----BEGIN OPENSSH PRIVATE KEY-----", +) +FORBIDDEN_BASENAMES = { + "commissioning-ed25519.seed", + "device-certificate.bin", + "product-model-key-v1.bin", + "product-pepper-v1.bin", + "release-private-key.o", +} + + +def archive_md5(path: pathlib.Path) -> str: + digest = hashlib.md5(usedforsecurity=False) + with path.open("rb") as stream: + for block in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(block) + return digest.hexdigest() + + +def verify_archive_name(path: pathlib.Path) -> None: + match = re.fullmatch( + r"cosmo-[Vv]\d+\.\d+\.\d+-([0-9a-fA-F]{32})\.tar\.gz", path.name + ) + if match is None or match.group(1).lower() != archive_md5(path): + raise PackageAuditError("archive name must contain its exact MD5 digest") + + +def verify_package(path: pathlib.Path, profile: str) -> None: + if not path.is_absolute() or path.is_symlink() or not path.is_file(): + raise PackageAuditError("archive must be one absolute regular file") + verify_archive_name(path) + entries: dict[str, tarfile.TarInfo] = {} + contents: dict[str, bytes] = {} + root: str | None = None + with tarfile.open(path, "r:gz") as archive: + for member in archive: + parts = pathlib.PurePosixPath(member.name).parts + if not parts or any(part in ("", ".", "..") for part in parts): + raise PackageAuditError(f"unsafe archive member: {member.name}") + root = parts[0] if root is None else root + if parts[0] != root: + raise PackageAuditError("archive must contain exactly one package root") + relative = pathlib.PurePosixPath(*parts[1:]).as_posix() + if not relative or relative == ".": + continue + if relative in entries or not (member.isdir() or member.isreg() or member.issym()): + raise PackageAuditError(f"unsupported or duplicate member: {relative}") + entries[relative] = member + if member.isreg(): + stream = archive.extractfile(member) + if stream is None: + raise PackageAuditError(f"cannot read member: {relative}") + data = stream.read() + contents[relative] = data + if any(marker in data for marker in PRIVATE_MARKERS): + raise PackageAuditError(f"private key material is forbidden: {relative}") + + for directory in REQUIRED_DIRS: + if directory not in entries or not entries[directory].isdir(): + raise PackageAuditError(f"required directory is missing: {directory}") + for filename in REQUIRED_FILES: + if filename not in entries or not entries[filename].isreg(): + raise PackageAuditError(f"required file is missing: {filename}") + for filename in REQUIRED_EXECUTABLES: + entry = entries.get(filename) + if entry is None or not entry.isreg() or not (entry.mode & stat.S_IXUSR): + raise PackageAuditError(f"required executable is missing: {filename}") + + for filename in entries: + if pathlib.PurePosixPath(filename).name.lower() in FORBIDDEN_BASENAMES: + raise PackageAuditError(f"controlled secret is forbidden: {filename}") + if filename.startswith(".release-bootstrap/") or "release_updater" in filename: + raise PackageAuditError(f"obsolete signed-release material is forbidden: {filename}") + + provision = entries.get("bin/cosmo-model-provision") + if profile == "public-runtime" and provision is not None: + raise PackageAuditError("Open package must not contain the provisioning tool") + if profile == "production-release" and ( + provision is None or not provision.isreg() or not (provision.mode & stat.S_IXUSR) + ): + raise PackageAuditError("Protected package requires cosmo-model-provision") + + models = { + name: data + for name, data in contents.items() + if name.startswith("resource/models/") and name.endswith("/model.nn") + } + for name, data in models.items(): + encrypted = data.startswith(b"CEMC") + if profile == "public-runtime" and encrypted: + raise PackageAuditError(f"Open package contains an encrypted preset model: {name}") + if profile == "production-release" and not encrypted: + raise PackageAuditError(f"Protected package contains a plaintext preset model: {name}") + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--archive", required=True) + parser.add_argument("--build-profile", required=True, choices=PROFILES) + arguments = parser.parse_args() + try: + verify_package(pathlib.Path(arguments.archive), arguments.build_profile) + except (OSError, tarfile.TarError, PackageAuditError) as error: + parser.error(str(error)) + print(f"Verified {arguments.build_profile} MD5 upgrade package: {arguments.archive}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/scripts/verify_sophon_open_benchmark_models.py b/scripts/verify_sophon_open_benchmark_models.py new file mode 100644 index 000000000..b82fc0aa3 --- /dev/null +++ b/scripts/verify_sophon_open_benchmark_models.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 +"""Verify platform-scoped copies of the open Sophon benchmark models.""" + +from __future__ import annotations + +import hashlib +import json +import pathlib + + +ROOT = pathlib.Path(__file__).resolve().parents[1] +IDENTITY_ROOT = ROOT / "docs" / "benchmarks" / "scenario-bench" / "v1.1" / "models" +RESOURCE_SETS = { + "bm1688": ROOT / "data" / "resource" / "aiboxresource_bm1688" / "models", + "cv186x": ROOT / "data" / "resource" / "aiboxresource_cv186x" / "models", +} +EXPECTED = { + "prod_BM1688_6047042_YOLOV8n_V1.0.0": { + "public_id": "person-detector", + "sha256": "56b207ef2876da76505e403a049d3c44a411b9fe707ab73dc64f1cd9d9b6c5c8", + "size_bytes": 7_023_600, + "model_type": "yolov8_det", + "algorithm_code": "6047042", + "input_size": [640, 640], + }, + "prod_BM1688_7486163_helmet_V1.0.0": { + "public_id": "safety-helmet-classifier", + "sha256": "33b0fb4bcb29e41a92f9c1c518671aefc69cbf9207934deaba32ca7cd8cd7c8a", + "size_bytes": 6_001_416, + "model_type": "classify", + "algorithm_code": "7486163", + "input_size": [224, 224], + }, +} + + +def fail(message: str) -> None: + raise SystemExit(f"Sophon open-model verification failed: {message}") + + +identities = { + platform: json.loads((IDENTITY_ROOT / f"{platform}.json").read_text(encoding="utf-8"))["models"] + for platform in RESOURCE_SETS +} + +for platform, model_root in RESOURCE_SETS.items(): + for directory, expected in EXPECTED.items(): + root = model_root / directory + model = root / "model.nn" + config_path = root / "config.json" + for path in (model, config_path): + if not path.is_file(): + fail(f"missing {path.relative_to(ROOT)}") + + model_bytes = model.read_bytes() + if not model_bytes.startswith(b"CENN"): + fail(f"{model.relative_to(ROOT)} is not a plaintext Open artifact") + if len(model_bytes) != expected["size_bytes"]: + fail(f"size mismatch for {model.relative_to(ROOT)}") + actual_sha256 = hashlib.sha256(model_bytes).hexdigest() + if actual_sha256 != expected["sha256"]: + fail(f"SHA-256 mismatch for {model.relative_to(ROOT)}") + + config = json.loads(config_path.read_text(encoding="utf-8")) + if config.get("model_type") != expected["model_type"]: + fail(f"model_type mismatch in {platform}/{directory}") + if config.get("algorithm_code") != expected["algorithm_code"]: + fail(f"algorithm_code mismatch in {platform}/{directory}") + models = config.get("models") or [] + if len(models) != 1 or models[0].get("params", {}).get("input_size") != expected["input_size"]: + fail(f"input_size mismatch in {platform}/{directory}") + + identity = next( + (entry for entry in identities[platform] if entry.get("publicId") == expected["public_id"]), + None, + ) + if identity is None: + fail(f"{platform} identity is missing for {expected['public_id']}") + if identity.get("sha256") != actual_sha256: + fail(f"{platform} identity hash mismatch for {expected['public_id']}") + if identity.get("sizeBytes") != len(model_bytes): + fail(f"{platform} identity size mismatch for {expected['public_id']}") + repository_path = model.parent.relative_to(ROOT).as_posix() + if identity.get("repositoryPath") != repository_path: + fail(f"{platform} repository path mismatch for {expected['public_id']}") + +print("Verified 4 platform-scoped Open Sophon model copies and BM1688/CV186X evidence bindings.") diff --git a/src/api/ApiRouter.cc b/src/api/ApiRouter.cc index a3ff15601..269dac2a9 100644 --- a/src/api/ApiRouter.cc +++ b/src/api/ApiRouter.cc @@ -26,6 +26,7 @@ #include "service/media/ILiveStreamService.h" #include "service/media/IVideoFrameCodec.h" #include "service/model/IModelService.h" +#include "service/modelguard/IModelAuthorizationService.h" #include "service/network/IAuthService.h" #include "service/network/INetworkService.h" #include "service/onboarding/IOnboardingService.h" @@ -79,7 +80,8 @@ ApiRouter::ApiRouter(MessageFromType from) service::ServiceRegistry::Instance().Get<service::IConfigNetworkService>(), service::ServiceRegistry::Instance().Get<service::IDeviceInfoService>(), service::ServiceRegistry::Instance().Get<service::ISystemOperationService>(), - service::ServiceRegistry::Instance().Get<service::ITimeService>())), + service::ServiceRegistry::Instance().Get<service::ITimeService>(), + service::ServiceRegistry::Instance().Get<service::IModelAuthorizationService>())), live_stream_handler_(std::make_unique<MessageLiveStreamHandler>( service::ServiceRegistry::Instance().Get<service::ILiveStreamService>())), lib_handler_(std::make_unique<MessageFaceLibHandler>( diff --git a/src/api/ApiRouterRoutes.cc b/src/api/ApiRouterRoutes.cc index 60feb717f..c0034a959 100644 --- a/src/api/ApiRouterRoutes.cc +++ b/src/api/ApiRouterRoutes.cc @@ -197,7 +197,12 @@ void ApiRouter::RegisterSystemRoutes() { ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, QueryDevRestartParam); ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, ResetSystem); ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, ExportFile); + ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, CheckUpgradeSpace); ROUTE_CONTEXT("/gtw/cwai/System/", kAuth, system_handler_, System, Upgrade); + ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, QueryModelAuthorization); + ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, DownloadModelAuthorizationRequest); + file_download_routes_.insert(util::ToLower("/gtw/cwai/System/DownloadModelAuthorizationRequest")); + ROUTE_CONTEXT("/gtw/cwai/System/", kAuth, system_handler_, System, InstallModelAuthorization); ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, QuerySystemLogo); ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, SetSystemLogo); ROUTE("/gtw/cwai/System/", kAuth, system_handler_, System, QueryDeviceStatus); diff --git a/src/api/MessageFaceLibHandler_ModifyPic.cc b/src/api/MessageFaceLibHandler_ModifyPic.cc index e8a7cd89d..115ed25b4 100644 --- a/src/api/MessageFaceLibHandler_ModifyPic.cc +++ b/src/api/MessageFaceLibHandler_ModifyPic.cc @@ -142,7 +142,7 @@ void MessageFaceLibHandler::HandleModifyFacePicUpdate(Lib::MsgModifyFacePicLibRe std::vector<std::string> vRemovePicId; std::vector<std::pair<std::string, std::vector<float>>> faceFeature; - if (!data.retainPictureId.empty() || !data.pictureBase64.empty()) { + if (!data.retainPictureId.empty() || !data.pictureBase64.empty() || !data.pictureData.empty()) { ProcessNewPictures(data, errc, retData, faceFeature, vFacePic); if (errc != util::ErrorEnum::Success) { return; diff --git a/src/api/MessageModelHandler.cc b/src/api/MessageModelHandler.cc index cd864b738..e13310266 100644 --- a/src/api/MessageModelHandler.cc +++ b/src/api/MessageModelHandler.cc @@ -50,10 +50,11 @@ namespace { std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), [](unsigned char value) { return static_cast<char>(std::tolower(value)); }); - const bool is_video = HasAnySuffix(lower_name, {".mp4", ".mkv", ".avi", ".dav"}); - const bool is_model_component = HasAnySuffix(lower_name, {".bmodel", ".onnx", ".txt", ".json"}); - const bool is_model_archive = HasAnySuffix(lower_name, {".zip", ".tgz", ".tar.gz"}); - const int match_count = static_cast<int>(is_video) + static_cast<int>(is_model_component) + + const bool is_video = HasAnySuffix(lower_name, {".mp4", ".mkv", ".avi", ".dav"}); + const bool is_model_component = + HasAnySuffix(lower_name, {".bmodel", ".onnx", ".rknn", ".txt", ".json"}); + const bool is_model_archive = HasAnySuffix(lower_name, {".zip", ".tgz", ".tar.gz"}); + const int match_count = static_cast<int>(is_video) + static_cast<int>(is_model_component) + static_cast<int>(is_model_archive); if (match_count != 1) { return false; diff --git a/src/api/MessageSystemHandler.cc b/src/api/MessageSystemHandler.cc index 69d77cd92..288a7f56d 100644 --- a/src/api/MessageSystemHandler.cc +++ b/src/api/MessageSystemHandler.cc @@ -6,7 +6,11 @@ #include "api/HttpUploadClaim.h" #include "media/PreviewPipelineMetrics.h" +#include "media/VideoDecoder.h" +#include "media/VideoEncoder.h" +#include "nn/core/inference_pipeline_metrics.h" #include "service/detail/ServiceRegistry.h" +#include "service/modelguard/IModelAuthorizationService.h" #include "service/path/IUploadStagingService.h" #include "service/system/IConfigReadService.h" #include "service/system/IConfigWriteService.h" @@ -36,6 +40,24 @@ namespace { constexpr const char* kRebootMsg = "Rebooting, please do not power off"; constexpr const char* kResetMsg = "Resetting, please do not power off"; constexpr int kRebootWaitSec = 40; + + class UnsupportedModelAuthorizationService final : public service::IModelAuthorizationService { + public: + service::ModelAuthorizationStatus Status() override { + return {}; + } + util::ErrorEnum CreateDeviceRequest(std::string&, std::string&) override { + return util::ErrorEnum::OperationNotSupport; + } + util::ErrorEnum InstallCertificate(const std::string&) override { + return util::ErrorEnum::OperationNotSupport; + } + }; + + service::IModelAuthorizationService& UnsupportedModelAuthorization() { + static UnsupportedModelAuthorizationService service; + return service; + } } // namespace MessageSystemHandler::MessageSystemHandler(service::IConfigReadService& config_read, @@ -44,12 +66,23 @@ MessageSystemHandler::MessageSystemHandler(service::IConfigReadService& config_r service::IDeviceInfoService& device_info, service::ISystemOperationService& system_op, service::ITimeService& time_service) + : MessageSystemHandler(config_read, config_write, config_network, device_info, system_op, time_service, + UnsupportedModelAuthorization()) {} + +MessageSystemHandler::MessageSystemHandler(service::IConfigReadService& config_read, + service::IConfigWriteService& config_write, + service::IConfigNetworkService& config_network, + service::IDeviceInfoService& device_info, + service::ISystemOperationService& system_op, + service::ITimeService& time_service, + service::IModelAuthorizationService& model_authorization) : config_read_(config_read), config_write_(config_write), config_network_(config_network), device_info_(device_info), system_op_(system_op), - time_service_(time_service) {} + time_service_(time_service), + model_authorization_(model_authorization) {} // Device information System::MsgQueryDeviceInfoSend MessageSystemHandler::Handle(System::MsgQueryDeviceInfoRecv&& /*data*/, @@ -72,32 +105,167 @@ System::MsgQueryHardwareResourceSend MessageSystemHandler::Handle( auto items = device_info_.GetHardwareResource(customScore); for (auto& item : items) { System::MsgQueryHardwareResourceSend::Item it{}; - it.key = item.key; - it.name = item.name; - it.usedPercent = item.usedPercent; - it.usedSize = item.usedSize; - it.unusedSize = item.unusedSize; - it.available = item.available; + it.key = item.key; + it.name = item.name; + it.usedPercent = item.usedPercent; + it.usedSize = item.usedSize; + it.unusedSize = item.unusedSize; + it.available = item.available; + it.memoryDomain = item.memoryDomain; retData.resData.itemList.push_back(std::move(it)); } - retData.resData.customScore = COSMO_FORMAT("{:.4f}", customScore); - retData.resData.accelerator = device_info_.GetGpuUtilization(); - const auto preview = media::GetPreviewPipelineMetrics().Snapshot(); - auto& accelerator = retData.resData.accelerator; - accelerator.activePreviewPublishers = preview.active_publishers; - accelerator.activePreviewStreams = preview.active_preview_streams; - accelerator.activeRawPreviewStreams = preview.active_raw_preview_streams; - accelerator.activeAlgorithmPreviewStreams = preview.active_algorithm_preview_streams; - accelerator.previewStreamStarts = preview.preview_stream_starts; - accelerator.previewStreamStops = preview.preview_stream_stops; - accelerator.previewStreamFailures = preview.preview_stream_failures; - accelerator.osdFrames = preview.osd_frames; - accelerator.osdMs = preview.osd_nanoseconds / 1000000.0; - accelerator.publishedFrames = preview.published_frames; - accelerator.publishMs = preview.publish_nanoseconds / 1000000.0; - accelerator.firstFrames = preview.first_frames; - accelerator.firstFrameMs = preview.first_frame_nanoseconds / 1000000.0; - accelerator.firstFrameMaxMs = preview.first_frame_max_nanoseconds / 1000000.0; + retData.resData.customScore = COSMO_FORMAT("{:.4f}", customScore); + retData.resData.accelerator = device_info_.GetGpuUtilization(); + const auto preview = media::GetPreviewPipelineMetrics().Snapshot(); + auto& accelerator = retData.resData.accelerator; + accelerator.activePreviewPublishers = preview.active_publishers; + accelerator.activePreviewStreams = preview.active_preview_streams; + accelerator.activeRawPreviewStreams = preview.active_raw_preview_streams; + accelerator.activeAlgorithmPreviewStreams = preview.active_algorithm_preview_streams; + accelerator.previewStreamStarts = preview.preview_stream_starts; + accelerator.previewStreamStops = preview.preview_stream_stops; + accelerator.previewStreamFailures = preview.preview_stream_failures; + accelerator.osdFrames = preview.osd_frames; + accelerator.osdMs = preview.osd_nanoseconds / 1000000.0; + accelerator.publishedFrames = preview.published_frames; + accelerator.publishMs = preview.publish_nanoseconds / 1000000.0; + accelerator.firstFrames = preview.first_frames; + accelerator.firstFrameMs = preview.first_frame_nanoseconds / 1000000.0; + accelerator.firstFrameMaxMs = preview.first_frame_max_nanoseconds / 1000000.0; + const auto encoder_capability = media::VideoEncoder::Probe(media::VideoCodecType::kH264); + accelerator.videoEncoderAvailable = encoder_capability.available; + accelerator.videoEncoderBackend = encoder_capability.backend; + accelerator.videoEncoderImplementation = encoder_capability.implementation; + accelerator.videoEncoderDetail = encoder_capability.detail; + const auto decoder_capability = media::VideoDecoder::Probe(media::VideoCodecType::kH264); + accelerator.videoDecoderAvailable = decoder_capability.available; + accelerator.videoDecoderBackend = decoder_capability.backend; + accelerator.videoDecoderImplementation = decoder_capability.implementation; + accelerator.videoDecoderDetail = decoder_capability.detail; + accelerator.rgaFrames = preview.rga_frames; + accelerator.rgaMs = preview.rga_nanoseconds / 1000000.0; + accelerator.rgaFailures = preview.rga_failures; + accelerator.mppEncodedFrames = preview.mpp_encoded_frames; + accelerator.mppEncodeMs = preview.mpp_encode_nanoseconds / 1000000.0; + accelerator.mppEncodeFailures = preview.mpp_encode_failures; + accelerator.mppDecodedFrames = preview.mpp_decoded_frames; + accelerator.mppDecodeMs = preview.mpp_decode_nanoseconds / 1000000.0; + accelerator.mppDecodeFailures = preview.mpp_decode_failures; + accelerator.mppDecodeFallbacks = preview.mpp_decode_fallbacks; + accelerator.mppCopyOutFrames = preview.mpp_copy_out_frames; + accelerator.mppCopyOutMs = preview.mpp_copy_out_nanoseconds / 1000000.0; + accelerator.mppCopyOutFailures = preview.mpp_copy_out_failures; + accelerator.mppEarlyDroppedFrames = preview.mpp_early_dropped_frames; + const auto inference = nn::GetInferencePipelineMetrics().Snapshot(); + accelerator.colorConvertFrames = inference.color_convert_frames; + accelerator.colorConvertMs = inference.color_convert_nanoseconds / 1000000.0; + accelerator.blobConvertFrames = inference.blob_convert_frames; + accelerator.blobConvertMs = inference.blob_convert_nanoseconds / 1000000.0; + accelerator.graphForwardFrames = inference.graph_forward_frames; + accelerator.graphForwardMs = inference.graph_forward_nanoseconds / 1000000.0; + accelerator.graphForwardFailures = inference.graph_forward_failures; + accelerator.resultParseFrames = inference.result_parse_frames; + accelerator.resultParseMs = inference.result_parse_nanoseconds / 1000000.0; + accelerator.resultParseFailures = inference.result_parse_failures; + accelerator.rknnForwards = inference.rknn_forwards; + accelerator.rknnForwardMs = inference.rknn_forward_nanoseconds / 1000000.0; + accelerator.rknnForwardFailures = inference.rknn_forward_failures; + accelerator.rknnPrepareCalls = inference.rknn_prepare_calls; + accelerator.rknnPrepareMs = inference.rknn_prepare_nanoseconds / 1000000.0; + accelerator.rknnInputsSetCalls = inference.rknn_inputs_set_calls; + accelerator.rknnInputsSetMs = inference.rknn_inputs_set_nanoseconds / 1000000.0; + accelerator.rknnRunCalls = inference.rknn_run_calls; + accelerator.rknnRunMs = inference.rknn_run_nanoseconds / 1000000.0; + accelerator.rknnOutputsGetCalls = inference.rknn_outputs_get_calls; + accelerator.rknnOutputsGetMs = inference.rknn_outputs_get_nanoseconds / 1000000.0; + accelerator.rknnOutputsReleaseCalls = inference.rknn_outputs_release_calls; + accelerator.rknnOutputsReleaseMs = inference.rknn_outputs_release_nanoseconds / 1000000.0; + accelerator.rknnOutputTransformCalls = inference.rknn_output_transform_calls; + accelerator.rknnOutputTransformMs = inference.rknn_output_transform_nanoseconds / 1000000.0; + accelerator.rknnMutexWaitCalls = inference.rknn_mutex_wait_calls; + accelerator.rknnMutexWaitMs = inference.rknn_mutex_wait_nanoseconds / 1000000.0; + accelerator.rknnDetectorForwards = inference.rknn_detector_forwards; + accelerator.rknnDetectorForwardMs = inference.rknn_detector_forward_nanoseconds / 1000000.0; + accelerator.rknnDetectorForwardFailures = inference.rknn_detector_forward_failures; + accelerator.rknnDetectorPrepareCalls = inference.rknn_detector_prepare_calls; + accelerator.rknnDetectorPrepareMs = inference.rknn_detector_prepare_nanoseconds / 1000000.0; + accelerator.rknnDetectorInputsSetCalls = inference.rknn_detector_inputs_set_calls; + accelerator.rknnDetectorInputsSetMs = inference.rknn_detector_inputs_set_nanoseconds / 1000000.0; + accelerator.rknnDetectorRunCalls = inference.rknn_detector_run_calls; + accelerator.rknnDetectorRunMs = inference.rknn_detector_run_nanoseconds / 1000000.0; + accelerator.rknnDetectorOutputsGetCalls = inference.rknn_detector_outputs_get_calls; + accelerator.rknnDetectorOutputsGetMs = inference.rknn_detector_outputs_get_nanoseconds / 1000000.0; + accelerator.rknnDetectorOutputsReleaseCalls = inference.rknn_detector_outputs_release_calls; + accelerator.rknnDetectorOutputsReleaseMs = + inference.rknn_detector_outputs_release_nanoseconds / 1000000.0; + accelerator.rknnDetectorOutputTransformCalls = inference.rknn_detector_output_transform_calls; + accelerator.rknnDetectorOutputTransformMs = + inference.rknn_detector_output_transform_nanoseconds / 1000000.0; + accelerator.rknnDetectorMutexWaitCalls = inference.rknn_detector_mutex_wait_calls; + accelerator.rknnDetectorMutexWaitMs = inference.rknn_detector_mutex_wait_nanoseconds / 1000000.0; + accelerator.rknnPreprocessFastHits = inference.rknn_preprocess_fast_hits; + accelerator.rknnRgaFillCalls = inference.rknn_rga_fill_calls; + accelerator.rknnRgaFillMs = inference.rknn_rga_fill_nanoseconds / 1000000.0; + accelerator.rknnRgaResizeColorCalls = inference.rknn_rga_resize_color_calls; + accelerator.rknnRgaResizeColorMs = inference.rknn_rga_resize_color_nanoseconds / 1000000.0; + accelerator.rknnRgaFailures = inference.rknn_rga_failures; + accelerator.rknnCpuResizeFallbackCalls = inference.rknn_cpu_resize_fallback_calls; + accelerator.rknnCpuResizeFallbackMs = inference.rknn_cpu_resize_fallback_nanoseconds / 1000000.0; + accelerator.rknnCpuNormalizeFallbackCalls = inference.rknn_cpu_normalize_fallback_calls; + accelerator.rknnCpuNormalizeFallbackMs = inference.rknn_cpu_normalize_fallback_nanoseconds / 1000000.0; + accelerator.rknnNativeInputMapCalls = inference.rknn_native_input_map_calls; + accelerator.rknnNativeInputMapMs = inference.rknn_native_input_map_nanoseconds / 1000000.0; + accelerator.rknnNativeInt8Inputs = inference.rknn_native_int8_inputs; + accelerator.rknnFloatInputs = inference.rknn_float_inputs; + accelerator.rknnUint8ContractInputs = inference.rknn_uint8_contract_inputs; + accelerator.rknnInputCompatibilityFallbacks = inference.rknn_input_compatibility_fallbacks; + accelerator.rknnBoundInputBindAttempts = inference.rknn_bound_input_bind_attempts; + accelerator.rknnBoundInputBindFailures = inference.rknn_bound_input_bind_failures; + accelerator.rknnBoundInputCopyCalls = inference.rknn_bound_input_copy_calls; + accelerator.rknnBoundInputCopyMs = inference.rknn_bound_input_copy_nanoseconds / 1000000.0; + accelerator.rknnBoundInputCopyBytes = inference.rknn_bound_input_copy_bytes; + accelerator.rknnBoundInputCopyFailures = inference.rknn_bound_input_copy_failures; + accelerator.rknnBoundInputSyncCalls = inference.rknn_bound_input_sync_calls; + accelerator.rknnBoundInputSyncMs = inference.rknn_bound_input_sync_nanoseconds / 1000000.0; + accelerator.rknnBoundInputSyncFailures = inference.rknn_bound_input_sync_failures; + accelerator.rknnBoundInputFrames = inference.rknn_bound_input_frames; + accelerator.rknnRgaBoundInputBindAttempts = inference.rknn_rga_bound_input_bind_attempts; + accelerator.rknnRgaBoundInputBindFailures = inference.rknn_rga_bound_input_bind_failures; + accelerator.rknnRgaBoundInputImportCalls = inference.rknn_rga_bound_input_import_calls; + accelerator.rknnRgaBoundInputImportMs = inference.rknn_rga_bound_input_import_nanoseconds / 1000000.0; + accelerator.rknnRgaBoundInputImportFailures = inference.rknn_rga_bound_input_import_failures; + accelerator.rknnRgaBoundInputFrames = inference.rknn_rga_bound_input_frames; + accelerator.rknnRgaBoundUint8Frames = inference.rknn_rga_bound_uint8_frames; + accelerator.rknnRgaBoundNativeInt8Frames = inference.rknn_rga_bound_native_int8_frames; + accelerator.rknnRgaBoundRequantizeCalls = inference.rknn_rga_bound_requantize_calls; + accelerator.rknnRgaBoundRequantizeMs = inference.rknn_rga_bound_requantize_nanoseconds / 1000000.0; + accelerator.rknnRgaBoundRequantizeFailures = inference.rknn_rga_bound_requantize_failures; + accelerator.rknnRgaBoundInputNormalizeBypasses = inference.rknn_rga_bound_input_normalize_bypasses; + accelerator.rknnMppDmaBufImportCalls = inference.rknn_mpp_dmabuf_import_calls; + accelerator.rknnMppDmaBufImportMs = inference.rknn_mpp_dmabuf_import_nanoseconds / 1000000.0; + accelerator.rknnMppDmaBufImportFailures = inference.rknn_mpp_dmabuf_import_failures; + accelerator.rknnMppDmaBufFrames = inference.rknn_mpp_dmabuf_frames; + accelerator.rknnMppDmaBufFallbacks = inference.rknn_mpp_dmabuf_fallbacks; + accelerator.rknnMppDmaBufSourceBytes = inference.rknn_mpp_dmabuf_source_bytes; + accelerator.rknnNativeInt8Outputs = inference.rknn_native_int8_outputs; + accelerator.rknnFloatOutputs = inference.rknn_float_outputs; + accelerator.rknnOutputCompatibilityFallbacks = inference.rknn_output_compatibility_fallbacks; + accelerator.rknnNativeOutputBytes = inference.rknn_native_output_bytes; + accelerator.rknnFloatOutputBytes = inference.rknn_float_output_bytes; + accelerator.rknnYolov8DflCalls = inference.rknn_yolov8_dfl_calls; + accelerator.rknnYolov8DflMs = inference.rknn_yolov8_dfl_nanoseconds / 1000000.0; + accelerator.rknnYolov8ClassCalls = inference.rknn_yolov8_class_calls; + accelerator.rknnYolov8ClassMs = inference.rknn_yolov8_class_nanoseconds / 1000000.0; + accelerator.rknnYolov8DirectCandidateCalls = inference.rknn_yolov8_direct_candidate_calls; + accelerator.rknnYolov8DirectCandidateFailures = inference.rknn_yolov8_direct_candidate_failures; + accelerator.rknnYolov8DirectPointsScanned = inference.rknn_yolov8_direct_points_scanned; + accelerator.rknnYolov8DirectPointsDecoded = inference.rknn_yolov8_direct_points_decoded; + accelerator.rknnYolov8ScoreSumPointsRejected = inference.rknn_yolov8_score_sum_points_rejected; + accelerator.rknnYolov8LogicalFloatBytesAvoided = inference.rknn_yolov8_logical_float_bytes_avoided; + accelerator.yolov8PostprocessCalls = inference.yolov8_postprocess_calls; + accelerator.yolov8PostprocessMs = inference.yolov8_postprocess_nanoseconds / 1000000.0; + accelerator.yolov8NmsCalls = inference.yolov8_nms_calls; + accelerator.yolov8NmsMs = inference.yolov8_nms_nanoseconds / 1000000.0; return retData; } @@ -334,6 +502,62 @@ System::MsgUpgradeSend MessageSystemHandler::Handle(System::MsgUpgradeRecv&& dat return retData; } +System::MsgCheckUpgradeSpaceSend MessageSystemHandler::Handle(System::MsgCheckUpgradeSpaceRecv&& data, + std::error_condition& errc) { + System::MsgCheckUpgradeSpaceSend result{}; + service::UpgradeSpaceStatus status; + errc = system_op_.CheckUpgradeSpace(data.packageSizeBytes, data.cleanupEventMedia, status); + result.resData.sufficient = status.sufficient; + result.resData.requiredBytes = status.required_bytes; + result.resData.availableBytes = status.available_bytes; + result.resData.eventMediaBytes = status.event_media_bytes; + result.resData.deletedMediaBytes = status.deleted_media_bytes; + result.resData.deletedMediaFiles = status.deleted_media_files; + return result; +} + +System::MsgQueryModelAuthorizationSend MessageSystemHandler::Handle( + System::MsgQueryModelAuthorizationRecv&& /*data*/, std::error_condition& errc) { + System::MsgQueryModelAuthorizationSend result{}; + const auto status = model_authorization_.Status(); + result.resData.supported = status.supported; + result.resData.authorized = status.authorized; + result.resData.state = status.state; + errc = util::ErrorEnum::Success; + return result; +} + +System::MsgDownloadModelAuthorizationRequestSend MessageSystemHandler::Handle( + System::MsgDownloadModelAuthorizationRequestRecv&& /*data*/, std::error_condition& errc) { + System::MsgDownloadModelAuthorizationRequestSend result{}; + errc = model_authorization_.CreateDeviceRequest(result.filePath, result.fileName); + return result; +} + +System::MsgInstallModelAuthorizationSend MessageSystemHandler::Handle( + System::MsgInstallModelAuthorizationRecv&& data, const RequestDispatchContext& context, + std::error_condition& errc) { + System::MsgInstallModelAuthorizationSend result{}; + if (context.transport != RequestTransport::kHttp || context.principal.empty()) { + errc = util::ErrorEnum::InvalidParam; + return result; + } + service::StagedFileLease lease; + if (!data.uploadId.empty()) { + errc = service::ServiceRegistry::Instance().Get<service::IUploadStagingService>().Consume( + context.principal, data.uploadId, service::UploadPurpose::kModelAuthorizationCertificate, lease); + } else { + errc = detail::ClaimHttpUpload(context, data.filePath, + service::UploadPurpose::kModelAuthorizationCertificate, lease); + } + if (!errc && lease.Revalidate()) { + errc = model_authorization_.InstallCertificate(lease.Path()); + } else if (!errc) { + errc = util::ErrorEnum::FileAnalysisFailed; + } + return result; +} + System::MsgUpgradeSend MessageSystemHandler::Handle(System::MsgUpgradeRecv&& data, const RequestDispatchContext& context, std::error_condition& errc) { diff --git a/src/api/MessageSystemHandler.h b/src/api/MessageSystemHandler.h index fc21d1cb9..eb2c7dffe 100644 --- a/src/api/MessageSystemHandler.h +++ b/src/api/MessageSystemHandler.h @@ -22,6 +22,7 @@ class IConfigNetworkService; class IDeviceInfoService; class ISystemOperationService; class ITimeService; +class IModelAuthorizationService; } // namespace cosmo::service namespace cosmo { @@ -33,6 +34,11 @@ class MessageSystemHandler { service::IConfigNetworkService& config_network, service::IDeviceInfoService& device_info, service::ISystemOperationService& system_op, service::ITimeService& time_service); + MessageSystemHandler(service::IConfigReadService& config_read, service::IConfigWriteService& config_write, + service::IConfigNetworkService& config_network, + service::IDeviceInfoService& device_info, + service::ISystemOperationService& system_op, service::ITimeService& time_service, + service::IModelAuthorizationService& model_authorization); System::MsgQueryDeviceInfoSend Handle(System::MsgQueryDeviceInfoRecv&& data, std::error_condition& errc); // @@ -71,6 +77,15 @@ class MessageSystemHandler { System::MsgUpgradeSend Handle(System::MsgUpgradeRecv&& data, std::error_condition& errc); // System::MsgUpgradeSend Handle(System::MsgUpgradeRecv&& data, const RequestDispatchContext& context, std::error_condition& errc); + System::MsgCheckUpgradeSpaceSend Handle(System::MsgCheckUpgradeSpaceRecv&& data, + std::error_condition& errc); + System::MsgQueryModelAuthorizationSend Handle(System::MsgQueryModelAuthorizationRecv&& data, + std::error_condition& errc); + System::MsgDownloadModelAuthorizationRequestSend Handle( + System::MsgDownloadModelAuthorizationRequestRecv&& data, std::error_condition& errc); + System::MsgInstallModelAuthorizationSend Handle(System::MsgInstallModelAuthorizationRecv&& data, + const RequestDispatchContext& context, + std::error_condition& errc); System::MsgQuerySystemLogoSend Handle(System::MsgQuerySystemLogoRecv&& data, std::error_condition& errc); // @@ -137,6 +152,7 @@ class MessageSystemHandler { service::IDeviceInfoService& device_info_; service::ISystemOperationService& system_op_; service::ITimeService& time_service_; + service::IModelAuthorizationService& model_authorization_; }; } // namespace cosmo diff --git a/src/app/app_init.cc b/src/app/app_init.cc index 360c51c9a..8acbdf96a 100644 --- a/src/app/app_init.cc +++ b/src/app/app_init.cc @@ -67,6 +67,8 @@ #include "service/model/IModelQuery.h" #include "service/model/IModelService.h" #include "service/model/impl/ModelServiceImpl.h" +#include "service/modelguard/IModelAuthorizationService.h" +#include "service/modelguard/impl/ModelAuthorizationServiceImpl.h" #include "service/network/INetworkService.h" #include "service/network/impl/AuthServiceImpl.h" #include "service/network/impl/ClientMessageServiceImpl.h" @@ -100,6 +102,7 @@ #include "service/task/ITaskService.h" #include "service/task/impl/ScheduleServiceImpl.h" #include "service/task/impl/TaskServiceImpl.h" +#include "util/EnvUtil.h" #include "util/Log.h" #include "util/NnBackendConstants.h" #include "util/PathUtil.h" @@ -107,6 +110,9 @@ namespace cosmo::app { void SwDevicePreInit() { + cosmo::path::OverrideRootPaths( + cosmo::util::GetEnvOrDefault("COSMO_DATA_DIR", "/data/cwaiuserdata"), + cosmo::util::GetEnvOrDefault("COSMO_APP_DATA_DIR", "/appfs/cosmo_wander/cwai_data")); cosmo::path::Init(); } @@ -222,6 +228,8 @@ static void RegisterBusinessServices() { registry.Register<cosmo::service::ISystemOperationService>( std::make_unique<cosmo::service::SystemOperationServiceImpl>()); registry.Register<cosmo::service::IModelService>(std::make_unique<cosmo::service::ModelServiceImpl>()); + registry.Register<cosmo::service::IModelAuthorizationService>( + std::make_unique<cosmo::service::ModelAuthorizationServiceImpl>()); auto& modelImpl = registry.Get<cosmo::service::IModelService>(); registry.Set<cosmo::service::IModelQuery>(static_cast<cosmo::service::IModelQuery*>(&modelImpl)); registry.Set<cosmo::service::IModelPathMapping>( @@ -326,12 +334,14 @@ static void InitializeExternalComponents() { cosmo::service::ServiceRegistry::Instance().Get<cosmo::service::IStorageCleanService>().Start(); // HTTP Server Init + const int http_port = cosmo::util::GetEnvIntOrDefault("COSMO_HTTP_PORT", kDefaultHttpPort); cosmo::service::ServiceRegistry::Instance().Get<cosmo::service::INetworkService>().InitHttpServer( - "0.0.0.0", kDefaultHttpPort); + "0.0.0.0", static_cast<uint16_t>(http_port)); // uWebSockets Server Init + const int websocket_port = cosmo::util::GetEnvIntOrDefault("COSMO_WEBSOCKET_PORT", kDefaultWebSocketPort); cosmo::service::ServiceRegistry::Instance().Get<cosmo::service::IEventNotifier>().InitializeWebSocket( - "0.0.0.0", kDefaultWebSocketPort); + "0.0.0.0", websocket_port); // Device discovery multicast service (async init with retry). cosmo::service::ServiceRegistry::Instance().Get<cosmo::service::IDeviceDiscoveryService>().Start(); diff --git a/src/flow/CMakeLists.txt b/src/flow/CMakeLists.txt index 707e3dc5d..36b757fd9 100644 --- a/src/flow/CMakeLists.txt +++ b/src/flow/CMakeLists.txt @@ -26,3 +26,9 @@ if(COSMO_NN_USE_CPU_BACKEND) COSMO_NN_USE_HOST_BACKEND COSMO_NN_USE_ONNX_BACKEND) endif() +if(COSMO_NN_USE_RKNN_BACKEND) + target_compile_definitions(cosmo_flow PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) +endif() diff --git a/src/flow/alarm/TaskAlarmSuppression.h b/src/flow/alarm/TaskAlarmSuppression.h index c3540eee2..aff93c384 100644 --- a/src/flow/alarm/TaskAlarmSuppression.h +++ b/src/flow/alarm/TaskAlarmSuppression.h @@ -2,6 +2,7 @@ #pragma once +#include <cstdint> #include <string> #include "util/Rect.h" diff --git a/src/flow/channel/AlgChannel.cc b/src/flow/channel/AlgChannel.cc index cd7f27e4a..ea0e3411f 100644 --- a/src/flow/channel/AlgChannel.cc +++ b/src/flow/channel/AlgChannel.cc @@ -12,7 +12,7 @@ namespace cosmo { AlgChannel::~AlgChannel() { Quit(); - LOG_INFO("Channel:{} Url:{} Delete", channel, url_); + LOG_INFO("Channel:{} Delete", channel); } AlgChannel::AlgChannel(const std::string& channel_id, const std::string& init_task_id, ActionNode& action, @@ -22,7 +22,7 @@ AlgChannel::AlgChannel(const std::string& channel_id, const std::string& init_ta demuxer_(channel_id, url), decoder_(*this, channel_id) { AddTask(init_task_id); - LOG_INFO("Channel:{}/{} Url:{} Init", channel, init_task_id, url_); + LOG_INFO("Channel:{}/{} Init", channel, init_task_id); } bool AlgChannel::RegistTaskQueue(AlgTaskUnit& param) { @@ -69,9 +69,9 @@ void AlgChannel::RemoveViewerPacketQueue(std::shared_ptr<AsyncQueue<VideoPacketP demuxer_.RemoveViewerPacketQueue(async_packet_queue); } -void AlgChannel::AddViewerFrameQueue(const std::string& alg_id, - AsyncQueue<VideoFramePtr>& async_frame_queue) { - decoder_.AddViewerFrameQueue(alg_id, async_frame_queue); +void AlgChannel::AddViewerFrameQueue(const std::string& alg_id, AsyncQueue<VideoFramePtr>& async_frame_queue, + std::function<bool()> prepare_frame) { + decoder_.AddViewerFrameQueue(alg_id, async_frame_queue, std::move(prepare_frame)); } void AlgChannel::RemoveViewerFrameQueue(const std::string& alg_id) { @@ -79,7 +79,7 @@ void AlgChannel::RemoveViewerFrameQueue(const std::string& alg_id) { } bool AlgChannel::SetUrl(const std::string& url) { - LOG_INFO("Channel {} Set Url:{}.", channel, url); + LOG_INFO("Channel {} Set URL.", channel); return demuxer_.SetUrl(url); } @@ -146,10 +146,7 @@ bool AlgChannel::ModifyParam(const std::string& /*channel_id*/, const std::strin for (const auto& param : params) { if (key::CHANNEL_URL == param.key.ToString()) { if (param.value.ToString() != GetUrl()) { - LOG_INFO( - "ModifyParam " - "Channel {} Url Change From :{} To {}.", - channel, GetUrl(), param.value); + LOG_INFO("ModifyParam Channel {} URL changed.", channel); failed_count += (false == SetUrl(param.value.ToString())); } } else if (key::CHANNEL_SOURCE_REPEAT == param.key.ToString()) { @@ -190,13 +187,13 @@ bool AlgChannel::Start() { } if (was_started) { - LOG_INFO("Channel:{} Url:{} Alread Started", channel, url_); + LOG_INFO("Channel:{} Already Started", channel); // Restart VoD stream from the beginning. demuxer_.SetForStartTask(); return true; } is_started_ = true; - LOG_INFO("Channel:{} Url:{} Start", channel, url_); + LOG_INFO("Channel:{} Start", channel); regist_task_.channel_id = channel; regist_task_.task_id = decoder_.GetName(); regist_task_.fps = decoder_.GetRequiredFps(); @@ -213,7 +210,7 @@ bool AlgChannel::Start() { void AlgChannel::Quit() { std::lock_guard<std::shared_mutex> lock(mtx_); if (is_started_) { - LOG_INFO("Channel:{} Url:{} Stop", channel, url_); + LOG_INFO("Channel:{} Stop", channel); is_started_ = false; demuxer_.RemoveProcQueue(regist_task_); decoder_.Stop(); @@ -225,7 +222,7 @@ void AlgChannel::Stop() { // Stop AlgActionBase consumer thread (if active). AlgActionBase::Stop(); if (is_started_) { - LOG_INFO("Channel:{} Url:{} Stop", channel, url_); + LOG_INFO("Channel:{} Stop", channel); } } diff --git a/src/flow/channel/AlgChannel.h b/src/flow/channel/AlgChannel.h index 8e46fe038..5fd40a4cf 100644 --- a/src/flow/channel/AlgChannel.h +++ b/src/flow/channel/AlgChannel.h @@ -2,6 +2,7 @@ #pragma once +#include <functional> #include <memory> #include <shared_mutex> #include <string> @@ -34,7 +35,8 @@ class AlgChannel : public AlgActionBase { void AddViewerPacketQueue(std::shared_ptr<AsyncQueue<VideoPacketPtr>> async_packet_queue); void RemoveViewerPacketQueue(std::shared_ptr<AsyncQueue<VideoPacketPtr>> async_packet_queue); - void AddViewerFrameQueue(const std::string& alg_id, AsyncQueue<VideoFramePtr>& async_frame_queue); + void AddViewerFrameQueue(const std::string& alg_id, AsyncQueue<VideoFramePtr>& async_frame_queue, + std::function<bool()> prepare_frame = {}); void RemoveViewerFrameQueue(const std::string& alg_id); // Modify parameters incrementally on top of existing values. diff --git a/src/flow/channel/AlgChannelDecode.cc b/src/flow/channel/AlgChannelDecode.cc index 094a0cd84..490f1f307 100644 --- a/src/flow/channel/AlgChannelDecode.cc +++ b/src/flow/channel/AlgChannelDecode.cc @@ -1,11 +1,15 @@ // AlgChannelDecode — video decoding, color conversion and frame distribution. // Image capture and viewer distribution are in AlgChannelDecodeCapture.cc. +#include <algorithm> +#include <cctype> +#include <cstdlib> #include <filesystem> #include "flow/channel/AlgChannel.h" #include "media/VideoFrame.h" #include "mem/IDeviceContext.h" +#include "nn/core/inference_pipeline_metrics.h" #include "service/detail/ServiceRegistry.h" #include "service/media/IVideoFrameCodec.h" #include "service/media/IVideoFrameOSD.h" @@ -23,6 +27,24 @@ namespace chrono = std::chrono; static constexpr const char* kTag = "ALGCHANNEL "; namespace cosmo { +namespace { + + bool NativeInferenceBufferEnabled() { +#if defined(COSMO_NN_USE_RKNN_BACKEND) && defined(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + const char* raw = std::getenv("COSMO_RKNN_MPP_DMABUF"); + if (!raw || *raw == '\0') { + return true; + } + std::string value(raw); + std::transform(value.begin(), value.end(), value.begin(), + [](unsigned char ch) { return static_cast<char>(std::tolower(ch)); }); + return value != "0" && value != "false" && value != "off" && value != "no"; +#else + return false; +#endif + } + +} // namespace AlgChannelDecode::~AlgChannelDecode() { LOG_INFO("ChannelDecode:{}/{} Delete", channel_id_, uuid_); @@ -146,8 +168,31 @@ void AlgChannelDecode::PrepareDecoder(VideoPacketPtr& video_frame) { auto* media_handle = service::ServiceRegistry::Instance().Get<mem::IDeviceContext>().GetMediaHandle(); decoder_ = media::VideoDecoder::Create(static_cast<size_t>(device_id_), media_handle); } - // Rebuild decoder on stream restart or exception. - if ((stream_index_ != video_frame->stream_idx) || (codec_reset_sign_)) { + const bool needs_resize = NeedsResize(video_frame); + const int decoder_width = needs_resize ? media::kVideoDefaultWidth : static_cast<int>(video_frame->width); + const int decoder_height = + needs_resize ? media::kVideoDefaultHeight : static_cast<int>(video_frame->height); + const bool stream_restarted = stream_index_ != video_frame->stream_idx; + + // A backend may retain a compatible hardware context across a clean + // keyframe boundary. CPU/Sophon keep their existing Close/Open behavior. + if (stream_restarted && !codec_reset_sign_ && + decoder_->ReuseForStreamRestart(video_frame->codec_type, decoder_width, decoder_height)) { + frame_info_.clear(); + stream_index_ = video_frame->stream_idx; + decode_count_ = 0; + frame_index_ = -1; + ++decoder_stream_reuse_count_; + if (decoder_stream_reuse_count_ == 1 || decoder_stream_reuse_count_ % 240 == 0) { + LOG_INFO("{} reused decoder across stream restart: stream={} codec={} size={}x{} count={}", name_, + stream_index_, video_frame->codec_type, decoder_width, decoder_height, + decoder_stream_reuse_count_); + } + return; + } + + // Rebuild decoder on an incompatible stream restart or exception. + if (stream_restarted || codec_reset_sign_) { if (decoder_->IsOpened()) { decoder_->Close(); LOG_INFO("{} Decoder Reset Last stream:{} New Stream:{} SuccessCount:{} codecResetSign:{} ", @@ -156,20 +201,15 @@ void AlgChannelDecode::PrepareDecoder(VideoPacketPtr& video_frame) { } if (!decoder_->IsOpened()) { frame_info_.clear(); - stream_index_ = video_frame->stream_idx; - codec_reset_sign_ = false; - decode_count_ = 0; - frame_index_ = -1; + stream_index_ = video_frame->stream_idx; + codec_reset_sign_ = false; + decode_count_ = 0; + frame_index_ = -1; + decoder_stream_reuse_count_ = 0; LOG_INFO("{} streamIndex:{} videoType:{} Changed, dumux video width:{}, height:{}", name_, stream_index_, video_frame->codec_type, video_frame->width, video_frame->height); - if (NeedsResize(video_frame)) { - decoder_->SetCodecType(video_frame->codec_type, media::kVideoDefaultWidth, - media::kVideoDefaultHeight); - } else { - decoder_->SetCodecType(video_frame->codec_type, static_cast<int>(video_frame->width), - static_cast<int>(video_frame->height)); - } + decoder_->SetCodecType(video_frame->codec_type, decoder_width, decoder_height); decoder_->Open(); } } @@ -220,12 +260,13 @@ void AlgChannelDecode::HandFrame(AlgDataPtr demux_data) { duration_stat_.BeginSample(); bool is_decode_ret = false; FrameInfoSave(video_frame); - VideoFramePtr frame_data = nullptr; + media::DecodedVideoFrame decoded_frame; #ifdef TEST_NO_DECODER - frame_data = std::make_shared<media::VideoFrame>(1920, 1080); + decoded_frame = media::DecodedVideoFrame(std::make_shared<media::VideoFrame>(1920, 1080)); + is_decode_ret = decoded_frame.HasFrame(); #else if (video_frame->codec_type == media::VideoCodecType::kMjpeg) { - frame_data = service::ServiceRegistry::Instance().Get<service::IVideoFrameCodec>().DecodeJpeg( + auto frame_data = service::ServiceRegistry::Instance().Get<service::IVideoFrameCodec>().DecodeJpeg( std::vector<u_int8_t>(video_frame->data.begin(), video_frame->data.end())); if (frame_data) { // MJPEG hardware decode returns frames without business-side frame @@ -235,10 +276,11 @@ void AlgChannelDecode::HandFrame(AlgDataPtr demux_data) { frame_data->SetTimestamp(video_frame->timestamp); } is_decode_ret = (frame_data != nullptr); + decoded_frame = media::DecodedVideoFrame(std::move(frame_data)); } else { try { - frame_data = decoder_->Decode(video_frame->data.data(), video_frame->data.size(), - video_frame->index, is_decode_ret); + decoded_frame = decoder_->DecodeFrame(video_frame->data.data(), video_frame->data.size(), + video_frame->index, is_decode_ret); } catch (const std::exception& e) { codec_reset_sign_ = true; LOG_ERRO("{} Last Frame is {} Have Decord Errors: {}", name_, frame_index_, e.what()); @@ -246,17 +288,9 @@ void AlgChannelDecode::HandFrame(AlgDataPtr demux_data) { } } #endif - duration_stat_.EndSample(); - if (frame_data) { - auto frame_info = FrameInfoGet(static_cast<int64_t>(frame_data->GetFrameIndex())); - if (static_cast<uint64_t>(frame_info.index) == frame_data->GetFrameIndex()) { - frame_data->SetTimestamp(frame_info.timestamp); - frame_data->SetStreamIndex(frame_info.streamIndex); - } else { - frame_data->SetTimestamp(util::GetMilliseconds()); - } - } else { + if (!decoded_frame.HasFrame()) { + duration_stat_.EndSample(); if (is_decode_ret) { frame_index_ = video_frame->index; // SendPacket succeeded but GetFrame returned no output (VPU internal buffering); not a failure. @@ -275,6 +309,57 @@ void AlgChannelDecode::HandFrame(AlgDataPtr demux_data) { return; } + const auto decoded_frame_index = decoded_frame.GetFrameIndex(); + const auto frame_info = FrameInfoGet(static_cast<int64_t>(decoded_frame_index)); + const bool matched_frame_info = + frame_info.index >= 0 && static_cast<uint64_t>(frame_info.index) == decoded_frame_index; + const int64_t output_timestamp = matched_frame_info ? frame_info.timestamp : util::GetMilliseconds(); + const int64_t output_stream_index = matched_frame_info ? frame_info.streamIndex : video_frame->stream_idx; + + AlgFrameDistributionPlan task_plan; + const bool prepared_task_distribution = decoded_frame.IsDeferred(); + if (prepared_task_distribution) { + task_plan = PrepareFrameDistribution(demux_data); + } + + media::NativeVideoBufferPtr native_inference_buffer; + if (task_plan.SupportsNativeInference() && NativeInferenceBufferEnabled()) { + native_inference_buffer = decoded_frame.ExportNativeBuffer(); + } + + ViewerDistributionPlan viewer_plan; +#ifdef COSMO_MEDIA_USE_ROCKCHIP_BACKEND + // Rockchip viewers move their existing FPS filter ahead of Copy-out. The + // callback also rejects a saturated preview queue before host allocation. + viewer_plan = PrepareViewerDistribution(); + constexpr bool prepared_viewer_distribution = true; +#else + constexpr bool prepared_viewer_distribution = false; +#endif + + const bool host_frame_required = !decoded_frame.IsDeferred() || !task_plan.Empty() || + !viewer_plan.empty() || NeedsHostFrame(output_stream_index); + if (!host_frame_required) { + decoded_frame.Discard(); + duration_stat_.EndSample(); + frame_index_ = video_frame->index; + decode_count_ += 1; + consecutive_decode_failures_ = 0; + action_status_ = util::ErrorEnum::Success; + return; + } + + auto frame_data = decoded_frame.Materialize(); + duration_stat_.EndSample(); + if (!frame_data || !frame_data->Active()) { + action_status_ = util::ErrorEnum::DecoderFrameFailed; + LOG_WARN("{} decoded frame materialization failed at frame:{} stream:{}", name_, video_frame->index, + video_frame->stream_idx); + return; + } + frame_data->SetTimestamp(output_timestamp); + frame_data->SetStreamIndex(output_stream_index); + frame_index_ = video_frame->index; decode_count_++; consecutive_decode_failures_ = 0; // Successful decode; reset consecutive failure counter. @@ -295,6 +380,8 @@ void AlgChannelDecode::HandFrame(AlgDataPtr demux_data) { media::kVideoDefaultHeight); return; } + output_frame->SetFrameIndex(frame_data->GetFrameIndex()); + output_frame->SetTimestamp(frame_data->GetTimestamp()); output_frame->SetStreamIndex(frame_data->GetStreamIndex()); } @@ -308,11 +395,21 @@ void AlgChannelDecode::HandFrame(AlgDataPtr demux_data) { return; } - DistributeViewer(output_frame); + if constexpr (prepared_viewer_distribution) { + DistributePreparedViewer(viewer_plan, output_frame); + } else { + DistributeViewer(output_frame); + } DoCaptureImage(output_frame); CaptureJpeg(output_frame); - DistributorData(demux_data, output_frame, - [this](AlgDataPtr frame, VideoFramePtr in_data) { return ColorConvert(frame, in_data); }); + const auto color_convert = [this, native_inference_buffer](AlgDataPtr frame, VideoFramePtr in_data) { + return ColorConvert(frame, in_data, native_inference_buffer); + }; + if (prepared_task_distribution) { + DistributorPreparedFrame(task_plan, demux_data, output_frame, color_convert); + } else { + DistributorData(demux_data, output_frame, color_convert); + } } void AlgChannelDecode::FrameInfoSave(VideoPacketPtr packet) { @@ -348,11 +445,19 @@ AlgFrameInfo AlgChannelDecode::FrameInfoGet(int64_t index) { // Image capture and viewer distribution — moved to AlgChannelDecodeCapture.cc -AlgDataPtr AlgChannelDecode::ColorConvert(AlgDataPtr demux_data, VideoFramePtr in_data) { +AlgDataPtr AlgChannelDecode::ColorConvert(AlgDataPtr demux_data, VideoFramePtr in_data, + media::NativeVideoBufferPtr native_buffer) { if (!VideoFrameValid(in_data, true)) { return nullptr; } + const auto convert_started = std::chrono::steady_clock::now(); + const auto record_duration = [&]() { + const auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>( + std::chrono::steady_clock::now() - convert_started) + .count(); + nn::GetInferencePipelineMetrics().RecordColorConvert(static_cast<uint64_t>(elapsed)); + }; auto& transform = service::ServiceRegistry::Instance().Get<service::IVideoFrameTransform>(); VideoFramePtr ai_frame; const auto pixel_format = in_data->GetPixelFormat(); @@ -369,6 +474,7 @@ AlgDataPtr AlgChannelDecode::ColorConvert(AlgDataPtr demux_data, VideoFramePtr i LOG_WARN("{} unsupported decoded pixel format {}", name_, static_cast<int>(pixel_format)); } if ((!ai_frame) || (!ai_frame->Active())) { + record_duration(); action_status_ = util::ErrorEnum::DecoderColorConvertFailed; return nullptr; } @@ -377,15 +483,17 @@ AlgDataPtr AlgChannelDecode::ColorConvert(AlgDataPtr demux_data, VideoFramePtr i ai_frame->SetTimestamp(in_data->GetTimestamp()); ai_frame->SetStreamIndex(in_data->GetStreamIndex()); - AlgDataPtr data = std::make_shared<AlgData>(); - data->chanDataOrig.packet = demux_data->chanDataOrig.packet; - data->chanDataOrig.fps = demux_data->chanDataOrig.fps; - data->dataType = AlgDataType::ChannelDataDec; - data->chanDataDec.frame = ai_frame; - data->channelId = channel_id_; + AlgDataPtr data = std::make_shared<AlgData>(); + data->chanDataOrig.packet = demux_data->chanDataOrig.packet; + data->chanDataOrig.fps = demux_data->chanDataOrig.fps; + data->dataType = AlgDataType::ChannelDataDec; + data->chanDataDec.frame = ai_frame; + data->chanDataDec.native_buffer = std::move(native_buffer); + data->channelId = channel_id_; data->firstTimePoint = demux_data->firstTimePoint; action_status_ = util::ErrorEnum::Success; + record_duration(); return data; } diff --git a/src/flow/channel/AlgChannelDecode.h b/src/flow/channel/AlgChannelDecode.h index 3c12b9706..5355649d5 100644 --- a/src/flow/channel/AlgChannelDecode.h +++ b/src/flow/channel/AlgChannelDecode.h @@ -3,6 +3,7 @@ #pragma once #include <atomic> +#include <functional> #include <list> #include <memory> #include <shared_mutex> @@ -36,7 +37,9 @@ struct AlgFrameInfo { struct ChannelTaskViewerQueue { std::string alg_id; AsyncQueue<VideoFramePtr>* async_frame_queue{nullptr}; + std::function<bool()> prepare_frame; }; +using ViewerDistributionPlan = std::vector<std::string>; class AlgChannelDecode : public AlgDataQueueDistributor, public util::Thread { public: AlgChannelDecode(AlgChannel& channelInst, const std::string& channelId); @@ -72,7 +75,8 @@ class AlgChannelDecode : public AlgDataQueueDistributor, public util::Thread { // Public interface for image capture. VideoFramePtr CaptureImage(int timeoutMs = 3000); - void AddViewerFrameQueue(const std::string& algId, AsyncQueue<VideoFramePtr>& asyncFrameQueue); + void AddViewerFrameQueue(const std::string& algId, AsyncQueue<VideoFramePtr>& asyncFrameQueue, + std::function<bool()> prepareFrame = {}); void RemoveViewerFrameQueue(const std::string& algId); protected: @@ -84,7 +88,8 @@ class AlgChannelDecode : public AlgDataQueueDistributor, public util::Thread { bool ValidateFrame(VideoPacketPtr& videoFrame, bool justNeedIFrame); void PrepareDecoder(VideoPacketPtr& videoFrame); bool NeedsResize(VideoPacketPtr& videoFrame); - AlgDataPtr ColorConvert(AlgDataPtr demuxData, VideoFramePtr inData); + AlgDataPtr ColorConvert(AlgDataPtr demuxData, VideoFramePtr inData, + media::NativeVideoBufferPtr nativeBuffer = nullptr); void FrameInfoSave(VideoPacketPtr packet); AlgFrameInfo FrameInfoGet(int64_t index); @@ -95,6 +100,9 @@ class AlgChannelDecode : public AlgDataQueueDistributor, public util::Thread { // Distribute frames to display viewers. void DistributeViewer(VideoFramePtr inData); + ViewerDistributionPlan PrepareViewerDistribution(); + void DistributePreparedViewer(const ViewerDistributionPlan& plan, VideoFramePtr inData); + bool NeedsHostFrame(int64_t streamIndex); private: mutable std::mutex mtx_; @@ -111,6 +119,7 @@ class AlgChannelDecode : public AlgDataQueueDistributor, public util::Thread { int64_t frame_index_{-1}; int64_t stream_index_{-1}; int64_t decode_count_{0}; + uint64_t decoder_stream_reuse_count_{0}; int64_t cap_image_stream_index_{-1}; float fps_{0.0}; std::atomic<bool> is_running_{false}; diff --git a/src/flow/channel/AlgChannelDecodeCapture.cc b/src/flow/channel/AlgChannelDecodeCapture.cc index 37a1e98bb..2b4955cc2 100644 --- a/src/flow/channel/AlgChannelDecodeCapture.cc +++ b/src/flow/channel/AlgChannelDecodeCapture.cc @@ -61,7 +61,8 @@ void AlgChannelDecode::CaptureJpeg(VideoFramePtr picture) { } void AlgChannelDecode::AddViewerFrameQueue(const std::string& alg_id, - AsyncQueue<VideoFramePtr>& async_frame_queue) { + AsyncQueue<VideoFramePtr>& async_frame_queue, + std::function<bool()> prepare_frame) { std::lock_guard<std::mutex> lock(mtx_); auto it = std::find_if(viewer_queue_.begin(), viewer_queue_.end(), [&](const ChannelTaskViewerQueue& viewer) { return (viewer.alg_id == alg_id); }); @@ -71,6 +72,7 @@ void AlgChannelDecode::AddViewerFrameQueue(const std::string& alg_id, ChannelTaskViewerQueue viewer; viewer.alg_id = alg_id; viewer.async_frame_queue = &async_frame_queue; + viewer.prepare_frame = std::move(prepare_frame); viewer_queue_.push_back(viewer); } @@ -93,4 +95,38 @@ void AlgChannelDecode::DistributeViewer(VideoFramePtr in_data) { } } +ViewerDistributionPlan AlgChannelDecode::PrepareViewerDistribution() { + ViewerDistributionPlan plan; + std::lock_guard<std::mutex> lock(mtx_); + for (auto& viewer : viewer_queue_) { + if (!viewer.async_frame_queue) { + continue; + } + if (viewer.prepare_frame && !viewer.prepare_frame()) { + continue; + } + plan.push_back(viewer.alg_id); + } + return plan; +} + +void AlgChannelDecode::DistributePreparedViewer(const ViewerDistributionPlan& plan, VideoFramePtr in_data) { + if (!in_data || plan.empty()) { + return; + } + std::lock_guard<std::mutex> lock(mtx_); + for (const auto& alg_id : plan) { + auto it = std::find_if(viewer_queue_.begin(), viewer_queue_.end(), + [&](const ChannelTaskViewerQueue& viewer) { return viewer.alg_id == alg_id; }); + if (it != viewer_queue_.end() && it->async_frame_queue) { + it->async_frame_queue->Insert(in_data); + } + } +} + +bool AlgChannelDecode::NeedsHostFrame(int64_t stream_index) { + std::lock_guard<std::mutex> lock(mtx_); + return is_capturing_ || stream_index != cap_image_stream_index_; +} + } // namespace cosmo diff --git a/src/flow/channel/AlgChannelDemux.cc b/src/flow/channel/AlgChannelDemux.cc index 9fda17847..d19bcda7e 100644 --- a/src/flow/channel/AlgChannelDemux.cc +++ b/src/flow/channel/AlgChannelDemux.cc @@ -4,6 +4,7 @@ #include <algorithm> +#include "flow/channel/VideoEofPolicy.h" #include "service/detail/ServiceRegistry.h" #include "service/event/IEventNotifier.h" #include "service/system/IConfigReadService.h" @@ -19,7 +20,7 @@ static constexpr const char* kTag = "ChannelDemux "; namespace cosmo { AlgChannelDemux::~AlgChannelDemux() { - LOG_INFO("{}:{} Url:{} Delete", kTag, channel_id_, url_); + LOG_INFO("{}:{} Delete", kTag, channel_id_); ClearLastFrame(); } @@ -33,14 +34,14 @@ AlgChannelDemux::AlgChannelDemux(const std::string& channel_id, const std::strin action_status_ = util::ErrorEnum::ActionReady; status_.status = service::camera::AlgDemuxStatus::AlgDemuxInit; status_.timePoint = chrono::steady_clock::now(); - LOG_INFO("{}:{} Url:{} Init", kTag, channel_id_, url_); + LOG_INFO("{}:{} Init", kTag, channel_id_); } bool AlgChannelDemux::SetUrl(const std::string& url) { if (url.empty()) return false; if (url_ != url) { - LOG_INFO("{}:{} Url Change From {} To {}", kTag, channel_id_, url_, url); + LOG_INFO("{}:{} URL changed", kTag, channel_id_); url_ = url; is_url_changed_ = true; video_read_count_ = 0; @@ -101,14 +102,14 @@ bool AlgChannelDemux::SetPollChannel(const std::string& channel_id) { void AlgChannelDemux::Start() { std::lock_guard<std::mutex> lock(lifecycle_mtx_); if (is_running_.exchange(true)) { - LOG_INFO("{}:{} Url:{} Already Running", kTag, channel_id_, url_); + LOG_INFO("{}:{} Already Running", kTag, channel_id_); return; } ResetDistributor(); if (!start()) { is_running_ = false; action_status_ = util::ErrorEnum::ActionStop; - LOG_ERRO("{}:{} Url:{} Start failed: previous thread still joinable", kTag, channel_id_, url_); + LOG_ERRO("{}:{} Start failed: previous thread still joinable", kTag, channel_id_); return; } action_status_ = util::ErrorEnum::ActionStart; @@ -118,7 +119,7 @@ void AlgChannelDemux::Stop() { std::lock_guard<std::mutex> lock(lifecycle_mtx_); LOG_INFO("{}:{} Wait To Stop", kTag, channel_id_); if (!is_running_.exchange(false)) { - LOG_INFO("{}:{} Url:{} Already Stopped", kTag, channel_id_, url_); + LOG_INFO("{}:{} Already Stopped", kTag, channel_id_); return; } stop(); @@ -174,11 +175,11 @@ bool AlgChannelDemux::OpenStream() { NotifyOnInfo(); video_read_count_ += 1; - bool was_repeat = is_need_repeat_; - is_need_repeat_ = false; - is_have_report_ = false; - is_opened_ = true; - read_frames_ = 0; + bool was_repeat = is_need_repeat_; + is_need_repeat_ = false; + is_have_report_ = false; + is_opened_ = true; + read_frames_ = 0; SetStatusInfo(service::camera::AlgDemuxStatus::AlgDemuxOpened); if (!was_repeat) { action_status_ = util::ErrorEnum::DemuxStreamStart; @@ -218,36 +219,36 @@ void AlgChannelDemux::HandleStream() { duration_stat_.EndSample(); if (media::ReadFrameStatus::Success != ret) { if (media::ReadFrameStatus::StreamEnd == ret) { - if ((video_read_count_ < video_repeat_count_) || (video_repeat_count_ <= 0)) { - LOG_INFO("{}:{} Stream End Now RepeatCount:{} Max RepeatCount:{}", kTag, channel_id_, - video_read_count_, video_repeat_count_); - is_need_repeat_ = true; - } else { - // Do not report completion for live streams. - if ((!is_have_report_) && (!IsLiveStream())) { - is_have_report_ = true; - NotifyOnComplete(); - } - } - if (IsLiveStream()) { - LOG_INFO("{}:{} Live Stream End Need ReOpen Or Request Url", kTag, channel_id_); - // Live stream has no definitive end — request new URL or reopen. - SetStatusInfo(service::camera::AlgDemuxStatus::AlgDemuxReadFailed); + const bool is_live_stream = IsLiveStream(); + const auto disposition = + flow::DecideVideoEof(is_live_stream, video_read_count_, video_repeat_count_); + if (flow::VideoEofDisposition::Reopen == disposition) { is_need_repeat_ = true; - action_status_ = util::ErrorEnum::DemuxReadStreamFail; - } else { - SetStatusInfo(service::camera::AlgDemuxStatus::AlgDemuxReadEnd); - if (!is_need_repeat_) { - action_status_ = util::ErrorEnum::DemuxStreamClosed; + if (is_live_stream) { + LOG_INFO("{}:{} Live Stream End Need ReOpen Or Request Url", kTag, channel_id_); + SetStatusInfo(service::camera::AlgDemuxStatus::AlgDemuxReadFailed); + action_status_ = util::ErrorEnum::DemuxReadStreamFail; + return; } - // When is_need_repeat_ is true the stream is about to loop — - // keep action_status_ as Success from the last frame read to - // prevent transient "取流无数据" during the loop transition. - // Signal unfinished recording tasks to finalize. + LOG_INFO("{}:{} Stream End Now RepeatCount:{} Max RepeatCount:{}", kTag, channel_id_, + video_read_count_, video_repeat_count_); + // A loop boundary is not terminal. Keep the last Reading state + // and successful action status until OpenStream publishes the + // next Opened/Reading transition. frame_packet->index = -1; recorder_->TaskFrame(frame_packet); + return; + } + + if (!is_have_report_) { + is_have_report_ = true; + NotifyOnComplete(); } + SetStatusInfo(service::camera::AlgDemuxStatus::AlgDemuxReadEnd); + action_status_ = util::ErrorEnum::DemuxStreamClosed; + frame_packet->index = -1; + recorder_->TaskFrame(frame_packet); return; } SetStatusInfo(service::camera::AlgDemuxStatus::AlgDemuxReadFailed); diff --git a/src/flow/channel/AlgChannelDemuxStream.cc b/src/flow/channel/AlgChannelDemuxStream.cc index ffee00469..2325df608 100644 --- a/src/flow/channel/AlgChannelDemuxStream.cc +++ b/src/flow/channel/AlgChannelDemuxStream.cc @@ -81,7 +81,7 @@ void AlgChannelDemux::RequestUrl() { getVideoReq, getVideoRsp)) { LOG_WARN("{}{} GetVideoPlay Failed", kTag, channel_id_); } else { - LOG_INFO("{}{} GetVideoPlay {}", kTag, channel_id_, getVideoRsp.resData.streamUrl); + LOG_INFO("{}{} GetVideoPlay OK", kTag, channel_id_); SetUrl(getVideoRsp.resData.streamUrl); } } @@ -145,7 +145,8 @@ bool AlgChannelDemux::GetAttr(MsgCameraAttr& attr) { attr.channelStatus = ChannelStatus::ChannelStatusResolusionUnSupport; } } - attr.dataStatus = static_cast<int>(status_.status); + attr.dataStatus = static_cast<int>(status_.status); + attr.repeatPending = is_need_repeat_.load(); return true; } diff --git a/src/flow/channel/AlgMp4Record.cc b/src/flow/channel/AlgMp4Record.cc index d42187d5a..8bf1ea309 100644 --- a/src/flow/channel/AlgMp4Record.cc +++ b/src/flow/channel/AlgMp4Record.cc @@ -83,7 +83,7 @@ AlgMp4Record::~AlgMp4Record() { std::string mp4Name = mp4_name_; if (service::ServiceRegistry::Instance().Get<service::IConfigReadService>().IsNetworkModel()) { - LOG_INFO(" {} Wait To Upload To {}", mp4_name_, upload_url_); + LOG_INFO("{} Wait To Upload", mp4_name_); service::ServiceRegistry::Instance().Get<service::IFileService>().UploadFile( event_name_, diff --git a/src/flow/channel/VideoEofPolicy.h b/src/flow/channel/VideoEofPolicy.h new file mode 100644 index 000000000..121166b78 --- /dev/null +++ b/src/flow/channel/VideoEofPolicy.h @@ -0,0 +1,28 @@ +// Local-video EOF lifecycle policy shared by the demuxer and monitor guard. + +#pragma once + +namespace cosmo::flow { + +enum class VideoEofDisposition { + Reopen, + Complete, +}; + +// video_read_count is the number of successful opens, including the current +// playback. A non-positive repeat count means infinite playback. +constexpr VideoEofDisposition DecideVideoEof(bool is_live_stream, int video_read_count, + int video_repeat_count) { + if (is_live_stream || video_repeat_count <= 0 || video_read_count < video_repeat_count) { + return VideoEofDisposition::Reopen; + } + return VideoEofDisposition::Complete; +} + +// Defense for the camera monitor: a transient ReadEnd can never be terminal +// while the demuxer has already committed to reopening the stream. +constexpr bool IsTerminalOfflineReadEnd(bool is_read_end, bool repeat_pending) { + return is_read_end && !repeat_pending; +} + +} // namespace cosmo::flow diff --git a/src/flow/classify/PClassifier.cc b/src/flow/classify/PClassifier.cc index 18ab29881..e72bf4bc7 100644 --- a/src/flow/classify/PClassifier.cc +++ b/src/flow/classify/PClassifier.cc @@ -57,6 +57,12 @@ bool PClassifier::ActionInit() { return true; } +void PClassifier::ActionDestroy() { + std::lock_guard<std::shared_mutex> lock(m_mtx); + m_inst.reset(); + m_actionStatus = util::ErrorEnum::ActionStop; +} + // Key format reference: aiParam.#{labelCode}.confidence bool PClassifier::ValidKey(MsgDynamicKeyValue& param) { if (param.keys.empty()) { @@ -111,6 +117,11 @@ bool PClassifier::SetParam(const std::string& /*taskId*/, std::vector<MsgDynamic return true; } +bool PClassifier::SetArea(const std::string& /*taskId*/, std::vector<MsgTaskArea>& /*areas*/, + std::vector<MsgTaskArea>& /*shieldedAreas*/) { + return true; +} + util::ErrorEnum PClassifier::HandPic(AlgDataPtr algData) { if (!algData || !algData->chanDataDec.frame || !algData->chanDataDec.frame->Active()) { return util::ErrorEnum::FrameDataInvalid; @@ -124,12 +135,26 @@ util::ErrorEnum PClassifier::HandPic(AlgDataPtr algData) { return util::ErrorEnum::Success; } + std::shared_ptr<AiClassifierUnify> instance; + { + std::shared_lock<std::shared_mutex> lock(m_mtx); + instance = m_inst; + } + if (!instance) + return util::ErrorEnum::AI_INST_NOTCREATED; + m_durationStat.BeginSample(); - m_actionStatus = m_inst->Classify(algData->chanDataDec.frame, algData->chanDataDetect.detRet->targets); + const auto result = + instance->Classify(algData->chanDataDec.frame, algData->chanDataDetect.detRet->targets); m_durationStat.EndSample(); + { + std::lock_guard<std::shared_mutex> lock(m_mtx); + if (m_inst == instance) + m_actionStatus = result; + } algData->dataType = AlgDataType::TaskDataClassify; return util::ErrorEnum::Success; } -} // namespace cosmo \ No newline at end of file +} // namespace cosmo diff --git a/src/flow/classify/PClassifier.h b/src/flow/classify/PClassifier.h index 927a60e30..4fd1322f6 100644 --- a/src/flow/classify/PClassifier.h +++ b/src/flow/classify/PClassifier.h @@ -20,12 +20,15 @@ class PClassifier : public PActionBase { ~PClassifier(); bool ActionInit() override; + void ActionDestroy() override; util::ErrorEnum HandPic(AlgDataPtr algData) override; // Modify parameters - update existing parameters incrementally. bool ModifyParam(const std::string& taskId, std::vector<MsgDynamicKeyValue>& params) override; // Set parameters - clear all existing parameters and apply new ones. bool SetParam(const std::string& taskId, std::vector<MsgDynamicKeyValue>& params) override; + bool SetArea(const std::string& taskId, std::vector<MsgTaskArea>& areas, + std::vector<MsgTaskArea>& shieldedAreas) override; private: bool ValidKey(MsgDynamicKeyValue& param); diff --git a/src/flow/common/AlgDataQueue.h b/src/flow/common/AlgDataQueue.h index 1e8de716a..cf893b795 100644 --- a/src/flow/common/AlgDataQueue.h +++ b/src/flow/common/AlgDataQueue.h @@ -43,6 +43,11 @@ class AlgDataQueue { bool IsRunning() const; + /// Snapshot whether an immediate non-forced insert can succeed. This is + /// used by Rockchip delayed Copy-out to avoid allocating a host frame that + /// a saturated downstream queue would discard immediately. + bool CanAccept() const; + const std::string& Name() const; size_t RestSize() const; diff --git a/src/flow/common/AlgDataQueue.inl b/src/flow/common/AlgDataQueue.inl index d95096b70..604bc215f 100644 --- a/src/flow/common/AlgDataQueue.inl +++ b/src/flow/common/AlgDataQueue.inl @@ -102,6 +102,12 @@ bool AlgDataQueue<DataType, QueueType>::IsRunning() const { return m_isRunning; } +template <typename DataType, typename QueueType> +bool AlgDataQueue<DataType, QueueType>::CanAccept() const { + std::lock_guard<std::mutex> lock(m_mtxQueue); + return m_isRunning && m_queue.size() < m_maxSize; +} + template <typename DataType, typename QueueType> const std::string& AlgDataQueue<DataType, QueueType>::Name() const { std::lock_guard<std::mutex> lock(m_mtxQueue); diff --git a/src/flow/common/AlgDataQueueDistributor.cc b/src/flow/common/AlgDataQueueDistributor.cc index f9e1bab04..12242c5f6 100644 --- a/src/flow/common/AlgDataQueueDistributor.cc +++ b/src/flow/common/AlgDataQueueDistributor.cc @@ -238,6 +238,85 @@ int AlgDataQueueDistributor::DistributorData(AlgDataPtr Frame, VideoFramePtr Dat return msgCount; } +AlgFrameDistributionPlan AlgDataQueueDistributor::PrepareFrameDistribution(AlgDataPtr frame) { + AlgFrameDistributionPlan plan; + in_fps_ = input_fps_calc_.Fps(); + data_index_++; + UpdateCtrlFps(); + if (!frame) { + return plan; + } + + std::shared_lock<std::shared_mutex> lock(task_mtx_); + for (auto& task_group : tasks_) { + const bool metadata_only_group = + !task_group.tasks.empty() && + std::all_of(task_group.tasks.begin(), task_group.tasks.end(), + [](const AlgTaskUnit& task) { return task.actionId == BAStreamChannel_Code.data(); }); + if (metadata_only_group) { + // The camera-owned BA_00001 ChannelTask inherits an empty + // AlgActionBase::HandFrame. It keeps channel lifecycle/FPS status + // alive but never reads decoded pixels, so forwarding the original + // packet metadata preserves that behavior without forcing an MPP + // frame to be copied to Host I420. + if (task_group.que && task_group.que->CanAccept()) { + task_group.que->Insert(frame); + } else if (task_group.que) { + task_group.que->RecordDiscard(); + } + continue; + } + if (out_fps_ctl_.IsFilter(data_index_, task_group.max_task_fps, frame->firstTimePoint)) { + continue; + } + if (!task_group.que) { + continue; + } + if (!task_group.que->CanAccept()) { + task_group.que->RecordDiscard(); + continue; + } + const bool detector_group = + !task_group.tasks.empty() && + std::all_of(task_group.tasks.begin(), task_group.tasks.end(), + [](const AlgTaskUnit& task) { return task.actionId == AADetect_Code.data(); }); + plan.native_inference_eligible = plan.native_inference_eligible && detector_group; + plan.queues.push_back(task_group.que); + } + return plan; +} + +int AlgDataQueueDistributor::DistributorPreparedFrame( + const AlgFrameDistributionPlan& plan, AlgDataPtr frame, VideoFramePtr data, + std::function<AlgDataPtr(AlgDataPtr, VideoFramePtr)> func) { + if (!frame || !data || plan.Empty()) { + return 0; + } + + auto converted = func(frame, data); + if (!converted) { + return 0; + } + + int message_count = 0; + for (const auto& queue : plan.queues) { + // Native inference buffers are released by each detector immediately + // after its synchronous Forward. Give parallel detector queues their + // own AlgData wrapper so one consumer cannot clear another consumer's + // borrowed DMA-BUF descriptor. VideoFrame and the native owner remain + // shared; the ordinary single-queue path keeps its existing allocation + // behavior. + auto queued = converted; + if (plan.queues.size() > 1 && converted->chanDataDec.native_buffer) { + queued = AlgDataCopy(converted); + } + if (queue && queue->Insert(std::move(queued))) { + message_count += 1; + } + } + return message_count; +} + // Only send to the channel registered by the task. Used for detection data distribution. // When the detector is multiplexed to multiple channels, those of the same channel are distributed through // channelId. diff --git a/src/flow/common/AlgDataQueueDistributor.h b/src/flow/common/AlgDataQueueDistributor.h index a9dee89dc..0df794901 100644 --- a/src/flow/common/AlgDataQueueDistributor.h +++ b/src/flow/common/AlgDataQueueDistributor.h @@ -26,6 +26,19 @@ struct AlgDataTask { std::vector<AlgTaskUnit> tasks; }; +struct AlgFrameDistributionPlan { + std::vector<std::shared_ptr<AlgDataQueue<AlgDataPtr>>> queues; + bool native_inference_eligible{true}; + + [[nodiscard]] bool Empty() const { + return queues.empty(); + } + + [[nodiscard]] bool SupportsNativeInference() const { + return !queues.empty() && native_inference_eligible; + } +}; + class AlgDataQueueDistributor { public: explicit AlgDataQueueDistributor(const std::string& moduleName); @@ -44,6 +57,16 @@ class AlgDataQueueDistributor { int DistributorData(AlgDataPtr Frame, VideoFramePtr Data, std::function<AlgDataPtr(AlgDataPtr, VideoFramePtr)> func); + /// Advance frame-rate control and snapshot queues that will actually + /// accept this frame. Queue saturation is treated as an early discard so + /// the Rockchip decoder can skip Host I420 materialization entirely. + AlgFrameDistributionPlan PrepareFrameDistribution(AlgDataPtr frame); + + /// Complete a previously prepared distribution after the host frame has + /// been materialized exactly once. + int DistributorPreparedFrame(const AlgFrameDistributionPlan& plan, AlgDataPtr frame, VideoFramePtr data, + std::function<AlgDataPtr(AlgDataPtr, VideoFramePtr)> func); + // Distribute data to specific registered queues // Only send to the channel registered by the task. Used for detection data distribution. // When the detector is multiplexed to multiple channels, those of the same channel are distributed diff --git a/src/flow/common/AlgDetectTypes.h b/src/flow/common/AlgDetectTypes.h index 099b0dbe0..c491e4d2d 100644 --- a/src/flow/common/AlgDetectTypes.h +++ b/src/flow/common/AlgDetectTypes.h @@ -9,6 +9,7 @@ #include "flow/common/AlgAlarmTypes.h" #include "flow/common/AlgDataType.h" #include "infer/AiCommon.h" +#include "media/NativeVideoBuffer.h" #include "media/VideoFrame.h" #include "media/VideoPacket.h" #include "util/Rect.h" @@ -23,6 +24,7 @@ struct AlgChannelDataOrig { struct AlgChannelDataDec { VideoFramePtr frame; // AI processed frame, might be YUV or BGR depending on platform + media::NativeVideoBufferPtr native_buffer; // Optional borrowed hardware inference source. int64_t reportTimeStamp{0}; }; diff --git a/src/flow/detect/AiDetector.cc b/src/flow/detect/AiDetector.cc index 7f9e70ef6..68ed58421 100644 --- a/src/flow/detect/AiDetector.cc +++ b/src/flow/detect/AiDetector.cc @@ -65,6 +65,14 @@ namespace { return std::clamp(parsed, static_cast<size_t>(1), kMaxRuntimeReuseLimit); } + ai_detector_fps::ReuseProfile BackendDefaultReuseProfile() { +#ifdef COSMO_NN_USE_RKNN_BACKEND + return ai_detector_fps::RknnDefaultReuseProfile(); +#else + return ai_detector_fps::DefaultReuseProfile(); +#endif + } + // Per-algCode fps budget overrides for instance placement. Unlisted algCodes fall back to // kDefaultInstanceFpsBudget. Populate from per-model stress-test results. float LookupInstanceFpsBudget(const std::string& alg_code) { @@ -88,14 +96,14 @@ namespace { ai_detector_fps::ReuseProfile LookupReuseProfile(const std::string& alg_code) { const auto raw_value = LookupPlacementEnv(kEnvReuseProfile, alg_code); if (raw_value.empty()) { - return ai_detector_fps::DefaultReuseProfile(); + return BackendDefaultReuseProfile(); } auto profile = ai_detector_fps::ParseReuseProfile(raw_value); if (profile.empty()) { LOG_WARN("{}Invalid {} value:{}, fallback to default reuse profile", kTag, kEnvReuseProfile, raw_value); - return ai_detector_fps::DefaultReuseProfile(); + return BackendDefaultReuseProfile(); } return profile; } @@ -149,7 +157,9 @@ AiDetector::AiDetector(ActionNode& action) name_ = action.atomicCode; uuid = util::GenerateUUID(); - batch_count_ = 4; + // Admit the first frame immediately. AiSdkInit replaces this with the + // loaded model's bounded batch before the next queue drain. + batch_count_ = 1; max_reuse_count_ = LookupMaxReuseCount(alg_code_); instance_fps_budget_ = LookupInstanceFpsBudget(alg_code_); reuse_profile_ = LookupReuseProfile(alg_code_); @@ -213,10 +223,20 @@ bool AiDetector::AiSdkInit() { init_retry_count_); return false; } - init_retry_count_ = 0; - action_status = util::ErrorEnum::AI_INST_CREATED; - labels_ = detector_->GetLabels(); - LOG_INFO("{}[{} {}] {} Init Sdk", kTag, name_, uuid, alg_code_); + init_retry_count_ = 0; + action_status = util::ErrorEnum::AI_INST_CREATED; + labels_ = detector_->GetLabels(); + size_t model_max_batch = 1; + const auto batch_status = detector_->GetMaxBatchSize(model_max_batch); + if (batch_status != util::ErrorEnum::Success || model_max_batch == 0) { + LOG_WARN("{}[{} {}] {} invalid model max batch:{}, keep single-frame drain", kTag, name_, uuid, + alg_code_, model_max_batch); + model_max_batch = 1; + } + batch_count_ = ai_detector_fps::EffectiveDetectorDrainBatch(ai_detector_fps::kMaxDetectorDrainBatch, + model_max_batch); + LOG_INFO("{}[{} {}] {} Init Sdk ModelMaxBatch:{} DrainBatch:{}", kTag, name_, uuid, alg_code_, + model_max_batch, batch_count_); is_detector_inst_initialized_ = true; return true; } @@ -263,10 +283,12 @@ void AiDetector::HandFrames(std::vector<AlgDataPtr> alg_datas) { return; } std::vector<VideoFramePtr> images; + std::vector<media::NativeVideoBufferPtr> native_buffers; std::vector<AlgDataPtr> activeAlgDatas; for (auto algData : alg_datas) { - if (algData->chanDataDec.frame->Active()) { + if (algData && algData->chanDataDec.frame && algData->chanDataDec.frame->Active()) { images.push_back(algData->chanDataDec.frame); + native_buffers.push_back(algData->chanDataDec.native_buffer); activeAlgDatas.push_back(algData); } } @@ -285,7 +307,11 @@ void AiDetector::HandFrames(std::vector<AlgDataPtr> alg_datas) { confThres = active_confidence_; LOG_INFO("{}[{} {}] Confidence Active. confThres size:{}", kTag, name_, uuid, confThres.size()); } - action_status = detector_->Detect(images, confThres, detRsts); + action_status = detector_->Detect(images, native_buffers, confThres, detRsts); + native_buffers.clear(); + for (auto& alg_data : activeAlgDatas) { + alg_data->chanDataDec.native_buffer.reset(); + } if (util::ErrorEnum::Success != action_status) { LOG_ERRO("{}[{} {}] Detect Failed. Ret:{} images:{} confThres:{}", kTag, name_, uuid, action_status, images.size(), confThres.size()); diff --git a/src/flow/detect/AiDetectorFps.h b/src/flow/detect/AiDetectorFps.h index 4e206fb69..8c505a0a5 100644 --- a/src/flow/detect/AiDetectorFps.h +++ b/src/flow/detect/AiDetectorFps.h @@ -38,6 +38,8 @@ inline constexpr size_t kUnknownFpsReuseCount = 3; namespace ai_detector_fps { + inline constexpr size_t kMaxDetectorDrainBatch = 4; + struct ReuseRule { float max_fps{0.0f}; size_t reuse_count{0}; @@ -50,6 +52,19 @@ namespace ai_detector_fps { return {{8.0f, 3}, {12.0f, 2}, {100.0f, 1}}; } + // RKNN CV graphs on RK3576 are admitted conservatively until a + // model/candidate-specific capacity result proves that sharing is safe. + // Environment overrides remain available for qualified models. + inline ReuseProfile RknnDefaultReuseProfile() { + return {{100.0f, 1}}; + } + + inline size_t EffectiveDetectorDrainBatch(size_t configured_batch, size_t model_max_batch) { + const size_t safe_configured = std::max<size_t>(1, configured_batch); + const size_t safe_model_max = std::max<size_t>(1, model_max_batch); + return std::min(safe_configured, safe_model_max); + } + inline bool HasConfiguredFps(float fps) { return fps > 0.0f && std::isfinite(fps); } @@ -69,8 +84,8 @@ namespace ai_detector_fps { return false; } - char* end = nullptr; - errno = 0; + char* end = nullptr; + errno = 0; const float result = std::strtof(trimmed.c_str(), &end); if (end == trimmed.c_str() || *end != '\0' || errno == ERANGE || !HasConfiguredFps(result)) { return false; @@ -85,8 +100,8 @@ namespace ai_detector_fps { return false; } - char* end = nullptr; - errno = 0; + char* end = nullptr; + errno = 0; const unsigned long long result = std::strtoull(trimmed.c_str(), &end, 10); if (end == trimmed.c_str() || *end != '\0' || errno == ERANGE || result == 0 || result > std::numeric_limits<size_t>::max()) { diff --git a/src/flow/detect/PDetector.cc b/src/flow/detect/PDetector.cc index 310b1d8c7..c4c8b80ec 100644 --- a/src/flow/detect/PDetector.cc +++ b/src/flow/detect/PDetector.cc @@ -58,6 +58,12 @@ bool PDetector::ActionInit() { return true; } +void PDetector::ActionDestroy() { + std::lock_guard<std::shared_mutex> lock(mtx_); + inst_.reset(); + action_status_ = util::ErrorEnum::ActionStop; +} + // Parameter key format: aiParam.#{labelCode}.confidence bool PDetector::ValidKey(const MsgDynamicKeyValue& param) const { if (param.keys.empty()) { @@ -162,16 +168,25 @@ util::ErrorEnum PDetector::HandPic(AlgDataPtr algData) { // Confidence thresholds std::vector<AiConfidence> confThres; + std::shared_ptr<AiDetectorUnify> instance; { std::shared_lock<std::shared_mutex> lock(mtx_); confThres = params_.confidence; + instance = inst_; } + if (!instance) + return util::ErrorEnum::AI_INST_NOTCREATED; std::vector<std::vector<AiDetectRstEl>> detRsts; std::vector<VideoFramePtr> images = {algData->chanDataDec.frame}; duration_stat_.BeginSample(); - action_status_ = inst_->Detect(images, confThres, detRsts); + const auto result = instance->Detect(images, confThres, detRsts); duration_stat_.EndSample(); + { + std::lock_guard<std::shared_mutex> lock(mtx_); + if (inst_ == instance) + action_status_ = result; + } if (!algData->chanDataDetect.detRet) { algData->chanDataDetect.detRet = std::make_shared<DataDetTrackClassify>(); @@ -188,4 +203,4 @@ util::ErrorEnum PDetector::HandPic(AlgDataPtr algData) { return util::ErrorEnum::Success; } -} // namespace cosmo \ No newline at end of file +} // namespace cosmo diff --git a/src/flow/detect/PDetector.h b/src/flow/detect/PDetector.h index e354531b3..e02a43a78 100644 --- a/src/flow/detect/PDetector.h +++ b/src/flow/detect/PDetector.h @@ -24,6 +24,7 @@ class PDetector : public PActionBase { ~PDetector() override; bool ActionInit() override; + void ActionDestroy() override; util::ErrorEnum HandPic(AlgDataPtr algData) override; // Modify parameters — update on top of existing parameters diff --git a/src/flow/qwen3vl/OpenAiVlmClient.cc b/src/flow/qwen3vl/OpenAiVlmClient.cc index 9f24e8c59..c42cb1d65 100644 --- a/src/flow/qwen3vl/OpenAiVlmClient.cc +++ b/src/flow/qwen3vl/OpenAiVlmClient.cc @@ -136,15 +136,16 @@ util::ErrorEnum OpenAiVlmClient::Generate(const OpenAiVlmConfig& config, auto response = service::ServiceRegistry::Instance().Get<service::IHttpClient>().Post( url, body.dump(), "application/json", 3, timeout_sec, headers); if (response.statusCode < 200 || response.statusCode >= 300) { - LOG_WARN("{}request failed. status:{} body:{}", kTag, response.statusCode, response.body); + LOG_WARN("{}request failed. status:{} response_bytes:{}", kTag, response.statusCode, + response.body.size()); return util::ErrorEnum::AI_FORWARD_FAILED; } nlohmann::json response_json; try { response_json = nlohmann::json::parse(response.body); - } catch (const std::exception& e) { - LOG_WARN("{}response json parse failed: {}", kTag, e.what()); + } catch (const std::exception&) { + LOG_WARN("{}response json parse failed, response_bytes:{}", kTag, response.body.size()); return util::ErrorEnum::AI_PARSE_OUTPUT_FAILED; } @@ -153,7 +154,7 @@ util::ErrorEnum OpenAiVlmClient::Generate(const OpenAiVlmConfig& config, result.frame_index = static_cast<int64_t>(images[i]->GetFrameIndex()); result.timestamp = images[i]->GetTimestamp(); if (result.text.empty()) { - LOG_WARN("{}empty text in response: {}", kTag, response.body); + LOG_WARN("{}empty text in response, response_bytes:{}", kTag, response.body.size()); } results.push_back(std::move(result)); } diff --git a/src/flow/stream/RtmpStreamPusher.cc b/src/flow/stream/RtmpStreamPusher.cc index cafe7edc6..f96ecae64 100644 --- a/src/flow/stream/RtmpStreamPusher.cc +++ b/src/flow/stream/RtmpStreamPusher.cc @@ -90,7 +90,7 @@ void RtmpStreamPusher::Stop() { return; } - LOG_INFO("RTMP publisher stopping: url={}", push_url_); + LOG_INFO("{}", "RTMP publisher stopping"); { std::lock_guard<std::mutex> lock(output_mtx_); CloseOutput(); @@ -99,7 +99,7 @@ void RtmpStreamPusher::Stop() { media::GetPreviewPipelineMetrics().PublisherClosed(); } ready_cv_.notify_all(); - LOG_INFO("RTMP publisher stopped and released: url={}", push_url_); + LOG_INFO("{}", "RTMP publisher stopped and released"); } std::string RtmpStreamPusher::LastError() const { @@ -115,7 +115,7 @@ void RtmpStreamPusher::RecordFailure(const char* stage, int error_no) { stream_ready_ = false; } ready_cv_.notify_all(); - LOG_ERRO("RTMP publisher failure: stage={} error={} url={}", stage, GetAvErr(error_no), push_url_); + LOG_ERRO("RTMP publisher failure: stage={} error={}", stage, GetAvErr(error_no)); } int RtmpStreamPusher::InitOutput() { @@ -143,7 +143,7 @@ int RtmpStreamPusher::InitOutput() { return ret; } - LOG_INFO("RTMP output initialized: url={}", push_url_); + LOG_INFO("{}", "RTMP output initialized"); return 0; } @@ -177,7 +177,7 @@ bool RtmpStreamPusher::ReopenOutput() { return false; } - LOG_INFO("reopen RTMP output success: {}", push_url_); + LOG_INFO("{}", "reopen RTMP output success"); return true; } diff --git a/src/flow/stream/StreamViewer.cc b/src/flow/stream/StreamViewer.cc index c82faf178..407395def 100644 --- a/src/flow/stream/StreamViewer.cc +++ b/src/flow/stream/StreamViewer.cc @@ -117,7 +117,7 @@ StreamViewer::StreamViewer(AlgChannelPtr channelInst, const std::string& channel ctrl_fps_ = 10.0; } url = BuildRtmpPushUrl(channelId, algId); - LOG_INFO("{}/{} RTMP push url: {}", channel_id_, alg_id_, url); + LOG_INFO("{}/{} RTMP push URL prepared", channel_id_, alg_id_); out_fps_ctl_.ChangeFps(attr.fps, ctrl_fps_); const bool shouldEncodeForPreview = !((algId.empty()) && (attr.codec == "H264")); @@ -167,7 +167,12 @@ StreamViewer::StreamViewer(AlgChannelPtr channelInst, const std::string& channel channelInst->AddViewerPacketQueue(async_packet_queue_); packet_queue_attached_ = true; } else { +#ifdef COSMO_MEDIA_USE_ROCKCHIP_BACKEND + channelInst->AddViewerFrameQueue(alg_id_, async_frame_queue_, + [this]() { return PrepareFrameForDecode(); }); +#else channelInst->AddViewerFrameQueue(alg_id_, async_frame_queue_); +#endif frame_queue_attached_ = true; } } else // Task preview, overlay @@ -175,7 +180,12 @@ StreamViewer::StreamViewer(AlgChannelPtr channelInst, const std::string& channel if (EncoderReady()) { data_overview_ = true; overviewer_ = std::make_shared<StreamViewerOverview>(channel_id_, alg_id_); +#ifdef COSMO_MEDIA_USE_ROCKCHIP_BACKEND + channelInst->AddViewerFrameQueue(alg_id_, async_frame_queue_, + [this]() { return PrepareFrameForDecode(); }); +#else channelInst->AddViewerFrameQueue(alg_id_, async_frame_queue_); +#endif frame_queue_attached_ = true; #ifdef COSMO_MEDIA_USE_CPU_BACKEND } else if (attr.codec == "H264" && IsEnabledEnv("COSMO_CPU_OVERLAY_RAW_FALLBACK")) { @@ -261,20 +271,42 @@ void StreamViewer::UpdateCtrlFps() { } } +bool StreamViewer::PrepareFrameForDecode() { + if (stopped_.load()) { + return false; + } + std::lock_guard<std::mutex> lock(frame_filter_mtx_); + in_fps_ = input_fps_calc_.Fps(); + data_index_++; + UpdateCtrlFps(); + if (out_fps_ctl_.IsFilter(data_index_)) { + return false; + } + if (!async_frame_queue_.CanAccept()) { + async_frame_queue_.RecordDiscard(); + return false; + } + return true; +} + void StreamViewer::HandleFrame(VideoFramePtr frame) { if (stopped_.load()) { return; } +#ifndef COSMO_MEDIA_USE_ROCKCHIP_BACKEND in_fps_ = input_fps_calc_.Fps(); data_index_++; UpdateCtrlFps(); +#endif if (!VideoFrameValid(frame)) { return; } +#ifndef COSMO_MEDIA_USE_ROCKCHIP_BACKEND if (out_fps_ctl_.IsFilter(data_index_)) // Frame rate filtering { return; } +#endif if (overviewer_) { if (encoder_) { diff --git a/src/flow/stream/StreamViewer.h b/src/flow/stream/StreamViewer.h index dc5191b13..fe7571534 100644 --- a/src/flow/stream/StreamViewer.h +++ b/src/flow/stream/StreamViewer.h @@ -82,6 +82,7 @@ class StreamViewer { private: void HandlePacket(VideoPacketPtr Frame); void HandleFrame(VideoFramePtr Frame); + bool PrepareFrameForDecode(); void UpdateCtrlFps(); bool EncoderReady() const; @@ -106,6 +107,7 @@ class StreamViewer { util::FpsCtrl out_fps_ctl_; util::FpsCalc input_fps_calc_; // Input FPS calculator size_t data_index_{0}; + std::mutex frame_filter_mtx_; RtmpStreamPusherPtr video_pusher_{nullptr}; StreamViewerOverviewPtr overviewer_{nullptr}; diff --git a/src/flow/stream/VideoStreamPush.cc b/src/flow/stream/VideoStreamPush.cc index 1e6189c7c..410018c50 100644 --- a/src/flow/stream/VideoStreamPush.cc +++ b/src/flow/stream/VideoStreamPush.cc @@ -14,7 +14,7 @@ VideoStreamPush::VideoStreamPush(const std::string& url, int width, int height, width = 1920; height = 1080; } - LOG_INFO("rtmp push url: {}, width: {}, height: {}, fps: {} ", push_url_, width, height, fps); + LOG_INFO("RTMP push configured, width:{}, height:{}, fps:{}", width, height, fps); if ((width < 64) || (height < 64) || (fps < 0.1f)) return; diff --git a/src/infer/AiClassifierUnify.cc b/src/infer/AiClassifierUnify.cc index 490e9dc6e..3e2ddf660 100644 --- a/src/infer/AiClassifierUnify.cc +++ b/src/infer/AiClassifierUnify.cc @@ -23,8 +23,10 @@ util::ErrorEnum AiClassifierUnify::Init() { return util::ErrorEnum::Created; } + cosmo::nn::DefaultComponent::Options options; + options.profiler = &profiler_; classifier_ = - std::make_unique<cosmo::nn::DefaultComponent>(cfg_path_, model_path_, GetDeviceType(), &profiler_); + std::make_unique<cosmo::nn::DefaultComponent>(options, cfg_path_, model_path_, GetDeviceType()); LOG_DEBUG("DEBUG: Classifier {} Init", model_path_); max_batch_size_ = static_cast<size_t>(classifier_->GetMaxBatchSize()); diff --git a/src/infer/AiComponment.cc b/src/infer/AiComponment.cc index 4f7f34870..8ee744ffa 100644 --- a/src/infer/AiComponment.cc +++ b/src/infer/AiComponment.cc @@ -16,6 +16,8 @@ void AppProfiler::ReportNodeTime(const char* /*node_name*/, double /*time*/) {} cosmo::nn::DeviceType GetDeviceType() { #if defined(COSMO_NN_USE_CPU_BACKEND) return cosmo::nn::DeviceType::DEVICE_CPU; +#elif defined(COSMO_NN_USE_RKNN_BACKEND) + return cosmo::nn::DeviceType::DEVICE_RKNN; #else return cosmo::nn::DeviceType::DEVICE_SOPHON_TPU; #endif @@ -30,6 +32,12 @@ cosmo::nn::ImageFormat GetImageFormatType() { util::ErrorEnum ConvertImagesToBlobs(const std::vector<VideoFramePtr>& images, std::vector<std::shared_ptr<cosmo::nn::Blob>>& blobs) { + return ConvertImagesToBlobs(images, {}, blobs); +} + +util::ErrorEnum ConvertImagesToBlobs(const std::vector<VideoFramePtr>& images, + const std::vector<media::NativeVideoBufferPtr>& native_buffers, + std::vector<std::shared_ptr<cosmo::nn::Blob>>& blobs) { if (images.empty()) { LOG_INFO("{}", "Input Images Is Empty."); return util::ErrorEnum::InvalidParam; @@ -107,6 +115,22 @@ util::ErrorEnum ConvertImagesToBlobs(const std::vector<VideoFramePtr>& images, desc.device_type = GetDeviceType(); cosmo::nn::BlobHandle handle; handle.base = image->GetData(); + if (i < native_buffers.size() && native_buffers[i] && native_buffers[i]->Valid() && + native_buffers[i]->width == static_cast<int>(image->GetWidth()) && + native_buffers[i]->height == static_cast<int>(image->GetHeight())) { + const auto& native = *native_buffers[i]; + handle.native_image.fd = native.fd; + handle.native_image.bytes = native.bytes; + handle.native_image.width = native.width; + handle.native_image.height = native.height; + handle.native_image.width_stride = native.width_stride; + handle.native_image.height_stride = native.height_stride; + if (native.format == media::NativeVideoBufferFormat::NV12) { + handle.native_image.format = cosmo::nn::IMAGE_NV12; + } else if (native.format == media::NativeVideoBufferFormat::I420) { + handle.native_image.format = cosmo::nn::IMAGE_I420; + } + } blob->SetBlobDesc(desc); blob->SetHandle(handle); blobs.push_back(blob); diff --git a/src/infer/AiComponment.h b/src/infer/AiComponment.h index 64c64dcb3..0d2857ac5 100644 --- a/src/infer/AiComponment.h +++ b/src/infer/AiComponment.h @@ -2,6 +2,7 @@ #pragma once +#include "media/NativeVideoBuffer.h" #include "media/VideoFrame.h" #include "nn/core/blob.h" #include "nn/utils/profiler.h" @@ -19,6 +20,9 @@ cosmo::nn::DeviceType GetDeviceType(); util::ErrorEnum ConvertImagesToBlobs(const std::vector<VideoFramePtr>& images, std::vector<std::shared_ptr<cosmo::nn::Blob>>& blobs); +util::ErrorEnum ConvertImagesToBlobs(const std::vector<VideoFramePtr>& images, + const std::vector<media::NativeVideoBufferPtr>& native_buffers, + std::vector<std::shared_ptr<cosmo::nn::Blob>>& blobs); util::ErrorEnum ConvertDatasToBlobs(const std::vector<std::vector<int>>& datas, std::vector<std::shared_ptr<cosmo::nn::Blob>>& blobs); diff --git a/src/infer/AiDetectorUnify.cc b/src/infer/AiDetectorUnify.cc index e6be8b28b..60a5dcf75 100644 --- a/src/infer/AiDetectorUnify.cc +++ b/src/infer/AiDetectorUnify.cc @@ -3,13 +3,25 @@ #include "infer/AiDetectorUnify.h" #include <algorithm> +#include <chrono> #include <exception> #include <iterator> +#include <utility> +#include "nn/core/inference_pipeline_metrics.h" #include "util/Log.h" #include "util/UuidUtil.h" namespace cosmo { +namespace { + using MetricsClock = std::chrono::steady_clock; + + uint64_t ElapsedNanoseconds(MetricsClock::time_point started_at) { + return static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::nanoseconds>(MetricsClock::now() - started_at).count()); + } +} // namespace + AiDetectorUnify::AiDetectorUnify(const std::string& atomic_code, const std::string& json_path, const std::string& model_path) : atomic_code_(atomic_code), cfg_path_(json_path), model_path_(model_path) {} @@ -25,8 +37,10 @@ util::ErrorEnum AiDetectorUnify::Init() { } try { - detector_ = std::make_unique<cosmo::nn::DefaultComponent>(cfg_path_, model_path_, GetDeviceType(), - &profiler_); + cosmo::nn::DefaultComponent::Options options; + options.profiler = &profiler_; + detector_ = + std::make_unique<cosmo::nn::DefaultComponent>(options, cfg_path_, model_path_, GetDeviceType()); } catch (const std::exception& e) { LOG_ERRO("Init SDK Detector Failed. CfgPath:{} ModelPath:{}, {}", cfg_path_, model_path_, e.what()); detector_.reset(); @@ -50,6 +64,13 @@ util::ErrorEnum AiDetectorUnify::Init() { util::ErrorEnum AiDetectorUnify::Detect(const std::vector<VideoFramePtr>& images, std::vector<AiConfidence> conf_thres, std::vector<std::vector<AiDetectRstEl>>& results) { + return Detect(images, {}, std::move(conf_thres), results); +} + +util::ErrorEnum AiDetectorUnify::Detect(const std::vector<VideoFramePtr>& images, + const std::vector<media::NativeVideoBufferPtr>& native_buffers, + std::vector<AiConfidence> conf_thres, + std::vector<std::vector<AiDetectRstEl>>& results) { if (!detector_) { LOG_WARN("{}", "SDK Detector Not Init"); return util::ErrorEnum::NotInit; @@ -61,12 +82,14 @@ util::ErrorEnum AiDetectorUnify::Detect(const std::vector<VideoFramePtr>& images try { size_t image_num = images.size(); std::vector<VideoFramePtr> inputs; + std::vector<media::NativeVideoBufferPtr> native_inputs; for (size_t i = 0; i < image_num; i++) { inputs.push_back(images[i]); + native_inputs.push_back(i < native_buffers.size() ? native_buffers[i] : nullptr); size_t input_size = inputs.size(); if (input_size == max_batch_size_ || (i + 1) == image_num) { std::vector<std::vector<AiDetectRstEl>> outputs; - auto ret = Forward(inputs, outputs); + auto ret = Forward(inputs, native_inputs, outputs); if (util::ErrorEnum::Success != ret) { LOG_ERRO("Forward Failed. Ret:{}", ret); return ret; @@ -80,6 +103,7 @@ util::ErrorEnum AiDetectorUnify::Detect(const std::vector<VideoFramePtr>& images std::copy(outputs.begin(), outputs.end(), std::back_inserter(results)); } inputs.clear(); + native_inputs.clear(); } } } catch (const std::exception& e) { @@ -95,42 +119,65 @@ util::ErrorEnum AiDetectorUnify::Detect(const std::vector<VideoFramePtr>& images } util::ErrorEnum AiDetectorUnify::Forward(const std::vector<VideoFramePtr>& images, + const std::vector<media::NativeVideoBufferPtr>& native_buffers, std::vector<std::vector<AiDetectRstEl>>& results) { std::vector<std::shared_ptr<cosmo::nn::Blob>> image_blobs{}; - auto ret = ConvertImagesToBlobs(images, image_blobs); + const auto blob_convert_started = MetricsClock::now(); + auto ret = ConvertImagesToBlobs(images, native_buffers, image_blobs); + cosmo::nn::GetInferencePipelineMetrics().RecordBlobConvert(ElapsedNanoseconds(blob_convert_started), + static_cast<uint64_t>(image_blobs.size())); if (util::ErrorEnum::Success != ret) { LOG_ERRO("ConvertImagesToBlobs Failed. Ret:{}", ret); return ret; } + const auto graph_forward_started = MetricsClock::now(); try { auto status = detector_->Forward({image_blobs}); if (!bool(status)) { + cosmo::nn::GetInferencePipelineMetrics().RecordGraphForward( + ElapsedNanoseconds(graph_forward_started), static_cast<uint64_t>(image_blobs.size()), false); LOG_ERRO("Forward Failed.({})", status.description()); return util::ErrorEnum::AI_FORWARD_FAILED; } } catch (const std::exception& e) { + cosmo::nn::GetInferencePipelineMetrics().RecordGraphForward( + ElapsedNanoseconds(graph_forward_started), static_cast<uint64_t>(image_blobs.size()), false); LOG_ERRO("Forward Exception. CfgPath:{} ModelPath:{} inputBatch:{}, {}", cfg_path_, model_path_, image_blobs.size(), e.what()); return util::ErrorEnum::AI_FORWARD_FAILED; } catch (...) { + cosmo::nn::GetInferencePipelineMetrics().RecordGraphForward( + ElapsedNanoseconds(graph_forward_started), static_cast<uint64_t>(image_blobs.size()), false); LOG_ERRO("Forward non-std exception. CfgPath:{} ModelPath:{} inputBatch:{}", cfg_path_, model_path_, image_blobs.size()); return util::ErrorEnum::AI_FORWARD_FAILED; } + cosmo::nn::GetInferencePipelineMetrics().RecordGraphForward( + ElapsedNanoseconds(graph_forward_started), static_cast<uint64_t>(image_blobs.size()), true); + std::vector<std::vector<cosmo::nn::ObjectInfoV1>> outputs; + const auto result_parse_started = MetricsClock::now(); try { auto status = detector_->ParseOutput<cosmo::nn::ObjectInfoV1>(outputs); if (!bool(status)) { + cosmo::nn::GetInferencePipelineMetrics().RecordResultParse( + ElapsedNanoseconds(result_parse_started), static_cast<uint64_t>(image_blobs.size()), false); LOG_ERRO("ParseOutput Failed.({})", status.description()); return util::ErrorEnum::AI_PARSE_OUTPUT_FAILED; } } catch (const std::exception& e) { + cosmo::nn::GetInferencePipelineMetrics().RecordResultParse( + ElapsedNanoseconds(result_parse_started), static_cast<uint64_t>(image_blobs.size()), false); LOG_ERRO("ParseOutput Exception. CfgPath:{} ModelPath:{}, {}", cfg_path_, model_path_, e.what()); return util::ErrorEnum::AI_PARSE_OUTPUT_FAILED; } catch (...) { + cosmo::nn::GetInferencePipelineMetrics().RecordResultParse( + ElapsedNanoseconds(result_parse_started), static_cast<uint64_t>(image_blobs.size()), false); LOG_ERRO("ParseOutput non-std exception. CfgPath:{} ModelPath:{}", cfg_path_, model_path_); return util::ErrorEnum::AI_PARSE_OUTPUT_FAILED; } + cosmo::nn::GetInferencePipelineMetrics().RecordResultParse( + ElapsedNanoseconds(result_parse_started), static_cast<uint64_t>(image_blobs.size()), true); if (outputs.size() > image_blobs.size()) { LOG_WARN( "ParseOutput size:{} larger than inputBatch:{}, extra outputs ignored. CfgPath:{} ModelPath:{}", diff --git a/src/infer/AiDetectorUnify.h b/src/infer/AiDetectorUnify.h index 5fcc953e4..935a6f18b 100644 --- a/src/infer/AiDetectorUnify.h +++ b/src/infer/AiDetectorUnify.h @@ -20,6 +20,10 @@ class AiDetectorUnify { util::ErrorEnum Detect(const std::vector<VideoFramePtr>& images, std::vector<AiConfidence> conf_thres, std::vector<std::vector<AiDetectRstEl>>& results); + util::ErrorEnum Detect(const std::vector<VideoFramePtr>& images, + const std::vector<media::NativeVideoBufferPtr>& native_buffers, + std::vector<AiConfidence> conf_thres, + std::vector<std::vector<AiDetectRstEl>>& results); std::vector<std::string> GetLabels() { return labels_; @@ -29,6 +33,7 @@ class AiDetectorUnify { private: util::ErrorEnum Forward(const std::vector<VideoFramePtr>& images, + const std::vector<media::NativeVideoBufferPtr>& native_buffers, std::vector<std::vector<AiDetectRstEl>>& results); size_t max_batch_size_ = 1; diff --git a/src/infer/AiLandmarkerUnify.cc b/src/infer/AiLandmarkerUnify.cc index 50d944857..e0bb77bce 100644 --- a/src/infer/AiLandmarkerUnify.cc +++ b/src/infer/AiLandmarkerUnify.cc @@ -10,6 +10,10 @@ namespace cosmo { AiLandmarkerUnify::AiLandmarkerUnify(const std::string& jsonPath, const std::string& modelPath) : cfg_path_(jsonPath), model_path_(modelPath) {} +AiLandmarkerUnify::AiLandmarkerUnify(const std::string&, const std::string& jsonPath, + const std::string& modelPath) + : cfg_path_(jsonPath), model_path_(modelPath) {} + AiLandmarkerUnify::~AiLandmarkerUnify() { LOG_INFO("{}", "AiLandmarkerUnify Delete"); } @@ -20,8 +24,10 @@ util::ErrorEnum AiLandmarkerUnify::Init() { return util::ErrorEnum::Created; } + cosmo::nn::DefaultComponent::Options options; + options.profiler = &profiler_; landmarker_ = - std::make_unique<cosmo::nn::DefaultComponent>(cfg_path_, model_path_, GetDeviceType(), &profiler_); + std::make_unique<cosmo::nn::DefaultComponent>(options, cfg_path_, model_path_, GetDeviceType()); LOG_DEBUG("Landmarker {} Init", model_path_); max_batch_size_ = static_cast<size_t>(landmarker_->GetMaxBatchSize()); @@ -242,4 +248,4 @@ util::ErrorEnum AiLandmarkerUnify::GetMaxBatchSize(size_t& value) { value = static_cast<size_t>(landmarker_->GetMaxBatchSize()); return util::ErrorEnum::Success; } -} // namespace cosmo \ No newline at end of file +} // namespace cosmo diff --git a/src/infer/AiLandmarkerUnify.h b/src/infer/AiLandmarkerUnify.h index f57f10452..0804f2d0f 100644 --- a/src/infer/AiLandmarkerUnify.h +++ b/src/infer/AiLandmarkerUnify.h @@ -17,10 +17,8 @@ class AiLandmarkerUnify { AiLandmarkerUnify(const std::string& jsonPath, const std::string& modelPath); /// 3-arg constructor for InstancePool<T,PTR> template compatibility. - /// The atomicCode is unused — pool-level keying is handled by InferPoolServiceImpl. - AiLandmarkerUnify(const std::string& /*atomicCode*/, const std::string& jsonPath, - const std::string& modelPath) - : AiLandmarkerUnify(jsonPath, modelPath) {} + AiLandmarkerUnify(const std::string& atomicCode, const std::string& jsonPath, + const std::string& modelPath); ~AiLandmarkerUnify(); util::ErrorEnum Init(); diff --git a/src/infer/AiOcrWordClassifierUnify.cc b/src/infer/AiOcrWordClassifierUnify.cc index d2fe7a1b1..52d053852 100644 --- a/src/infer/AiOcrWordClassifierUnify.cc +++ b/src/infer/AiOcrWordClassifierUnify.cc @@ -31,8 +31,11 @@ util::ErrorEnum AiOcrWordClassifierUnify::Init() { return util::ErrorEnum::Failed; } try { - classifier_ = std::make_unique<cosmo::nn::DefaultComponent>(json_path_, model_path_, GetDeviceType(), - &profiler_, "", word_dict_path_); + cosmo::nn::DefaultComponent::Options options; + options.profiler = &profiler_; + options.word_table_path = word_dict_path_; + classifier_ = + std::make_unique<cosmo::nn::DefaultComponent>(options, json_path_, model_path_, GetDeviceType()); } catch (const std::exception& e) { LOG_ERRO("Init OCR classifier failed. AlgCode:{} Error:{}", atomic_code_, e.what()); classifier_.reset(); diff --git a/src/infer/AiRecognizerUnify.cc b/src/infer/AiRecognizerUnify.cc index 61e503c3c..6c0316da7 100644 --- a/src/infer/AiRecognizerUnify.cc +++ b/src/infer/AiRecognizerUnify.cc @@ -8,6 +8,10 @@ namespace cosmo { AiRecognizerUnify::AiRecognizerUnify(const std::string& json_path, const std::string& model_path) : cfg_path_(json_path), model_path_(model_path) {} +AiRecognizerUnify::AiRecognizerUnify(const std::string&, const std::string& json_path, + const std::string& model_path) + : cfg_path_(json_path), model_path_(model_path) {} + AiRecognizerUnify::~AiRecognizerUnify() { LOG_INFO("{}", "AiRecognizerUnify Delete"); } @@ -19,8 +23,10 @@ util::ErrorEnum AiRecognizerUnify::Init() { } try { - recognizer_ = std::make_unique<cosmo::nn::DefaultComponent>(cfg_path_, model_path_, GetDeviceType(), - &profiler_); + cosmo::nn::DefaultComponent::Options options; + options.profiler = &profiler_; + recognizer_ = + std::make_unique<cosmo::nn::DefaultComponent>(options, cfg_path_, model_path_, GetDeviceType()); } catch (const std::exception& e) { LOG_ERRO("Init SDK Recognizer Failed. CfgPath:{} ModelPath:{}, {}", cfg_path_, model_path_, e.what()); recognizer_.reset(); @@ -333,4 +339,4 @@ util::ErrorEnum AiRecognizerUnify::GetMaxBatchSize(size_t& value) { value = static_cast<size_t>(recognizer_->GetMaxBatchSize()); return util::ErrorEnum::Success; } -} // namespace cosmo \ No newline at end of file +} // namespace cosmo diff --git a/src/infer/AiRecognizerUnify.h b/src/infer/AiRecognizerUnify.h index 8cc5791ff..6bb27816d 100644 --- a/src/infer/AiRecognizerUnify.h +++ b/src/infer/AiRecognizerUnify.h @@ -15,10 +15,8 @@ class AiRecognizerUnify { AiRecognizerUnify(const std::string& json_path, const std::string& model_path); /// 3-arg constructor for InstancePool<T,PTR> template compatibility. - /// The atomicCode is unused — pool-level keying is handled by InferPoolServiceImpl. - AiRecognizerUnify(const std::string& /*atomic_code*/, const std::string& json_path, - const std::string& model_path) - : AiRecognizerUnify(json_path, model_path) {} + AiRecognizerUnify(const std::string& atomic_code, const std::string& json_path, + const std::string& model_path); ~AiRecognizerUnify(); util::ErrorEnum Init(); diff --git a/src/infer/BmodelTool.cc b/src/infer/BmodelTool.cc index 2438d7291..4d5948c90 100644 --- a/src/infer/BmodelTool.cc +++ b/src/infer/BmodelTool.cc @@ -25,6 +25,10 @@ #ifdef COSMO_NN_USE_ONNX_BACKEND #include "onnxruntime_cxx_api.h" #endif +#ifdef COSMO_NN_USE_RKNN_BACKEND +#include "nn/device/rknn/rknn_yolov8_adapter.h" +#include "rknn_api.h" +#endif namespace fs = std::filesystem; @@ -189,6 +193,138 @@ BmodelInfo BmodelTool::GetBmodelInfo(const std::string& bmodelPath) { return info; } +#elif defined(COSMO_NN_USE_RKNN_BACKEND) + +namespace { + class RknnContextGuard { + public: + ~RknnContextGuard() { + if (context != 0) + rknn_destroy(context); + } + rknn_context context{0}; + }; + + std::vector<int> RknnShape(const rknn_tensor_attr& attr) { + std::vector<int> shape; + shape.reserve(attr.n_dims); + for (uint32_t index = 0; index < attr.n_dims; ++index) { + if (attr.dims[index] > static_cast<uint32_t>(std::numeric_limits<int>::max())) + return {}; + shape.push_back(static_cast<int>(attr.dims[index])); + } + return shape; + } + + std::vector<int> RknnInputShapeNchw(const rknn_tensor_attr& attr) { + auto shape = RknnShape(attr); + if (shape.size() == 4 && attr.fmt == RKNN_TENSOR_NHWC) + return {shape[0], shape[3], shape[1], shape[2]}; + return shape; + } +} // namespace + +BmodelInfo BmodelTool::GetBmodelInfo(const std::string& bmodelPath) { + BmodelInfo info; + info.file_path = bmodelPath; + std::error_code ec; + const auto file_size = fs::file_size(bmodelPath, ec); + if (ec || file_size == 0 || file_size > std::numeric_limits<uint32_t>::max()) { + info.error_msg = ec ? "File does not exist or is inaccessible: " + bmodelPath + : "RKNN model file has an invalid size"; + return info; + } + + std::vector<unsigned char> model(static_cast<size_t>(file_size)); + std::ifstream stream(bmodelPath, std::ios::binary); + if (!stream.read(reinterpret_cast<char*>(model.data()), static_cast<std::streamsize>(model.size()))) { + info.error_msg = "Failed to read RKNN model file"; + return info; + } + + RknnContextGuard guard; + int result = rknn_init(&guard.context, model.data(), static_cast<uint32_t>(model.size()), 0, nullptr); + if (result != RKNN_SUCC) { + info.error_msg = "rknn_init failed with code " + std::to_string(result); + return info; + } + rknn_input_output_num count{}; + result = rknn_query(guard.context, RKNN_QUERY_IN_OUT_NUM, &count, sizeof(count)); + if (result != RKNN_SUCC || count.n_input == 0 || count.n_output == 0 || count.n_output > 64) { + info.error_msg = "Failed to query RKNN input/output count"; + return info; + } + + BmodelNetworkInfo network; + network.name = "rknn_network"; + for (uint32_t index = 0; index < count.n_input; ++index) { + rknn_tensor_attr attr{}; + attr.index = index; + result = rknn_query(guard.context, RKNN_QUERY_INPUT_ATTR, &attr, sizeof(attr)); + if (result != RKNN_SUCC) { + info.error_msg = "Failed to query RKNN input attributes"; + return info; + } + BmodelNodeInfo node; + node.name = attr.name[0] ? attr.name : "input_" + std::to_string(index); + node.shape = RknnInputShapeNchw(attr); + node.data_type = 0; // Cosmo host boundary supplies float NCHW. + if (node.shape.empty()) { + info.error_msg = "RKNN input shape cannot be represented"; + return info; + } + network.inputs.push_back(std::move(node)); + } + if (!network.inputs.empty() && !network.inputs[0].shape.empty()) + network.max_batch = network.inputs[0].shape[0]; + + std::vector<rknn_tensor_attr> output_attrs(count.n_output); + std::vector<std::vector<int>> output_shapes; + for (uint32_t index = 0; index < count.n_output; ++index) { + output_attrs[index].index = index; + result = rknn_query(guard.context, RKNN_QUERY_OUTPUT_ATTR, &output_attrs[index], + sizeof(output_attrs[index])); + if (result != RKNN_SUCC) { + info.error_msg = "Failed to query RKNN output attributes"; + return info; + } + auto shape = RknnShape(output_attrs[index]); + if (shape.empty()) { + info.error_msg = "RKNN output shape cannot be represented"; + return info; + } + output_shapes.push_back(std::move(shape)); + } + + cosmo::nn::RknnOutputAdapterContract output_adapter; + std::string adapter_error; + if (!cosmo::nn::ResolveRknnOutputAdapter(output_shapes, output_adapter, adapter_error)) { + info.error_msg = adapter_error; + return info; + } + if (cosmo::nn::IsRknnYolov8DflAdapter(output_adapter.kind)) { + BmodelNodeInfo node; + node.name = "output0"; + node.shape = output_adapter.logical_shape; + node.data_type = 0; + network.outputs.push_back(std::move(node)); + } else { + for (uint32_t index = 0; index < count.n_output; ++index) { + BmodelNodeInfo node; + node.name = + output_attrs[index].name[0] ? output_attrs[index].name : "output_" + std::to_string(index); + node.shape = std::move(output_shapes[index]); + node.data_type = 0; // rknn_outputs_get(want_float=1) + network.outputs.push_back(std::move(node)); + } + } + + info.networks.push_back(std::move(network)); + info.valid = true; + LogBmodelInfo(info, "[BmodelTool][RKNN]"); + return info; +} + #elif defined(COSMO_NN_USE_ONNX_BACKEND) static int ConvertOnnxDataType(ONNXTensorElementDataType onnxType) { @@ -301,7 +437,7 @@ BmodelInfo BmodelTool::GetBmodelInfo(const std::string& bmodelPath) { LOG_INFO("{}", "[BmodelTool] No inference backend enabled, returning SDK_NOT_AVAILABLE"); return info; } -#endif // COSMO_NN_USE_SOPHON_BACKEND / COSMO_NN_USE_ONNX_BACKEND +#endif // selected inference backend std::string BmodelTool::ConvertToNn(const std::vector<std::string>& bmodelPaths, const std::string& outputPath) { diff --git a/src/infer/CMakeLists.txt b/src/infer/CMakeLists.txt index 093fb3212..23c039f11 100644 --- a/src/infer/CMakeLists.txt +++ b/src/infer/CMakeLists.txt @@ -40,3 +40,17 @@ if(COSMO_NN_USE_CPU_BACKEND) COSMO_NN_USE_HOST_BACKEND COSMO_NN_USE_ONNX_BACKEND) endif() + +if(COSMO_NN_USE_RKLLM_BACKEND) + target_sources(cosmo_infer PRIVATE RkllmVlmBackend.cc RkllmVlmBackend.h) + target_link_libraries(cosmo_infer PRIVATE rknnrt rkllmrt) +elseif(COSMO_NN_USE_RKNN_BACKEND) + target_link_libraries(cosmo_infer PRIVATE rknnrt) +endif() + +if(COSMO_NN_USE_RKNN_BACKEND) + target_compile_definitions(cosmo_infer PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) +endif() diff --git a/src/infer/DinoDetectorUnify.cc b/src/infer/DinoDetectorUnify.cc index 0d6dc9a14..9bf2fb11b 100644 --- a/src/infer/DinoDetectorUnify.cc +++ b/src/infer/DinoDetectorUnify.cc @@ -31,9 +31,11 @@ util::ErrorEnum DinoDetectorUnify::Init() { } try { - // Pass vocabPath as the tokenizer_path parameter - detector_ = std::make_unique<cosmo::nn::DefaultComponent>(cfg_path_, model_path_, GetDeviceType(), - &profiler_, vocab_path_); + cosmo::nn::DefaultComponent::Options options; + options.profiler = &profiler_; + options.tokenizer_path = vocab_path_; + detector_ = + std::make_unique<cosmo::nn::DefaultComponent>(options, cfg_path_, model_path_, GetDeviceType()); } catch (const std::exception& e) { LOG_ERRO("Init SDK Dino Detector Failed. CfgPath:{} ModelPath:{} VocabPath:{}, {}", cfg_path_, model_path_, vocab_path_, e.what()); diff --git a/src/infer/Qwen3VLUnify.cc b/src/infer/Qwen3VLUnify.cc index e5cc694ea..8188333cc 100644 --- a/src/infer/Qwen3VLUnify.cc +++ b/src/infer/Qwen3VLUnify.cc @@ -6,31 +6,48 @@ #include <cstring> #include "infer/AiComponment.h" +#ifdef COSMO_NN_USE_RKLLM_BACKEND +#include "infer/RkllmVlmBackend.h" +#endif #include "util/Log.h" #include "util/UuidUtil.h" namespace cosmo { -Qwen3VLUnify::Qwen3VLUnify(const std::string& atomic_code, const std::string& json_path, - const std::string& model_path, const std::string& tokenizer_path) - : atomic_code_(atomic_code), - cfg_path_(json_path), - model_path_(model_path), - tokenizer_path_(tokenizer_path) {} +Qwen3VLUnify::Qwen3VLUnify(const std::string&, const std::string& json_path, const std::string& model_path, + const std::string& tokenizer_path) + : cfg_path_(json_path), model_path_(model_path), tokenizer_path_(tokenizer_path) {} Qwen3VLUnify::~Qwen3VLUnify() { LOG_INFO("{}", "Qwen3VLUnify Delete"); } util::ErrorEnum Qwen3VLUnify::Init() { +#ifdef COSMO_NN_USE_RKLLM_BACKEND + if (rkllm_backend_) { + return util::ErrorEnum::Created; + } + auto backend = std::make_unique<RkllmVlmBackend>(model_path_); + auto ret = backend->Init(); + if (ret != util::ErrorEnum::Success) { + LOG_ERRO("RKLLM Qwen3.5 initialization failed. ModelPath:{} Ret:{}", model_path_, ret); + return ret; + } + rkllm_backend_ = std::move(backend); + max_batch_size_ = 1; + LOG_INFO("RKLLM Qwen3.5 initialized. ModelPath:{}", model_path_); + return util::ErrorEnum::Success; +#else if (generator_) { LOG_WARN("{}", "Init SDK Qwen3VL Failed. Already Init"); return util::ErrorEnum::Created; } try { - // Pass tokenizer_path as the tokenizer_path parameter - generator_ = std::make_unique<cosmo::nn::DefaultComponent>(cfg_path_, model_path_, GetDeviceType(), - &profiler_, tokenizer_path_); + cosmo::nn::DefaultComponent::Options options; + options.profiler = &profiler_; + options.tokenizer_path = tokenizer_path_; + generator_ = + std::make_unique<cosmo::nn::DefaultComponent>(options, cfg_path_, model_path_, GetDeviceType()); } catch (const std::exception& e) { LOG_ERRO("Init SDK Qwen3VL Failed. CfgPath:{} ModelPath:{} TokenizerPath:{}, {}", cfg_path_, model_path_, tokenizer_path_, e.what()); @@ -49,6 +66,7 @@ util::ErrorEnum Qwen3VLUnify::Init() { max_batch_size_ = static_cast<size_t>(generator_->GetMaxBatchSize()); return util::ErrorEnum::Success; +#endif } util::ErrorEnum Qwen3VLUnify::Generate(const std::vector<VideoFramePtr>& images, @@ -56,7 +74,11 @@ util::ErrorEnum Qwen3VLUnify::Generate(const std::vector<VideoFramePtr>& images, const Qwen3VLGenerationParam& gen_param, std::vector<Qwen3VLResult>& results) { auto start = std::chrono::high_resolution_clock::now(); +#ifdef COSMO_NN_USE_RKLLM_BACKEND + if (!rkllm_backend_) { +#else if (!generator_) { +#endif LOG_WARN("{}", "SDK Qwen3VL Not Init"); return util::ErrorEnum::NotInit; } @@ -104,8 +126,11 @@ util::ErrorEnum Qwen3VLUnify::Generate(const std::vector<VideoFramePtr>& images, util::ErrorEnum Qwen3VLUnify::Forward(const std::vector<VideoFramePtr>& images, const std::vector<std::string>& prompts, - const Qwen3VLGenerationParam& /*gen_param*/, + const Qwen3VLGenerationParam& gen_param, std::vector<Qwen3VLResult>& results) { +#ifdef COSMO_NN_USE_RKLLM_BACKEND + return rkllm_backend_->Generate(images, prompts, gen_param, results); +#else // Qwen3VL uses host-memory BGR blobs (VideoFrame is decoded host memory) std::vector<std::shared_ptr<cosmo::nn::Blob>> image_blobs{}; for (const auto& img : images) { @@ -205,15 +230,20 @@ util::ErrorEnum Qwen3VLUnify::Forward(const std::vector<VideoFramePtr>& images, } LOG_DEBUG("[Qwen3VL] Forward done. images:{} results:{}", images.size(), results.size()); return util::ErrorEnum::Success; +#endif } util::ErrorEnum Qwen3VLUnify::GetMaxBatchSize(size_t* value) const { +#ifdef COSMO_NN_USE_RKLLM_BACKEND + if (!rkllm_backend_) { +#else if (!generator_) { +#endif LOG_WARN("{}", "SDK Qwen3VL Not Init"); return util::ErrorEnum::NotInit; } if (value) { - *value = static_cast<size_t>(generator_->GetMaxBatchSize()); + *value = max_batch_size_; } return util::ErrorEnum::Success; } diff --git a/src/infer/Qwen3VLUnify.h b/src/infer/Qwen3VLUnify.h index da70998cf..f5b4a32dc 100644 --- a/src/infer/Qwen3VLUnify.h +++ b/src/infer/Qwen3VLUnify.h @@ -12,6 +12,9 @@ #include "nn/utils/default_component.h" namespace cosmo { +#ifdef COSMO_NN_USE_RKLLM_BACKEND +class RkllmVlmBackend; +#endif struct Qwen3VLGenerationParam { bool do_sample{true}; int top_k{20}; @@ -46,11 +49,14 @@ class Qwen3VLUnify { private: size_t max_batch_size_{1}; - std::string atomic_code_; std::string cfg_path_; std::string model_path_; std::string tokenizer_path_; +#ifdef COSMO_NN_USE_RKLLM_BACKEND + std::unique_ptr<RkllmVlmBackend> rkllm_backend_; +#else std::unique_ptr<cosmo::nn::DefaultComponent> generator_; +#endif AppProfiler profiler_; }; diff --git a/src/infer/RkllmVlmBackend.cc b/src/infer/RkllmVlmBackend.cc new file mode 100644 index 000000000..1a7320dd9 --- /dev/null +++ b/src/infer/RkllmVlmBackend.cc @@ -0,0 +1,404 @@ +#include "infer/RkllmVlmBackend.h" + +#include <algorithm> +#include <chrono> +#include <cmath> +#include <cstring> +#include <filesystem> +#include <memory> +#include <utility> + +#include "infer/Qwen3VLUnify.h" +#include "media/PixelFormat.h" +#include "rkllm.h" +#include "rknn_api.h" +#include "util/Log.h" + +namespace cosmo { +namespace { + + struct ImageEncoderContext { + rknn_context ctx{0}; + rknn_input_output_num io_num{}; + std::vector<rknn_tensor_attr> inputs; + std::vector<rknn_tensor_attr> outputs; + int width{0}; + int height{0}; + int channels{0}; + int image_tokens{0}; + int embed_size{0}; + }; + + struct RunContext { + std::string text; + bool failed{false}; + }; + + int RkllmResultCallback(RKLLMResult* result, void* userdata, LLMCallState state) { + auto* context = static_cast<RunContext*>(userdata); + if (!context) { + return 0; + } + if (state == RKLLM_RUN_ERROR) { + context->failed = true; + } else if (state == RKLLM_RUN_NORMAL && result && result->text) { + context->text.append(result->text); + } + return 0; + } + + void ReleaseImageEncoder(ImageEncoderContext& encoder) { + if (encoder.ctx != 0) { + rknn_destroy(encoder.ctx); + encoder.ctx = 0; + } + encoder.inputs.clear(); + encoder.outputs.clear(); + } + + bool InitImageEncoder(const std::string& path, ImageEncoderContext& encoder) { + int ret = rknn_init(&encoder.ctx, const_cast<char*>(path.c_str()), 0, 0, nullptr); + if (ret != RKNN_SUCC) { + LOG_ERRO("RKLLM vision encoder init failed. path:{} ret:{}", path, ret); + return false; + } + + ret = rknn_set_core_mask(encoder.ctx, RKNN_NPU_CORE_0_1); + if (ret != RKNN_SUCC) { + LOG_ERRO("RKLLM vision encoder core selection failed. ret:{}", ret); + ReleaseImageEncoder(encoder); + return false; + } + + ret = rknn_query(encoder.ctx, RKNN_QUERY_IN_OUT_NUM, &encoder.io_num, sizeof(encoder.io_num)); + if (ret != RKNN_SUCC || encoder.io_num.n_input != 1 || encoder.io_num.n_output < 1) { + LOG_ERRO("RKLLM invalid vision encoder IO. ret:{} inputs:{} outputs:{}", ret, + encoder.io_num.n_input, encoder.io_num.n_output); + ReleaseImageEncoder(encoder); + return false; + } + + encoder.inputs.resize(encoder.io_num.n_input); + for (uint32_t i = 0; i < encoder.io_num.n_input; ++i) { + encoder.inputs[i] = {}; + encoder.inputs[i].index = i; + if (rknn_query(encoder.ctx, RKNN_QUERY_INPUT_ATTR, &encoder.inputs[i], + sizeof(rknn_tensor_attr)) != RKNN_SUCC) { + LOG_ERRO("RKLLM vision encoder input query failed. index:{}", i); + ReleaseImageEncoder(encoder); + return false; + } + } + + encoder.outputs.resize(encoder.io_num.n_output); + for (uint32_t i = 0; i < encoder.io_num.n_output; ++i) { + encoder.outputs[i] = {}; + encoder.outputs[i].index = i; + if (rknn_query(encoder.ctx, RKNN_QUERY_OUTPUT_ATTR, &encoder.outputs[i], + sizeof(rknn_tensor_attr)) != RKNN_SUCC) { + LOG_ERRO("RKLLM vision encoder output query failed. index:{}", i); + ReleaseImageEncoder(encoder); + return false; + } + } + + const auto& input = encoder.inputs.front(); + if (input.fmt == RKNN_TENSOR_NCHW) { + encoder.channels = input.dims[1]; + encoder.height = input.dims[2]; + encoder.width = input.dims[3]; + } else { + encoder.height = input.dims[1]; + encoder.width = input.dims[2]; + encoder.channels = input.dims[3]; + } + + const auto& output = encoder.outputs.front(); + for (uint32_t i = 0; i + 1 < output.n_dims; ++i) { + if (output.dims[i] > 1 && output.dims[i + 1] > 1) { + encoder.image_tokens = output.dims[i]; + encoder.embed_size = output.dims[i + 1]; + break; + } + } + if (encoder.width <= 0 || encoder.height <= 0 || encoder.channels != 3 || encoder.image_tokens <= 0 || + encoder.embed_size <= 0) { + LOG_ERRO("RKLLM unsupported vision encoder shape. image:{}x{}x{} tokens:{} embed:{}", + encoder.width, encoder.height, encoder.channels, encoder.image_tokens, + encoder.embed_size); + ReleaseImageEncoder(encoder); + return false; + } + + LOG_INFO("RKLLM vision encoder ready. path:{} image:{}x{} tokens:{} embed:{} outputs:{}", path, + encoder.width, encoder.height, encoder.image_tokens, encoder.embed_size, + encoder.io_num.n_output); + return true; + } + + bool ResizeFrameToRgb(const VideoFramePtr& frame, int dst_width, int dst_height, + std::vector<uint8_t>& output) { + const int src_width = static_cast<int>(frame->GetWidth()); + const int src_height = static_cast<int>(frame->GetHeight()); + auto* src = frame->GetHostData() ? frame->GetHostData() : frame->GetData(); + if (!src || src_width <= 0 || src_height <= 0 || dst_width <= 0 || dst_height <= 0) { + return false; + } + + const int square_size = std::max(src_width, src_height); + const int x_offset = (square_size - src_width) / 2; + const int y_offset = (square_size - src_height) / 2; + const bool input_bgr = frame->GetPixelFormat() == media::PixelFormat::PIXEL_BGR8; + const bool input_rgb = frame->GetPixelFormat() == media::PixelFormat::PIXEL_RGB8; + if (!input_bgr && !input_rgb) { + return false; + } + + output.resize(static_cast<size_t>(dst_width) * dst_height * 3); + std::fill(output.begin(), output.end(), 128); + auto channel = [&](int x, int y, int c) -> float { + if (x < x_offset || x >= x_offset + src_width || y < y_offset || y >= y_offset + src_height) { + return 127.5F; + } + const int sx = x - x_offset; + const int sy = y - y_offset; + const int source_channel = input_bgr ? (2 - c) : c; + return static_cast<float>(src[(static_cast<size_t>(sy) * src_width + sx) * 3 + source_channel]); + }; + + for (int y = 0; y < dst_height; ++y) { + const float square_y = (static_cast<float>(y) + 0.5F) * square_size / dst_height - 0.5F; + const int y0 = static_cast<int>(std::floor(square_y)); + const int y1 = y0 + 1; + const float fy = square_y - y0; + for (int x = 0; x < dst_width; ++x) { + const float square_x = (static_cast<float>(x) + 0.5F) * square_size / dst_width - 0.5F; + const int x0 = static_cast<int>(std::floor(square_x)); + const int x1 = x0 + 1; + const float fx = square_x - x0; + for (int c = 0; c < 3; ++c) { + const float v00 = + channel(std::clamp(x0, 0, square_size - 1), std::clamp(y0, 0, square_size - 1), c); + const float v01 = + channel(std::clamp(x1, 0, square_size - 1), std::clamp(y0, 0, square_size - 1), c); + const float v10 = + channel(std::clamp(x0, 0, square_size - 1), std::clamp(y1, 0, square_size - 1), c); + const float v11 = + channel(std::clamp(x1, 0, square_size - 1), std::clamp(y1, 0, square_size - 1), c); + const float value = + (v00 * (1.0F - fx) + v01 * fx) * (1.0F - fy) + (v10 * (1.0F - fx) + v11 * fx) * fy; + output[(static_cast<size_t>(y) * dst_width + x) * 3 + c] = + static_cast<uint8_t>(std::clamp(value, 0.0F, 255.0F)); + } + } + } + return true; + } + + bool EncodeImage(ImageEncoderContext& encoder, const std::vector<uint8_t>& image, + std::vector<float>& embedding) { + rknn_input input{}; + input.index = 0; + input.type = RKNN_TENSOR_UINT8; + input.fmt = RKNN_TENSOR_NHWC; + input.size = static_cast<uint32_t>(image.size()); + input.buf = const_cast<uint8_t*>(image.data()); + if (rknn_inputs_set(encoder.ctx, 1, &input) != RKNN_SUCC || + rknn_run(encoder.ctx, nullptr) != RKNN_SUCC) { + LOG_ERRO("{}", "RKLLM vision encoder inference failed"); + return false; + } + + std::vector<rknn_output> outputs(encoder.io_num.n_output); + for (uint32_t i = 0; i < encoder.io_num.n_output; ++i) { + outputs[i] = {}; + outputs[i].index = i; + outputs[i].want_float = 1; + } + if (rknn_outputs_get(encoder.ctx, encoder.io_num.n_output, outputs.data(), nullptr) != RKNN_SUCC) { + LOG_ERRO("{}", "RKLLM vision encoder output retrieval failed"); + return false; + } + + const size_t per_output = static_cast<size_t>(encoder.image_tokens) * encoder.embed_size; + embedding.resize(per_output * encoder.io_num.n_output); + if (encoder.io_num.n_output == 1) { + const size_t available = outputs[0].size / sizeof(float); + std::memcpy(embedding.data(), outputs[0].buf, + std::min(embedding.size(), available) * sizeof(float)); + } else { + for (int token = 0; token < encoder.image_tokens; ++token) { + for (uint32_t j = 0; j < encoder.io_num.n_output; ++j) { + const auto* source = static_cast<const float*>(outputs[j].buf) + + static_cast<size_t>(token) * encoder.embed_size; + auto* destination = + embedding.data() + + (static_cast<size_t>(token) * encoder.io_num.n_output + j) * encoder.embed_size; + std::memcpy(destination, source, encoder.embed_size * sizeof(float)); + } + } + } + rknn_outputs_release(encoder.ctx, encoder.io_num.n_output, outputs.data()); + return true; + } + +} // namespace + +struct RkllmVlmBackend::Impl { + LLMHandle llm{nullptr}; + RKLLMCallback callback{}; + ImageEncoderContext encoder; +}; + +RkllmVlmBackend::RkllmVlmBackend(std::string model_path) : model_path_(std::move(model_path)) {} + +RkllmVlmBackend::~RkllmVlmBackend() { + if (!impl_) { + return; + } + ReleaseImageEncoder(impl_->encoder); + if (impl_->llm) { + rkllm_destroy(impl_->llm); + impl_->llm = nullptr; + } + delete impl_; + impl_ = nullptr; +} + +util::ErrorEnum RkllmVlmBackend::Init() { + if (impl_) { + return util::ErrorEnum::Created; + } + const std::filesystem::path configured_path(model_path_); + const auto model_dir = + std::filesystem::is_directory(configured_path) ? configured_path : configured_path.parent_path(); + const auto llm_path = + configured_path.extension() == ".rkllm" ? configured_path : model_dir / "model.rkllm"; + const auto vision_path = model_dir / "vision.rknn"; + if (!std::filesystem::is_regular_file(llm_path) || !std::filesystem::is_regular_file(vision_path)) { + LOG_ERRO("RKLLM model files missing. llm:{} vision:{}", llm_path.string(), vision_path.string()); + return util::ErrorEnum::FileNotExist; + } + // ModelPathMapper may select vision.rknn after the visual encoder is added to the + // model directory. RKLLM must always receive the adjacent language model instead. + model_path_ = llm_path.string(); + + std::unique_ptr<Impl> candidate(new Impl()); + RKLLMParam param = rkllm_createDefaultParam(); + param.model_path = model_path_.c_str(); + param.top_k = 1; + // This backend is used for short visual judgements. 64 image tokens plus the + // prompt and answer fit comfortably in 512 tokens, avoiding an oversized KV + // cache and generation budget on the edge device. + param.max_new_tokens = 2; + param.max_context_len = 512; + param.skip_special_token = true; + param.extend_param.base_domain_id = 1; + candidate->callback.result_callback = RkllmResultCallback; + if (rkllm_init(&candidate->llm, ¶m, &candidate->callback) != 0) { + LOG_ERRO("RKLLM language model init failed. path:{}", model_path_); + return util::ErrorEnum::Failed; + } + if (!InitImageEncoder(vision_path.string(), candidate->encoder)) { + rkllm_destroy(candidate->llm); + candidate->llm = nullptr; + return util::ErrorEnum::Failed; + } + + impl_ = candidate.release(); + LOG_INFO("RKLLM multimodal backend initialized. llm:{} vision:{}", model_path_, vision_path.string()); + return util::ErrorEnum::Success; +} + +util::ErrorEnum RkllmVlmBackend::Generate(const std::vector<VideoFramePtr>& images, + const std::vector<std::string>& prompts, + const Qwen3VLGenerationParam& gen_param, + std::vector<Qwen3VLResult>& results) { + if (!impl_) { + return util::ErrorEnum::NotInit; + } + if (images.size() != prompts.size()) { + return util::ErrorEnum::InvalidParam; + } + + // The worker repeatedly calls Generate on the same thread. Keep the two large + // scratch buffers thread-local so they retain capacity without sharing mutable + // memory between camera workers. + thread_local std::vector<uint8_t> rgb; + thread_local std::vector<float> embedding; + for (size_t i = 0; i < images.size(); ++i) { + if (!images[i] || !VideoFrameValid(images[i])) { + return util::ErrorEnum::InvalidParam; + } + const auto preprocess_start = std::chrono::steady_clock::now(); + if (!ResizeFrameToRgb(images[i], impl_->encoder.width, impl_->encoder.height, rgb)) { + LOG_ERRO("RKLLM unsupported or empty frame. format:{} dims:{}x{}", + static_cast<int>(images[i]->GetPixelFormat()), images[i]->GetWidth(), + images[i]->GetHeight()); + return util::ErrorEnum::InvalidParam; + } + const auto vision_start = std::chrono::steady_clock::now(); + if (!EncodeImage(impl_->encoder, rgb, embedding)) { + return util::ErrorEnum::AI_FORWARD_FAILED; + } + const auto prefill_start = std::chrono::steady_clock::now(); + + std::string prompt = prompts[i]; + if (prompt.find("<image>") == std::string::npos) { + prompt.insert(0, "<image>"); + } + RKLLMInput input{}; + input.role = "user"; + input.enable_thinking = false; + input.input_type = RKLLM_INPUT_MULTIMODAL; + input.multimodal_input.prompt = prompt.data(); + input.multimodal_input.image.image_embed = embedding.data(); + input.multimodal_input.image.n_image_tokens = impl_->encoder.image_tokens; + input.multimodal_input.image.n_image = 1; + input.multimodal_input.image.image_start = "<|vision_start|>"; + input.multimodal_input.image.image_end = "<|vision_end|>"; + input.multimodal_input.image.image_content = "<|image_pad|>"; + input.multimodal_input.image.image_width = impl_->encoder.width; + input.multimodal_input.image.image_height = impl_->encoder.height; + + RKLLMSamplingParam sampling{}; + sampling.top_k = gen_param.do_sample ? gen_param.top_k : 1; + sampling.top_p = gen_param.do_sample ? gen_param.top_p : 1.0F; + sampling.temperature = gen_param.do_sample ? gen_param.temperature : 0.0F; + sampling.repeat_penalty = 1.1F; + RKLLMInferParam infer{}; + infer.mode = RKLLM_INFER_GENERATE; + infer.keep_history = 0; + infer.max_new_tokens = 2; + infer.sampling_params = &sampling; + RunContext run; + run.text.reserve(8); + const int ret = rkllm_run(impl_->llm, &input, &infer, &run); + if (ret != 0 || run.failed) { + LOG_ERRO("RKLLM multimodal inference failed. ret:{} callbackError:{}", ret, run.failed); + return util::ErrorEnum::AI_FORWARD_FAILED; + } + + Qwen3VLResult result; + result.text = std::move(run.text); + result.frame_index = static_cast<int64_t>(images[i]->GetFrameIndex()); + result.timestamp = images[i]->GetTimestamp(); + const auto finish = std::chrono::steady_clock::now(); + const auto preprocess_ms = + std::chrono::duration_cast<std::chrono::milliseconds>(vision_start - preprocess_start).count(); + const auto vision_ms = + std::chrono::duration_cast<std::chrono::milliseconds>(prefill_start - vision_start).count(); + const auto llm_ms = + std::chrono::duration_cast<std::chrono::milliseconds>(finish - prefill_start).count(); + LOG_INFO( + "[Qwen3VL][RKLLM][Timing] preprocess:{}ms vision:{}ms llm:{}ms total:{}ms " + "tokens:{}", + preprocess_ms, vision_ms, llm_ms, preprocess_ms + vision_ms + llm_ms, + impl_->encoder.image_tokens); + LOG_INFO("[Qwen3VL][RKLLM] frameIndex:{} result:{}", result.frame_index, result.text); + results.push_back(std::move(result)); + } + return util::ErrorEnum::Success; +} + +} // namespace cosmo diff --git a/src/infer/RkllmVlmBackend.h b/src/infer/RkllmVlmBackend.h new file mode 100644 index 000000000..5d014f8c0 --- /dev/null +++ b/src/infer/RkllmVlmBackend.h @@ -0,0 +1,36 @@ +#pragma once + +#include <cstddef> +#include <cstdint> +#include <string> +#include <vector> + +#include "infer/AiCommon.h" +#include "media/VideoFrame.h" +#include "util/ErrorCode.h" + +namespace cosmo { + +struct Qwen3VLGenerationParam; +struct Qwen3VLResult; + +class RkllmVlmBackend { +public: + explicit RkllmVlmBackend(std::string model_path); + ~RkllmVlmBackend(); + + RkllmVlmBackend(const RkllmVlmBackend&) = delete; + RkllmVlmBackend& operator=(const RkllmVlmBackend&) = delete; + + util::ErrorEnum Init(); + util::ErrorEnum Generate(const std::vector<VideoFramePtr>& images, + const std::vector<std::string>& prompts, const Qwen3VLGenerationParam& gen_param, + std::vector<Qwen3VLResult>& results); + +private: + struct Impl; + Impl* impl_{nullptr}; + std::string model_path_; +}; + +} // namespace cosmo diff --git a/src/infer/Sam2SegmenterUnify.cc b/src/infer/Sam2SegmenterUnify.cc index 5c42bad45..be38d0cfc 100644 --- a/src/infer/Sam2SegmenterUnify.cc +++ b/src/infer/Sam2SegmenterUnify.cc @@ -9,9 +9,9 @@ #include "util/UuidUtil.h" namespace cosmo { -Sam2SegmenterUnify::Sam2SegmenterUnify(const std::string &atomicCode, const std::string &jsonPath, +Sam2SegmenterUnify::Sam2SegmenterUnify(const std::string &, const std::string &jsonPath, const std::string &modelPath) - : atomic_code_(atomicCode), cfg_path_(jsonPath), model_path_(modelPath) {} + : cfg_path_(jsonPath), model_path_(modelPath) {} Sam2SegmenterUnify::~Sam2SegmenterUnify() { LOG_INFO("{}", "Sam2SegmenterUnify Delete"); @@ -25,8 +25,10 @@ util::ErrorEnum Sam2SegmenterUnify::Init() { try { // SAM2 contains encoder+decoder; current SDK does not support chaining, use single model for now - segmenter_ = std::make_unique<cosmo::nn::DefaultComponent>(cfg_path_, model_path_, GetDeviceType(), - &profiler_); + cosmo::nn::DefaultComponent::Options options; + options.profiler = &profiler_; + segmenter_ = + std::make_unique<cosmo::nn::DefaultComponent>(options, cfg_path_, model_path_, GetDeviceType()); } catch (const std::exception &e) { LOG_ERRO("Init SDK SAM2 Segmenter Failed. CfgPath:{} ModelPath:{}, {}", cfg_path_, model_path_, e.what()); diff --git a/src/infer/Sam2SegmenterUnify.h b/src/infer/Sam2SegmenterUnify.h index 52a591d74..980972962 100644 --- a/src/infer/Sam2SegmenterUnify.h +++ b/src/infer/Sam2SegmenterUnify.h @@ -40,7 +40,6 @@ class Sam2SegmenterUnify { private: size_t max_batch_size_ = 1; - std::string atomic_code_; std::string cfg_path_; std::string model_path_; std::unique_ptr<cosmo::nn::DefaultComponent> segmenter_; diff --git a/src/media/CMakeLists.txt b/src/media/CMakeLists.txt index abee5ec19..2d3a8bc44 100644 --- a/src/media/CMakeLists.txt +++ b/src/media/CMakeLists.txt @@ -47,10 +47,27 @@ set(MEDIA_CPU_SRC VideoFrameProcCpu.cc VideoFrameProcCpu.h ) +# Rockchip Copy-first backend. MPP handles H.264/H.265 decode and H.264 encode, +# RGA handles admitted color-conversion/resize operations, and FFmpeg remains a +# deterministic fallback. No DMA-BUF zero-copy path is compiled in this phase. +set(MEDIA_ROCKCHIP_SRC + VideoDecoderCpu.cc VideoDecoderCpu.h + VideoDecoderCreateRockchip.cc + VideoDecoderRockchip.cc VideoDecoderRockchip.h + VideoEncoderCpu.cc VideoEncoderCpu.h + VideoEncoderCreateRockchip.cc + VideoEncoderRockchip.cc VideoEncoderRockchip.h + VideoFrameProcCpu.cc VideoFrameProcCpu.h + VideoFrameProcFactoryRockchip.cc + VideoFrameProcRockchip.cc VideoFrameProcRockchip.h +) + if(COSMO_MEDIA_USE_SOPHON_BACKEND) add_library(cosmo_media OBJECT ${MEDIA_COMMON_SRC} ${MEDIA_SOPHON_SRC}) elseif(COSMO_MEDIA_USE_CPU_BACKEND) add_library(cosmo_media OBJECT ${MEDIA_COMMON_SRC} ${MEDIA_CPU_SRC}) +elseif(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + add_library(cosmo_media OBJECT ${MEDIA_COMMON_SRC} ${MEDIA_ROCKCHIP_SRC}) else() message(FATAL_ERROR "No media backend selected") endif() @@ -66,4 +83,6 @@ target_link_libraries(cosmo_media PRIVATE cosmo_common ) if(COSMO_MEDIA_USE_SOPHON_BACKEND) target_link_libraries(cosmo_media PRIVATE bmlib bmcv bmvd bmvenc) +elseif(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + target_link_libraries(cosmo_media PRIVATE rockchip_mpp rockchip_rga) endif() diff --git a/src/media/NativeVideoBuffer.h b/src/media/NativeVideoBuffer.h new file mode 100644 index 000000000..2db070a97 --- /dev/null +++ b/src/media/NativeVideoBuffer.h @@ -0,0 +1,37 @@ +#pragma once + +#include <cstddef> +#include <memory> + +namespace cosmo::media { + +enum class NativeVideoBufferFormat { + Unknown = 0, + I420, + NV12, + NV21, +}; + +/// Optional, backend-owned image buffer presented to a hardware consumer. +/// +/// The file descriptor is borrowed from owner. Keeping this object alive keeps +/// the underlying decoder buffer referenced; consumers must not close fd. +struct NativeVideoBuffer { + int fd{-1}; + size_t bytes{0}; + int width{0}; + int height{0}; + int width_stride{0}; + int height_stride{0}; + NativeVideoBufferFormat format{NativeVideoBufferFormat::Unknown}; + std::shared_ptr<void> owner; + + [[nodiscard]] bool Valid() const { + return fd >= 0 && bytes > 0 && width > 0 && height > 0 && width_stride >= width && + height_stride >= height && format != NativeVideoBufferFormat::Unknown && owner; + } +}; + +using NativeVideoBufferPtr = std::shared_ptr<const NativeVideoBuffer>; + +} // namespace cosmo::media diff --git a/src/media/PreviewPipelineMetrics.cc b/src/media/PreviewPipelineMetrics.cc index bbbcd0e75..854bbec22 100644 --- a/src/media/PreviewPipelineMetrics.cc +++ b/src/media/PreviewPipelineMetrics.cc @@ -57,6 +57,50 @@ void PreviewPipelineMetrics::RecordPublishedFrame(uint64_t nanoseconds) { publish_nanoseconds_.fetch_add(nanoseconds, std::memory_order_relaxed); } +void PreviewPipelineMetrics::RecordRgaOperation(bool success, uint64_t nanoseconds) { + if (success) { + rga_frames_.fetch_add(1, std::memory_order_relaxed); + rga_nanoseconds_.fetch_add(nanoseconds, std::memory_order_relaxed); + } else { + rga_failures_.fetch_add(1, std::memory_order_relaxed); + } +} + +void PreviewPipelineMetrics::RecordMppEncode(bool success, uint64_t nanoseconds) { + if (success) { + mpp_encoded_frames_.fetch_add(1, std::memory_order_relaxed); + mpp_encode_nanoseconds_.fetch_add(nanoseconds, std::memory_order_relaxed); + } else { + mpp_encode_failures_.fetch_add(1, std::memory_order_relaxed); + } +} + +void PreviewPipelineMetrics::RecordMppDecode(bool success, uint64_t nanoseconds) { + if (success) { + mpp_decoded_frames_.fetch_add(1, std::memory_order_relaxed); + mpp_decode_nanoseconds_.fetch_add(nanoseconds, std::memory_order_relaxed); + } else { + mpp_decode_failures_.fetch_add(1, std::memory_order_relaxed); + } +} + +void PreviewPipelineMetrics::RecordMppDecodeFallback() { + mpp_decode_fallbacks_.fetch_add(1, std::memory_order_relaxed); +} + +void PreviewPipelineMetrics::RecordMppCopyOut(bool success, uint64_t nanoseconds) { + if (success) { + mpp_copy_out_frames_.fetch_add(1, std::memory_order_relaxed); + mpp_copy_out_nanoseconds_.fetch_add(nanoseconds, std::memory_order_relaxed); + } else { + mpp_copy_out_failures_.fetch_add(1, std::memory_order_relaxed); + } +} + +void PreviewPipelineMetrics::RecordMppEarlyDrop() { + mpp_early_dropped_frames_.fetch_add(1, std::memory_order_relaxed); +} + PreviewPipelineMetricsSnapshot PreviewPipelineMetrics::Snapshot() const { return { active_publishers_.load(std::memory_order_relaxed), @@ -73,6 +117,20 @@ PreviewPipelineMetricsSnapshot PreviewPipelineMetrics::Snapshot() const { first_frames_.load(std::memory_order_relaxed), first_frame_nanoseconds_.load(std::memory_order_relaxed), first_frame_max_nanoseconds_.load(std::memory_order_relaxed), + rga_frames_.load(std::memory_order_relaxed), + rga_nanoseconds_.load(std::memory_order_relaxed), + rga_failures_.load(std::memory_order_relaxed), + mpp_encoded_frames_.load(std::memory_order_relaxed), + mpp_encode_nanoseconds_.load(std::memory_order_relaxed), + mpp_encode_failures_.load(std::memory_order_relaxed), + mpp_decoded_frames_.load(std::memory_order_relaxed), + mpp_decode_nanoseconds_.load(std::memory_order_relaxed), + mpp_decode_failures_.load(std::memory_order_relaxed), + mpp_decode_fallbacks_.load(std::memory_order_relaxed), + mpp_copy_out_frames_.load(std::memory_order_relaxed), + mpp_copy_out_nanoseconds_.load(std::memory_order_relaxed), + mpp_copy_out_failures_.load(std::memory_order_relaxed), + mpp_early_dropped_frames_.load(std::memory_order_relaxed), }; } diff --git a/src/media/PreviewPipelineMetrics.h b/src/media/PreviewPipelineMetrics.h index fb9e0c5c1..b9f3d2d4f 100644 --- a/src/media/PreviewPipelineMetrics.h +++ b/src/media/PreviewPipelineMetrics.h @@ -20,6 +20,20 @@ struct PreviewPipelineMetricsSnapshot { uint64_t first_frames{0}; uint64_t first_frame_nanoseconds{0}; uint64_t first_frame_max_nanoseconds{0}; + uint64_t rga_frames{0}; + uint64_t rga_nanoseconds{0}; + uint64_t rga_failures{0}; + uint64_t mpp_encoded_frames{0}; + uint64_t mpp_encode_nanoseconds{0}; + uint64_t mpp_encode_failures{0}; + uint64_t mpp_decoded_frames{0}; + uint64_t mpp_decode_nanoseconds{0}; + uint64_t mpp_decode_failures{0}; + uint64_t mpp_decode_fallbacks{0}; + uint64_t mpp_copy_out_frames{0}; + uint64_t mpp_copy_out_nanoseconds{0}; + uint64_t mpp_copy_out_failures{0}; + uint64_t mpp_early_dropped_frames{0}; }; class PreviewPipelineMetrics { @@ -31,6 +45,12 @@ class PreviewPipelineMetrics { void PreviewFailed(); void RecordOsdFrame(uint64_t nanoseconds); void RecordPublishedFrame(uint64_t nanoseconds); + void RecordRgaOperation(bool success, uint64_t nanoseconds); + void RecordMppEncode(bool success, uint64_t nanoseconds); + void RecordMppDecode(bool success, uint64_t nanoseconds); + void RecordMppDecodeFallback(); + void RecordMppCopyOut(bool success, uint64_t nanoseconds); + void RecordMppEarlyDrop(); [[nodiscard]] PreviewPipelineMetricsSnapshot Snapshot() const; @@ -49,6 +69,20 @@ class PreviewPipelineMetrics { std::atomic<uint64_t> first_frames_{0}; std::atomic<uint64_t> first_frame_nanoseconds_{0}; std::atomic<uint64_t> first_frame_max_nanoseconds_{0}; + std::atomic<uint64_t> rga_frames_{0}; + std::atomic<uint64_t> rga_nanoseconds_{0}; + std::atomic<uint64_t> rga_failures_{0}; + std::atomic<uint64_t> mpp_encoded_frames_{0}; + std::atomic<uint64_t> mpp_encode_nanoseconds_{0}; + std::atomic<uint64_t> mpp_encode_failures_{0}; + std::atomic<uint64_t> mpp_decoded_frames_{0}; + std::atomic<uint64_t> mpp_decode_nanoseconds_{0}; + std::atomic<uint64_t> mpp_decode_failures_{0}; + std::atomic<uint64_t> mpp_decode_fallbacks_{0}; + std::atomic<uint64_t> mpp_copy_out_frames_{0}; + std::atomic<uint64_t> mpp_copy_out_nanoseconds_{0}; + std::atomic<uint64_t> mpp_copy_out_failures_{0}; + std::atomic<uint64_t> mpp_early_dropped_frames_{0}; }; PreviewPipelineMetrics& GetPreviewPipelineMetrics(); diff --git a/src/media/VideoDecoder.cc b/src/media/VideoDecoder.cc index 0a973a56e..de9166ba0 100644 --- a/src/media/VideoDecoder.cc +++ b/src/media/VideoDecoder.cc @@ -13,6 +13,83 @@ static constexpr const char* kTag = "[DECODER] "; namespace cosmo { namespace media { + DecodedVideoFrame::DecodedVideoFrame(VideoFramePtr frame) : frame_(std::move(frame)) { + if (frame_) { + frame_index_ = frame_->GetFrameIndex(); + width_ = frame_->GetWidth(); + height_ = frame_->GetHeight(); + format_ = frame_->GetPixelFormat(); + } + } + + DecodedVideoFrame::DecodedVideoFrame(uint64_t frame_index, size_t width, size_t height, + PixelFormat format, Materializer materializer, + DiscardHandler discard_handler, + NativeBufferExporter native_buffer_exporter) + : frame_index_(frame_index), + width_(width), + height_(height), + format_(format), + materializer_(std::move(materializer)), + discard_handler_(std::move(discard_handler)), + native_buffer_exporter_(std::move(native_buffer_exporter)) {} + + bool DecodedVideoFrame::HasFrame() const { + return frame_ != nullptr || static_cast<bool>(materializer_); + } + + bool DecodedVideoFrame::IsDeferred() const { + return frame_ == nullptr && static_cast<bool>(materializer_); + } + + uint64_t DecodedVideoFrame::GetFrameIndex() const { + return frame_ ? frame_->GetFrameIndex() : frame_index_; + } + + size_t DecodedVideoFrame::GetWidth() const { + return frame_ ? frame_->GetWidth() : width_; + } + + size_t DecodedVideoFrame::GetHeight() const { + return frame_ ? frame_->GetHeight() : height_; + } + + PixelFormat DecodedVideoFrame::GetPixelFormat() const { + return frame_ ? frame_->GetPixelFormat() : format_; + } + + NativeVideoBufferPtr DecodedVideoFrame::ExportNativeBuffer() { + if (!native_buffer_ && native_buffer_exporter_) { + native_buffer_ = native_buffer_exporter_(); + } + return native_buffer_; + } + + VideoFramePtr DecodedVideoFrame::Materialize() { + if (frame_) { + return frame_; + } + if (!materializer_) { + return nullptr; + } + + auto materializer = std::move(materializer_); + discard_handler_ = nullptr; + frame_ = materializer(); + return frame_; + } + + void DecodedVideoFrame::Discard() { + if (IsDeferred() && discard_handler_) { + discard_handler_(); + } + frame_.reset(); + materializer_ = nullptr; + discard_handler_ = nullptr; + native_buffer_exporter_ = nullptr; + native_buffer_.reset(); + } + VideoDecoder::VideoDecoder(size_t name) : idx_name_("atomicDecoder_" + std::to_string(name)) { LOG_INFO("{} Construction", idx_name_); } @@ -33,7 +110,8 @@ namespace media { return height_; } - VideoFramePtr VideoDecoder::Decode(const uint8_t* pkt, size_t len, int64_t frame_idx, bool& result) { + DecodedVideoFrame VideoDecoder::DecodeFrame(const uint8_t* pkt, size_t len, int64_t frame_idx, + bool& result) { auto send_result = SendPacket(pkt, len, frame_idx); send_pkt_cnt_ += 1; if (frame_idx % (25 * 60) == 0) { @@ -53,18 +131,27 @@ namespace media { } LOG_WARN("{}{} Frame Size:{} Decode Failed. frameIndex:{} data:{}", kTag, idx_name_, len, frame_idx, prefix.str()); - return nullptr; + return {}; } result = true; - auto frame = GetFrame(); - if (frame) { + auto frame = GetDecodedFrame(); + if (frame.HasFrame()) { recv_frame_cnt_ += 1; } return frame; } + VideoFramePtr VideoDecoder::Decode(const uint8_t* pkt, size_t len, int64_t frame_idx, bool& result) { + auto frame = DecodeFrame(pkt, len, frame_idx, result); + return frame.Materialize(); + } + + DecodedVideoFrame VideoDecoder::GetDecodedFrame() { + return DecodedVideoFrame(GetFrame()); + } + } // namespace media } // namespace cosmo diff --git a/src/media/VideoDecoder.h b/src/media/VideoDecoder.h index d224b1192..3edc7c712 100644 --- a/src/media/VideoDecoder.h +++ b/src/media/VideoDecoder.h @@ -1,14 +1,70 @@ #pragma once +#include <functional> #include <memory> #include <string> +#include "media/NativeVideoBuffer.h" #include "media/VideoCodecType.h" #include "media/VideoFrame.h" namespace cosmo { namespace media { + struct VideoDecoderCapability { + bool available{false}; + std::string backend; + std::string implementation; + std::string detail; + }; + + /// One decoded output whose host pixels may be materialized later. + /// + /// CPU and Sophon decoders return an already-materialized VideoFrame. The + /// Rockchip decoder can instead retain one MPP frame until the channel has + /// completed its task/viewer sampling decision. A deferred output must be + /// materialized or explicitly discarded on the decoder thread before the + /// decoder is closed. + class DecodedVideoFrame { + public: + using Materializer = std::function<VideoFramePtr()>; + using DiscardHandler = std::function<void()>; + using NativeBufferExporter = std::function<NativeVideoBufferPtr()>; + + DecodedVideoFrame() = default; + explicit DecodedVideoFrame(VideoFramePtr frame); + DecodedVideoFrame(uint64_t frame_index, size_t width, size_t height, PixelFormat format, + Materializer materializer, DiscardHandler discard_handler, + NativeBufferExporter native_buffer_exporter = {}); + + DecodedVideoFrame(const DecodedVideoFrame&) = delete; + DecodedVideoFrame& operator=(const DecodedVideoFrame&) = delete; + DecodedVideoFrame(DecodedVideoFrame&&) noexcept = default; + DecodedVideoFrame& operator=(DecodedVideoFrame&&) noexcept = default; + + [[nodiscard]] bool HasFrame() const; + [[nodiscard]] bool IsDeferred() const; + [[nodiscard]] uint64_t GetFrameIndex() const; + [[nodiscard]] size_t GetWidth() const; + [[nodiscard]] size_t GetHeight() const; + [[nodiscard]] PixelFormat GetPixelFormat() const; + NativeVideoBufferPtr ExportNativeBuffer(); + + VideoFramePtr Materialize(); + void Discard(); + + private: + VideoFramePtr frame_; + uint64_t frame_index_{0}; + size_t width_{0}; + size_t height_{0}; + PixelFormat format_{PixelFormat::PIXEL_UNKNOWN}; + Materializer materializer_; + DiscardHandler discard_handler_; + NativeBufferExporter native_buffer_exporter_; + NativeVideoBufferPtr native_buffer_; + }; + class VideoDecoder { public: VideoDecoder(size_t name); @@ -22,12 +78,31 @@ namespace media { virtual bool IsOpened() = 0; + /// Allow a backend to retain a compatible decoder context when a new + /// stream generation starts at an independently decodable keyframe. + /// Backends that do not explicitly support this keep the existing + /// Close/Open lifecycle. + virtual bool ReuseForStreamRestart(VideoCodecType type, int width, int height) { + (void)type; + (void)width; + (void)height; + return false; + } + VideoFramePtr Decode(const uint8_t* pkt, size_t len, int64_t frame_idx, bool& result); + /// Decode one packet while preserving a backend-specific delayed + /// materialization boundary when available. + DecodedVideoFrame DecodeFrame(const uint8_t* pkt, size_t len, int64_t frame_idx, bool& result); + virtual bool SendPacket(const uint8_t* pkt, size_t len, int64_t frame_idx) = 0; virtual VideoFramePtr GetFrame() = 0; + /// CPU/Sophon default to GetFrame(); Rockchip overrides this to return + /// an MPP-backed deferred output. + virtual DecodedVideoFrame GetDecodedFrame(); + size_t GetWidth() const; size_t GetHeight() const; @@ -37,6 +112,9 @@ namespace media { /// @param mediaHandle Device handle (used by Sophon, ignored by CPU) static std::unique_ptr<VideoDecoder> Create(size_t name, void* mediaHandle); + /// Reports the deterministic implementation selected for this codec. + static VideoDecoderCapability Probe(VideoCodecType type); + protected: std::string idx_name_; std::string url_; diff --git a/src/media/VideoDecoderCpu.cc b/src/media/VideoDecoderCpu.cc index 599536644..c37960b98 100644 --- a/src/media/VideoDecoderCpu.cc +++ b/src/media/VideoDecoderCpu.cc @@ -19,6 +19,18 @@ extern "C" { namespace cosmo { namespace media { + namespace { + AVCodecID ToAvCodecId(VideoCodecType type) { + if (type == VideoCodecType::kH264) { + return AV_CODEC_ID_H264; + } + if (type == VideoCodecType::kH265) { + return AV_CODEC_ID_HEVC; + } + return AV_CODEC_ID_NONE; + } + } // namespace + VideoDecoderCpu::VideoDecoderCpu(size_t name) : VideoDecoder(name) {} VideoDecoderCpu::~VideoDecoderCpu() { @@ -29,13 +41,26 @@ namespace media { return opened_; } + VideoDecoderCapability VideoDecoderCpu::Probe(VideoCodecType type) { + VideoDecoderCapability capability; + capability.backend = "ffmpeg-software"; + const auto codec_id = ToAvCodecId(type); + if (codec_id == AV_CODEC_ID_NONE) { + capability.detail = "unsupported codec"; + return capability; + } + const auto* codec = avcodec_find_decoder(codec_id); + capability.available = codec != nullptr; + capability.implementation = codec ? codec->name : std::string{}; + capability.detail = capability.available ? "FFmpeg software decoder is registered" + : "FFmpeg software decoder is unavailable"; + return capability; + } + bool VideoDecoderCpu::Open() { - AVCodecID codec_id = AV_CODEC_ID_NONE; - if (codec_type_ == VideoCodecType::kH265) { - codec_id = AV_CODEC_ID_HEVC; - } else if (codec_type_ == VideoCodecType::kH264) { - codec_id = AV_CODEC_ID_H264; - } else { + Close(); + const auto codec_id = ToAvCodecId(codec_type_); + if (codec_id == AV_CODEC_ID_NONE) { LOG_WARN("{} OpenDecoder unsupported codec type ({})", idx_name_, static_cast<int>(codec_type_)); return false; } @@ -75,9 +100,6 @@ namespace media { } bool VideoDecoderCpu::Close() { - if (!opened_) - return true; - opened_ = false; if (av_frame_) { diff --git a/src/media/VideoDecoderCpu.h b/src/media/VideoDecoderCpu.h index 051635ebf..13c6732ac 100644 --- a/src/media/VideoDecoderCpu.h +++ b/src/media/VideoDecoderCpu.h @@ -33,6 +33,8 @@ namespace media { VideoFramePtr GetFrame() override; + static VideoDecoderCapability Probe(VideoCodecType type); + private: /// Copy decoded AVFrame (YUV420P) data into a VideoFrame's host-memory Block. bool CopyAVFrameToVideoFrame(AVFrame* src, VideoFramePtr dst); diff --git a/src/media/VideoDecoderCreateCpu.cc b/src/media/VideoDecoderCreateCpu.cc index 4983f7d57..b8e0e636a 100644 --- a/src/media/VideoDecoderCreateCpu.cc +++ b/src/media/VideoDecoderCreateCpu.cc @@ -12,5 +12,9 @@ namespace media { return std::make_unique<VideoDecoderCpu>(name); } + VideoDecoderCapability VideoDecoder::Probe(VideoCodecType type) { + return VideoDecoderCpu::Probe(type); + } + } // namespace media } // namespace cosmo diff --git a/src/media/VideoDecoderCreateRockchip.cc b/src/media/VideoDecoderCreateRockchip.cc new file mode 100644 index 000000000..2f2fc5ae4 --- /dev/null +++ b/src/media/VideoDecoderCreateRockchip.cc @@ -0,0 +1,15 @@ +#include "media/VideoDecoder.h" +#include "media/VideoDecoderRockchip.h" + +namespace cosmo::media { + +std::unique_ptr<VideoDecoder> VideoDecoder::Create(size_t name, void* media_handle) { + static_cast<void>(media_handle); + return std::make_unique<VideoDecoderRockchip>(name); +} + +VideoDecoderCapability VideoDecoder::Probe(VideoCodecType type) { + return VideoDecoderRockchip::Probe(type); +} + +} // namespace cosmo::media diff --git a/src/media/VideoDecoderCreateSophon.cc b/src/media/VideoDecoderCreateSophon.cc index 4b8756fb4..8582ee185 100644 --- a/src/media/VideoDecoderCreateSophon.cc +++ b/src/media/VideoDecoderCreateSophon.cc @@ -11,5 +11,9 @@ namespace media { return std::make_unique<VideoDecoderSophon>(name, mediaHandle); } + VideoDecoderCapability VideoDecoder::Probe(VideoCodecType type) { + return VideoDecoderSophon::Probe(type); + } + } // namespace media } // namespace cosmo diff --git a/src/media/VideoDecoderRockchip.cc b/src/media/VideoDecoderRockchip.cc new file mode 100644 index 000000000..1cd82de02 --- /dev/null +++ b/src/media/VideoDecoderRockchip.cc @@ -0,0 +1,650 @@ +#include "media/VideoDecoderRockchip.h" + +#include <unistd.h> + +#include <algorithm> +#include <chrono> +#include <cstring> +#include <deque> +#include <limits> +#include <thread> + +#define MODULE_TAG "cosmo_mpp_decoder" +#include <rockchip/mpp_buffer.h> +#include <rockchip/mpp_frame.h> +#include <rockchip/mpp_packet.h> +#include <rockchip/rk_mpi.h> +#include <rockchip/rk_vdec_cfg.h> + +#include "media/PreviewPipelineMetrics.h" +#include "media/VideoDecoderCpu.h" +#include "util/Log.h" + +namespace cosmo::media { +namespace { + + constexpr RK_U32 kDecoderBufferCount = 24; + constexpr int kPacketSubmitAttempts = 30; + constexpr auto kPacketSubmitWait = std::chrono::milliseconds(1); + constexpr size_t kMaxPendingTimings = 256; + + struct MppFrameHolder { + explicit MppFrameHolder(MppFrame value) : frame(value) {} + + ~MppFrameHolder() { + if (frame) { + mpp_frame_deinit(&frame); + } + } + + MppFrame frame{nullptr}; + }; + + MppCodingType ToMppCoding(VideoCodecType type) { + if (type == VideoCodecType::kH264) { + return MPP_VIDEO_CodingAVC; + } + if (type == VideoCodecType::kH265) { + return MPP_VIDEO_CodingHEVC; + } + return MPP_VIDEO_CodingUnused; + } + + uint64_t ElapsedNanoseconds(std::chrono::steady_clock::time_point started) { + return static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - started) + .count()); + } + + bool IsCompact420Format(MppFrameFormat format) { + const auto properties = static_cast<RK_U32>(format) & MPP_FRAME_FMT_PROP_MASK; + if ((properties & (MPP_FRAME_FBC_MASK | MPP_FRAME_TILE_FLAG)) != 0 || + MPP_FRAME_FMT_IS_YUV_10BIT(format)) { + return false; + } + const auto base = static_cast<RK_U32>(format) & MPP_FRAME_FMT_MASK; + return base == MPP_FMT_YUV420P || base == MPP_FMT_YUV420SP || base == MPP_FMT_YUV420SP_VU; + } + + NativeVideoBufferPtr ExportMppBuffer(const std::string& decoder_name, MppFrame frame) { + if (!frame) { + return nullptr; + } + auto buffer = mpp_frame_get_buffer(frame); + const auto format = mpp_frame_get_fmt(frame); + const auto base_format = static_cast<RK_U32>(format) & MPP_FRAME_FMT_MASK; + const size_t width = mpp_frame_get_width(frame); + const size_t height = mpp_frame_get_height(frame); + const size_t horizontal_stride = mpp_frame_get_hor_stride(frame); + const size_t vertical_stride = mpp_frame_get_ver_stride(frame); + if (!buffer || !IsCompact420Format(format) || width == 0 || height == 0 || + width > static_cast<size_t>(std::numeric_limits<int>::max()) || + height > static_cast<size_t>(std::numeric_limits<int>::max()) || + horizontal_stride > static_cast<size_t>(std::numeric_limits<int>::max()) || + vertical_stride > static_cast<size_t>(std::numeric_limits<int>::max()) || + horizontal_stride < width || vertical_stride < height) { + return nullptr; + } + + NativeVideoBufferFormat native_format = NativeVideoBufferFormat::Unknown; + if (base_format == MPP_FMT_YUV420SP) { + native_format = NativeVideoBufferFormat::NV12; + } else if (base_format == MPP_FMT_YUV420SP_VU) { + native_format = NativeVideoBufferFormat::NV21; + } else if (base_format == MPP_FMT_YUV420P) { + native_format = NativeVideoBufferFormat::I420; + } + const int fd = mpp_buffer_get_fd(buffer); + if (native_format == NativeVideoBufferFormat::Unknown || fd < 0 || + mpp_buffer_inc_ref(buffer) != MPP_OK) { + LOG_WARN("{} could not retain MPP DMA-BUF for inference", decoder_name); + return nullptr; + } + + auto result = std::make_shared<NativeVideoBuffer>(); + result->fd = fd; + result->bytes = mpp_buffer_get_size(buffer); + result->width = static_cast<int>(width); + result->height = static_cast<int>(height); + result->width_stride = static_cast<int>(horizontal_stride); + result->height_stride = static_cast<int>(vertical_stride); + result->format = native_format; + result->owner = std::shared_ptr<void>(buffer, [](void* value) { + if (value) { + mpp_buffer_put(static_cast<MppBuffer>(value)); + } + }); + return result; + } + + VideoFramePtr CopyMppFrame(const std::string& decoder_name, MppFrame frame) { + if (!frame) { + return nullptr; + } + + const size_t width = mpp_frame_get_width(frame); + const size_t height = mpp_frame_get_height(frame); + const size_t horizontal_stride = mpp_frame_get_hor_stride(frame); + const size_t vertical_stride = mpp_frame_get_ver_stride(frame); + const auto format = mpp_frame_get_fmt(frame); + auto buffer = mpp_frame_get_buffer(frame); + if (width == 0 || height == 0 || width % 2 != 0 || height % 2 != 0 || horizontal_stride < width || + vertical_stride < height || !IsCompact420Format(format) || !buffer) { + LOG_WARN("{} MPP decoder rejected output layout: {}x{} stride={}x{} format=0x{:x}", decoder_name, + width, height, horizontal_stride, vertical_stride, static_cast<RK_U32>(format)); + return nullptr; + } + if (horizontal_stride > std::numeric_limits<size_t>::max() / vertical_stride) { + return nullptr; + } + const size_t y_plane_size = horizontal_stride * vertical_stride; + if (y_plane_size > std::numeric_limits<size_t>::max() - y_plane_size / 2) { + return nullptr; + } + const size_t required = y_plane_size * 3 / 2; + if (mpp_buffer_get_size(buffer) < required) { + LOG_WARN("{} MPP decoder output buffer too small: {} < {}", decoder_name, + mpp_buffer_get_size(buffer), required); + return nullptr; + } + + auto output = std::make_shared<VideoFrame>(static_cast<int>(width), static_cast<int>(height), + PixelFormat::PIXEL_I420); + if (!output || !output->Active() || !output->GetData()) { + LOG_WARN("{} compact I420 VideoFrame allocation failed for {}x{}", decoder_name, width, height); + return nullptr; + } + + auto* source = static_cast<const uint8_t*>(mpp_buffer_get_ptr(buffer)); + if (!source || mpp_buffer_sync_ro_begin(buffer) != MPP_OK) { + return nullptr; + } + struct ReadSyncGuard { + MppBuffer buffer; + ~ReadSyncGuard() { + mpp_buffer_sync_ro_end(buffer); + } + } sync_guard{buffer}; + + auto* destination = output->GetData(); + const size_t compact_y = width * height; + const size_t compact_uv = compact_y / 4; + auto* destination_u = destination + compact_y; + auto* destination_v = destination_u + compact_uv; + for (size_t row = 0; row < height; ++row) { + std::memcpy(destination + row * width, source + row * horizontal_stride, width); + } + + const auto base_format = static_cast<RK_U32>(format) & MPP_FRAME_FMT_MASK; + if (base_format == MPP_FMT_YUV420P) { + const size_t chroma_stride = horizontal_stride / 2; + const size_t chroma_height = vertical_stride / 2; + const auto* source_u = source + y_plane_size; + const auto* source_v = source_u + chroma_stride * chroma_height; + for (size_t row = 0; row < height / 2; ++row) { + std::memcpy(destination_u + row * (width / 2), source_u + row * chroma_stride, width / 2); + std::memcpy(destination_v + row * (width / 2), source_v + row * chroma_stride, width / 2); + } + } else { + const bool vu_order = base_format == MPP_FMT_YUV420SP_VU; + const auto* source_chroma = source + y_plane_size; + for (size_t row = 0; row < height / 2; ++row) { + const auto* source_row = source_chroma + row * horizontal_stride; + auto* u_row = destination_u + row * (width / 2); + auto* v_row = destination_v + row * (width / 2); + for (size_t column = 0; column < width / 2; ++column) { + const auto first = source_row[column * 2]; + const auto second = source_row[column * 2 + 1]; + u_row[column] = vu_order ? second : first; + v_row[column] = vu_order ? first : second; + } + } + } + + return output; + } + +} // namespace + +struct PendingDecodeTiming { + int64_t pts{0}; +}; + +struct RockchipDecoderState { + MppCtx context{nullptr}; + MppApi* api{nullptr}; + MppDecCfg config{nullptr}; + MppBufferGroup frame_group{nullptr}; + size_t frame_group_buffer_size{0}; + bool frame_group_reuse_logged{false}; + MppCodingType coding{MPP_VIDEO_CodingUnused}; + bool opened{false}; + std::deque<PendingDecodeTiming> pending; + std::deque<DecodedVideoFrame> ready_frames; +}; + +VideoDecoderRockchip::VideoDecoderRockchip(size_t name) : VideoDecoder(name) {} + +VideoDecoderRockchip::~VideoDecoderRockchip() { + VideoDecoderRockchip::Close(); +} + +VideoDecoderCapability VideoDecoderRockchip::Probe(VideoCodecType type) { + VideoDecoderCapability capability; + capability.backend = "rockchip-copy-out"; + capability.implementation = "rockchip-mpp-vpu"; + + const auto coding = ToMppCoding(type); + if (coding == MPP_VIDEO_CodingUnused) { + const auto cpu = VideoDecoderCpu::Probe(type); + capability.available = cpu.available; + capability.backend = cpu.available ? "ffmpeg-software-fallback" : capability.backend; + capability.implementation = cpu.available ? cpu.implementation : std::string{}; + capability.detail = cpu.available + ? "Codec is outside the MPP H264/H265 scope; FFmpeg fallback is available" + : "Codec is outside the MPP H264/H265 scope; FFmpeg fallback unavailable"; + return capability; + } + + const bool device_accessible = access("/dev/mpp_service", R_OK | W_OK) == 0; + const bool format_supported = mpp_check_support_format(MPP_CTX_DEC, coding) == MPP_OK; + if (device_accessible && format_supported) { + capability.available = true; + capability.detail = "MPP VPU decoder is available; decoded frames are copied out as compact I420"; + return capability; + } + + const auto cpu = VideoDecoderCpu::Probe(type); + if (cpu.available) { + capability.available = true; + capability.backend = "ffmpeg-software-fallback"; + capability.implementation = cpu.implementation; + capability.detail = "MPP decoder unavailable; FFmpeg software fallback is available"; + return capability; + } + + capability.detail = std::string("MPP decoder unavailable (") + + (device_accessible ? "codec unsupported" : "device inaccessible") + + "); FFmpeg fallback unavailable"; + return capability; +} + +bool VideoDecoderRockchip::Open() { + Close(); + if (OpenMpp()) { + return true; + } + + const auto cpu_capability = VideoDecoderCpu::Probe(codec_type_); + if (!cpu_capability.available) { + LOG_WARN("{} MPP decoder open failed and FFmpeg fallback is unavailable: {}", idx_name_, + cpu_capability.detail); + return false; + } + + fallback_ = std::make_unique<VideoDecoderCpu>(0); + fallback_->SetCodecType(codec_type_, static_cast<int>(width_), static_cast<int>(height_)); + if (!fallback_->Open()) { + fallback_.reset(); + return false; + } + GetPreviewPipelineMetrics().RecordMppDecodeFallback(); + LOG_WARN("{} MPP decoder unavailable; using FFmpeg decoder {}", idx_name_, cpu_capability.implementation); + return true; +} + +bool VideoDecoderRockchip::OpenMpp() { + const auto coding = ToMppCoding(codec_type_); + if (coding == MPP_VIDEO_CodingUnused) { + return false; + } + + const auto capability = Probe(codec_type_); + if (!capability.available || capability.implementation != "rockchip-mpp-vpu") { + LOG_WARN("{} MPP decoder admission failed: {}", idx_name_, capability.detail); + return false; + } + + state_ = std::make_unique<RockchipDecoderState>(); + state_->coding = coding; + auto ret = mpp_create(&state_->context, &state_->api); + if (ret != MPP_OK || !state_->context || !state_->api) { + LOG_WARN("{} MPP decoder context creation failed: {}", idx_name_, ret); + CleanMpp(); + return false; + } + ret = mpp_init(state_->context, MPP_CTX_DEC, coding); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder initialization failed: {}", idx_name_, ret); + CleanMpp(); + return false; + } + + ret = mpp_dec_cfg_init(&state_->config); + if (ret != MPP_OK || !state_->config) { + LOG_WARN("{} MPP decoder config allocation failed: {}", idx_name_, ret); + CleanMpp(); + return false; + } + ret = state_->api->control(state_->context, MPP_DEC_GET_CFG, state_->config); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder config query failed: {}", idx_name_, ret); + CleanMpp(); + return false; + } + // VideoDemuxer already emits one Annex-B access unit per VideoPacket. + ret = mpp_dec_cfg_set_u32(state_->config, "base:split_parse", 0); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder split-parse configuration failed: {}", idx_name_, ret); + CleanMpp(); + return false; + } + ret = state_->api->control(state_->context, MPP_DEC_SET_CFG, state_->config); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder config commit failed: {}", idx_name_, ret); + CleanMpp(); + return false; + } + + // NV12 is the native RK3576 decoder output. It is deinterleaved during the + // explicit Copy-out boundary, so downstream code still receives I420. + MppFrameFormat output_format = MPP_FMT_YUV420SP; + ret = state_->api->control(state_->context, MPP_DEC_SET_OUTPUT_FORMAT, &output_format); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder output-format request failed: {}", idx_name_, ret); + CleanMpp(); + return false; + } + + MppPollType output_timeout = static_cast<MppPollType>(10); + ret = state_->api->control(state_->context, MPP_SET_OUTPUT_TIMEOUT, &output_timeout); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder timeout configuration failed: {}", idx_name_, ret); + CleanMpp(); + return false; + } + + state_->opened = true; + LOG_INFO("{} MPP VPU decoder opened: codec={} copy-out=I420", idx_name_, static_cast<int>(codec_type_)); + return true; +} + +bool VideoDecoderRockchip::Close() { + bool result = true; + if (fallback_) { + result = fallback_->Close(); + fallback_.reset(); + } + CleanMpp(); + return result; +} + +bool VideoDecoderRockchip::IsOpened() { + return (fallback_ && fallback_->IsOpened()) || (state_ && state_->opened); +} + +bool VideoDecoderRockchip::ReuseForStreamRestart(VideoCodecType type, int width, int height) { + if (fallback_ || !state_ || !state_->opened || !state_->context || !state_->api || type != codec_type_ || + width <= 0 || height <= 0 || static_cast<size_t>(width) != width_ || + static_cast<size_t>(height) != height_) { + return false; + } + + // A local loop or RTSP reconnect starts with a validated keyframe. Keep + // the MPP context and its external frame group alive so synchronous RGA + // imports never outlive a frame group that is destroyed every few seconds. + // Codec parameter sets on the new keyframe update the decoder as needed; + // ConfigureFrameGroup reuses the group when the requested buffer layout is + // unchanged and reconfigures it when the layout really changes. + state_->pending.clear(); + state_->ready_frames.clear(); + return true; +} + +bool VideoDecoderRockchip::SendPacket(const uint8_t* pkt, size_t len, int64_t frame_idx) { + if (fallback_) { + return fallback_->SendPacket(pkt, len, frame_idx); + } + + const auto started = std::chrono::steady_clock::now(); + const auto fail = [&]() { + GetPreviewPipelineMetrics().RecordMppDecode(false, ElapsedNanoseconds(started)); + return false; + }; + if (!state_ || !state_->opened || !state_->context || !state_->api || !pkt || len == 0) { + return fail(); + } + + MppPacket packet = nullptr; + auto ret = mpp_packet_init(&packet, const_cast<uint8_t*>(pkt), len); + if (ret != MPP_OK || !packet) { + return fail(); + } + mpp_packet_set_pos(packet, const_cast<uint8_t*>(pkt)); + mpp_packet_set_length(packet, len); + mpp_packet_set_pts(packet, frame_idx); + mpp_packet_set_dts(packet, frame_idx); + + bool submitted = false; + for (int attempt = 0; attempt < kPacketSubmitAttempts; ++attempt) { + ret = state_->api->decode_put_packet(state_->context, packet); + if (ret == MPP_OK) { + submitted = true; + break; + } + if (ret != MPP_ERR_BUFFER_FULL) { + break; + } + // The common VideoDecoder contract calls SendPacket before GetFrame. + // Under load MPP may therefore have a completed output waiting while + // its input queue is full. Drain exactly one output, retain it for the + // subsequent GetFrame call, then retry the same input packet. + bool made_progress = false; + auto ready = ReceiveMppFrame(made_progress); + if (ready.HasFrame()) { + state_->ready_frames.push_back(std::move(ready)); + } + if (!made_progress) { + std::this_thread::sleep_for(kPacketSubmitWait); + } + } + mpp_packet_deinit(&packet); + if (!submitted) { + LOG_WARN("{} MPP decode_put_packet failed: {}", idx_name_, ret); + return fail(); + } + + state_->pending.push_back({frame_idx}); + while (state_->pending.size() > kMaxPendingTimings) { + state_->pending.pop_front(); + } + return true; +} + +bool VideoDecoderRockchip::ConfigureFrameGroup(size_t buffer_size) { + if (!state_ || !state_->context || !state_->api || buffer_size == 0) { + return false; + } + + MPP_RET ret = MPP_OK; + const bool reuse_existing_group = state_->frame_group && state_->frame_group_buffer_size == buffer_size; + if (!state_->frame_group) { + ret = mpp_buffer_group_get_internal( + &state_->frame_group, + static_cast<MppBufferType>(MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_CACHABLE)); + } else if (!reuse_existing_group) { + ret = mpp_buffer_group_clear(state_->frame_group); + } + if (ret != MPP_OK || !state_->frame_group) { + LOG_WARN("{} MPP decoder frame-group allocation/reset failed: {}", idx_name_, ret); + return false; + } + if (!reuse_existing_group) { + ret = mpp_buffer_group_limit_config(state_->frame_group, buffer_size, kDecoderBufferCount); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder frame-group limit failed: {}", idx_name_, ret); + return false; + } + ret = state_->api->control(state_->context, MPP_DEC_SET_EXT_BUF_GROUP, state_->frame_group); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder external frame-group setup failed: {}", idx_name_, ret); + return false; + } + state_->frame_group_buffer_size = buffer_size; + } + ret = state_->api->control(state_->context, MPP_DEC_SET_INFO_CHANGE_READY, nullptr); + if (ret != MPP_OK) { + LOG_WARN("{} MPP decoder info-change acknowledgement failed: {}", idx_name_, ret); + if (!reuse_existing_group) { + state_->frame_group_buffer_size = 0; + } + return false; + } + return true; +} + +DecodedVideoFrame VideoDecoderRockchip::ReceiveMppFrame(bool& made_progress) { + made_progress = false; + if (!state_ || !state_->opened || !state_->context || !state_->api) { + return {}; + } + + const auto decode_started = std::chrono::steady_clock::now(); + MppFrame frame = nullptr; + const auto ret = state_->api->decode_get_frame(state_->context, &frame); + if (ret == MPP_ERR_TIMEOUT || (ret == MPP_OK && !frame)) { + return {}; + } + if (ret != MPP_OK) { + made_progress = true; + GetPreviewPipelineMetrics().RecordMppDecode(false, ElapsedNanoseconds(decode_started)); + LOG_WARN("{} MPP decode_get_frame failed: {}", idx_name_, ret); + return {}; + } + + if (mpp_frame_get_info_change(frame)) { + made_progress = true; + const auto buffer_size = mpp_frame_get_buf_size(frame); + const bool reused_group = state_->frame_group && state_->frame_group_buffer_size == buffer_size; + const auto configured = ConfigureFrameGroup(buffer_size); + if (!reused_group || !configured) { + LOG_INFO("{} MPP decoder info change: {}x{} stride={}x{} buffer={} configured={} reused={}", + idx_name_, mpp_frame_get_width(frame), mpp_frame_get_height(frame), + mpp_frame_get_hor_stride(frame), mpp_frame_get_ver_stride(frame), buffer_size, + configured, reused_group); + } else if (!state_->frame_group_reuse_logged) { + state_->frame_group_reuse_logged = true; + LOG_INFO("{} MPP decoder reuses its existing {}-byte frame group for repeated stream headers", + idx_name_, buffer_size); + } + mpp_frame_deinit(&frame); + if (!configured) { + GetPreviewPipelineMetrics().RecordMppDecode(false, ElapsedNanoseconds(decode_started)); + } + return {}; + } + + const auto pts = mpp_frame_get_pts(frame); + made_progress = true; + auto timing = state_->pending.end(); + if (pts >= 0) { + timing = std::find_if(state_->pending.begin(), state_->pending.end(), + [pts](const auto& item) { return item.pts == pts; }); + } + if (timing == state_->pending.end() && !state_->pending.empty()) { + timing = state_->pending.begin(); + } + const bool frame_valid = mpp_frame_get_errinfo(frame) == 0 && mpp_frame_get_discard(frame) == 0; + if (!frame_valid) { + LOG_WARN("{} MPP decoder discarded frame pts={} err=0x{:x} discard=0x{:x}", idx_name_, pts, + mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame)); + mpp_frame_deinit(&frame); + if (timing != state_->pending.end()) { + state_->pending.erase(timing); + } + GetPreviewPipelineMetrics().RecordMppDecode(false, ElapsedNanoseconds(decode_started)); + return {}; + } + + int64_t resolved_pts = pts; + if (resolved_pts < 0 && timing != state_->pending.end()) { + resolved_pts = timing->pts; + } + if (timing != state_->pending.end()) { + state_->pending.erase(timing); + } + const size_t frame_width = mpp_frame_get_width(frame); + const size_t frame_height = mpp_frame_get_height(frame); + width_ = frame_width; + height_ = frame_height; + auto holder = std::make_shared<MppFrameHolder>(frame); + frame = nullptr; + const auto decoder_name = idx_name_; + + // This counter measures a valid MPP output becoming available. Host + // allocation and copying are measured separately by RecordMppCopyOut. + GetPreviewPipelineMetrics().RecordMppDecode(true, ElapsedNanoseconds(decode_started)); + return DecodedVideoFrame( + static_cast<uint64_t>(std::max<int64_t>(0, resolved_pts)), frame_width, frame_height, + PixelFormat::PIXEL_I420, + [holder, decoder_name, resolved_pts]() { + const auto copy_started = std::chrono::steady_clock::now(); + auto output = CopyMppFrame(decoder_name, holder->frame); + if (output) { + output->SetFrameIndex(static_cast<uint64_t>(std::max<int64_t>(0, resolved_pts))); + } + GetPreviewPipelineMetrics().RecordMppCopyOut(output != nullptr, ElapsedNanoseconds(copy_started)); + return output; + }, + []() { GetPreviewPipelineMetrics().RecordMppEarlyDrop(); }, + [holder, decoder_name]() { return ExportMppBuffer(decoder_name, holder->frame); }); +} + +VideoFramePtr VideoDecoderRockchip::GetFrame() { + auto frame = GetDecodedFrame(); + return frame.Materialize(); +} + +DecodedVideoFrame VideoDecoderRockchip::GetDecodedFrame() { + if (fallback_) { + return DecodedVideoFrame(fallback_->GetFrame()); + } + if (!state_ || !state_->opened) { + return {}; + } + if (!state_->ready_frames.empty()) { + auto output = std::move(state_->ready_frames.front()); + state_->ready_frames.pop_front(); + return output; + } + bool made_progress = false; + return ReceiveMppFrame(made_progress); +} + +void VideoDecoderRockchip::CleanMpp() { + if (!state_) { + return; + } + state_->opened = false; + state_->pending.clear(); + state_->ready_frames.clear(); + if (state_->context && state_->api) { + state_->api->reset(state_->context); + } + if (state_->context) { + mpp_destroy(state_->context); + state_->context = nullptr; + state_->api = nullptr; + } + if (state_->frame_group) { + mpp_buffer_group_put(state_->frame_group); + state_->frame_group = nullptr; + } + if (state_->config) { + mpp_dec_cfg_deinit(state_->config); + state_->config = nullptr; + } + state_.reset(); +} + +} // namespace cosmo::media diff --git a/src/media/VideoDecoderRockchip.h b/src/media/VideoDecoderRockchip.h new file mode 100644 index 000000000..6e7aa8abe --- /dev/null +++ b/src/media/VideoDecoderRockchip.h @@ -0,0 +1,45 @@ +#pragma once + +#include <memory> + +#include "media/VideoDecoder.h" + +namespace cosmo::media { + +class VideoDecoderCpu; +struct RockchipDecoderState; + +/// Rockchip MPP decoder with a bounded device-to-host copy boundary. +/// +/// Compressed H.264/H.265 packets are decoded by the VPU. A decoded MPP frame +/// is retained on the decoder thread until the channel sampling decision; only +/// selected outputs are copied into the compact I420 VideoFrame expected by +/// the existing CosmoEdge pipeline. DMA-BUF zero-copy ownership is +/// intentionally outside this phase. +class VideoDecoderRockchip final : public VideoDecoder { +public: + explicit VideoDecoderRockchip(size_t name); + ~VideoDecoderRockchip() override; + + bool Open() override; + bool Close() override; + bool IsOpened() override; + bool ReuseForStreamRestart(VideoCodecType type, int width, int height) override; + + bool SendPacket(const uint8_t* pkt, size_t len, int64_t frame_idx) override; + VideoFramePtr GetFrame() override; + DecodedVideoFrame GetDecodedFrame() override; + + static VideoDecoderCapability Probe(VideoCodecType type); + +private: + bool OpenMpp(); + bool ConfigureFrameGroup(size_t buffer_size); + DecodedVideoFrame ReceiveMppFrame(bool& made_progress); + void CleanMpp(); + + std::unique_ptr<RockchipDecoderState> state_; + std::unique_ptr<VideoDecoderCpu> fallback_; +}; + +} // namespace cosmo::media diff --git a/src/media/VideoDecoderSophon.cc b/src/media/VideoDecoderSophon.cc index 97ecd8f36..dc8502219 100644 --- a/src/media/VideoDecoderSophon.cc +++ b/src/media/VideoDecoderSophon.cc @@ -56,6 +56,16 @@ namespace media { return opened_.load() && !stop_.load(); } + VideoDecoderCapability VideoDecoderSophon::Probe(VideoCodecType type) { + VideoDecoderCapability capability; + capability.backend = "sophon-vpu"; + capability.implementation = "bmvpu-decoder"; + capability.available = type == VideoCodecType::kH264 || type == VideoCodecType::kH265; + capability.detail = + capability.available ? "Sophon VPU decoder supports the requested codec" : "unsupported codec"; + return capability; + } + bool VideoDecoderSophon::Open() { std::lock_guard<std::mutex> operation_lock(operation_mutex_); if (opened_.load()) { diff --git a/src/media/VideoDecoderSophon.h b/src/media/VideoDecoderSophon.h index d028e4208..43022f31b 100644 --- a/src/media/VideoDecoderSophon.h +++ b/src/media/VideoDecoderSophon.h @@ -32,6 +32,8 @@ namespace media { VideoFramePtr GetFrame() override; + static VideoDecoderCapability Probe(VideoCodecType type); + private: bool AttachVideoFrame(bm_image* image, BMVidFrame* frame); diff --git a/src/media/VideoEncoder.h b/src/media/VideoEncoder.h index 985e5f3c2..5e32bbf44 100644 --- a/src/media/VideoEncoder.h +++ b/src/media/VideoEncoder.h @@ -1,6 +1,7 @@ #pragma once #include <memory> +#include <string> #include "media/VideoFrame.h" #include "media/VideoPacket.h" @@ -8,6 +9,13 @@ namespace cosmo { namespace media { + struct VideoEncoderCapability { + bool available{false}; + std::string backend; + std::string implementation; + std::string detail; + }; + class VideoEncoder { public: explicit VideoEncoder(); @@ -28,10 +36,15 @@ namespace media { size_t GetWidth() const; size_t GetHeight() const; - /// Factory — creates the correct backend encoder (Sophon or CPU). - /// @param mediaHandle Device handle (used by Sophon, ignored by CPU) + /// Factory — creates the selected platform backend encoder. + /// @param mediaHandle Device handle (used by hardware backends, ignored by CPU) static std::shared_ptr<VideoEncoder> Create(void* mediaHandle); + /// Reports the deterministic implementation that Create/Open will use. + /// A missing approved implementation is reported as unavailable instead + /// of falling through to an arbitrary FFmpeg hardware encoder. + static VideoEncoderCapability Probe(VideoCodecType type); + protected: VideoCodecType codec_type_{VideoCodecType::kInvalid}; diff --git a/src/media/VideoEncoderCpu.cc b/src/media/VideoEncoderCpu.cc index 86c9d057d..fa6421fe2 100644 --- a/src/media/VideoEncoderCpu.cc +++ b/src/media/VideoEncoderCpu.cc @@ -4,6 +4,7 @@ #include <cstring> #include <string> +#include <string_view> #include <vector> #ifdef __cplusplus @@ -27,19 +28,19 @@ namespace media { return buf; } - const AVCodec* FindEncoder(AVCodecID codecId) { - if (codecId == AV_CODEC_ID_H264) { - if (const AVCodec* codec = avcodec_find_encoder_by_name("libopenh264")) { - return codec; - } - - } else if (codecId == AV_CODEC_ID_HEVC) { - if (const AVCodec* codec = avcodec_find_encoder_by_name("libx265")) { - return codec; - } - } + std::string_view ApprovedEncoderName(VideoCodecType type) { + if (type == VideoCodecType::kH264) + return "libopenh264"; + if (type == VideoCodecType::kH265) + return "libx265"; + return {}; + } - return avcodec_find_encoder(codecId); + const AVCodec* FindEncoder(VideoCodecType type) { + const auto name = ApprovedEncoderName(type); + if (name.empty()) + return nullptr; + return avcodec_find_encoder_by_name(std::string(name).c_str()); } struct H264NaluView { @@ -128,6 +129,28 @@ namespace media { Clean(); } + VideoEncoderCapability VideoEncoderCpu::Probe(VideoCodecType type) { + VideoEncoderCapability capability; + capability.backend = "ffmpeg-software"; + const auto approved = ApprovedEncoderName(type); + if (approved.empty()) { + capability.detail = "unsupported codec"; + return capability; + } + + capability.implementation = std::string(approved); + const auto* codec = FindEncoder(type); + capability.available = codec != nullptr; + capability.detail = capability.available + ? "approved FFmpeg encoder is registered" + : "approved FFmpeg encoder is not registered; generic fallback disabled"; + return capability; + } + + bool VideoEncoderCpu::IsAllowedEncoderName(VideoCodecType type, std::string_view name) { + return name == ApprovedEncoderName(type); + } + bool VideoEncoderCpu::Open() { AVCodecID codec_id = AV_CODEC_ID_NONE; if (codec_type_ == VideoCodecType::kH264) { @@ -139,10 +162,12 @@ namespace media { return false; } - auto* codec = FindEncoder(codec_id); + const auto capability = Probe(codec_type_); + auto* codec = FindEncoder(codec_type_); if (!codec) { - // H.265 encoder may not be available in all FFmpeg builds - LOG_WARN("CPU encoder: avcodec_find_encoder failed for codec_id {}", static_cast<int>(codec_id)); + LOG_WARN("CPU encoder unavailable: codec_id={} backend={} implementation={} detail={}", + static_cast<int>(codec_id), capability.backend, capability.implementation, + capability.detail); return false; } @@ -210,7 +235,8 @@ namespace media { frame_pts_ = 0; closed_ = false; - LOG_INFO("CPU encoder opened ({}x{}, codec_id={})", width_, height_, static_cast<int>(codec_id)); + LOG_INFO("CPU encoder opened ({}x{}, codec_id={}, implementation={})", width_, height_, + static_cast<int>(codec_id), capability.implementation); return true; } diff --git a/src/media/VideoEncoderCpu.h b/src/media/VideoEncoderCpu.h index 4804d123b..0e75f51bc 100644 --- a/src/media/VideoEncoderCpu.h +++ b/src/media/VideoEncoderCpu.h @@ -1,6 +1,7 @@ #pragma once #include <cstdint> +#include <string_view> #ifdef __cplusplus extern "C" { @@ -28,6 +29,9 @@ namespace media { VideoPacketPtr SendYUVFrame(void* data) override; + static VideoEncoderCapability Probe(VideoCodecType type); + static bool IsAllowedEncoderName(VideoCodecType type, std::string_view name); + private: void Clean(); diff --git a/src/media/VideoEncoderCreateCpu.cc b/src/media/VideoEncoderCreateCpu.cc index 6b3eefa15..77e922bcd 100644 --- a/src/media/VideoEncoderCreateCpu.cc +++ b/src/media/VideoEncoderCreateCpu.cc @@ -12,5 +12,9 @@ namespace media { return std::make_shared<VideoEncoderCpu>(); } + VideoEncoderCapability VideoEncoder::Probe(VideoCodecType type) { + return VideoEncoderCpu::Probe(type); + } + } // namespace media } // namespace cosmo diff --git a/src/media/VideoEncoderCreateRockchip.cc b/src/media/VideoEncoderCreateRockchip.cc new file mode 100644 index 000000000..060548076 --- /dev/null +++ b/src/media/VideoEncoderCreateRockchip.cc @@ -0,0 +1,15 @@ +#include "media/VideoEncoder.h" +#include "media/VideoEncoderRockchip.h" + +namespace cosmo::media { + +std::shared_ptr<VideoEncoder> VideoEncoder::Create(void* media_handle) { + static_cast<void>(media_handle); + return std::make_shared<VideoEncoderRockchip>(); +} + +VideoEncoderCapability VideoEncoder::Probe(VideoCodecType type) { + return VideoEncoderRockchip::Probe(type); +} + +} // namespace cosmo::media diff --git a/src/media/VideoEncoderCreateSophon.cc b/src/media/VideoEncoderCreateSophon.cc index 8f73820e6..86bd2c099 100644 --- a/src/media/VideoEncoderCreateSophon.cc +++ b/src/media/VideoEncoderCreateSophon.cc @@ -11,5 +11,22 @@ namespace media { return std::make_shared<VideoEncoderSophon>(mediaHandle); } + VideoEncoderCapability VideoEncoder::Probe(VideoCodecType type) { + VideoEncoderCapability capability; + capability.backend = "sophon-vpu"; + if (type == VideoCodecType::kH264) { + capability.available = true; + capability.implementation = "bmvpu-h264"; + capability.detail = "compiled Sophon VPU encoder"; + } else if (type == VideoCodecType::kH265) { + capability.available = true; + capability.implementation = "bmvpu-h265"; + capability.detail = "compiled Sophon VPU encoder"; + } else { + capability.detail = "unsupported codec"; + } + return capability; + } + } // namespace media } // namespace cosmo diff --git a/src/media/VideoEncoderRockchip.cc b/src/media/VideoEncoderRockchip.cc new file mode 100644 index 000000000..d9ac9d9b5 --- /dev/null +++ b/src/media/VideoEncoderRockchip.cc @@ -0,0 +1,481 @@ +#include "media/VideoEncoderRockchip.h" + +#include <unistd.h> + +#include <algorithm> +#include <chrono> +#include <cstring> +#include <limits> +#include <string> +#include <vector> + +#define MODULE_TAG "cosmo_mpp_encoder" +#include <rockchip/mpp_buffer.h> +#include <rockchip/mpp_frame.h> +#include <rockchip/mpp_meta.h> +#include <rockchip/mpp_packet.h> +#include <rockchip/rk_mpi.h> +#include <rockchip/rk_venc_cfg.h> +#include <rockchip/rk_venc_rc.h> + +#include "media/PreviewPipelineMetrics.h" +#include "media/VideoEncoderCpu.h" +#include "util/Log.h" + +namespace cosmo::media { +namespace { + + constexpr size_t kMppAlignment = 16; + constexpr RK_S32 kFrameRate = 25; + constexpr RK_S32 kGopLength = 10; + constexpr RK_S32 kBitRate = 4'000'000; + + MppCodingType ToMppCoding(VideoCodecType type) { + return type == VideoCodecType::kH264 ? MPP_VIDEO_CodingAVC : MPP_VIDEO_CodingUnused; + } + + size_t AlignUp(size_t value, size_t alignment) { + return (value + alignment - 1) / alignment * alignment; + } + + bool ContainsH264ParameterSet(const uint8_t* data, size_t size) { + if (!data || size < 5) { + return false; + } + bool has_sps = false; + bool has_pps = false; + for (size_t pos = 0; pos + 4 < size; ++pos) { + size_t prefix = 0; + if (data[pos] == 0 && data[pos + 1] == 0 && data[pos + 2] == 1) { + prefix = 3; + } else if (pos + 4 < size && data[pos] == 0 && data[pos + 1] == 0 && data[pos + 2] == 0 && + data[pos + 3] == 1) { + prefix = 4; + } + if (prefix != 0 && pos + prefix < size) { + const auto type = static_cast<uint8_t>(data[pos + prefix] & 0x1f); + has_sps = has_sps || type == 7; + has_pps = has_pps || type == 8; + } + } + return has_sps && has_pps; + } + + bool ContainsH264Idr(const uint8_t* data, size_t size) { + if (!data || size < 5) { + return false; + } + for (size_t pos = 0; pos + 4 < size; ++pos) { + size_t prefix = 0; + if (data[pos] == 0 && data[pos + 1] == 0 && data[pos + 2] == 1) { + prefix = 3; + } else if (pos + 4 < size && data[pos] == 0 && data[pos + 1] == 0 && data[pos + 2] == 0 && + data[pos + 3] == 1) { + prefix = 4; + } + if (prefix != 0 && pos + prefix < size && (data[pos + prefix] & 0x1f) == 5) { + return true; + } + } + return false; + } + + uint64_t ElapsedNanoseconds(std::chrono::steady_clock::time_point started) { + return static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - started) + .count()); + } + +} // namespace + +struct RockchipEncoderState { + MppCtx context{nullptr}; + MppApi* api{nullptr}; + MppEncCfg config{nullptr}; + MppBufferGroup buffer_group{nullptr}; + MppBuffer frame_buffer{nullptr}; + MppBuffer packet_buffer{nullptr}; + MppCodingType coding{MPP_VIDEO_CodingUnused}; + size_t horizontal_stride{0}; + size_t vertical_stride{0}; + size_t frame_buffer_size{0}; + int64_t frame_pts{0}; + std::vector<uint8_t> codec_header; +}; + +VideoEncoderRockchip::VideoEncoderRockchip() : VideoEncoder() {} + +VideoEncoderRockchip::~VideoEncoderRockchip() { + Clean(); +} + +VideoEncoderCapability VideoEncoderRockchip::Probe(VideoCodecType type) { + VideoEncoderCapability capability; + capability.backend = "rockchip-copy-first"; + capability.implementation = "rockchip-mpp"; + + const auto coding = ToMppCoding(type); + if (coding == MPP_VIDEO_CodingUnused) { + const auto cpu = VideoEncoderCpu::Probe(type); + capability.available = cpu.available; + capability.backend = cpu.available ? "ffmpeg-software-fallback" : capability.backend; + capability.implementation = cpu.available ? cpu.implementation : std::string{}; + capability.detail = + cpu.available ? "Rockchip MPP qualification is H264-only; approved FFmpeg fallback is available" + : "Rockchip MPP qualification is H264-only; approved FFmpeg fallback unavailable"; + return capability; + } + + const bool device_accessible = access("/dev/mpp_service", R_OK | W_OK) == 0; + const bool format_supported = mpp_check_support_format(MPP_CTX_ENC, coding) == MPP_OK; + if (device_accessible && format_supported) { + capability.available = true; + capability.detail = + "MPP encoder device and codec are available; compact I420 is copied into a " + "stride-aligned MPP buffer"; + return capability; + } + + const auto cpu = VideoEncoderCpu::Probe(type); + if (cpu.available) { + capability.available = true; + capability.backend = "ffmpeg-software-fallback"; + capability.implementation = cpu.implementation; + capability.detail = "MPP unavailable; deterministic approved FFmpeg fallback is available"; + return capability; + } + + capability.detail = std::string("MPP unavailable (") + + (device_accessible ? "codec unsupported" : "device inaccessible") + + "); approved FFmpeg fallback unavailable"; + return capability; +} + +bool VideoEncoderRockchip::Open() { + Clean(); + if (OpenMpp()) { + return true; + } + + const auto cpu_capability = VideoEncoderCpu::Probe(codec_type_); + if (!cpu_capability.available) { + LOG_WARN("Rockchip encoder open failed and deterministic CPU fallback is unavailable: {}", + cpu_capability.detail); + return false; + } + + fallback_ = std::make_unique<VideoEncoderCpu>(); + fallback_->Set(codec_type_, width_, height_); + if (!fallback_->Open()) { + fallback_.reset(); + return false; + } + LOG_WARN("Rockchip MPP unavailable; using approved CPU encoder {}", cpu_capability.implementation); + return true; +} + +bool VideoEncoderRockchip::OpenMpp() { + const auto coding = ToMppCoding(codec_type_); + if (coding == MPP_VIDEO_CodingUnused || width_ == 0 || height_ == 0 || width_ % 2 != 0 || + height_ % 2 != 0 || width_ > static_cast<size_t>(std::numeric_limits<RK_S32>::max()) || + height_ > static_cast<size_t>(std::numeric_limits<RK_S32>::max()) - kMppAlignment) { + LOG_WARN("MPP encoder invalid codec or dimensions: codec={} size={}x{}", + static_cast<int>(codec_type_), width_, height_); + return false; + } + + const auto capability = Probe(codec_type_); + if (!capability.available || capability.implementation != "rockchip-mpp") { + LOG_WARN("MPP encoder admission failed: {}", capability.detail); + return false; + } + + state_ = std::make_unique<RockchipEncoderState>(); + state_->coding = coding; + state_->horizontal_stride = AlignUp(width_, kMppAlignment); + state_->vertical_stride = AlignUp(height_, kMppAlignment); + if (state_->horizontal_stride > std::numeric_limits<size_t>::max() / state_->vertical_stride) { + CleanMpp(); + return false; + } + const size_t y_plane = state_->horizontal_stride * state_->vertical_stride; + if (y_plane > std::numeric_limits<size_t>::max() - y_plane / 2) { + CleanMpp(); + return false; + } + state_->frame_buffer_size = y_plane * 3 / 2; + + auto ret = mpp_buffer_group_get_internal( + &state_->buffer_group, static_cast<MppBufferType>(MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_CACHABLE)); + if (ret != MPP_OK) { + LOG_WARN("MPP buffer group allocation failed: {}", ret); + CleanMpp(); + return false; + } + ret = mpp_buffer_get(state_->buffer_group, &state_->frame_buffer, state_->frame_buffer_size); + if (ret != MPP_OK) { + LOG_WARN("MPP frame buffer allocation failed: {}", ret); + CleanMpp(); + return false; + } + ret = mpp_buffer_get(state_->buffer_group, &state_->packet_buffer, state_->frame_buffer_size); + if (ret != MPP_OK) { + LOG_WARN("MPP packet buffer allocation failed: {}", ret); + CleanMpp(); + return false; + } + + ret = mpp_create(&state_->context, &state_->api); + if (ret != MPP_OK || !state_->context || !state_->api) { + LOG_WARN("MPP context creation failed: {}", ret); + CleanMpp(); + return false; + } + MppPollType timeout = MPP_POLL_BLOCK; + ret = state_->api->control(state_->context, MPP_SET_OUTPUT_TIMEOUT, &timeout); + if (ret != MPP_OK) { + LOG_WARN("MPP output timeout configuration failed: {}", ret); + CleanMpp(); + return false; + } + ret = mpp_init(state_->context, MPP_CTX_ENC, coding); + if (ret != MPP_OK) { + LOG_WARN("MPP encoder initialization failed: {}", ret); + CleanMpp(); + return false; + } + ret = mpp_enc_cfg_init(&state_->config); + if (ret != MPP_OK || !state_->config) { + LOG_WARN("MPP encoder config allocation failed: {}", ret); + CleanMpp(); + return false; + } + ret = state_->api->control(state_->context, MPP_ENC_GET_CFG, state_->config); + if (ret != MPP_OK) { + LOG_WARN("MPP encoder config query failed: {}", ret); + CleanMpp(); + return false; + } + + bool config_ok = true; + const auto set_s32 = [&](const char* name, RK_S32 value) { + const auto result = mpp_enc_cfg_set_s32(state_->config, name, value); + if (result != MPP_OK) { + LOG_WARN("MPP encoder config {}={} failed: {}", name, value, result); + config_ok = false; + } + }; + set_s32("prep:width", static_cast<RK_S32>(width_)); + set_s32("prep:height", static_cast<RK_S32>(height_)); + set_s32("prep:hor_stride", static_cast<RK_S32>(state_->horizontal_stride)); + set_s32("prep:ver_stride", static_cast<RK_S32>(state_->vertical_stride)); + set_s32("prep:format", MPP_FMT_YUV420P); + set_s32("rc:mode", MPP_ENC_RC_MODE_CBR); + set_s32("rc:fps_in_flex", 0); + set_s32("rc:fps_in_num", kFrameRate); + set_s32("rc:fps_in_denom", 1); + set_s32("rc:fps_out_flex", 0); + set_s32("rc:fps_out_num", kFrameRate); + set_s32("rc:fps_out_denom", 1); + set_s32("rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED); + set_s32("rc:bps_target", kBitRate); + set_s32("rc:bps_max", kBitRate * 17 / 16); + set_s32("rc:bps_min", kBitRate * 15 / 16); + set_s32("rc:qp_init", -1); + set_s32("rc:qp_max", 51); + set_s32("rc:qp_min", 10); + set_s32("rc:qp_max_i", 51); + set_s32("rc:qp_min_i", 10); + set_s32("rc:qp_ip", 2); + set_s32("rc:gop", kGopLength); + set_s32("codec:type", coding); + if (coding == MPP_VIDEO_CodingAVC) { + set_s32("h264:profile", 100); + set_s32("h264:level", 40); + set_s32("h264:cabac_en", 1); + set_s32("h264:cabac_idc", 0); + set_s32("h264:trans8x8", 1); + } + if (!config_ok) { + CleanMpp(); + return false; + } + ret = state_->api->control(state_->context, MPP_ENC_SET_CFG, state_->config); + if (ret != MPP_OK) { + LOG_WARN("MPP encoder config commit failed: {}", ret); + CleanMpp(); + return false; + } + + MppPacket header = nullptr; + ret = mpp_packet_init_with_buffer(&header, state_->packet_buffer); + if (ret == MPP_OK && header) { + mpp_packet_set_length(header, 0); + ret = state_->api->control(state_->context, MPP_ENC_GET_HDR_SYNC, header); + if (ret == MPP_OK) { + const auto* bytes = static_cast<const uint8_t*>(mpp_packet_get_pos(header)); + const auto length = mpp_packet_get_length(header); + if (bytes && length > 0) { + state_->codec_header.assign(bytes, bytes + length); + } + } + mpp_packet_deinit(&header); + } + if (ret != MPP_OK || state_->codec_header.empty()) { + LOG_WARN("MPP encoder parameter-set query failed: {}", ret); + CleanMpp(); + return false; + } + + LOG_INFO("MPP encoder opened: codec={} size={}x{} stride={}x{} header={} bytes", + static_cast<int>(codec_type_), width_, height_, state_->horizontal_stride, + state_->vertical_stride, state_->codec_header.size()); + return true; +} + +VideoPacketPtr VideoEncoderRockchip::SendYUVFrame(void* data) { + if (fallback_) { + return fallback_->SendYUVFrame(data); + } + const auto started = std::chrono::steady_clock::now(); + const auto fail = [&]() -> VideoPacketPtr { + GetPreviewPipelineMetrics().RecordMppEncode(false, ElapsedNanoseconds(started)); + return nullptr; + }; + if (!state_ || !state_->context || !state_->api || !state_->frame_buffer || !data) { + return fail(); + } + + auto* destination = static_cast<uint8_t*>(mpp_buffer_get_ptr(state_->frame_buffer)); + if (!destination) { + return fail(); + } + const auto* source = static_cast<const uint8_t*>(data); + const size_t compact_y_size = width_ * height_; + const size_t compact_uv_size = compact_y_size / 4; + const size_t mpp_y_size = state_->horizontal_stride * state_->vertical_stride; + const size_t mpp_uv_stride = state_->horizontal_stride / 2; + const size_t mpp_uv_height = state_->vertical_stride / 2; + + mpp_buffer_sync_begin(state_->frame_buffer); + std::memset(destination, 0, mpp_y_size); + std::memset(destination + mpp_y_size, 128, state_->frame_buffer_size - mpp_y_size); + for (size_t row = 0; row < height_; ++row) { + std::memcpy(destination + row * state_->horizontal_stride, source + row * width_, width_); + } + auto* destination_u = destination + mpp_y_size; + auto* destination_v = destination_u + mpp_uv_stride * mpp_uv_height; + const auto* source_u = source + compact_y_size; + const auto* source_v = source_u + compact_uv_size; + for (size_t row = 0; row < height_ / 2; ++row) { + std::memcpy(destination_u + row * mpp_uv_stride, source_u + row * (width_ / 2), width_ / 2); + std::memcpy(destination_v + row * mpp_uv_stride, source_v + row * (width_ / 2), width_ / 2); + } + mpp_buffer_sync_end(state_->frame_buffer); + + MppFrame frame = nullptr; + auto ret = mpp_frame_init(&frame); + if (ret != MPP_OK || !frame) { + return fail(); + } + mpp_frame_set_width(frame, static_cast<RK_S32>(width_)); + mpp_frame_set_height(frame, static_cast<RK_S32>(height_)); + mpp_frame_set_hor_stride(frame, static_cast<RK_S32>(state_->horizontal_stride)); + mpp_frame_set_ver_stride(frame, static_cast<RK_S32>(state_->vertical_stride)); + mpp_frame_set_fmt(frame, MPP_FMT_YUV420P); + mpp_frame_set_pts(frame, state_->frame_pts++); + mpp_frame_set_buffer(frame, state_->frame_buffer); + + MppPacket packet = nullptr; + ret = mpp_packet_init_with_buffer(&packet, state_->packet_buffer); + if (ret != MPP_OK || !packet) { + mpp_frame_deinit(&frame); + return fail(); + } + mpp_packet_set_length(packet, 0); + auto meta = mpp_frame_get_meta(frame); + mpp_meta_set_packet(meta, KEY_OUTPUT_PACKET, packet); + + ret = state_->api->encode_put_frame(state_->context, frame); + mpp_frame_deinit(&frame); + if (ret != MPP_OK) { + LOG_WARN("MPP encode_put_frame failed: {}", ret); + mpp_packet_deinit(&packet); + return fail(); + } + ret = state_->api->encode_get_packet(state_->context, &packet); + if (ret != MPP_OK || !packet) { + LOG_WARN("MPP encode_get_packet failed: {}", ret); + if (packet) { + mpp_packet_deinit(&packet); + } + return fail(); + } + + const auto* bytes = static_cast<const uint8_t*>(mpp_packet_get_pos(packet)); + const auto length = mpp_packet_get_length(packet); + RK_S32 output_intra = 0; + const auto packet_meta = mpp_packet_has_meta(packet) ? mpp_packet_get_meta(packet) : nullptr; + if (packet_meta) { + mpp_meta_get_s32(packet_meta, KEY_OUTPUT_INTRA, &output_intra); + } + const bool is_intra = + output_intra != 0 || (codec_type_ == VideoCodecType::kH264 && ContainsH264Idr(bytes, length)); + if (!bytes || length == 0) { + mpp_packet_deinit(&packet); + return fail(); + } + + auto output = std::make_shared<VideoPacket>(); + output->is_i_frame = is_intra; + output->pts = mpp_packet_get_pts(packet); + if (is_intra && codec_type_ == VideoCodecType::kH264 && !ContainsH264ParameterSet(bytes, length)) { + output->data.reserve(state_->codec_header.size() + length); + output->data.insert(output->data.end(), state_->codec_header.begin(), state_->codec_header.end()); + } else { + output->data.reserve(length); + } + output->data.insert(output->data.end(), bytes, bytes + length); + mpp_packet_deinit(&packet); + + GetPreviewPipelineMetrics().RecordMppEncode(true, ElapsedNanoseconds(started)); + return output; +} + +void VideoEncoderRockchip::CleanMpp() { + if (!state_) { + return; + } + if (state_->context && state_->api) { + state_->api->reset(state_->context); + } + if (state_->context) { + mpp_destroy(state_->context); + state_->context = nullptr; + state_->api = nullptr; + } + if (state_->config) { + mpp_enc_cfg_deinit(state_->config); + state_->config = nullptr; + } + if (state_->frame_buffer) { + mpp_buffer_put(state_->frame_buffer); + state_->frame_buffer = nullptr; + } + if (state_->packet_buffer) { + mpp_buffer_put(state_->packet_buffer); + state_->packet_buffer = nullptr; + } + if (state_->buffer_group) { + mpp_buffer_group_put(state_->buffer_group); + state_->buffer_group = nullptr; + } + state_.reset(); +} + +void VideoEncoderRockchip::Clean() { + fallback_.reset(); + CleanMpp(); +} + +} // namespace cosmo::media diff --git a/src/media/VideoEncoderRockchip.h b/src/media/VideoEncoderRockchip.h new file mode 100644 index 000000000..0a61f7a49 --- /dev/null +++ b/src/media/VideoEncoderRockchip.h @@ -0,0 +1,36 @@ +#pragma once + +#include <memory> + +#include "media/VideoEncoder.h" + +namespace cosmo::media { + +class VideoEncoderCpu; +struct RockchipEncoderState; + +/// Rockchip MPP encoder with a bounded host-to-MPP copy boundary. +/// +/// The caller still owns compact I420 host memory. Each frame is copied into a +/// reusable, stride-aligned MPP buffer before hardware encoding. DMA-BUF +/// zero-copy ownership is intentionally outside this phase. +class VideoEncoderRockchip final : public VideoEncoder { +public: + VideoEncoderRockchip(); + ~VideoEncoderRockchip() override; + + bool Open() override; + VideoPacketPtr SendYUVFrame(void* data) override; + + static VideoEncoderCapability Probe(VideoCodecType type); + +private: + bool OpenMpp(); + void Clean(); + void CleanMpp(); + + std::unique_ptr<RockchipEncoderState> state_; + std::unique_ptr<VideoEncoderCpu> fallback_; +}; + +} // namespace cosmo::media diff --git a/src/media/VideoFrameProcFactory.h b/src/media/VideoFrameProcFactory.h index 4f65f31f2..0d47e1405 100644 --- a/src/media/VideoFrameProcFactory.h +++ b/src/media/VideoFrameProcFactory.h @@ -1,9 +1,8 @@ /// @file VideoFrameProcFactory.h /// @brief Factory function for creating the correct backend VideoFrameProc. /// -/// The concrete implementation (Sophon or CPU) is selected at CMake time — -/// only one of VideoFrameProcFactorySophon.cc or VideoFrameProcFactoryCpu.cc -/// is compiled into the binary. +/// The concrete implementation (Sophon, CPU, or Rockchip) is selected at +/// CMake time; exactly one factory implementation is compiled into the binary. #pragma once #include <memory> @@ -17,7 +16,7 @@ namespace mem { namespace media { class IOsdTextRenderer; - /// Creates the correct backend VideoFrameProc (Sophon or CPU). + /// Creates the configured backend VideoFrameProc. /// @param ctx Device context providing hardware handles /// @param osd OSD text rendering service std::unique_ptr<IVideoFrameProc> CreateVideoFrameProc(mem::IDeviceContext& ctx, IOsdTextRenderer& osd); diff --git a/src/media/VideoFrameProcFactoryRockchip.cc b/src/media/VideoFrameProcFactoryRockchip.cc new file mode 100644 index 000000000..6a13c638f --- /dev/null +++ b/src/media/VideoFrameProcFactoryRockchip.cc @@ -0,0 +1,13 @@ +#include "media/IOsdTextRenderer.h" +#include "media/VideoFrameProcFactory.h" +#include "media/VideoFrameProcRockchip.h" +#include "mem/IDeviceContext.h" + +namespace cosmo::media { + +std::unique_ptr<IVideoFrameProc> CreateVideoFrameProc(mem::IDeviceContext& ctx, IOsdTextRenderer& osd) { + static_cast<void>(ctx); + return std::make_unique<VideoFrameProcRockchip>(osd); +} + +} // namespace cosmo::media diff --git a/src/media/VideoFrameProcRockchip.cc b/src/media/VideoFrameProcRockchip.cc new file mode 100644 index 000000000..9043890ed --- /dev/null +++ b/src/media/VideoFrameProcRockchip.cc @@ -0,0 +1,172 @@ +#include "media/VideoFrameProcRockchip.h" + +#include <rga/im2d.h> + +#include <chrono> +#include <limits> + +#include "media/PreviewPipelineMetrics.h" +#include "util/Log.h" + +namespace cosmo::media { +namespace { + + class ScopedRgaHandle { + public: + ScopedRgaHandle(void* data, size_t size) { + if (data && size > 0 && size <= static_cast<size_t>(std::numeric_limits<int>::max())) { + handle_ = importbuffer_virtualaddr(data, static_cast<int>(size)); + } + } + + ~ScopedRgaHandle() { + if (handle_ != 0) { + releasebuffer_handle(handle_); + } + } + + ScopedRgaHandle(const ScopedRgaHandle&) = delete; + ScopedRgaHandle& operator=(const ScopedRgaHandle&) = delete; + + [[nodiscard]] rga_buffer_handle_t Get() const { + return handle_; + } + + private: + rga_buffer_handle_t handle_{0}; + }; + + bool RgaSucceeded(IM_STATUS status) { + return status == IM_STATUS_SUCCESS || status == IM_STATUS_NOERROR; + } + + uint64_t ElapsedNanoseconds(std::chrono::steady_clock::time_point started) { + return static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now() - started) + .count()); + } + +} // namespace + +VideoFrameProcRockchip::VideoFrameProcRockchip(IOsdTextRenderer& osd_service) + : VideoFrameProcCpu(osd_service) {} + +VideoFramePtr VideoFrameProcRockchip::BGR2I420(VideoFramePtr frame) { + auto converted = ConvertWithRga(frame, PixelFormat::PIXEL_I420, RK_FORMAT_BGR_888, RK_FORMAT_YCbCr_420_P, + IM_RGB_TO_YUV_BT601_LIMIT, "BGR2I420"); + return converted ? converted : VideoFrameProcCpu::BGR2I420(std::move(frame)); +} + +VideoFramePtr VideoFrameProcRockchip::RGB2I420(VideoFramePtr frame) { + auto converted = ConvertWithRga(frame, PixelFormat::PIXEL_I420, RK_FORMAT_RGB_888, RK_FORMAT_YCbCr_420_P, + IM_RGB_TO_YUV_BT601_LIMIT, "RGB2I420"); + return converted ? converted : VideoFrameProcCpu::RGB2I420(std::move(frame)); +} + +VideoFramePtr VideoFrameProcRockchip::I4202BGR(VideoFramePtr frame) { + auto converted = ConvertWithRga(frame, PixelFormat::PIXEL_BGR8, RK_FORMAT_YCbCr_420_P, RK_FORMAT_BGR_888, + IM_YUV_TO_RGB_BT601_LIMIT, "I4202BGR"); + return converted ? converted : VideoFrameProcCpu::I4202BGR(std::move(frame)); +} + +VideoFramePtr VideoFrameProcRockchip::I4202RGB(VideoFramePtr frame) { + auto converted = ConvertWithRga(frame, PixelFormat::PIXEL_RGB8, RK_FORMAT_YCbCr_420_P, RK_FORMAT_RGB_888, + IM_YUV_TO_RGB_BT601_LIMIT, "I4202RGB"); + return converted ? converted : VideoFrameProcCpu::I4202RGB(std::move(frame)); +} + +VideoFramePtr VideoFrameProcRockchip::Resize(VideoFramePtr frame, int dst_height, int dst_width) { + auto resized = ResizeWithRga(frame, dst_height, dst_width, "Resize"); + return resized ? resized : VideoFrameProcCpu::Resize(std::move(frame), dst_height, dst_width); +} + +VideoFramePtr VideoFrameProcRockchip::ConvertWithRga(const VideoFramePtr& frame, PixelFormat dst_format, + int src_rga_format, int dst_rga_format, int color_mode, + const char* operation) { + if (!VideoFrameValid(frame, true) || frame->GetWidth() == 0 || frame->GetHeight() == 0 || + frame->GetWidth() > static_cast<size_t>(std::numeric_limits<int>::max()) || + frame->GetHeight() > static_cast<size_t>(std::numeric_limits<int>::max())) { + return nullptr; + } + + const int width = static_cast<int>(frame->GetWidth()); + const int height = static_cast<int>(frame->GetHeight()); + auto output = std::make_shared<VideoFrame>(width, height, dst_format, frame->GetFrameIndex(), + frame->GetTimestamp()); + if (!VideoFrameValid(output, true)) { + return nullptr; + } + output->SetStreamIndex(frame->GetStreamIndex()); + + const auto started = std::chrono::steady_clock::now(); + ScopedRgaHandle src_handle(frame->GetData(), frame->GetSize()); + ScopedRgaHandle dst_handle(output->GetData(), output->GetSize()); + if (src_handle.Get() == 0 || dst_handle.Get() == 0) { + const auto elapsed = ElapsedNanoseconds(started); + GetPreviewPipelineMetrics().RecordRgaOperation(false, elapsed); + LogFallbackOnce(operation, IM_STATUS_OUT_OF_MEMORY); + return nullptr; + } + + auto src = wrapbuffer_handle_t(src_handle.Get(), width, height, width, height, src_rga_format); + auto dst = wrapbuffer_handle_t(dst_handle.Get(), width, height, width, height, dst_rga_format); + const auto status = imcvtcolor_t(src, dst, src_rga_format, dst_rga_format, color_mode, 1); + const auto elapsed = ElapsedNanoseconds(started); + GetPreviewPipelineMetrics().RecordRgaOperation(RgaSucceeded(status), elapsed); + if (!RgaSucceeded(status)) { + LogFallbackOnce(operation, status); + return nullptr; + } + return output; +} + +VideoFramePtr VideoFrameProcRockchip::ResizeWithRga(const VideoFramePtr& frame, int dst_height, int dst_width, + const char* operation) { + if (!VideoFrameValid(frame, true) || frame->GetPixelFormat() != PixelFormat::PIXEL_I420 || + dst_width <= 0 || dst_height <= 0 || + frame->GetWidth() > static_cast<size_t>(std::numeric_limits<int>::max()) || + frame->GetHeight() > static_cast<size_t>(std::numeric_limits<int>::max())) { + return nullptr; + } + + const int src_width = static_cast<int>(frame->GetWidth()); + const int src_height = static_cast<int>(frame->GetHeight()); + auto output = std::make_shared<VideoFrame>(dst_width, dst_height, PixelFormat::PIXEL_I420, + frame->GetFrameIndex(), frame->GetTimestamp()); + if (!VideoFrameValid(output, true)) { + return nullptr; + } + output->SetStreamIndex(frame->GetStreamIndex()); + + const auto started = std::chrono::steady_clock::now(); + ScopedRgaHandle src_handle(frame->GetData(), frame->GetSize()); + ScopedRgaHandle dst_handle(output->GetData(), output->GetSize()); + if (src_handle.Get() == 0 || dst_handle.Get() == 0) { + const auto elapsed = ElapsedNanoseconds(started); + GetPreviewPipelineMetrics().RecordRgaOperation(false, elapsed); + LogFallbackOnce(operation, IM_STATUS_OUT_OF_MEMORY); + return nullptr; + } + + auto src = wrapbuffer_handle_t(src_handle.Get(), src_width, src_height, src_width, src_height, + RK_FORMAT_YCbCr_420_P); + auto dst = wrapbuffer_handle_t(dst_handle.Get(), dst_width, dst_height, dst_width, dst_height, + RK_FORMAT_YCbCr_420_P); + const auto status = imresize_t(src, dst, 0.0, 0.0, INTER_LINEAR, 1); + const auto elapsed = ElapsedNanoseconds(started); + GetPreviewPipelineMetrics().RecordRgaOperation(RgaSucceeded(status), elapsed); + if (!RgaSucceeded(status)) { + LogFallbackOnce(operation, status); + return nullptr; + } + return output; +} + +void VideoFrameProcRockchip::LogFallbackOnce(const char* operation, int status) { + if (!fallback_warning_logged_.test_and_set(std::memory_order_relaxed)) { + LOG_WARN("RGA {} failed with status {} ({}); using CPU fallback", operation, status, + imStrError_t(static_cast<IM_STATUS>(status))); + } +} + +} // namespace cosmo::media diff --git a/src/media/VideoFrameProcRockchip.h b/src/media/VideoFrameProcRockchip.h new file mode 100644 index 000000000..b0b3ca46d --- /dev/null +++ b/src/media/VideoFrameProcRockchip.h @@ -0,0 +1,36 @@ +#pragma once + +#include <atomic> + +#include "media/VideoFrameProcCpu.h" + +namespace cosmo::media { + +/// Rockchip Copy-first frame processor. +/// +/// Frames remain owned by CosmoEdge's host memory pool. Each admitted RGA +/// operation imports the host buffers for the duration of one synchronous +/// operation and releases the handles before returning. This deliberately +/// does not introduce DMA-BUF ownership or zero-copy lifetime coupling. +class VideoFrameProcRockchip final : public VideoFrameProcCpu { +public: + explicit VideoFrameProcRockchip(IOsdTextRenderer& osd_service); + ~VideoFrameProcRockchip() override = default; + + VideoFramePtr BGR2I420(VideoFramePtr frame) override; + VideoFramePtr RGB2I420(VideoFramePtr frame) override; + VideoFramePtr I4202BGR(VideoFramePtr frame) override; + VideoFramePtr I4202RGB(VideoFramePtr frame) override; + VideoFramePtr Resize(VideoFramePtr src, int dst_height, int dst_width) override; + +private: + VideoFramePtr ConvertWithRga(const VideoFramePtr& frame, PixelFormat dst_format, int src_rga_format, + int dst_rga_format, int color_mode, const char* operation); + VideoFramePtr ResizeWithRga(const VideoFramePtr& frame, int dst_height, int dst_width, + const char* operation); + void LogFallbackOnce(const char* operation, int status); + + std::atomic_flag fallback_warning_logged_ = ATOMIC_FLAG_INIT; +}; + +} // namespace cosmo::media diff --git a/src/mem/CMakeLists.txt b/src/mem/CMakeLists.txt index f33ae66ff..e44fd209f 100644 --- a/src/mem/CMakeLists.txt +++ b/src/mem/CMakeLists.txt @@ -3,6 +3,7 @@ set(MEM_COMMON_SOURCES BlockFreqCalc.cc BlockFreqCalc.h FixedBlockPool.cc FixedBlockPool.h MemoryPoolMng.cc MemoryPoolMng.h + AllocatorCpu.cc AllocatorCpu.h Allocator.h Block.h IDeviceContext.h @@ -17,7 +18,6 @@ if(COSMO_NN_USE_SOPHON_BACKEND) ) else() set(MEM_BACKEND_SOURCES - AllocatorCpu.cc AllocatorCpu.h DeviceContextCpu.cc ) endif() diff --git a/src/mem/MemoryPoolMng.cc b/src/mem/MemoryPoolMng.cc index 094d77797..5948c6ff3 100644 --- a/src/mem/MemoryPoolMng.cc +++ b/src/mem/MemoryPoolMng.cc @@ -244,10 +244,10 @@ void MemoryPoolMng::Recycle(Block* block) { // Periodically print pool status, assist in diagnosing if RealFree is triggered static thread_local uint64_t recycle_counter = 0; if (0 == (++recycle_counter % 100)) { - LOG_INFO("[POOL:{}] Recycle#{} Using:{} Idle:{} Total:{} FreeThres:{} MinLimit:{}{}", - pool->BlockSize(), recycle_counter, pool->UsingCount(), pool->IdleCount(), - pool->TotalBlockCount(), pool->GetFreeThres(), pool->GetMinLimit(), - pool->IdleCount() > pool->GetFreeThres() ? " -> TriggerFree" : ""); + LOG_DEBUG("[POOL:{}] Recycle#{} Using:{} Idle:{} Total:{} FreeThres:{} MinLimit:{}{}", + pool->BlockSize(), recycle_counter, pool->UsingCount(), pool->IdleCount(), + pool->TotalBlockCount(), pool->GetFreeThres(), pool->GetMinLimit(), + pool->IdleCount() > pool->GetFreeThres() ? " -> TriggerFree" : ""); } if (pool->IdleCount() > pool->GetFreeThres()) { diff --git a/src/network/http/HttpPost.h b/src/network/http/HttpPost.h index a9a0538aa..0ef6d24c7 100644 --- a/src/network/http/HttpPost.h +++ b/src/network/http/HttpPost.h @@ -85,18 +85,18 @@ class HttpPost { } else { http_req.SetData("{}"); } - LOG_INFO("HTTP Post Url[{}], Msg:{}", GetPostUrl(type).c_str(), json_result); + LOG_DEBUG("HTTP POST request_bytes:{}", json_result.size()); http_req.SetTimeout(10); auto ret = http_req.Submit(HttpRequestMethod::kPost); // Will rename this next if (200 != ret) { - LOG_ERRO("http poster submit failed, errret[{}]", ret); + LOG_ERRO("HTTP POST failed, status:{} response_bytes:{}", ret, http_hnd.GetData().size()); return false; } - LOG_INFO("Msg:{} Get Response is:{}", GetPostUrl(type), http_hnd.GetData()); + LOG_DEBUG("HTTP POST completed, status:{} response_bytes:{}", ret, http_hnd.GetData().size()); if (!cosmo::util::DecodeJson(http_hnd.GetData(), rgt_out)) { - LOG_ERRO("cosmo::util::DecodeJson failed, [{}]", http_hnd.GetData()); + LOG_ERRO("HTTP POST response DecodeJson failed, response_bytes:{}", http_hnd.GetData().size()); return false; } return true; diff --git a/src/network/http/HttpServer.cc b/src/network/http/HttpServer.cc index bf86124e9..21b203269 100644 --- a/src/network/http/HttpServer.cc +++ b/src/network/http/HttpServer.cc @@ -382,7 +382,7 @@ void HttpServer::InsertHttpMsg(struct evhttp_request* req, InnerMsgId msg_id, DispatchJsonMsg(&response_task); return; } - LOG_INFO("Put request {} token {} to HTTP pool", static_cast<int>(msg_id), token); + LOG_DEBUG("Put request {} token {} to HTTP pool", static_cast<int>(msg_id), token); } std::unique_ptr<HttpReqTask> HttpServer::BuildHttpReqTask(struct evhttp_request* req, diff --git a/src/network/http/HttpServer.h b/src/network/http/HttpServer.h index 8f0f1fad5..afa94a94d 100644 --- a/src/network/http/HttpServer.h +++ b/src/network/http/HttpServer.h @@ -54,7 +54,8 @@ class HttpServer { if (!cosmo::util::EncodeJson(t, strJsonRes)) { // log failed } - LOG_DEBUG("{}", strJsonRes); + LOG_DEBUG("Queue HTTP response status:{} response_bytes:{}", static_cast<int>(hcode), + strJsonRes.size()); cosmo::MsgEnvelope msg(static_cast<int>(InnerMsgId::kHttpAck), std::make_unique<HttpAckTask>(static_cast<int>(hcode), request_token, std::move(strJsonRes), req_id)); diff --git a/src/network/http/HttpServerThread.cc b/src/network/http/HttpServerThread.cc index b5614f66a..e8ae358fe 100644 --- a/src/network/http/HttpServerThread.cc +++ b/src/network/http/HttpServerThread.cc @@ -75,23 +75,21 @@ void MsgHanderThread::DelTmpPath(const HttpReqTask& task) { void MsgHanderThread::ProcessHttpReqTask(HttpReqTask& task) { const auto& uri = task.interface; if (!task.x_forwarded_for.empty()) { - LOG_INFO("{} Handle {}, From:{}", Name(), uri, task.x_forwarded_for); + LOG_DEBUG("{} Handle {}, From:{}", Name(), uri, task.x_forwarded_for); } else { - LOG_INFO("{} Handle {}", Name(), uri); + LOG_DEBUG("{} Handle {}", Name(), uri); } std::string request_id; - // Truncate large bodies in logs to avoid memory/disk pressure - if (task.body.size() > 4096) { - LOG_INFO("{} Receive uri:{}, body: {:.4096} ...", Name(), uri, task.body); - } else { - LOG_INFO("{} Receive uri:{}, body: {}", Name(), uri, task.body); - } + // Request bodies can contain passwords, tokens, stream credentials, and + // model parameters. Log metadata only, at debug level, so routine polling + // cannot disclose payloads or flood production logs. + LOG_DEBUG("{} Receive uri:{} request_bytes:{}", Name(), uri, task.body.size()); RequestDispatchResponse dispatch_response; if (!handler_->SupportsRoute(uri)) { - LOG_INFO("{} Handle uri:{} BAD REQUEST", Name(), uri); + LOG_WARN("{} Handle uri:{} BAD REQUEST", Name(), uri); SendHttpAck(HttpResponseCode::kBadRequest, task.request_token, std::string("{}"), std::move(request_id)); return; @@ -109,9 +107,11 @@ void MsgHanderThread::ProcessHttpReqTask(HttpReqTask& task) { context.multipart_file_size = task.multipart_file_size; context.transport = RequestTransport::kHttp; if (!handler_->DispatchRequestResponse(context, task.body, dispatch_response)) { - LOG_INFO("{} Handle uri:{} With {} Ms Rsp: MV_HTTP_NEED_AUTHENTICATE", Name(), uri, - chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - task.request_time) - .count()); + LOG_DEBUG("{} Handle uri:{} status:{} elapsed_ms:{} response_bytes:{}", Name(), uri, + static_cast<int>(HttpResponseCode::kNeedAuthenticate), + chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - task.request_time) + .count(), + dispatch_response.body.size()); SendHttpAck(HttpResponseCode::kNeedAuthenticate, task.request_token, std::move(dispatch_response.body), std::move(request_id)); return; @@ -125,16 +125,17 @@ void MsgHanderThread::ProcessHttpReqTask(HttpReqTask& task) { ack_task->file_name = std::move(dispatch_response.file_name); ack_task->range_request = task.range_request; ack_task->delete_file_after_send = dispatch_response.delete_file_after_send; - LOG_INFO("{} Handle {} file:{}", Name(), uri, ack_task->file_name); + LOG_DEBUG("{} Handle {} file:{}", Name(), uri, ack_task->file_name); cosmo::MsgEnvelope msg(static_cast<int>(InnerMsgId::kHttpOctetAck), std::move(ack_task)); server_->Put(std::move(msg)); return; } - LOG_INFO( - "{} Handle uri:{} With {} Ms Rsp: {:.4096}{}", Name(), uri, + LOG_DEBUG( + "{} Handle uri:{} status:{} elapsed_ms:{} response_bytes:{}", Name(), uri, + static_cast<int>(HttpResponseCode::kOk), chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - task.request_time).count(), - dispatch_response.body, dispatch_response.body.size() > 4096 ? " ..." : ""); + dispatch_response.body.size()); SendHttpAck(HttpResponseCode::kOk, task.request_token, std::move(dispatch_response.body), std::move(request_id)); } @@ -194,7 +195,7 @@ void MsgHanderThread::ProcessHttpOctetReqTask(HttpReqTask& task) { ackTask->file_name = file_name; ackTask->file_path = std::move(resolved_path); ackTask->range_request = task.range_request; - LOG_INFO("{} Handle {} interface:{}", Name(), uri, ackTask->file_name); + LOG_DEBUG("{} Handle {} interface:{}", Name(), uri, ackTask->file_name); cosmo::MsgEnvelope msg(static_cast<int>(InnerMsgId::kHttpOctetAck), std::move(ackTask)); server_->Put(std::move(msg)); } diff --git a/src/nn/CMakeLists.txt b/src/nn/CMakeLists.txt index 087202c7d..5b55e9142 100644 --- a/src/nn/CMakeLists.txt +++ b/src/nn/CMakeLists.txt @@ -5,12 +5,13 @@ set(NN_DIR ${CMAKE_CURRENT_SOURCE_DIR}) # ── Sophon SDK path (used only for Sophon backend) ── if(COSMO_NN_USE_SOPHON_BACKEND) - set(SOPHON_ROOT_DIR ${CMAKE_SOURCE_DIR}/3rd/libsophon-0.4.11) + set(SOPHON_ROOT_DIR ${DEVICE_ROOT_DIR}) endif() # ── Collect NN source files ── file(GLOB_RECURSE NN_ALL_SRC "${NN_DIR}/core/*.h" "${NN_DIR}/core/*.cc" + "${NN_DIR}/guard/*.h" "${NN_DIR}/guard/*.cc" "${NN_DIR}/node/*.h" "${NN_DIR}/node/*.cc" "${NN_DIR}/pipeline/*.h" "${NN_DIR}/pipeline/*.cc" "${NN_DIR}/utils/*.h" "${NN_DIR}/utils/*.cc" @@ -30,7 +31,7 @@ if(COSMO_NN_USE_SOPHON_BACKEND) list(APPEND NN_ALL_SRC ${NN_SOPHON_SRC}) endif() -if(COSMO_NN_USE_CPU_BACKEND) +if(COSMO_NN_USE_CPU_BACKEND OR COSMO_NN_USE_RKNN_BACKEND) file(GLOB_RECURSE NN_CPU_SRC "${NN_DIR}/device/cpu/*.h" "${NN_DIR}/device/cpu/*.cc" ) @@ -40,6 +41,13 @@ if(COSMO_NN_USE_CPU_BACKEND) list(APPEND NN_ALL_SRC ${NN_CPU_SRC} ${NN_HOST_SRC}) endif() +if(COSMO_NN_USE_RKNN_BACKEND) + file(GLOB_RECURSE NN_RKNN_SRC + "${NN_DIR}/device/rknn/*.h" "${NN_DIR}/device/rknn/*.cc" + ) + list(APPEND NN_ALL_SRC ${NN_RKNN_SRC}) +endif() + # ── Build cosmo_nn OBJECT library ── add_library(cosmo_nn OBJECT ${NN_ALL_SRC}) @@ -57,6 +65,7 @@ endif() if(COSMO_MODEL_GUARD) target_compile_definitions(cosmo_nn PRIVATE COSMO_HAS_MODEL_GUARD=1) + target_link_libraries(cosmo_nn PRIVATE cosmo_model_guard_v2) endif() if(COSMO_NN_USE_CPU_BACKEND) @@ -67,6 +76,13 @@ if(COSMO_NN_USE_CPU_BACKEND) # ORT headers provided by onnxruntime IMPORTED target endif() +if(COSMO_NN_USE_RKNN_BACKEND) + target_compile_definitions(cosmo_nn PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) +endif() + # Symbol hiding + suppress C++11-era warnings target_compile_options(cosmo_nn PRIVATE -fvisibility=hidden @@ -83,6 +99,12 @@ endif() if(COSMO_NN_USE_CPU_BACKEND) target_link_libraries(cosmo_nn PRIVATE onnxruntime) endif() +if(COSMO_NN_USE_RKNN_BACKEND) + target_link_libraries(cosmo_nn PRIVATE rknnrt) + if(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + target_link_libraries(cosmo_nn PRIVATE rockchip_rga) + endif() +endif() # Ensure all ExternalProject third-party targets are built before compiling NN add_dependencies(cosmo_nn third_build) diff --git a/src/nn/core/blob.h b/src/nn/core/blob.h index 48d71a49c..eb210d107 100644 --- a/src/nn/core/blob.h +++ b/src/nn/core/blob.h @@ -1,5 +1,6 @@ #pragma once +#include <cstddef> #include <map> #include <memory> #include <string> @@ -28,6 +29,23 @@ struct PUBLIC BlobDesc { struct PUBLIC BlobHandle { void* base = nullptr; unsigned long phy = 0; + + // Optional borrowed DMA-BUF image. The object supplying base owns the + // descriptor lifetime; Blob does not close fd or alter that ownership. + struct NativeImage { + int fd{-1}; + size_t bytes{0}; + int width{0}; + int height{0}; + int width_stride{0}; + int height_stride{0}; + ImageFormat format{IMAGE_UNKNOWN}; + + [[nodiscard]] bool Valid() const { + return fd >= 0 && bytes > 0 && width > 0 && height > 0 && width_stride >= width && + height_stride >= height && format != IMAGE_UNKNOWN; + } + } native_image; }; class BlobImpl; diff --git a/src/nn/core/common.h b/src/nn/core/common.h index 8da8e47ac..25b6c6205 100644 --- a/src/nn/core/common.h +++ b/src/nn/core/common.h @@ -27,13 +27,14 @@ typedef enum { DEVICE_NAIVE = 0x0000, DEVICE_SOPHON_TPU = 0x0007, DEVICE_CPU = 0x0010, + DEVICE_RKNN = 0x0011, } DeviceType; // Centralizes the graph's memory-boundary decision. New backends that consume // and produce host buffers extend this capability without duplicating CPU // checks throughout graph wiring and inference adapters. inline bool UsesHostMemory(DeviceType device_type) { - return device_type == DEVICE_NAIVE || device_type == DEVICE_CPU; + return device_type == DEVICE_NAIVE || device_type == DEVICE_CPU || device_type == DEVICE_RKNN; } struct PUBLIC BackendConfig { diff --git a/src/nn/core/graph.cc b/src/nn/core/graph.cc index 077bc1b78..bb9815253 100644 --- a/src/nn/core/graph.cc +++ b/src/nn/core/graph.cc @@ -27,9 +27,10 @@ #include "nn/utils/string_format.h" #include "util/DurationLogger.h" -#if defined(COSMO_NN_USE_SOPHON_BACKEND) && defined(COSMO_HAS_MODEL_GUARD) +#ifdef COSMO_NN_USE_SOPHON_BACKEND #include "nn/device/sophon/sophon_net_node.h" -#include "nn/guard/cosmo_model_guard.h" +#include "nn/guard/CemV2SophonLoader.h" +#include "nn/guard/ModelLoadPolicy.h" #endif namespace cosmo::nn { @@ -410,6 +411,7 @@ Status Graph::WireNetNode(const ModelInfo& model, const std::vector<std::string> } net_ptr->SetNetworkInputNames(actual_input_names); net_ptr->SetNetworkOutputNames(actual_output_names); + net_ptr->SetInputContract(model.input_contract); // Insert copy nodes right before net_node (after all preprocess nodes) for (auto& copy_node : new_copy_nodes) { @@ -622,79 +624,101 @@ Status Graph::LoadWeight(const std::string& model_path) { int net_node_num = NodeTypeUtils::TypedNodeCount(nodes, NODE_NET); - std::ifstream stream(model_path, std::ios::in | std::ios::binary); -#ifdef COSMO_NN_USE_ONNX_BACKEND - if (stream.fail() && !std::filesystem::is_directory(model_path)) - return Status(COSMO_NN_ERR_LOAD_MODEL, "open model file failed"); -#else - if (stream.fail()) - return Status(COSMO_NN_ERR_LOAD_MODEL, "open model file failed"); -#endif + std::string authorized_model_path; + +#ifdef COSMO_NN_USE_SOPHON_BACKEND + // CEMC authorization belongs exclusively to Guard. Edge only routes by + // file format and does not derive a second model identity. + const ModelLoadDecision load_decision = + ModelLoadPolicy::Production().Evaluate(model_path, ModelLoadIntent::kCosmoNn); + if (!load_decision.IsAllowed()) { + return Status(COSMO_NN_ERR_LOAD_MODEL, "model format is not supported"); + } + authorized_model_path = load_decision.model_path; + + if (load_decision.action == ModelLoadAction::kGuardV2) { + if (net_node_num <= 0 || shared_resource == nullptr || shared_resource->m_handle == nullptr) { + return Status(COSMO_NN_ERR_LOAD_MODEL, "protected model graph shape is invalid"); + } -#if defined(COSMO_NN_USE_SOPHON_BACKEND) && defined(COSMO_HAS_MODEL_GUARD) - // Peek first 4 bytes to detect encrypted model. - uint32_t magic = 0; - stream.read(reinterpret_cast<char*>(&magic), sizeof(magic)); - stream.seekg(0); - - if (cosmo::guard::IsEncryptedModel(magic)) { - // File-based guard API: the .so reads segments on demand from disk. - // No need to load the entire encrypted file into memory. - stream.close(); - - // Validate segment count matches graph structure. - int seg_count = cosmo::guard::GetEncryptedSegmentCountFromFile(model_path.c_str()); - if (seg_count < 0) - return Status(COSMO_NN_ERR_LOAD_MODEL, "Failed to read encrypted segment count (error: " + - std::to_string(seg_count) + ")"); - if (seg_count != net_node_num) - return Status(COSMO_NN_ERR_LOAD_MODEL, "Encrypted segment count (" + std::to_string(seg_count) + - ") does not match graph net nodes (" + - std::to_string(net_node_num) + ")"); - - // Decrypt and load each segment into its own independent bmrt, - // mirroring the plaintext path where each NetNode has its own bmrt. - for (int i = 0; i < net_node_num; i++) { - auto net_node = GetNodeByName("net_" + std::to_string(i)); - if (!net_node) - return Status(COSMO_NN_ERR_LOAD_MODEL, "Can not find net node"); - - // The .so handles everything internally per segment: - // open file → seek to segment → read ciphertext - // → SN validation → key derivation → decrypt → bmrt_create → bmrt_load → wipe - void* bmrt = nullptr; - int ret = 0; - { - cosmo::util::DurationLogger logger("DecryptAndLoadSegmentFromFile net_" + std::to_string(i)); - ret = cosmo::guard::DecryptAndLoadSegmentFromFile( - model_path.c_str(), shared_resource->m_handle, static_cast<uint32_t>(i), &bmrt); + // Validate every ownership destination before opening the artifact. The + // guard then authenticates once and loads every segment through the + // same immutable artifact handle. + std::vector<SophonNetNode*> target_nodes; + try { + target_nodes.reserve(static_cast<size_t>(net_node_num)); + } catch (const std::bad_alloc&) { + return Status(COSMO_NN_ERR_OUT_OF_MEMORY, "protected model graph allocation failed"); + } + for (int index = 0; index < net_node_num; ++index) { + Node* node = GetNodeByName("net_" + std::to_string(index)); + auto* sophon_node = dynamic_cast<SophonNetNode*>(node); + if (sophon_node == nullptr) { + return Status(COSMO_NN_ERR_LOAD_MODEL, "protected model requires Sophon network nodes"); } - if (ret != 0 || !bmrt) - return Status(COSMO_NN_ERR_LOAD_MODEL, - "Encrypted segment " + std::to_string(i) + - " load failed (guard error: " + std::to_string(ret) + ")"); - - // AttachBmrt is on SophonNetNode only (ISP: not on NetNode base class). - // Within this #ifdef block, the node is guaranteed to be SophonNetNode. - auto* sophon_node = dynamic_cast<SophonNetNode*>(net_node); - if (!sophon_node) { - bmrt_destroy(bmrt); - return Status(COSMO_NN_ERR_LOAD_MODEL, "Expected SophonNetNode for encrypted model"); + target_nodes.push_back(sophon_node); + } + + SophonModelLoadResult loaded; + { + cosmo::util::DurationLogger logger("Load protected CEM v2 artifact"); + loaded = + LoadCemV2SophonArtifact(FrozenCemV2Api(), NativeSophonRuntimeApi(), authorized_model_path, + CMG_V2_SOURCE_COSMO_NN_V1, shared_resource->m_handle, 0); + } + if (!loaded.IsSuccess() || loaded.runtimes.size() != target_nodes.size()) { + if (loaded.IsOutOfMemory()) { + return Status(COSMO_NN_ERR_OUT_OF_MEMORY, "protected model load ran out of memory"); + } + return Status(COSMO_NN_ERR_LOAD_MODEL, "protected model load failed"); + } + + for (size_t index = 0; index < target_nodes.size(); ++index) { + OwnedBmrt runtime(loaded.runtimes[index].release()); + Status attach_status = target_nodes[index]->AttachOwnedBmrt(std::move(runtime)); + if (!bool(attach_status)) { + // Some earlier runtimes may already have transferred to their + // nodes. Destroy the whole failed graph immediately so later + // segments and attached runtimes cannot survive partial init. + nodes.clear(); + return attach_status; } - RETURN_ON_FAIL(sophon_node->AttachBmrt(bmrt)); } return COSMO_NN_OK; } + + // A protected CEMC decision is handled above and every failure returns. + if (load_decision.action != ModelLoadAction::kNativeCenn) { + return Status(COSMO_NN_ERR_LOAD_MODEL, "model loader action is not available"); + } +#else + authorized_model_path = model_path; +#endif + + std::ifstream stream(authorized_model_path, std::ios::in | std::ios::binary); +#if defined(COSMO_NN_USE_ONNX_BACKEND) || defined(COSMO_NN_USE_RKNN_BACKEND) + if (stream.fail() && !std::filesystem::is_directory(authorized_model_path)) + return Status(COSMO_NN_ERR_LOAD_MODEL, "open model file failed"); +#else + if (stream.fail()) + return Status(COSMO_NN_ERR_LOAD_MODEL, "open model file failed"); #endif -#ifdef COSMO_NN_USE_ONNX_BACKEND +#if defined(COSMO_NN_USE_ONNX_BACKEND) || defined(COSMO_NN_USE_RKNN_BACKEND) stream.close(); namespace fs = std::filesystem; - fs::path base_path(model_path); + fs::path base_path(authorized_model_path); +#ifdef COSMO_NN_USE_RKNN_BACKEND + constexpr const char* model_extension = ".rknn"; + constexpr const char* backend_name = "RKNN"; +#else + constexpr const char* model_extension = ".onnx"; + constexpr const char* backend_name = "ONNX"; +#endif if (net_node_num == 1 && fs::is_regular_file(base_path)) { - std::ifstream model_stream(model_path, std::ios::in | std::ios::binary); + std::ifstream model_stream(authorized_model_path, std::ios::in | std::ios::binary); if (model_stream.fail()) return Status(COSMO_NN_ERR_LOAD_MODEL, "open model file failed"); @@ -726,51 +750,55 @@ Status Graph::LoadWeight(const std::string& model_path) { if (!fs::is_directory(base_path)) { return Status(COSMO_NN_ERR_LOAD_MODEL, - "ONNX backend expects a model directory with per-net ONNX files"); + std::string(backend_name) + " backend expects a model directory with per-net files"); } if (net_node_num != static_cast<int>(model_infos_.size())) { - return Status(COSMO_NN_ERR_LOAD_MODEL, "ONNX graph net nodes (" + std::to_string(net_node_num) + - ") do not match config models (" + - std::to_string(model_infos_.size()) + ")"); + return Status(COSMO_NN_ERR_LOAD_MODEL, + std::string(backend_name) + " graph net nodes (" + std::to_string(net_node_num) + + ") do not match config models (" + std::to_string(model_infos_.size()) + ")"); } - std::vector<fs::path> onnx_files; + std::vector<fs::path> model_files; for (const auto& entry : fs::directory_iterator(base_path)) { - if (entry.is_regular_file() && entry.path().extension() == ".onnx") - onnx_files.push_back(entry.path()); + if (entry.is_regular_file() && entry.path().extension() == model_extension) + model_files.push_back(entry.path()); } - std::sort(onnx_files.begin(), onnx_files.end()); + std::sort(model_files.begin(), model_files.end()); for (int i = 0; i < net_node_num; i++) { fs::path part_path; if (!model_infos_.at(i).filename.empty()) { part_path = base_path / model_infos_.at(i).filename; - } else if (static_cast<size_t>(i) < onnx_files.size()) { - part_path = onnx_files.at(i); + } else if (static_cast<size_t>(i) < model_files.size()) { + part_path = model_files.at(i); } else { - return Status(COSMO_NN_ERR_LOAD_MODEL, - "Multi-net ONNX model missing file_name for net_" + std::to_string(i)); + return Status(COSMO_NN_ERR_LOAD_MODEL, "Multi-net " + std::string(backend_name) + + " model missing file_name for net_" + + std::to_string(i)); } std::ifstream model_stream(part_path, std::ios::in | std::ios::binary); if (model_stream.fail()) { - return Status(COSMO_NN_ERR_LOAD_MODEL, "open ONNX model file failed: " + part_path.string()); + return Status(COSMO_NN_ERR_LOAD_MODEL, + "open " + std::string(backend_name) + " model file failed: " + part_path.string()); } model_stream.seekg(0, std::ios::end); long int model_size = static_cast<long int>(model_stream.tellg()); model_stream.seekg(0, std::ios::beg); if (model_size <= 0) { - return Status(COSMO_NN_ERR_LOAD_MODEL, - "ONNX model file is empty or unreadable: " + part_path.string()); + return Status( + COSMO_NN_ERR_LOAD_MODEL, + std::string(backend_name) + " model file is empty or unreadable: " + part_path.string()); } std::unique_ptr<char[]> model_data; try { model_data.reset(new char[static_cast<size_t>(model_size)]); } catch (const std::bad_alloc&) { - return Status(COSMO_NN_ERR_OUT_OF_MEMORY, "not enough memory to load ONNX model"); + return Status(COSMO_NN_ERR_OUT_OF_MEMORY, + "not enough memory to load " + std::string(backend_name) + " model"); } model_stream.read(model_data.get(), model_size); diff --git a/src/nn/core/inference_pipeline_metrics.cc b/src/nn/core/inference_pipeline_metrics.cc new file mode 100644 index 000000000..38a840dc4 --- /dev/null +++ b/src/nn/core/inference_pipeline_metrics.cc @@ -0,0 +1,354 @@ +#include "nn/core/inference_pipeline_metrics.h" + +namespace cosmo::nn { + +void InferencePipelineMetrics::RecordStage(std::atomic<uint64_t>& count, std::atomic<uint64_t>& duration, + uint64_t samples, uint64_t nanoseconds) { + count.fetch_add(samples, std::memory_order_relaxed); + duration.fetch_add(nanoseconds, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordColorConvert(uint64_t nanoseconds, uint64_t frames) { + RecordStage(color_convert_frames_, color_convert_nanoseconds_, frames, nanoseconds); +} + +void InferencePipelineMetrics::RecordBlobConvert(uint64_t nanoseconds, uint64_t frames) { + RecordStage(blob_convert_frames_, blob_convert_nanoseconds_, frames, nanoseconds); +} + +void InferencePipelineMetrics::RecordGraphForward(uint64_t nanoseconds, uint64_t frames, bool success) { + RecordStage(graph_forward_frames_, graph_forward_nanoseconds_, frames, nanoseconds); + if (!success) + graph_forward_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordResultParse(uint64_t nanoseconds, uint64_t frames, bool success) { + RecordStage(result_parse_frames_, result_parse_nanoseconds_, frames, nanoseconds); + if (!success) + result_parse_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnForward(uint64_t nanoseconds, bool success, RknnModelScope scope) { + RecordStage(rknn_forwards_, rknn_forward_nanoseconds_, 1, nanoseconds); + if (!success) + rknn_forward_failures_.fetch_add(1, std::memory_order_relaxed); + if (scope == RknnModelScope::Detector) { + RecordStage(rknn_detector_forwards_, rknn_detector_forward_nanoseconds_, 1, nanoseconds); + if (!success) + rknn_detector_forward_failures_.fetch_add(1, std::memory_order_relaxed); + } +} + +void InferencePipelineMetrics::RecordRknnPrepare(uint64_t nanoseconds, RknnModelScope scope) { + RecordStage(rknn_prepare_calls_, rknn_prepare_nanoseconds_, 1, nanoseconds); + if (scope == RknnModelScope::Detector) + RecordStage(rknn_detector_prepare_calls_, rknn_detector_prepare_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnInputsSet(uint64_t nanoseconds, RknnModelScope scope) { + RecordStage(rknn_inputs_set_calls_, rknn_inputs_set_nanoseconds_, 1, nanoseconds); + if (scope == RknnModelScope::Detector) + RecordStage(rknn_detector_inputs_set_calls_, rknn_detector_inputs_set_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnRun(uint64_t nanoseconds, RknnModelScope scope) { + RecordStage(rknn_run_calls_, rknn_run_nanoseconds_, 1, nanoseconds); + if (scope == RknnModelScope::Detector) + RecordStage(rknn_detector_run_calls_, rknn_detector_run_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnOutputsGet(uint64_t nanoseconds, RknnModelScope scope) { + RecordStage(rknn_outputs_get_calls_, rknn_outputs_get_nanoseconds_, 1, nanoseconds); + if (scope == RknnModelScope::Detector) + RecordStage(rknn_detector_outputs_get_calls_, rknn_detector_outputs_get_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnOutputsRelease(uint64_t nanoseconds, RknnModelScope scope) { + RecordStage(rknn_outputs_release_calls_, rknn_outputs_release_nanoseconds_, 1, nanoseconds); + if (scope == RknnModelScope::Detector) { + RecordStage(rknn_detector_outputs_release_calls_, rknn_detector_outputs_release_nanoseconds_, 1, + nanoseconds); + } +} + +void InferencePipelineMetrics::RecordRknnOutputTransform(uint64_t nanoseconds, RknnModelScope scope) { + RecordStage(rknn_output_transform_calls_, rknn_output_transform_nanoseconds_, 1, nanoseconds); + if (scope == RknnModelScope::Detector) + RecordStage(rknn_detector_output_transform_calls_, rknn_detector_output_transform_nanoseconds_, 1, + nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnMutexWait(uint64_t nanoseconds, RknnModelScope scope) { + RecordStage(rknn_mutex_wait_calls_, rknn_mutex_wait_nanoseconds_, 1, nanoseconds); + if (scope == RknnModelScope::Detector) + RecordStage(rknn_detector_mutex_wait_calls_, rknn_detector_mutex_wait_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnPreprocessFastHit() { + rknn_preprocess_fast_hits_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnRgaFill(uint64_t nanoseconds) { + RecordStage(rknn_rga_fill_calls_, rknn_rga_fill_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnRgaResizeColor(uint64_t nanoseconds) { + RecordStage(rknn_rga_resize_color_calls_, rknn_rga_resize_color_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnRgaFailure() { + rknn_rga_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnCpuResizeFallback(uint64_t nanoseconds) { + RecordStage(rknn_cpu_resize_fallback_calls_, rknn_cpu_resize_fallback_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnCpuNormalizeFallback(uint64_t nanoseconds) { + RecordStage(rknn_cpu_normalize_fallback_calls_, rknn_cpu_normalize_fallback_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnNativeInputMap(uint64_t nanoseconds) { + RecordStage(rknn_native_input_map_calls_, rknn_native_input_map_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnInputFormat(bool native_int8, bool compatibility_fallback, + bool uint8_contract) { + if (uint8_contract) + rknn_uint8_contract_inputs_.fetch_add(1, std::memory_order_relaxed); + else + (native_int8 ? rknn_native_int8_inputs_ : rknn_float_inputs_).fetch_add(1, std::memory_order_relaxed); + if (compatibility_fallback) + rknn_input_compatibility_fallbacks_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnBoundInputBind(bool success) { + rknn_bound_input_bind_attempts_.fetch_add(1, std::memory_order_relaxed); + if (!success) + rknn_bound_input_bind_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnBoundInputCopy(uint64_t nanoseconds, uint64_t bytes, bool success) { + RecordStage(rknn_bound_input_copy_calls_, rknn_bound_input_copy_nanoseconds_, 1, nanoseconds); + if (success) + rknn_bound_input_copy_bytes_.fetch_add(bytes, std::memory_order_relaxed); + else + rknn_bound_input_copy_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnBoundInputSync(uint64_t nanoseconds, bool success) { + RecordStage(rknn_bound_input_sync_calls_, rknn_bound_input_sync_nanoseconds_, 1, nanoseconds); + if (!success) + rknn_bound_input_sync_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnBoundInputFrame() { + rknn_bound_input_frames_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnRgaBoundInputBind(bool success) { + RecordRknnBoundInputBind(success); + rknn_rga_bound_input_bind_attempts_.fetch_add(1, std::memory_order_relaxed); + if (!success) + rknn_rga_bound_input_bind_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnRgaBoundInputImport(uint64_t nanoseconds, bool success) { + RecordStage(rknn_rga_bound_input_import_calls_, rknn_rga_bound_input_import_nanoseconds_, 1, nanoseconds); + if (!success) + rknn_rga_bound_input_import_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnRgaBoundInputRequantize(uint64_t nanoseconds, bool success) { + RecordStage(rknn_rga_bound_requantize_calls_, rknn_rga_bound_requantize_nanoseconds_, 1, nanoseconds); + if (!success) + rknn_rga_bound_requantize_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnRgaBoundInputFrame(bool fused_uint8) { + rknn_rga_bound_input_frames_.fetch_add(1, std::memory_order_relaxed); + if (fused_uint8) + rknn_rga_bound_uint8_frames_.fetch_add(1, std::memory_order_relaxed); + else + rknn_rga_bound_native_int8_frames_.fetch_add(1, std::memory_order_relaxed); + RecordRknnBoundInputFrame(); +} + +void InferencePipelineMetrics::RecordRknnRgaBoundInputNormalizeBypass() { + rknn_rga_bound_input_normalize_bypasses_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnMppDmaBufImport(uint64_t nanoseconds, bool success) { + RecordStage(rknn_mpp_dmabuf_import_calls_, rknn_mpp_dmabuf_import_nanoseconds_, 1, nanoseconds); + if (!success) + rknn_mpp_dmabuf_import_failures_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnMppDmaBufFrame(uint64_t source_bytes) { + rknn_mpp_dmabuf_frames_.fetch_add(1, std::memory_order_relaxed); + rknn_mpp_dmabuf_source_bytes_.fetch_add(source_bytes, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnMppDmaBufFallback() { + rknn_mpp_dmabuf_fallbacks_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnOutputFormat(bool native_int8, uint64_t bytes, + bool compatibility_fallback) { + (native_int8 ? rknn_native_int8_outputs_ : rknn_float_outputs_).fetch_add(1, std::memory_order_relaxed); + (native_int8 ? rknn_native_output_bytes_ : rknn_float_output_bytes_) + .fetch_add(bytes, std::memory_order_relaxed); + if (compatibility_fallback) + rknn_output_compatibility_fallbacks_.fetch_add(1, std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordRknnYolov8Transform(uint64_t dfl_nanoseconds, + uint64_t class_nanoseconds) { + RecordStage(rknn_yolov8_dfl_calls_, rknn_yolov8_dfl_nanoseconds_, 1, dfl_nanoseconds); + RecordStage(rknn_yolov8_class_calls_, rknn_yolov8_class_nanoseconds_, 1, class_nanoseconds); +} + +void InferencePipelineMetrics::RecordRknnYolov8DirectCandidates(bool success, uint64_t points_scanned, + uint64_t points_decoded, + uint64_t logical_float_bytes_avoided, + uint64_t score_sum_points_rejected) { + rknn_yolov8_direct_candidate_calls_.fetch_add(1, std::memory_order_relaxed); + if (!success) { + rknn_yolov8_direct_candidate_failures_.fetch_add(1, std::memory_order_relaxed); + return; + } + rknn_yolov8_direct_points_scanned_.fetch_add(points_scanned, std::memory_order_relaxed); + rknn_yolov8_direct_points_decoded_.fetch_add(points_decoded, std::memory_order_relaxed); + rknn_yolov8_score_sum_points_rejected_.fetch_add(score_sum_points_rejected, std::memory_order_relaxed); + rknn_yolov8_logical_float_bytes_avoided_.fetch_add(logical_float_bytes_avoided, + std::memory_order_relaxed); +} + +void InferencePipelineMetrics::RecordYolov8Postprocess(uint64_t nanoseconds) { + RecordStage(yolov8_postprocess_calls_, yolov8_postprocess_nanoseconds_, 1, nanoseconds); +} + +void InferencePipelineMetrics::RecordYolov8Nms(uint64_t nanoseconds) { + RecordStage(yolov8_nms_calls_, yolov8_nms_nanoseconds_, 1, nanoseconds); +} + +InferencePipelineMetricsSnapshot InferencePipelineMetrics::Snapshot() const { + InferencePipelineMetricsSnapshot snapshot; +#define SNAPSHOT_FIELD(field) snapshot.field = field##_.load(std::memory_order_relaxed) + SNAPSHOT_FIELD(color_convert_frames); + SNAPSHOT_FIELD(color_convert_nanoseconds); + SNAPSHOT_FIELD(blob_convert_frames); + SNAPSHOT_FIELD(blob_convert_nanoseconds); + SNAPSHOT_FIELD(graph_forward_frames); + SNAPSHOT_FIELD(graph_forward_nanoseconds); + SNAPSHOT_FIELD(graph_forward_failures); + SNAPSHOT_FIELD(result_parse_frames); + SNAPSHOT_FIELD(result_parse_nanoseconds); + SNAPSHOT_FIELD(result_parse_failures); + SNAPSHOT_FIELD(rknn_forwards); + SNAPSHOT_FIELD(rknn_forward_nanoseconds); + SNAPSHOT_FIELD(rknn_forward_failures); + SNAPSHOT_FIELD(rknn_prepare_calls); + SNAPSHOT_FIELD(rknn_prepare_nanoseconds); + SNAPSHOT_FIELD(rknn_inputs_set_calls); + SNAPSHOT_FIELD(rknn_inputs_set_nanoseconds); + SNAPSHOT_FIELD(rknn_run_calls); + SNAPSHOT_FIELD(rknn_run_nanoseconds); + SNAPSHOT_FIELD(rknn_outputs_get_calls); + SNAPSHOT_FIELD(rknn_outputs_get_nanoseconds); + SNAPSHOT_FIELD(rknn_outputs_release_calls); + SNAPSHOT_FIELD(rknn_outputs_release_nanoseconds); + SNAPSHOT_FIELD(rknn_output_transform_calls); + SNAPSHOT_FIELD(rknn_output_transform_nanoseconds); + SNAPSHOT_FIELD(rknn_mutex_wait_calls); + SNAPSHOT_FIELD(rknn_mutex_wait_nanoseconds); + SNAPSHOT_FIELD(rknn_detector_forwards); + SNAPSHOT_FIELD(rknn_detector_forward_nanoseconds); + SNAPSHOT_FIELD(rknn_detector_forward_failures); + SNAPSHOT_FIELD(rknn_detector_prepare_calls); + SNAPSHOT_FIELD(rknn_detector_prepare_nanoseconds); + SNAPSHOT_FIELD(rknn_detector_inputs_set_calls); + SNAPSHOT_FIELD(rknn_detector_inputs_set_nanoseconds); + SNAPSHOT_FIELD(rknn_detector_run_calls); + SNAPSHOT_FIELD(rknn_detector_run_nanoseconds); + SNAPSHOT_FIELD(rknn_detector_outputs_get_calls); + SNAPSHOT_FIELD(rknn_detector_outputs_get_nanoseconds); + SNAPSHOT_FIELD(rknn_detector_outputs_release_calls); + SNAPSHOT_FIELD(rknn_detector_outputs_release_nanoseconds); + SNAPSHOT_FIELD(rknn_detector_output_transform_calls); + SNAPSHOT_FIELD(rknn_detector_output_transform_nanoseconds); + SNAPSHOT_FIELD(rknn_detector_mutex_wait_calls); + SNAPSHOT_FIELD(rknn_detector_mutex_wait_nanoseconds); + SNAPSHOT_FIELD(rknn_preprocess_fast_hits); + SNAPSHOT_FIELD(rknn_rga_fill_calls); + SNAPSHOT_FIELD(rknn_rga_fill_nanoseconds); + SNAPSHOT_FIELD(rknn_rga_resize_color_calls); + SNAPSHOT_FIELD(rknn_rga_resize_color_nanoseconds); + SNAPSHOT_FIELD(rknn_rga_failures); + SNAPSHOT_FIELD(rknn_cpu_resize_fallback_calls); + SNAPSHOT_FIELD(rknn_cpu_resize_fallback_nanoseconds); + SNAPSHOT_FIELD(rknn_cpu_normalize_fallback_calls); + SNAPSHOT_FIELD(rknn_cpu_normalize_fallback_nanoseconds); + SNAPSHOT_FIELD(rknn_native_input_map_calls); + SNAPSHOT_FIELD(rknn_native_input_map_nanoseconds); + SNAPSHOT_FIELD(rknn_native_int8_inputs); + SNAPSHOT_FIELD(rknn_float_inputs); + SNAPSHOT_FIELD(rknn_uint8_contract_inputs); + SNAPSHOT_FIELD(rknn_input_compatibility_fallbacks); + SNAPSHOT_FIELD(rknn_bound_input_bind_attempts); + SNAPSHOT_FIELD(rknn_bound_input_bind_failures); + SNAPSHOT_FIELD(rknn_bound_input_copy_calls); + SNAPSHOT_FIELD(rknn_bound_input_copy_nanoseconds); + SNAPSHOT_FIELD(rknn_bound_input_copy_bytes); + SNAPSHOT_FIELD(rknn_bound_input_copy_failures); + SNAPSHOT_FIELD(rknn_bound_input_sync_calls); + SNAPSHOT_FIELD(rknn_bound_input_sync_nanoseconds); + SNAPSHOT_FIELD(rknn_bound_input_sync_failures); + SNAPSHOT_FIELD(rknn_bound_input_frames); + SNAPSHOT_FIELD(rknn_rga_bound_input_bind_attempts); + SNAPSHOT_FIELD(rknn_rga_bound_input_bind_failures); + SNAPSHOT_FIELD(rknn_rga_bound_input_import_calls); + SNAPSHOT_FIELD(rknn_rga_bound_input_import_nanoseconds); + SNAPSHOT_FIELD(rknn_rga_bound_input_import_failures); + SNAPSHOT_FIELD(rknn_rga_bound_input_frames); + SNAPSHOT_FIELD(rknn_rga_bound_uint8_frames); + SNAPSHOT_FIELD(rknn_rga_bound_native_int8_frames); + SNAPSHOT_FIELD(rknn_rga_bound_requantize_calls); + SNAPSHOT_FIELD(rknn_rga_bound_requantize_nanoseconds); + SNAPSHOT_FIELD(rknn_rga_bound_requantize_failures); + SNAPSHOT_FIELD(rknn_rga_bound_input_normalize_bypasses); + SNAPSHOT_FIELD(rknn_mpp_dmabuf_import_calls); + SNAPSHOT_FIELD(rknn_mpp_dmabuf_import_nanoseconds); + SNAPSHOT_FIELD(rknn_mpp_dmabuf_import_failures); + SNAPSHOT_FIELD(rknn_mpp_dmabuf_frames); + SNAPSHOT_FIELD(rknn_mpp_dmabuf_fallbacks); + SNAPSHOT_FIELD(rknn_mpp_dmabuf_source_bytes); + SNAPSHOT_FIELD(rknn_native_int8_outputs); + SNAPSHOT_FIELD(rknn_float_outputs); + SNAPSHOT_FIELD(rknn_output_compatibility_fallbacks); + SNAPSHOT_FIELD(rknn_native_output_bytes); + SNAPSHOT_FIELD(rknn_float_output_bytes); + SNAPSHOT_FIELD(rknn_yolov8_dfl_calls); + SNAPSHOT_FIELD(rknn_yolov8_dfl_nanoseconds); + SNAPSHOT_FIELD(rknn_yolov8_class_calls); + SNAPSHOT_FIELD(rknn_yolov8_class_nanoseconds); + SNAPSHOT_FIELD(rknn_yolov8_direct_candidate_calls); + SNAPSHOT_FIELD(rknn_yolov8_direct_candidate_failures); + SNAPSHOT_FIELD(rknn_yolov8_direct_points_scanned); + SNAPSHOT_FIELD(rknn_yolov8_direct_points_decoded); + SNAPSHOT_FIELD(rknn_yolov8_score_sum_points_rejected); + SNAPSHOT_FIELD(rknn_yolov8_logical_float_bytes_avoided); + SNAPSHOT_FIELD(yolov8_postprocess_calls); + SNAPSHOT_FIELD(yolov8_postprocess_nanoseconds); + SNAPSHOT_FIELD(yolov8_nms_calls); + SNAPSHOT_FIELD(yolov8_nms_nanoseconds); +#undef SNAPSHOT_FIELD + return snapshot; +} + +InferencePipelineMetrics& GetInferencePipelineMetrics() { + static InferencePipelineMetrics metrics; + return metrics; +} + +} // namespace cosmo::nn diff --git a/src/nn/core/inference_pipeline_metrics.h b/src/nn/core/inference_pipeline_metrics.h new file mode 100644 index 000000000..756bb1963 --- /dev/null +++ b/src/nn/core/inference_pipeline_metrics.h @@ -0,0 +1,285 @@ +#pragma once + +#include <atomic> +#include <cstdint> + +namespace cosmo::nn { + +enum class RknnModelScope : uint8_t { + Other = 0, + Detector, +}; + +struct InferencePipelineMetricsSnapshot { + uint64_t color_convert_frames{0}; + uint64_t color_convert_nanoseconds{0}; + uint64_t blob_convert_frames{0}; + uint64_t blob_convert_nanoseconds{0}; + uint64_t graph_forward_frames{0}; + uint64_t graph_forward_nanoseconds{0}; + uint64_t graph_forward_failures{0}; + uint64_t result_parse_frames{0}; + uint64_t result_parse_nanoseconds{0}; + uint64_t result_parse_failures{0}; + uint64_t rknn_forwards{0}; + uint64_t rknn_forward_nanoseconds{0}; + uint64_t rknn_forward_failures{0}; + uint64_t rknn_prepare_calls{0}; + uint64_t rknn_prepare_nanoseconds{0}; + uint64_t rknn_inputs_set_calls{0}; + uint64_t rknn_inputs_set_nanoseconds{0}; + uint64_t rknn_run_calls{0}; + uint64_t rknn_run_nanoseconds{0}; + uint64_t rknn_outputs_get_calls{0}; + uint64_t rknn_outputs_get_nanoseconds{0}; + uint64_t rknn_outputs_release_calls{0}; + uint64_t rknn_outputs_release_nanoseconds{0}; + uint64_t rknn_output_transform_calls{0}; + uint64_t rknn_output_transform_nanoseconds{0}; + uint64_t rknn_mutex_wait_calls{0}; + uint64_t rknn_mutex_wait_nanoseconds{0}; + uint64_t rknn_detector_forwards{0}; + uint64_t rknn_detector_forward_nanoseconds{0}; + uint64_t rknn_detector_forward_failures{0}; + uint64_t rknn_detector_prepare_calls{0}; + uint64_t rknn_detector_prepare_nanoseconds{0}; + uint64_t rknn_detector_inputs_set_calls{0}; + uint64_t rknn_detector_inputs_set_nanoseconds{0}; + uint64_t rknn_detector_run_calls{0}; + uint64_t rknn_detector_run_nanoseconds{0}; + uint64_t rknn_detector_outputs_get_calls{0}; + uint64_t rknn_detector_outputs_get_nanoseconds{0}; + uint64_t rknn_detector_outputs_release_calls{0}; + uint64_t rknn_detector_outputs_release_nanoseconds{0}; + uint64_t rknn_detector_output_transform_calls{0}; + uint64_t rknn_detector_output_transform_nanoseconds{0}; + uint64_t rknn_detector_mutex_wait_calls{0}; + uint64_t rknn_detector_mutex_wait_nanoseconds{0}; + uint64_t rknn_preprocess_fast_hits{0}; + uint64_t rknn_rga_fill_calls{0}; + uint64_t rknn_rga_fill_nanoseconds{0}; + uint64_t rknn_rga_resize_color_calls{0}; + uint64_t rknn_rga_resize_color_nanoseconds{0}; + uint64_t rknn_rga_failures{0}; + uint64_t rknn_cpu_resize_fallback_calls{0}; + uint64_t rknn_cpu_resize_fallback_nanoseconds{0}; + uint64_t rknn_cpu_normalize_fallback_calls{0}; + uint64_t rknn_cpu_normalize_fallback_nanoseconds{0}; + uint64_t rknn_native_input_map_calls{0}; + uint64_t rknn_native_input_map_nanoseconds{0}; + uint64_t rknn_native_int8_inputs{0}; + uint64_t rknn_float_inputs{0}; + uint64_t rknn_uint8_contract_inputs{0}; + uint64_t rknn_input_compatibility_fallbacks{0}; + uint64_t rknn_bound_input_bind_attempts{0}; + uint64_t rknn_bound_input_bind_failures{0}; + uint64_t rknn_bound_input_copy_calls{0}; + uint64_t rknn_bound_input_copy_nanoseconds{0}; + uint64_t rknn_bound_input_copy_bytes{0}; + uint64_t rknn_bound_input_copy_failures{0}; + uint64_t rknn_bound_input_sync_calls{0}; + uint64_t rknn_bound_input_sync_nanoseconds{0}; + uint64_t rknn_bound_input_sync_failures{0}; + uint64_t rknn_bound_input_frames{0}; + uint64_t rknn_rga_bound_input_bind_attempts{0}; + uint64_t rknn_rga_bound_input_bind_failures{0}; + uint64_t rknn_rga_bound_input_import_calls{0}; + uint64_t rknn_rga_bound_input_import_nanoseconds{0}; + uint64_t rknn_rga_bound_input_import_failures{0}; + uint64_t rknn_rga_bound_input_frames{0}; + uint64_t rknn_rga_bound_uint8_frames{0}; + uint64_t rknn_rga_bound_native_int8_frames{0}; + uint64_t rknn_rga_bound_requantize_calls{0}; + uint64_t rknn_rga_bound_requantize_nanoseconds{0}; + uint64_t rknn_rga_bound_requantize_failures{0}; + uint64_t rknn_rga_bound_input_normalize_bypasses{0}; + uint64_t rknn_mpp_dmabuf_import_calls{0}; + uint64_t rknn_mpp_dmabuf_import_nanoseconds{0}; + uint64_t rknn_mpp_dmabuf_import_failures{0}; + uint64_t rknn_mpp_dmabuf_frames{0}; + uint64_t rknn_mpp_dmabuf_fallbacks{0}; + uint64_t rknn_mpp_dmabuf_source_bytes{0}; + uint64_t rknn_native_int8_outputs{0}; + uint64_t rknn_float_outputs{0}; + uint64_t rknn_output_compatibility_fallbacks{0}; + uint64_t rknn_native_output_bytes{0}; + uint64_t rknn_float_output_bytes{0}; + uint64_t rknn_yolov8_dfl_calls{0}; + uint64_t rknn_yolov8_dfl_nanoseconds{0}; + uint64_t rknn_yolov8_class_calls{0}; + uint64_t rknn_yolov8_class_nanoseconds{0}; + uint64_t rknn_yolov8_direct_candidate_calls{0}; + uint64_t rknn_yolov8_direct_candidate_failures{0}; + uint64_t rknn_yolov8_direct_points_scanned{0}; + uint64_t rknn_yolov8_direct_points_decoded{0}; + uint64_t rknn_yolov8_score_sum_points_rejected{0}; + uint64_t rknn_yolov8_logical_float_bytes_avoided{0}; + uint64_t yolov8_postprocess_calls{0}; + uint64_t yolov8_postprocess_nanoseconds{0}; + uint64_t yolov8_nms_calls{0}; + uint64_t yolov8_nms_nanoseconds{0}; +}; + +// Process-wide cumulative counters. Consumers derive interval averages from two +// snapshots, which keeps sampling independent from the inference threads. +class InferencePipelineMetrics { +public: + void RecordColorConvert(uint64_t nanoseconds, uint64_t frames = 1); + void RecordBlobConvert(uint64_t nanoseconds, uint64_t frames); + void RecordGraphForward(uint64_t nanoseconds, uint64_t frames, bool success); + void RecordResultParse(uint64_t nanoseconds, uint64_t frames, bool success); + void RecordRknnForward(uint64_t nanoseconds, bool success, RknnModelScope scope = RknnModelScope::Other); + void RecordRknnPrepare(uint64_t nanoseconds, RknnModelScope scope = RknnModelScope::Other); + void RecordRknnInputsSet(uint64_t nanoseconds, RknnModelScope scope = RknnModelScope::Other); + void RecordRknnRun(uint64_t nanoseconds, RknnModelScope scope = RknnModelScope::Other); + void RecordRknnOutputsGet(uint64_t nanoseconds, RknnModelScope scope = RknnModelScope::Other); + void RecordRknnOutputsRelease(uint64_t nanoseconds, RknnModelScope scope = RknnModelScope::Other); + void RecordRknnOutputTransform(uint64_t nanoseconds, RknnModelScope scope = RknnModelScope::Other); + void RecordRknnMutexWait(uint64_t nanoseconds, RknnModelScope scope = RknnModelScope::Other); + void RecordRknnPreprocessFastHit(); + void RecordRknnRgaFill(uint64_t nanoseconds); + void RecordRknnRgaResizeColor(uint64_t nanoseconds); + void RecordRknnRgaFailure(); + void RecordRknnCpuResizeFallback(uint64_t nanoseconds); + void RecordRknnCpuNormalizeFallback(uint64_t nanoseconds); + void RecordRknnNativeInputMap(uint64_t nanoseconds); + void RecordRknnInputFormat(bool native_int8, bool compatibility_fallback = false, + bool uint8_contract = false); + void RecordRknnBoundInputBind(bool success); + void RecordRknnBoundInputCopy(uint64_t nanoseconds, uint64_t bytes, bool success); + void RecordRknnBoundInputSync(uint64_t nanoseconds, bool success); + void RecordRknnBoundInputFrame(); + void RecordRknnRgaBoundInputBind(bool success); + void RecordRknnRgaBoundInputImport(uint64_t nanoseconds, bool success); + void RecordRknnRgaBoundInputRequantize(uint64_t nanoseconds, bool success); + void RecordRknnRgaBoundInputFrame(bool fused_uint8 = false); + void RecordRknnRgaBoundInputNormalizeBypass(); + void RecordRknnMppDmaBufImport(uint64_t nanoseconds, bool success); + void RecordRknnMppDmaBufFrame(uint64_t source_bytes); + void RecordRknnMppDmaBufFallback(); + void RecordRknnOutputFormat(bool native_int8, uint64_t bytes, bool compatibility_fallback = false); + void RecordRknnYolov8Transform(uint64_t dfl_nanoseconds, uint64_t class_nanoseconds); + void RecordRknnYolov8DirectCandidates(bool success, uint64_t points_scanned, uint64_t points_decoded, + uint64_t logical_float_bytes_avoided, + uint64_t score_sum_points_rejected = 0); + void RecordYolov8Postprocess(uint64_t nanoseconds); + void RecordYolov8Nms(uint64_t nanoseconds); + + [[nodiscard]] InferencePipelineMetricsSnapshot Snapshot() const; + +private: + static void RecordStage(std::atomic<uint64_t>& count, std::atomic<uint64_t>& duration, uint64_t samples, + uint64_t nanoseconds); + + std::atomic<uint64_t> color_convert_frames_{0}; + std::atomic<uint64_t> color_convert_nanoseconds_{0}; + std::atomic<uint64_t> blob_convert_frames_{0}; + std::atomic<uint64_t> blob_convert_nanoseconds_{0}; + std::atomic<uint64_t> graph_forward_frames_{0}; + std::atomic<uint64_t> graph_forward_nanoseconds_{0}; + std::atomic<uint64_t> graph_forward_failures_{0}; + std::atomic<uint64_t> result_parse_frames_{0}; + std::atomic<uint64_t> result_parse_nanoseconds_{0}; + std::atomic<uint64_t> result_parse_failures_{0}; + std::atomic<uint64_t> rknn_forwards_{0}; + std::atomic<uint64_t> rknn_forward_nanoseconds_{0}; + std::atomic<uint64_t> rknn_forward_failures_{0}; + std::atomic<uint64_t> rknn_prepare_calls_{0}; + std::atomic<uint64_t> rknn_prepare_nanoseconds_{0}; + std::atomic<uint64_t> rknn_inputs_set_calls_{0}; + std::atomic<uint64_t> rknn_inputs_set_nanoseconds_{0}; + std::atomic<uint64_t> rknn_run_calls_{0}; + std::atomic<uint64_t> rknn_run_nanoseconds_{0}; + std::atomic<uint64_t> rknn_outputs_get_calls_{0}; + std::atomic<uint64_t> rknn_outputs_get_nanoseconds_{0}; + std::atomic<uint64_t> rknn_outputs_release_calls_{0}; + std::atomic<uint64_t> rknn_outputs_release_nanoseconds_{0}; + std::atomic<uint64_t> rknn_output_transform_calls_{0}; + std::atomic<uint64_t> rknn_output_transform_nanoseconds_{0}; + std::atomic<uint64_t> rknn_mutex_wait_calls_{0}; + std::atomic<uint64_t> rknn_mutex_wait_nanoseconds_{0}; + std::atomic<uint64_t> rknn_detector_forwards_{0}; + std::atomic<uint64_t> rknn_detector_forward_nanoseconds_{0}; + std::atomic<uint64_t> rknn_detector_forward_failures_{0}; + std::atomic<uint64_t> rknn_detector_prepare_calls_{0}; + std::atomic<uint64_t> rknn_detector_prepare_nanoseconds_{0}; + std::atomic<uint64_t> rknn_detector_inputs_set_calls_{0}; + std::atomic<uint64_t> rknn_detector_inputs_set_nanoseconds_{0}; + std::atomic<uint64_t> rknn_detector_run_calls_{0}; + std::atomic<uint64_t> rknn_detector_run_nanoseconds_{0}; + std::atomic<uint64_t> rknn_detector_outputs_get_calls_{0}; + std::atomic<uint64_t> rknn_detector_outputs_get_nanoseconds_{0}; + std::atomic<uint64_t> rknn_detector_outputs_release_calls_{0}; + std::atomic<uint64_t> rknn_detector_outputs_release_nanoseconds_{0}; + std::atomic<uint64_t> rknn_detector_output_transform_calls_{0}; + std::atomic<uint64_t> rknn_detector_output_transform_nanoseconds_{0}; + std::atomic<uint64_t> rknn_detector_mutex_wait_calls_{0}; + std::atomic<uint64_t> rknn_detector_mutex_wait_nanoseconds_{0}; + std::atomic<uint64_t> rknn_preprocess_fast_hits_{0}; + std::atomic<uint64_t> rknn_rga_fill_calls_{0}; + std::atomic<uint64_t> rknn_rga_fill_nanoseconds_{0}; + std::atomic<uint64_t> rknn_rga_resize_color_calls_{0}; + std::atomic<uint64_t> rknn_rga_resize_color_nanoseconds_{0}; + std::atomic<uint64_t> rknn_rga_failures_{0}; + std::atomic<uint64_t> rknn_cpu_resize_fallback_calls_{0}; + std::atomic<uint64_t> rknn_cpu_resize_fallback_nanoseconds_{0}; + std::atomic<uint64_t> rknn_cpu_normalize_fallback_calls_{0}; + std::atomic<uint64_t> rknn_cpu_normalize_fallback_nanoseconds_{0}; + std::atomic<uint64_t> rknn_native_input_map_calls_{0}; + std::atomic<uint64_t> rknn_native_input_map_nanoseconds_{0}; + std::atomic<uint64_t> rknn_native_int8_inputs_{0}; + std::atomic<uint64_t> rknn_float_inputs_{0}; + std::atomic<uint64_t> rknn_uint8_contract_inputs_{0}; + std::atomic<uint64_t> rknn_input_compatibility_fallbacks_{0}; + std::atomic<uint64_t> rknn_bound_input_bind_attempts_{0}; + std::atomic<uint64_t> rknn_bound_input_bind_failures_{0}; + std::atomic<uint64_t> rknn_bound_input_copy_calls_{0}; + std::atomic<uint64_t> rknn_bound_input_copy_nanoseconds_{0}; + std::atomic<uint64_t> rknn_bound_input_copy_bytes_{0}; + std::atomic<uint64_t> rknn_bound_input_copy_failures_{0}; + std::atomic<uint64_t> rknn_bound_input_sync_calls_{0}; + std::atomic<uint64_t> rknn_bound_input_sync_nanoseconds_{0}; + std::atomic<uint64_t> rknn_bound_input_sync_failures_{0}; + std::atomic<uint64_t> rknn_bound_input_frames_{0}; + std::atomic<uint64_t> rknn_rga_bound_input_bind_attempts_{0}; + std::atomic<uint64_t> rknn_rga_bound_input_bind_failures_{0}; + std::atomic<uint64_t> rknn_rga_bound_input_import_calls_{0}; + std::atomic<uint64_t> rknn_rga_bound_input_import_nanoseconds_{0}; + std::atomic<uint64_t> rknn_rga_bound_input_import_failures_{0}; + std::atomic<uint64_t> rknn_rga_bound_input_frames_{0}; + std::atomic<uint64_t> rknn_rga_bound_uint8_frames_{0}; + std::atomic<uint64_t> rknn_rga_bound_native_int8_frames_{0}; + std::atomic<uint64_t> rknn_rga_bound_requantize_calls_{0}; + std::atomic<uint64_t> rknn_rga_bound_requantize_nanoseconds_{0}; + std::atomic<uint64_t> rknn_rga_bound_requantize_failures_{0}; + std::atomic<uint64_t> rknn_rga_bound_input_normalize_bypasses_{0}; + std::atomic<uint64_t> rknn_mpp_dmabuf_import_calls_{0}; + std::atomic<uint64_t> rknn_mpp_dmabuf_import_nanoseconds_{0}; + std::atomic<uint64_t> rknn_mpp_dmabuf_import_failures_{0}; + std::atomic<uint64_t> rknn_mpp_dmabuf_frames_{0}; + std::atomic<uint64_t> rknn_mpp_dmabuf_fallbacks_{0}; + std::atomic<uint64_t> rknn_mpp_dmabuf_source_bytes_{0}; + std::atomic<uint64_t> rknn_native_int8_outputs_{0}; + std::atomic<uint64_t> rknn_float_outputs_{0}; + std::atomic<uint64_t> rknn_output_compatibility_fallbacks_{0}; + std::atomic<uint64_t> rknn_native_output_bytes_{0}; + std::atomic<uint64_t> rknn_float_output_bytes_{0}; + std::atomic<uint64_t> rknn_yolov8_dfl_calls_{0}; + std::atomic<uint64_t> rknn_yolov8_dfl_nanoseconds_{0}; + std::atomic<uint64_t> rknn_yolov8_class_calls_{0}; + std::atomic<uint64_t> rknn_yolov8_class_nanoseconds_{0}; + std::atomic<uint64_t> rknn_yolov8_direct_candidate_calls_{0}; + std::atomic<uint64_t> rknn_yolov8_direct_candidate_failures_{0}; + std::atomic<uint64_t> rknn_yolov8_direct_points_scanned_{0}; + std::atomic<uint64_t> rknn_yolov8_direct_points_decoded_{0}; + std::atomic<uint64_t> rknn_yolov8_score_sum_points_rejected_{0}; + std::atomic<uint64_t> rknn_yolov8_logical_float_bytes_avoided_{0}; + std::atomic<uint64_t> yolov8_postprocess_calls_{0}; + std::atomic<uint64_t> yolov8_postprocess_nanoseconds_{0}; + std::atomic<uint64_t> yolov8_nms_calls_{0}; + std::atomic<uint64_t> yolov8_nms_nanoseconds_{0}; +}; + +InferencePipelineMetrics& GetInferencePipelineMetrics(); + +} // namespace cosmo::nn diff --git a/src/nn/core/shared_resource.h b/src/nn/core/shared_resource.h index 6b1e4af03..7bf4fd1b5 100644 --- a/src/nn/core/shared_resource.h +++ b/src/nn/core/shared_resource.h @@ -5,6 +5,8 @@ #include "bmruntime_interface.h" #endif +#include <cstddef> +#include <cstdint> #include <string> #include <vector> @@ -12,6 +14,68 @@ namespace cosmo::nn { +struct Yolov8DirectPostprocessConfig { + bool configured{false}; + float confidence_threshold{0.0f}; + int input_width{0}; + int input_height{0}; +}; + +struct Yolov8Candidate { + float x{0.0f}; + float y{0.0f}; + float width{0.0f}; + float height{0.0f}; + float confidence{0.0f}; + int class_id{-1}; +}; + +struct Yolov8CandidateBatch { + bool ready{false}; + std::vector<Yolov8Candidate> candidates; + + void Reset() { + ready = false; + candidates.clear(); + } +}; + +class RknnBoundInputProvider { +public: + virtual ~RknnBoundInputProvider() = default; + virtual bool EnsureRgaBoundInput(int height, int width, std::string& reason) = 0; +}; + +// Optional graph-local sidecar for RKNN/RGA input hand-off. The provider owns +// the memory; preprocessing only imports the fd and marks the current frame +// ready. Graph instances are exclusively leased while Forward runs. +struct RknnBoundInputTarget { + RknnBoundInputProvider* owner{nullptr}; + void* virtual_address{nullptr}; + int fd{-1}; + size_t bytes{0}; + int height{0}; + int width{0}; + int channels{0}; + int width_stride{0}; + uint64_t generation{0}; + bool frame_ready{false}; + + [[nodiscard]] bool Matches(int expected_height, int expected_width) const { + if (!owner || !virtual_address || fd < 0 || height != expected_height || width != expected_width || + height <= 0 || width <= 0 || channels != 3 || width_stride < width) { + return false; + } + const auto required = static_cast<uint64_t>(height) * static_cast<uint64_t>(width_stride) * + static_cast<uint64_t>(channels); + return required <= bytes; + } + + void Reset() { + *this = {}; + } +}; + class SharedResource { public: explicit SharedResource(int i = 0) noexcept(false); @@ -36,6 +100,20 @@ class SharedResource { int net_input_w = 0; int net_input_h = 0; float model_input_scale = 1.0f; // for INT8 quantized models + + // Optional producer/consumer hint. Only compatible RKNN YOLOv8 native-output + // graphs set this; every other backend keeps the established box-major scan. + bool prefer_yolov8_class_major_scan = false; + + // Optional producer/consumer capability for a backend that can decode native + // YOLOv8 heads directly into candidates. The graph instance is exclusively + // leased by InstancePool while Forward runs, so this sidecar has the same + // lifetime and concurrency boundary as the graph's ordinary BlobStore. + Yolov8DirectPostprocessConfig yolov8_direct_postprocess{}; + Yolov8CandidateBatch yolov8_candidate_batch{}; + + RknnBoundInputProvider* rknn_bound_input_provider{nullptr}; + RknnBoundInputTarget rknn_bound_input_target{}; }; } // namespace cosmo::nn diff --git a/src/nn/device/rknn/rknn_device.cc b/src/nn/device/rknn/rknn_device.cc new file mode 100644 index 000000000..3a2b8c7db --- /dev/null +++ b/src/nn/device/rknn/rknn_device.cc @@ -0,0 +1,14 @@ +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include "nn/device/naive/naive_device.h" + +namespace cosmo::nn { + +// RKNN's copy-first backend uses graph-owned host buffers. Registering a +// DEVICE_RKNN allocator keeps externally wrapped image blobs and BlobStore's +// calculate-device lifecycle valid without pretending the buffers are NPU DMA. +TypeDeviceRegister<NaiveDevice> g_rknn_device_register(DEVICE_RKNN); + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/src/nn/device/rknn/rknn_net_node.cc b/src/nn/device/rknn/rknn_net_node.cc new file mode 100644 index 000000000..c18caed42 --- /dev/null +++ b/src/nn/device/rknn/rknn_net_node.cc @@ -0,0 +1,1257 @@ +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include "nn/device/rknn/rknn_net_node.h" + +#include <algorithm> +#include <cctype> +#include <chrono> +#include <cmath> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <limits> +#include <mutex> +#include <numeric> +#include <unordered_map> + +#include "nn/core/inference_pipeline_metrics.h" +#include "nn/device/rknn/rknn_yolov8_adapter.h" +#include "nn/node/node_type_utils.h" +#include "util/Log.h" + +namespace cosmo::nn { +namespace { + + using MetricsClock = std::chrono::steady_clock; + + uint64_t ElapsedNanoseconds(MetricsClock::time_point started_at) { + return static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::nanoseconds>(MetricsClock::now() - started_at).count()); + } + + Status RknnError(const std::string& operation, int code) { + return Status(COSMO_NN_ERR_NET, operation + " failed with RKNN code " + std::to_string(code)); + } + + class OutputGuard { + public: + OutputGuard(rknn_context context, std::vector<rknn_output>& outputs) + : context_(context), outputs_(outputs) {} + ~OutputGuard() { + if (active_) + rknn_outputs_release(context_, static_cast<uint32_t>(outputs_.size()), outputs_.data()); + } + void Activate() { + active_ = true; + } + int Release() { + if (!active_) + return RKNN_SUCC; + active_ = false; + return rknn_outputs_release(context_, static_cast<uint32_t>(outputs_.size()), outputs_.data()); + } + + private: + rknn_context context_; + std::vector<rknn_output>& outputs_; + bool active_{false}; + }; + + size_t BlobElementCount(const BlobDesc& desc) { + if (desc.dims.empty()) + return 0; + size_t count = 1; + for (int dim : desc.dims) { + if (dim <= 0 || count > std::numeric_limits<size_t>::max() / static_cast<size_t>(dim)) + return 0; + count *= static_cast<size_t>(dim); + } + return count; + } + + size_t TensorAttrElementCount(const rknn_tensor_attr& attr) { + if (attr.n_elems != 0) + return attr.n_elems; + if (attr.n_dims == 0) + return 0; + size_t count = 1; + for (uint32_t index = 0; index < attr.n_dims; ++index) { + if (attr.dims[index] == 0 || + count > std::numeric_limits<size_t>::max() / static_cast<size_t>(attr.dims[index])) { + return 0; + } + count *= static_cast<size_t>(attr.dims[index]); + } + return count; + } + + std::vector<int> TensorAttrShape(const rknn_tensor_attr& attr) { + std::vector<int> shape; + shape.reserve(attr.n_dims); + for (uint32_t index = 0; index < attr.n_dims; ++index) { + if (attr.dims[index] > static_cast<uint32_t>(std::numeric_limits<int>::max())) + return {}; + shape.push_back(static_cast<int>(attr.dims[index])); + } + return shape; + } + + bool EnvironmentFlag(const char* name, bool default_value) { + const char* raw = std::getenv(name); + if (!raw || *raw == '\0') + return default_value; + std::string value(raw); + std::transform(value.begin(), value.end(), value.begin(), + [](unsigned char c) { return static_cast<char>(std::tolower(c)); }); + if (value == "0" || value == "false" || value == "off" || value == "no") + return false; + if (value == "1" || value == "true" || value == "on" || value == "yes") + return true; + return default_value; + } + + std::string LowercaseTrimmed(std::string value) { + const auto begin = value.find_first_not_of(" \t\n\r\f\v"); + if (begin == std::string::npos) + return {}; + const auto end = value.find_last_not_of(" \t\n\r\f\v"); + value = value.substr(begin, end - begin + 1); + std::transform(value.begin(), value.end(), value.begin(), + [](unsigned char c) { return static_cast<char>(std::tolower(c)); }); + return value; + } + + uint64_t ModelFingerprint(const std::vector<unsigned char>& model) { + constexpr uint64_t kFnvOffset = 1469598103934665603ULL; + constexpr uint64_t kFnvPrime = 1099511628211ULL; + uint64_t fingerprint = kFnvOffset; + for (const auto byte : model) { + fingerprint ^= byte; + fingerprint *= kFnvPrime; + } + return fingerprint; + } + + uint64_t NextModelContextSequence(const std::vector<unsigned char>& model) { + static std::mutex sequence_mutex; + static std::unordered_map<uint64_t, uint64_t> model_sequences; + const auto fingerprint = ModelFingerprint(model); + std::lock_guard<std::mutex> lock(sequence_mutex); + auto& sequence = model_sequences[fingerprint]; + return sequence++; + } + +} // namespace + +RknnCoreMode ParseRknnCoreMode(const std::string& value, bool* valid) { + const auto normalized = LowercaseTrimmed(value); + if (valid) + *valid = true; + if (normalized.empty() || normalized == "auto") + return RknnCoreMode::Auto; + if (normalized == "core0" || normalized == "core_0" || normalized == "0") + return RknnCoreMode::Core0; + if (normalized == "core1" || normalized == "core_1" || normalized == "1") + return RknnCoreMode::Core1; + if (normalized == "core01" || normalized == "core0_1" || normalized == "core_0_1" || + normalized == "dual") { + return RknnCoreMode::Core01; + } + if (normalized == "split") + return RknnCoreMode::Split; + if (valid) + *valid = false; + return RknnCoreMode::Auto; +} + +rknn_core_mask ResolveRknnCoreMask(RknnCoreMode mode, uint64_t context_sequence) { + switch (mode) { + case RknnCoreMode::Core0: + return RKNN_NPU_CORE_0; + case RknnCoreMode::Core1: + return RKNN_NPU_CORE_1; + case RknnCoreMode::Core01: + return RKNN_NPU_CORE_0_1; + case RknnCoreMode::Split: + return (context_sequence % 2 == 0) ? RKNN_NPU_CORE_0 : RKNN_NPU_CORE_1; + case RknnCoreMode::Auto: + default: + return RKNN_NPU_CORE_AUTO; + } +} + +const char* RknnCoreModeName(RknnCoreMode mode) { + switch (mode) { + case RknnCoreMode::Core0: + return "core0"; + case RknnCoreMode::Core1: + return "core1"; + case RknnCoreMode::Core01: + return "core0_1"; + case RknnCoreMode::Split: + return "split"; + case RknnCoreMode::Auto: + default: + return "auto"; + } +} + +bool IsRknnRgbUint8InputContract(const std::string& contract) { + return contract == kRknnRgbUint8InputContract; +} + +bool IsRknnNativeInt8InputCompatible(const rknn_tensor_attr& attr, const BlobDesc& desc) { + constexpr float kExpectedScale = 0.00392157f; + return desc.data_type == DATA_TYPE_INT8 && desc.data_format == DATA_FORMAT_NHWC && + desc.dims.size() == 4 && desc.dims[0] == 1 && desc.dims[1] > 0 && desc.dims[2] > 0 && + desc.dims[3] == 3 && attr.n_dims == 4 && attr.fmt == RKNN_TENSOR_NHWC && + attr.type == RKNN_TENSOR_INT8 && attr.qnt_type == RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC && + attr.zp == -128 && std::fabs(attr.scale - kExpectedScale) <= 1e-7f && attr.dims[0] == 1 && + attr.dims[1] == static_cast<uint32_t>(desc.dims[1]) && + attr.dims[2] == static_cast<uint32_t>(desc.dims[2]) && attr.dims[3] == 3; +} + +bool IsRknnNativeYolov8OutputCompatible(const std::vector<rknn_tensor_attr>& attrs, std::string* reason) { + const auto reject = [&](const char* message) { + if (reason) + *reason = message; + return false; + }; + std::vector<std::vector<int>> shapes; + shapes.reserve(attrs.size()); + for (const auto& attr : attrs) { + if (attr.type != RKNN_TENSOR_INT8) + return reject(attr.type == RKNN_TENSOR_FLOAT16 + ? "FP16 outputs retain the RKNN float compatibility path" + : "output type is not INT8"); + if (attr.fmt != RKNN_TENSOR_NCHW) + return reject("INT8 output format is not NCHW"); + if (attr.qnt_type != RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC) + return reject("INT8 output quantization is not affine asymmetric"); + if (!std::isfinite(attr.scale) || !(attr.scale > 0.0f) || attr.zp < -128 || attr.zp > 127) + return reject("INT8 output quantization parameters are invalid"); + const size_t element_count = TensorAttrElementCount(attr); + if (element_count == 0 || attr.size != element_count) + return reject("INT8 output byte count does not match its compact shape"); + auto shape = TensorAttrShape(attr); + if (shape.empty()) + return reject("INT8 output shape cannot be represented"); + shapes.push_back(std::move(shape)); + } + RknnYolov8Layout layout; + std::string adapter_error; + if (!DetectRknnYolov8Layout(shapes, layout, adapter_error)) { + if (reason) + *reason = adapter_error; + return false; + } + if (reason) + reason->clear(); + return true; +} + +bool IsRknnBoundInt8InputCompatible(const rknn_tensor_attr& attr, const BlobDesc& desc, std::string* reason) { + const auto reject = [&](const char* message) { + if (reason) + *reason = message; + return false; + }; + if (desc.data_type != DATA_TYPE_INT8 || desc.data_format != DATA_FORMAT_NHWC || desc.dims.size() != 4 || + desc.dims[0] != 1 || desc.dims[1] <= 0 || desc.dims[2] <= 0 || desc.dims[3] <= 0) { + return reject("bound input requires packed batch-1 INT8 NHWC data"); + } + if (attr.n_dims != 4 || attr.fmt != RKNN_TENSOR_NHWC || attr.type != RKNN_TENSOR_INT8) + return reject("RKNN native input is not INT8 NHWC"); + if (attr.qnt_type != RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC || attr.zp != -128 || !std::isfinite(attr.scale) || + std::fabs(attr.scale - 0.00392157f) > 1e-7f) { + return reject("RKNN native input quantization does not match the host fast path"); + } + if (attr.dims[0] != 1 || attr.dims[1] != static_cast<uint32_t>(desc.dims[1]) || + attr.dims[2] != static_cast<uint32_t>(desc.dims[2]) || + attr.dims[3] != static_cast<uint32_t>(desc.dims[3])) { + return reject("RKNN native input dimensions do not match the graph blob"); + } + const uint32_t width_stride = attr.w_stride == 0 ? attr.dims[2] : attr.w_stride; + if (width_stride < attr.dims[2]) + return reject("RKNN native input width stride is smaller than the tensor width"); + const uint64_t required = static_cast<uint64_t>(attr.dims[1]) * width_stride * attr.dims[3]; + const uint64_t available = attr.size_with_stride == 0 ? attr.size : attr.size_with_stride; + if (required == 0 || available < required) + return reject("RKNN native input stride allocation is too small"); + if (reason) + reason->clear(); + return true; +} + +bool IsRknnRgaBoundInputCompatible(const rknn_tensor_attr& attr, int height, int width, std::string* reason) { + BlobDesc desc; + desc.data_type = DATA_TYPE_INT8; + desc.data_format = DATA_FORMAT_NHWC; + desc.dims = {1, height, width, 3}; + return IsRknnBoundInt8InputCompatible(attr, desc, reason); +} + +bool ConfigureRknnRgaUint8InputAttr(const rknn_tensor_attr& native_attr, int height, int width, + rknn_tensor_attr& bound_attr, std::string* reason) { + if (!IsRknnRgaBoundInputCompatible(native_attr, height, width, reason)) + return false; + + // RKNN's native tensor is INT8, but the zero-copy contract permits a UINT8 + // bound input. Runtime then fuses the model's normalize/quantize operation + // onto the NPU, so RGA can write RGB bytes directly without a host-wide + // XOR/subtract-128 pass. This mirrors Rockchip's rknpu2 zero-copy sample. + bound_attr = native_attr; + bound_attr.type = RKNN_TENSOR_UINT8; + bound_attr.fmt = RKNN_TENSOR_NHWC; + bound_attr.pass_through = 0; + if (reason) + reason->clear(); + return true; +} + +bool CopyRknnPackedInt8Input(const int8_t* source, size_t source_bytes, int8_t* destination, + size_t destination_bytes, int height, int width, int channels, int width_stride, + std::string* reason) { + const auto reject = [&](const char* message) { + if (reason) + *reason = message; + return false; + }; + if (!source || !destination || height <= 0 || width <= 0 || channels <= 0) + return reject("bound input copy received an invalid packed tensor"); + const int effective_stride = width_stride == 0 ? width : width_stride; + if (effective_stride < width) + return reject("bound input copy width stride is too small"); + const uint64_t row_bytes = static_cast<uint64_t>(width) * channels; + const uint64_t source_required = static_cast<uint64_t>(height) * row_bytes; + const uint64_t destination_required = static_cast<uint64_t>(height) * effective_stride * channels; + if (source_required > source_bytes || destination_required > destination_bytes) + return reject("bound input copy buffer is smaller than its tensor contract"); + if (effective_stride == width) { + std::memcpy(destination, source, static_cast<size_t>(source_required)); + } else { + const size_t source_row_bytes = static_cast<size_t>(row_bytes); + const size_t destination_row_bytes = + static_cast<size_t>(effective_stride) * static_cast<size_t>(channels); + for (int row = 0; row < height; ++row) { + std::memcpy(destination + static_cast<size_t>(row) * destination_row_bytes, + source + static_cast<size_t>(row) * source_row_bytes, source_row_bytes); + } + } + if (reason) + reason->clear(); + return true; +} + +bool CopyRknnPackedNativeInt8ToUint8(const int8_t* source, size_t source_bytes, uint8_t* destination, + size_t destination_bytes, int height, int width, int channels, + int width_stride, std::string* reason) { + const auto reject = [&](const char* message) { + if (reason) + *reason = message; + return false; + }; + if (!source || !destination || height <= 0 || width <= 0 || channels <= 0) + return reject("UINT8 contract restore received an invalid packed tensor"); + const int effective_stride = width_stride == 0 ? width : width_stride; + if (effective_stride < width) + return reject("UINT8 contract restore width stride is too small"); + const uint64_t row_elements = static_cast<uint64_t>(width) * channels; + const uint64_t source_required = static_cast<uint64_t>(height) * row_elements; + const uint64_t destination_required = static_cast<uint64_t>(height) * effective_stride * channels; + if (source_required > source_bytes || destination_required > destination_bytes) + return reject("UINT8 contract restore buffer is smaller than its tensor contract"); + const size_t source_row_elements = static_cast<size_t>(row_elements); + const size_t destination_stride = static_cast<size_t>(effective_stride) * static_cast<size_t>(channels); + for (int row = 0; row < height; ++row) { + const auto* source_row = source + static_cast<size_t>(row) * source_row_elements; + auto* destination_row = destination + static_cast<size_t>(row) * destination_stride; + for (size_t index = 0; index < source_row_elements; ++index) + destination_row[index] = static_cast<uint8_t>(static_cast<int>(source_row[index]) + 128); + } + if (reason) + reason->clear(); + return true; +} + +bool ConvertRknnNormalizedFloatToUint8(const float* source, size_t source_count, uint8_t* destination, + size_t destination_count, std::string* reason) { + const auto reject = [&](const char* message) { + if (reason) + *reason = message; + return false; + }; + if (!source || !destination || source_count == 0 || destination_count < source_count) + return reject("UINT8 contract conversion received an invalid tensor"); + for (size_t index = 0; index < source_count; ++index) { + if (!std::isfinite(source[index])) + return reject("UINT8 contract conversion received a non-finite value"); + destination[index] = + static_cast<uint8_t>(std::lround(std::clamp(source[index], 0.0f, 1.0f) * 255.0f)); + } + if (reason) + reason->clear(); + return true; +} + +bool RequantizeRknnPackedUint8ToInt8InPlace(uint8_t* data, size_t data_bytes, int height, int width, + int channels, int width_stride, std::string* reason) { + const auto reject = [&](const char* message) { + if (reason) + *reason = message; + return false; + }; + if (!data || height <= 0 || width <= 0 || channels <= 0) + return reject("RGA bound input requantization received an invalid packed tensor"); + const int effective_stride = width_stride == 0 ? width : width_stride; + if (effective_stride < width) + return reject("RGA bound input requantization width stride is too small"); + const uint64_t required = static_cast<uint64_t>(height) * effective_stride * channels; + if (required == 0 || required > data_bytes) + return reject("RGA bound input requantization buffer is smaller than its tensor contract"); + const size_t row_bytes = static_cast<size_t>(width) * static_cast<size_t>(channels); + const size_t stride_bytes = static_cast<size_t>(effective_stride) * static_cast<size_t>(channels); + for (int row = 0; row < height; ++row) { + auto* row_data = data + static_cast<size_t>(row) * stride_bytes; + for (size_t index = 0; index < row_bytes; ++index) + row_data[index] ^= 0x80; + } + if (reason) + reason->clear(); + return true; +} + +bool RknnFastOutputEnabled() { + return EnvironmentFlag("COSMO_RKNN_FAST_OUTPUT", true); +} + +bool RknnDirectCandidatesEnabled() { + return EnvironmentFlag("COSMO_RKNN_DIRECT_CANDIDATES", true); +} + +bool RknnBoundInputEnabled() { + return EnvironmentFlag("COSMO_RKNN_BOUND_INPUT", true); +} + +bool RknnRgaBoundInputEnabled() { + return EnvironmentFlag("COSMO_RKNN_RGA_BOUND_INPUT", true); +} + +RknnNetNode::RknnNetNode() : NetNode() { + name = NodeTypeUtils::NodeTypeToStr(NodeType::NODE_NET).append("_0"); +} + +RknnNetNode::~RknnNetNode() { + std::lock_guard<std::mutex> lock(mutex_); + DestroyContext(); +} + +void RknnNetNode::DestroyContext() { + ClearRgaBoundInputTarget(); + if (bound_input_memory_) { + if (context_ != 0) + rknn_destroy_mem(context_, bound_input_memory_); + bound_input_memory_ = nullptr; + } + if (context_ != 0) { + rknn_destroy(context_); + context_ = 0; + } + input_attrs_.clear(); + output_attrs_.clear(); + std::vector<rknn_output>().swap(runtime_outputs_); + std::vector<RknnYolov8Head>().swap(float_yolov8_heads_); + std::vector<RknnYolov8QuantizedHead>().swap(quantized_yolov8_heads_); + std::vector<int8_t>().swap(yolov8_candidate_scratch_.class_max); + std::vector<int>().swap(yolov8_candidate_scratch_.class_ids); + std::vector<int>().swap(yolov8_candidate_scratch_.active_points); + model_data_.clear(); + std::vector<float>().swap(input_nhwc_); + std::vector<uint8_t>().swap(input_uint8_); + io_count_ = {}; + output_adapter_contract_ = {}; + bound_input_attr_ = {}; + yolov8_heads_ = false; + native_yolov8_outputs_ = false; + detector_model_ = false; + bound_input_eligible_ = true; + rga_bound_input_eligible_ = true; + bound_input_mode_ = BoundInputMode::None; + yolov8_class_count_ = 0; + yolov8_point_count_ = 0; +} + +bool RknnNetNode::AllocateAndBindInputMemory(rknn_tensor_attr attr, BoundInputMode mode, + std::string& reason) { + if (bound_input_memory_) { + reason = "RKNN input memory is already bound"; + return false; + } + const uint32_t bytes = attr.size_with_stride == 0 ? attr.size : attr.size_with_stride; + auto* memory = rknn_create_mem(context_, bytes); + if (!memory || !memory->virt_addr || memory->size < bytes) { + if (memory) + rknn_destroy_mem(context_, memory); + reason = "rknn_create_mem failed for the bound input"; + return false; + } + const int result = rknn_set_io_mem(context_, memory, &attr); + if (result != RKNN_SUCC) { + rknn_destroy_mem(context_, memory); + reason = "rknn_set_io_mem failed with RKNN code " + std::to_string(result); + return false; + } + bound_input_attr_ = attr; + bound_input_memory_ = memory; + bound_input_mode_ = mode; + if (mode == BoundInputMode::RgaUint8 || mode == BoundInputMode::RgaNativeInt8) + PublishRgaBoundInputTarget(); + reason.clear(); + return true; +} + +bool RknnNetNode::TryBindNativeInputMemory(const BlobDesc& desc, std::string& reason) { + rknn_tensor_attr attr{}; + attr.index = 0; + int result = rknn_query(context_, RKNN_QUERY_NATIVE_INPUT_ATTR, &attr, sizeof(attr)); + if (result != RKNN_SUCC) { + reason = "RKNN_QUERY_NATIVE_INPUT_ATTR failed with RKNN code " + std::to_string(result); + return false; + } + if (!IsRknnBoundInt8InputCompatible(attr, desc, &reason)) + return false; + attr.pass_through = 1; + return AllocateAndBindInputMemory(attr, BoundInputMode::NativeInt8, reason); +} + +bool RknnNetNode::TryBindRgaInputMemory(int height, int width, std::string& reason) { + rknn_tensor_attr native_attr{}; + native_attr.index = 0; + int result = rknn_query(context_, RKNN_QUERY_NATIVE_INPUT_ATTR, &native_attr, sizeof(native_attr)); + if (result != RKNN_SUCC) { + reason = "RKNN_QUERY_NATIVE_INPUT_ATTR failed with RKNN code " + std::to_string(result); + return false; + } + if (!IsRknnRgaBoundInputCompatible(native_attr, height, width, &reason)) + return false; + + if (IsRknnRgbUint8InputContract(input_contract_)) { + rknn_tensor_attr uint8_attr{}; + if (!ConfigureRknnRgaUint8InputAttr(native_attr, height, width, uint8_attr, &reason)) + return false; + std::string uint8_reason; + if (AllocateAndBindInputMemory(uint8_attr, BoundInputMode::RgaUint8, uint8_reason)) + return true; + + // Older or model-specific runtimes may reject the declared UINT8 + // contract. Preserve the native-INT8 binding as a correctness fallback; + // telemetry keeps this CPU-requantized mode visible. + native_attr.pass_through = 1; + if (AllocateAndBindInputMemory(native_attr, BoundInputMode::RgaNativeInt8, reason)) { + LOG_WARN("RKNN fused UINT8 bound input unavailable ({}); using native INT8 fallback", + uint8_reason); + return true; + } + reason = "UINT8 bound input failed: " + uint8_reason + "; native INT8 fallback failed: " + reason; + return false; + } + + // A native INT8 tensor does not prove that the model embeds normalization. + // Host-owned models therefore retain the exact, already-qualified + // uint8-to-int8 conversion until their config declares the contract. + native_attr.pass_through = 1; + return AllocateAndBindInputMemory(native_attr, BoundInputMode::RgaNativeInt8, reason); +} + +void RknnNetNode::PublishRgaBoundInputTarget() { + const bool rga_bound_mode = + bound_input_mode_ == BoundInputMode::RgaUint8 || bound_input_mode_ == BoundInputMode::RgaNativeInt8; + if (!shared_resource || !bound_input_memory_ || !rga_bound_mode) { + return; + } + auto& target = shared_resource->rknn_bound_input_target; + target.owner = this; + target.virtual_address = bound_input_memory_->virt_addr; + target.fd = bound_input_memory_->fd; + target.bytes = bound_input_memory_->size; + target.height = static_cast<int>(bound_input_attr_.dims[1]); + target.width = static_cast<int>(bound_input_attr_.dims[2]); + target.channels = static_cast<int>(bound_input_attr_.dims[3]); + target.width_stride = static_cast<int>(bound_input_attr_.w_stride == 0 ? bound_input_attr_.dims[2] + : bound_input_attr_.w_stride); + target.generation = ++bound_input_generation_; + target.frame_ready = false; +} + +void RknnNetNode::ClearRgaBoundInputTarget() { + if (!shared_resource) + return; + if (shared_resource->rknn_bound_input_provider == this) + shared_resource->rknn_bound_input_provider = nullptr; + if (shared_resource->rknn_bound_input_target.owner == this) + shared_resource->rknn_bound_input_target.Reset(); +} + +bool RknnNetNode::EnsureRgaBoundInput(int height, int width, std::string& reason) { + std::lock_guard<std::mutex> lock(mutex_); + if (context_ == 0 || !detector_model_) { + reason = "RKNN detector context is not initialized"; + return false; + } + if (!RknnBoundInputEnabled() || !RknnRgaBoundInputEnabled()) { + reason = "RKNN RGA bound input is disabled"; + return false; + } + if (bound_input_memory_) { + const bool rga_bound_mode = bound_input_mode_ == BoundInputMode::RgaUint8 || + bound_input_mode_ == BoundInputMode::RgaNativeInt8; + if (rga_bound_mode && shared_resource && shared_resource->rknn_bound_input_target.owner == this && + shared_resource->rknn_bound_input_target.Matches(height, width)) { + reason.clear(); + return true; + } + reason = "RKNN input was already bound by another input path"; + return false; + } + if (!rga_bound_input_eligible_) { + reason = "RKNN RGA bound input was previously rejected"; + return false; + } + const bool bound = TryBindRgaInputMemory(height, width, reason); + GetInferencePipelineMetrics().RecordRknnRgaBoundInputBind(bound); + if (!bound) { + rga_bound_input_eligible_ = false; + return false; + } + LOG_INFO("RKNN RGA input bound: mode={} bytes={} fd={} width_stride={}", + bound_input_mode_ == BoundInputMode::RgaUint8 ? "fused-uint8" : "native-int8", + bound_input_memory_->size, bound_input_memory_->fd, bound_input_attr_.w_stride); + return true; +} + +size_t RknnNetNode::TensorElementCount(const rknn_tensor_attr& attr) const { + if (attr.n_elems != 0) + return attr.n_elems; + size_t count = 1; + for (uint32_t index = 0; index < attr.n_dims; ++index) { + if (attr.dims[index] == 0 || + count > std::numeric_limits<size_t>::max() / static_cast<size_t>(attr.dims[index])) + return 0; + count *= static_cast<size_t>(attr.dims[index]); + } + return count; +} + +std::vector<int> RknnNetNode::TensorShape(const rknn_tensor_attr& attr) const { + std::vector<int> shape; + shape.reserve(attr.n_dims); + for (uint32_t index = 0; index < attr.n_dims; ++index) { + if (attr.dims[index] > static_cast<uint32_t>(std::numeric_limits<int>::max())) + return {}; + shape.push_back(static_cast<int>(attr.dims[index])); + } + return shape; +} + +Status RknnNetNode::QueryTensorAttributes() { + int result = rknn_query(context_, RKNN_QUERY_IN_OUT_NUM, &io_count_, sizeof(io_count_)); + if (result != RKNN_SUCC) + return RknnError("RKNN_QUERY_IN_OUT_NUM", result); + if (io_count_.n_input != 1 || io_count_.n_output == 0 || io_count_.n_output > 64) + return Status(COSMO_NN_ERR_UNSUPPORT_NET, + "RKNN backend currently requires one input and 1-64 outputs"); + + input_attrs_.resize(io_count_.n_input); + for (uint32_t index = 0; index < io_count_.n_input; ++index) { + input_attrs_[index] = {}; + input_attrs_[index].index = index; + result = + rknn_query(context_, RKNN_QUERY_INPUT_ATTR, &input_attrs_[index], sizeof(input_attrs_[index])); + if (result != RKNN_SUCC) + return RknnError("RKNN_QUERY_INPUT_ATTR", result); + } + + output_attrs_.resize(io_count_.n_output); + std::vector<std::vector<int>> output_shapes; + output_shapes.reserve(io_count_.n_output); + for (uint32_t index = 0; index < io_count_.n_output; ++index) { + output_attrs_[index] = {}; + output_attrs_[index].index = index; + result = + rknn_query(context_, RKNN_QUERY_OUTPUT_ATTR, &output_attrs_[index], sizeof(output_attrs_[index])); + if (result != RKNN_SUCC) + return RknnError("RKNN_QUERY_OUTPUT_ATTR", result); + auto shape = TensorShape(output_attrs_[index]); + if (shape.empty() || TensorElementCount(output_attrs_[index]) == 0) + return Status(COSMO_NN_ERR_UNSUPPORT_NET, "RKNN model contains an invalid output shape"); + output_shapes.push_back(std::move(shape)); + } + runtime_outputs_.resize(output_attrs_.size()); + float_yolov8_heads_.reserve(output_attrs_.size()); + quantized_yolov8_heads_.reserve(output_attrs_.size()); + + std::string adapter_error; + if (!ResolveRknnOutputAdapter(output_shapes, output_adapter_contract_, adapter_error)) + return Status(COSMO_NN_ERR_UNSUPPORT_NET, adapter_error); + yolov8_heads_ = IsRknnYolov8DflAdapter(output_adapter_contract_.kind); + if (yolov8_heads_) { + yolov8_class_count_ = output_adapter_contract_.class_count; + yolov8_point_count_ = output_adapter_contract_.point_count; + } + std::string native_output_reason; + native_yolov8_outputs_ = + yolov8_heads_ && IsRknnNativeYolov8OutputCompatible(output_attrs_, &native_output_reason); + if (yolov8_heads_ && !native_yolov8_outputs_) { + LOG_INFO("RKNN YOLOv8 native INT8 output disabled: {}", native_output_reason); + } + const auto& input = input_attrs_.front(); + detector_model_ = yolov8_heads_ && input.n_dims == 4 && input.fmt == RKNN_TENSOR_NHWC && + input.dims[0] == 1 && input.dims[1] == 640 && input.dims[2] == 640 && + input.dims[3] == 3; + return COSMO_NN_OK; +} + +Status RknnNetNode::LoadWeight(const char* data, size_t size) { + if (!data || size == 0) + return Status(COSMO_NN_ERR_LOAD_MODEL, "RKNN model data is empty"); + if (size > std::numeric_limits<uint32_t>::max()) + return Status(COSMO_NN_ERR_LOAD_MODEL, "RKNN model exceeds the runtime size limit"); + + std::lock_guard<std::mutex> lock(mutex_); + DestroyContext(); + try { + model_data_.assign(reinterpret_cast<const unsigned char*>(data), + reinterpret_cast<const unsigned char*>(data) + size); + } catch (const std::bad_alloc&) { + return Status(COSMO_NN_ERR_OUT_OF_MEMORY, "Not enough memory to retain RKNN model data"); + } + + int result = + rknn_init(&context_, model_data_.data(), static_cast<uint32_t>(model_data_.size()), 0, nullptr); + if (result != RKNN_SUCC) { + DestroyContext(); + return RknnError("rknn_init", result); + } + const uint64_t context_sequence = NextModelContextSequence(model_data_); + bool core_mode_valid = true; + const char* core_mode_env = std::getenv("COSMO_RKNN_CORE_MODE"); + const auto core_mode = ParseRknnCoreMode(core_mode_env ? core_mode_env : "auto", &core_mode_valid); + if (!core_mode_valid) { + LOG_WARN("Invalid COSMO_RKNN_CORE_MODE value:{}, fallback:auto", core_mode_env ? core_mode_env : ""); + } + const auto core_mask = ResolveRknnCoreMask(core_mode, context_sequence); + result = rknn_set_core_mask(context_, core_mask); + if (result != RKNN_SUCC) { + DestroyContext(); + return RknnError("rknn_set_core_mask", result); + } + + rknn_sdk_version version{}; + result = rknn_query(context_, RKNN_QUERY_SDK_VERSION, &version, sizeof(version)); + if (result != RKNN_SUCC) { + DestroyContext(); + return RknnError("RKNN_QUERY_SDK_VERSION", result); + } + auto status = QueryTensorAttributes(); + if (!status) { + DestroyContext(); + return status; + } + if (network_input_names.size() != io_count_.n_input) { + DestroyContext(); + return Status(COSMO_NN_ERR_INVALID_CFG, "RKNN input count does not match config.json"); + } + const size_t logical_outputs = yolov8_heads_ ? 1 : io_count_.n_output; + if (network_output_names.size() != logical_outputs) { + DestroyContext(); + return Status(COSMO_NN_ERR_INVALID_CFG, "RKNN logical output count does not match config.json"); + } + if (detector_model_ && shared_resource) + shared_resource->rknn_bound_input_provider = this; + + LOG_INFO( + "RKNN model loaded: api={} driver={} inputs={} runtime_outputs={} logical_outputs={} " + "output_adapter={} native_int8_output={} core_mode={} core_mask={} context_sequence={}", + version.api_version, version.drv_version, io_count_.n_input, io_count_.n_output, logical_outputs, + RknnOutputAdapterName(output_adapter_contract_.kind), native_yolov8_outputs_, + RknnCoreModeName(core_mode), static_cast<int>(core_mask), context_sequence); + return COSMO_NN_OK; +} + +DeviceType RknnNetNode::GetTopBlobDeviceType() { + return DEVICE_NAIVE; +} + +Status RknnNetNode::InferTopShapes() { + std::lock_guard<std::mutex> lock(mutex_); + if (context_ == 0) + return Status(COSMO_NN_ERR_GRAPH_NOT_INIT, "RKNN context is not initialized"); + top_blob_shapes.clear(); + top_blob_data_types.clear(); + if (yolov8_heads_) { + top_blob_shapes.push_back({1, 4 + yolov8_class_count_, yolov8_point_count_}); + top_blob_data_types.push_back(DATA_TYPE_FLOAT); + return COSMO_NN_OK; + } + for (const auto& attr : output_attrs_) { + auto shape = TensorShape(attr); + if (shape.empty()) + return Status(COSMO_NN_ERR_UNSUPPORT_NET, "RKNN output shape cannot be represented"); + top_blob_shapes.push_back(std::move(shape)); + // rknn_outputs_get(want_float=1) always materializes float output. + top_blob_data_types.push_back(DATA_TYPE_FLOAT); + } + return COSMO_NN_OK; +} + +Status RknnNetNode::PrepareInput(const Blob& blob, std::vector<float>& nhwc, int& height, int& width) const { + auto& mutable_blob = const_cast<Blob&>(blob); + const auto desc = mutable_blob.GetBlobDesc(); + const auto handle = mutable_blob.GetHandle(); + if (!handle.base || desc.data_type != DATA_TYPE_FLOAT || desc.data_format != DATA_FORMAT_NCHW || + desc.dims.size() != 4 || desc.dims[0] != 1 || desc.dims[1] <= 0 || desc.dims[2] <= 0 || + desc.dims[3] <= 0) { + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN input must be a non-empty batch-1 NCHW float blob"); + } + const int channels = desc.dims[1]; + height = desc.dims[2]; + width = desc.dims[3]; + if (channels != 3) + return Status(COSMO_NN_ERR_UNSUPPORT_NET, "RKNN CV backend currently requires three channels"); + if (BlobElementCount(desc) != TensorElementCount(input_attrs_[0])) + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN input shape does not match the model"); + + const auto& attr = input_attrs_[0]; + if (attr.n_dims != 4) + return Status(COSMO_NN_ERR_UNSUPPORT_NET, "RKNN CV backend requires a four-dimensional input"); + if (attr.fmt == RKNN_TENSOR_NHWC) { + if (attr.dims[0] != 1 || attr.dims[1] != static_cast<uint32_t>(height) || + attr.dims[2] != static_cast<uint32_t>(width) || attr.dims[3] != 3) + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN NHWC model dimensions do not match the graph"); + } else if (attr.fmt == RKNN_TENSOR_NCHW) { + if (attr.dims[0] != 1 || attr.dims[1] != 3 || attr.dims[2] != static_cast<uint32_t>(height) || + attr.dims[3] != static_cast<uint32_t>(width)) + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN NCHW model dimensions do not match the graph"); + } else { + return Status(COSMO_NN_ERR_UNSUPPORT_NET, "RKNN input format must be NCHW or NHWC"); + } + + const size_t plane = static_cast<size_t>(height) * static_cast<size_t>(width); + try { + nhwc.resize(plane * static_cast<size_t>(channels)); + } catch (const std::bad_alloc&) { + return Status(COSMO_NN_ERR_OUT_OF_MEMORY, "Not enough memory for RKNN NCHW-to-NHWC copy"); + } + const auto* source = static_cast<const float*>(handle.base); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + const size_t pixel = static_cast<size_t>(y) * static_cast<size_t>(width) + x; + for (int channel = 0; channel < channels; ++channel) + nhwc[pixel * static_cast<size_t>(channels) + channel] = + source[static_cast<size_t>(channel) * plane + pixel]; + } + } + return COSMO_NN_OK; +} + +Status RknnNetNode::PrepareNativeCompatibilityInput(const Blob& blob, std::vector<float>& nhwc, int& height, + int& width) const { + auto& mutable_blob = const_cast<Blob&>(blob); + const auto desc = mutable_blob.GetBlobDesc(); + const auto handle = mutable_blob.GetHandle(); + if (!handle.base || desc.data_type != DATA_TYPE_INT8 || desc.data_format != DATA_FORMAT_NHWC || + desc.dims.size() != 4 || desc.dims[0] != 1 || desc.dims[1] <= 0 || desc.dims[2] <= 0 || + desc.dims[3] != 3 || BlobElementCount(desc) != TensorElementCount(input_attrs_[0])) { + return Status(COSMO_NN_ERR_INVALID_INPUT, + "RKNN native compatibility input must be batch-1 NHWC int8"); + } + height = desc.dims[1]; + width = desc.dims[2]; + const auto count = BlobElementCount(desc); + try { + nhwc.resize(count); + } catch (const std::bad_alloc&) { + return Status(COSMO_NN_ERR_OUT_OF_MEMORY, + "Not enough memory for RKNN native-input compatibility fallback"); + } + const auto* source = static_cast<const int8_t*>(handle.base); + constexpr float kNormalizeScale = 0.00392157f; + for (size_t index = 0; index < count; ++index) + nhwc[index] = static_cast<float>(static_cast<int>(source[index]) + 128) * kNormalizeScale; + return COSMO_NN_OK; +} + +Status RknnNetNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blobs, + std::vector<std::shared_ptr<Blob>>& top_blobs) { + const auto mutex_wait_started = MetricsClock::now(); + std::unique_lock<std::mutex> lock(mutex_); + const auto scope = detector_model_ ? RknnModelScope::Detector : RknnModelScope::Other; + GetInferencePipelineMetrics().RecordRknnMutexWait(ElapsedNanoseconds(mutex_wait_started), scope); + if (context_ == 0) + return Status(COSMO_NN_ERR_GRAPH_NOT_INIT, "RKNN context is not initialized"); + if (bottom_blobs.size() != 1 || !bottom_blobs[0]) + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN backend requires exactly one input blob"); + const size_t logical_outputs = yolov8_heads_ ? 1 : output_attrs_.size(); + if (top_blobs.size() != logical_outputs) + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN output blob count mismatch"); + if (yolov8_heads_ && shared_resource) + shared_resource->yolov8_candidate_batch.Reset(); + + timer.Start(); + const auto forward_started = MetricsClock::now(); + const auto finish = [&](Status status) -> Status { + timer.Stop(); + GetInferencePipelineMetrics().RecordRknnForward(ElapsedNanoseconds(forward_started), bool(status), + scope); + return status; + }; + int input_height = 0, input_width = 0; + bool native_int8 = false; + bool uint8_contract_input = false; + bool compatibility_fallback = false; + rknn_input input{}; + input.index = 0; + const auto prepare_started = MetricsClock::now(); + const auto input_desc = bottom_blobs[0]->GetBlobDesc(); + bool rga_bound_frame = false; + if (shared_resource && shared_resource->rknn_bound_input_target.frame_ready && + shared_resource->rknn_bound_input_target.owner == this) { + auto& target = shared_resource->rknn_bound_input_target; + target.frame_ready = false; + const bool rga_bound_mode = bound_input_mode_ == BoundInputMode::RgaUint8 || + bound_input_mode_ == BoundInputMode::RgaNativeInt8; + const bool blob_matches = input_desc.data_type == DATA_TYPE_INT8 && + input_desc.data_format == DATA_FORMAT_NHWC && + input_desc.image_format == IMAGE_RGB && input_desc.dims.size() == 4 && + input_desc.dims[0] == 1 && input_desc.dims[1] == target.height && + input_desc.dims[2] == target.width && input_desc.dims[3] == 3; + if (target.owner != this || !rga_bound_mode || !blob_matches || + target.generation != bound_input_generation_ || + !target.Matches(input_desc.dims[1], input_desc.dims[2])) { + return finish( + Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN RGA bound input frame has a stale target")); + } + input_height = target.height; + input_width = target.width; + rga_bound_frame = true; + } + Status prepare_status; + if (rga_bound_frame) { + prepare_status = COSMO_NN_OK; + } else if (input_desc.data_type == DATA_TYPE_INT8 && input_desc.data_format == DATA_FORMAT_NHWC) { + native_int8 = IsRknnNativeInt8InputCompatible(input_attrs_[0], input_desc); + if (native_int8) { + const auto count = BlobElementCount(input_desc); + if (!bottom_blobs[0]->GetHandle().base || count == 0 || + count > std::numeric_limits<uint32_t>::max()) { + prepare_status = + Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN native input exceeds runtime size limit"); + } else { + input.buf = bottom_blobs[0]->GetHandle().base; + input.size = static_cast<uint32_t>(count); + input.pass_through = 1; + input.type = RKNN_TENSOR_INT8; + input.fmt = RKNN_TENSOR_NHWC; + input_height = input_desc.dims[1]; + input_width = input_desc.dims[2]; + prepare_status = COSMO_NN_OK; + } + } else if (IsRknnRgbUint8InputContract(input_contract_)) { + const auto count = BlobElementCount(input_desc); + if (!bottom_blobs[0]->GetHandle().base || count == 0 || + count > std::numeric_limits<uint32_t>::max()) { + prepare_status = Status(COSMO_NN_ERR_INVALID_INPUT, + "RKNN UINT8 contract input exceeds runtime size limit"); + } else { + try { + input_uint8_.resize(count); + } catch (const std::bad_alloc&) { + return finish(Status(COSMO_NN_ERR_OUT_OF_MEMORY, + "Not enough memory for RKNN UINT8 contract input")); + } + std::string conversion_reason; + const bool converted = CopyRknnPackedNativeInt8ToUint8( + static_cast<const int8_t*>(bottom_blobs[0]->GetHandle().base), count, input_uint8_.data(), + input_uint8_.size(), input_desc.dims[1], input_desc.dims[2], input_desc.dims[3], + input_desc.dims[2], &conversion_reason); + if (!converted) { + prepare_status = Status(COSMO_NN_ERR_INVALID_INPUT, conversion_reason); + } else { + input_height = input_desc.dims[1]; + input_width = input_desc.dims[2]; + uint8_contract_input = true; + prepare_status = COSMO_NN_OK; + } + } + } else { + compatibility_fallback = true; + prepare_status = + PrepareNativeCompatibilityInput(*bottom_blobs[0], input_nhwc_, input_height, input_width); + } + } else { + prepare_status = PrepareInput(*bottom_blobs[0], input_nhwc_, input_height, input_width); + if (prepare_status && IsRknnRgbUint8InputContract(input_contract_)) { + try { + input_uint8_.resize(input_nhwc_.size()); + } catch (const std::bad_alloc&) { + return finish( + Status(COSMO_NN_ERR_OUT_OF_MEMORY, "Not enough memory for RKNN UINT8 contract input")); + } + std::string conversion_reason; + if (!ConvertRknnNormalizedFloatToUint8(input_nhwc_.data(), input_nhwc_.size(), + input_uint8_.data(), input_uint8_.size(), + &conversion_reason)) { + prepare_status = Status(COSMO_NN_ERR_INVALID_INPUT, conversion_reason); + } else { + uint8_contract_input = true; + } + } + } + GetInferencePipelineMetrics().RecordRknnPrepare(ElapsedNanoseconds(prepare_started), scope); + if (!prepare_status) + return finish(prepare_status); + if (uint8_contract_input) { + input.buf = input_uint8_.data(); + input.size = static_cast<uint32_t>(input_uint8_.size()); + input.pass_through = 0; + input.type = RKNN_TENSOR_UINT8; + input.fmt = RKNN_TENSOR_NHWC; + } else if (!native_int8 && !rga_bound_frame) { + if (input_nhwc_.size() > std::numeric_limits<uint32_t>::max() / sizeof(float)) + return finish(Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN input exceeds the runtime size limit")); + input.buf = input_nhwc_.data(); + input.size = static_cast<uint32_t>(input_nhwc_.size() * sizeof(float)); + input.pass_through = 0; + input.type = RKNN_TENSOR_FLOAT32; + // Runtime 2.3.2 silently rejects source NCHW on this model path while + // reporting success. The graph boundary copy above makes NHWC explicit. + input.fmt = RKNN_TENSOR_NHWC; + } + bool use_bound_input = rga_bound_frame; + if (bound_input_memory_ && !native_int8 && !uint8_contract_input && !rga_bound_frame) { + return finish( + Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN bound input cannot accept a non-native tensor")); + } + if (native_int8 && !bound_input_memory_ && bound_input_eligible_ && RknnBoundInputEnabled()) { + std::string bind_reason; + const bool bound = TryBindNativeInputMemory(input_desc, bind_reason); + GetInferencePipelineMetrics().RecordRknnBoundInputBind(bound); + if (bound) { + LOG_INFO("RKNN bound input enabled: bytes={} fd={} width_stride={}", bound_input_memory_->size, + bound_input_memory_->fd, bound_input_attr_.w_stride); + } else { + bound_input_eligible_ = false; + LOG_WARN("RKNN bound input unavailable; retaining rknn_inputs_set path: {}", bind_reason); + } + } + const bool runtime_uint8_contract = + uint8_contract_input || + (native_int8 && bound_input_memory_ && bound_input_mode_ == BoundInputMode::RgaUint8); + if (!rga_bound_frame) + GetInferencePipelineMetrics().RecordRknnInputFormat(native_int8 && !runtime_uint8_contract, + compatibility_fallback, runtime_uint8_contract); + if ((native_int8 || uint8_contract_input) && bound_input_memory_) { + std::string copy_reason; + const auto copy_started = MetricsClock::now(); + const size_t source_bytes = input.size; + bool copied = false; + if (bound_input_mode_ == BoundInputMode::RgaUint8 && native_int8) { + copied = CopyRknnPackedNativeInt8ToUint8( + static_cast<const int8_t*>(input.buf), source_bytes, + static_cast<uint8_t*>(bound_input_memory_->virt_addr), bound_input_memory_->size, + input_height, input_width, 3, static_cast<int>(bound_input_attr_.w_stride), ©_reason); + } else if (bound_input_mode_ == BoundInputMode::RgaUint8 && uint8_contract_input) { + copied = CopyRknnPackedInt8Input(reinterpret_cast<const int8_t*>(input.buf), source_bytes, + static_cast<int8_t*>(bound_input_memory_->virt_addr), + bound_input_memory_->size, input_height, input_width, 3, + static_cast<int>(bound_input_attr_.w_stride), ©_reason); + } else if (native_int8) { + copied = CopyRknnPackedInt8Input(static_cast<const int8_t*>(input.buf), source_bytes, + static_cast<int8_t*>(bound_input_memory_->virt_addr), + bound_input_memory_->size, input_height, input_width, 3, + static_cast<int>(bound_input_attr_.w_stride), ©_reason); + } else { + copy_reason = "RKNN bound input mode does not accept the UINT8 contract tensor"; + } + GetInferencePipelineMetrics().RecordRknnBoundInputCopy(ElapsedNanoseconds(copy_started), + copied ? source_bytes : 0, copied); + if (!copied) + return finish(Status(COSMO_NN_ERR_INVALID_INPUT, copy_reason)); + const auto sync_started = MetricsClock::now(); + const int sync_result = rknn_mem_sync(context_, bound_input_memory_, RKNN_MEMORY_SYNC_TO_DEVICE); + GetInferencePipelineMetrics().RecordRknnBoundInputSync(ElapsedNanoseconds(sync_started), + sync_result == RKNN_SUCC); + if (sync_result != RKNN_SUCC) + return finish(RknnError("rknn_mem_sync", sync_result)); + GetInferencePipelineMetrics().RecordRknnBoundInputFrame(); + use_bound_input = true; + } + if (rga_bound_frame && bound_input_mode_ == BoundInputMode::RgaNativeInt8) { + const auto sync_from_started = MetricsClock::now(); + int sync_result = rknn_mem_sync(context_, bound_input_memory_, RKNN_MEMORY_SYNC_FROM_DEVICE); + GetInferencePipelineMetrics().RecordRknnBoundInputSync(ElapsedNanoseconds(sync_from_started), + sync_result == RKNN_SUCC); + if (sync_result != RKNN_SUCC) + return finish(RknnError("rknn_mem_sync from device", sync_result)); + + std::string requantize_reason; + const auto requantize_started = MetricsClock::now(); + const bool requantized = RequantizeRknnPackedUint8ToInt8InPlace( + static_cast<uint8_t*>(bound_input_memory_->virt_addr), bound_input_memory_->size, input_height, + input_width, 3, static_cast<int>(bound_input_attr_.w_stride), &requantize_reason); + GetInferencePipelineMetrics().RecordRknnRgaBoundInputRequantize( + ElapsedNanoseconds(requantize_started), requantized); + if (!requantized) + return finish(Status(COSMO_NN_ERR_INVALID_INPUT, requantize_reason)); + + const auto sync_to_started = MetricsClock::now(); + sync_result = rknn_mem_sync(context_, bound_input_memory_, RKNN_MEMORY_SYNC_TO_DEVICE); + GetInferencePipelineMetrics().RecordRknnBoundInputSync(ElapsedNanoseconds(sync_to_started), + sync_result == RKNN_SUCC); + if (sync_result != RKNN_SUCC) + return finish(RknnError("rknn_mem_sync to device", sync_result)); + } + if (rga_bound_frame) { + GetInferencePipelineMetrics().RecordRknnRgaBoundInputFrame(bound_input_mode_ == + BoundInputMode::RgaUint8); + } + int result = RKNN_SUCC; + if (!use_bound_input) { + bound_input_eligible_ = false; + const auto inputs_set_started = MetricsClock::now(); + result = rknn_inputs_set(context_, 1, &input); + GetInferencePipelineMetrics().RecordRknnInputsSet(ElapsedNanoseconds(inputs_set_started), scope); + if (result != RKNN_SUCC) + return finish(RknnError("rknn_inputs_set", result)); + } + const auto run_started = MetricsClock::now(); + result = rknn_run(context_, nullptr); + GetInferencePipelineMetrics().RecordRknnRun(ElapsedNanoseconds(run_started), scope); + if (result != RKNN_SUCC) + return finish(RknnError("rknn_run", result)); + + const bool native_yolov8_output = native_yolov8_outputs_ && RknnFastOutputEnabled(); + const bool direct_yolov8_candidates = + native_yolov8_output && RknnDirectCandidatesEnabled() && shared_resource && + shared_resource->yolov8_direct_postprocess.configured && + shared_resource->yolov8_direct_postprocess.input_width == input_width && + shared_resource->yolov8_direct_postprocess.input_height == input_height; + if (shared_resource) + shared_resource->prefer_yolov8_class_major_scan = native_yolov8_output && !direct_yolov8_candidates; + auto& outputs = runtime_outputs_; + std::fill(outputs.begin(), outputs.end(), rknn_output{}); + for (uint32_t index = 0; index < outputs.size(); ++index) { + outputs[index].index = index; + outputs[index].want_float = native_yolov8_output ? 0 : 1; + outputs[index].is_prealloc = 0; + } + OutputGuard output_guard(context_, outputs); + const auto outputs_get_started = MetricsClock::now(); + result = rknn_outputs_get(context_, static_cast<uint32_t>(outputs.size()), outputs.data(), nullptr); + GetInferencePipelineMetrics().RecordRknnOutputsGet(ElapsedNanoseconds(outputs_get_started), scope); + if (result != RKNN_SUCC) + return finish(RknnError("rknn_outputs_get", result)); + output_guard.Activate(); + + uint64_t output_bytes = 0; + for (const auto& output : outputs) + output_bytes += output.size; + GetInferencePipelineMetrics().RecordRknnOutputFormat(native_yolov8_output, output_bytes, + yolov8_heads_ && !native_yolov8_outputs_); + + const auto output_transform_started = MetricsClock::now(); + const auto release_outputs = [&]() { + const auto release_started = MetricsClock::now(); + const int release_result = output_guard.Release(); + GetInferencePipelineMetrics().RecordRknnOutputsRelease(ElapsedNanoseconds(release_started), scope); + return release_result; + }; + const auto finish_output_error = [&](Status status) -> Status { + GetInferencePipelineMetrics().RecordRknnOutputTransform(ElapsedNanoseconds(output_transform_started), + scope); + release_outputs(); + return finish(status); + }; + if (yolov8_heads_) { + auto top_desc = top_blobs[0]->GetBlobDesc(); + const size_t top_count = BlobElementCount(top_desc); + if (!top_blobs[0]->GetHandle().base || top_desc.data_type != DATA_TYPE_FLOAT) + return finish_output_error(Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN YOLOv8 top blob is invalid")); + std::string adapter_error; + if (native_yolov8_output) { + auto& heads = quantized_yolov8_heads_; + heads.clear(); + for (size_t index = 0; index < outputs.size(); ++index) { + if (!outputs[index].buf || outputs[index].size != output_attrs_[index].size) { + return finish_output_error( + Status(COSMO_NN_ERR_NET, "RKNN returned an invalid native YOLOv8 output buffer")); + } + heads.push_back({static_cast<const int8_t*>(outputs[index].buf), outputs[index].size, + TensorShape(output_attrs_[index]), output_attrs_[index].zp, + output_attrs_[index].scale}); + } + if (direct_yolov8_candidates) { + auto& candidate_batch = shared_resource->yolov8_candidate_batch; + const auto& config = shared_resource->yolov8_direct_postprocess; + RknnYolov8CandidateTiming timing; + const bool decoded = DecodeRknnYolov8QuantizedCandidates( + heads, input_height, input_width, config.confidence_threshold, yolov8_candidate_scratch_, + candidate_batch.candidates, adapter_error, &timing); + GetInferencePipelineMetrics().RecordRknnYolov8Transform(timing.dfl_nanoseconds, + timing.class_nanoseconds); + GetInferencePipelineMetrics().RecordRknnYolov8DirectCandidates( + decoded, timing.points_scanned, timing.points_decoded, + decoded ? top_count * sizeof(float) : 0, timing.score_sum_points_rejected); + if (!decoded) + return finish_output_error(Status(COSMO_NN_ERR_NET, adapter_error)); + candidate_batch.ready = true; + } else { + RknnYolov8TransformTiming timing; + const bool reconstructed = ReconstructRknnYolov8Quantized( + heads, input_height, input_width, static_cast<float*>(top_blobs[0]->GetHandle().base), + top_count, adapter_error, &timing); + GetInferencePipelineMetrics().RecordRknnYolov8Transform(timing.dfl_nanoseconds, + timing.class_nanoseconds); + if (!reconstructed) + return finish_output_error(Status(COSMO_NN_ERR_NET, adapter_error)); + } + } else { + auto& heads = float_yolov8_heads_; + heads.clear(); + for (size_t index = 0; index < outputs.size(); ++index) { + if (!outputs[index].buf || outputs[index].size % sizeof(float) != 0) { + return finish_output_error( + Status(COSMO_NN_ERR_NET, "RKNN returned an invalid YOLOv8 output buffer")); + } + heads.push_back({static_cast<const float*>(outputs[index].buf), + outputs[index].size / sizeof(float), TensorShape(output_attrs_[index])}); + } + if (!ReconstructRknnYolov8(heads, input_height, input_width, + static_cast<float*>(top_blobs[0]->GetHandle().base), top_count, + adapter_error)) { + return finish_output_error(Status(COSMO_NN_ERR_NET, adapter_error)); + } + } + } else { + for (size_t index = 0; index < outputs.size(); ++index) { + auto desc = top_blobs[index]->GetBlobDesc(); + const size_t count = BlobElementCount(desc); + if (!top_blobs[index]->GetHandle().base || desc.data_type != DATA_TYPE_FLOAT || + !outputs[index].buf || outputs[index].size != count * sizeof(float)) { + return finish_output_error( + Status(COSMO_NN_ERR_NET, "RKNN output size does not match the graph blob")); + } + std::memcpy(top_blobs[index]->GetHandle().base, outputs[index].buf, outputs[index].size); + } + } + GetInferencePipelineMetrics().RecordRknnOutputTransform(ElapsedNanoseconds(output_transform_started), + scope); + result = release_outputs(); + if (result != RKNN_SUCC) + return finish(RknnError("rknn_outputs_release", result)); + return finish(COSMO_NN_OK); +} + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/src/nn/device/rknn/rknn_net_node.h b/src/nn/device/rknn/rknn_net_node.h new file mode 100644 index 000000000..d71bfa80e --- /dev/null +++ b/src/nn/device/rknn/rknn_net_node.h @@ -0,0 +1,119 @@ +#pragma once + +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include <cstdint> +#include <mutex> +#include <string> +#include <vector> + +#include "nn/device/rknn/rknn_yolov8_adapter.h" +#include "nn/node/net_node.h" +#include "rknn_api.h" + +namespace cosmo::nn { + +inline constexpr char kRknnRgbUint8InputContract[] = "cosmo.rknn.input.rgb_u8_nhwc_0_255_to_0_1.v1"; + +bool IsRknnRgbUint8InputContract(const std::string& contract); +bool IsRknnNativeInt8InputCompatible(const rknn_tensor_attr& attr, const BlobDesc& desc); +bool IsRknnNativeYolov8OutputCompatible(const std::vector<rknn_tensor_attr>& attrs, + std::string* reason = nullptr); +bool IsRknnBoundInt8InputCompatible(const rknn_tensor_attr& attr, const BlobDesc& desc, + std::string* reason = nullptr); +bool IsRknnRgaBoundInputCompatible(const rknn_tensor_attr& attr, int height, int width, + std::string* reason = nullptr); +bool ConfigureRknnRgaUint8InputAttr(const rknn_tensor_attr& native_attr, int height, int width, + rknn_tensor_attr& bound_attr, std::string* reason = nullptr); +bool CopyRknnPackedInt8Input(const int8_t* source, size_t source_bytes, int8_t* destination, + size_t destination_bytes, int height, int width, int channels, int width_stride, + std::string* reason = nullptr); +bool CopyRknnPackedNativeInt8ToUint8(const int8_t* source, size_t source_bytes, uint8_t* destination, + size_t destination_bytes, int height, int width, int channels, + int width_stride, std::string* reason = nullptr); +bool ConvertRknnNormalizedFloatToUint8(const float* source, size_t source_count, uint8_t* destination, + size_t destination_count, std::string* reason = nullptr); +bool RequantizeRknnPackedUint8ToInt8InPlace(uint8_t* data, size_t data_bytes, int height, int width, + int channels, int width_stride, std::string* reason = nullptr); +bool RknnFastOutputEnabled(); +bool RknnDirectCandidatesEnabled(); +bool RknnBoundInputEnabled(); +bool RknnRgaBoundInputEnabled(); + +enum class RknnCoreMode : uint8_t { + Auto = 0, + Core0, + Core1, + Core01, + Split, +}; + +RknnCoreMode ParseRknnCoreMode(const std::string& value, bool* valid = nullptr); +rknn_core_mask ResolveRknnCoreMask(RknnCoreMode mode, uint64_t context_sequence); +const char* RknnCoreModeName(RknnCoreMode mode); + +class RknnNetNode final : public NetNode, public RknnBoundInputProvider { +public: + RknnNetNode(); + ~RknnNetNode() override; + + RknnNetNode(const RknnNetNode&) = delete; + RknnNetNode& operator=(const RknnNetNode&) = delete; + + DeviceType GetTopBlobDeviceType() override; + Status InferTopShapes() override; + Status LoadWeight(const char* data, size_t size) override; + Status Forward(std::vector<std::shared_ptr<Blob>>& bottom_blobs, + std::vector<std::shared_ptr<Blob>>& top_blobs) override; + bool EnsureRgaBoundInput(int height, int width, std::string& reason) override; + +private: + enum class BoundInputMode : uint8_t { + None = 0, + NativeInt8, + RgaUint8, + RgaNativeInt8, + }; + + Status QueryTensorAttributes(); + Status PrepareInput(const Blob& blob, std::vector<float>& nhwc, int& height, int& width) const; + Status PrepareNativeCompatibilityInput(const Blob& blob, std::vector<float>& nhwc, int& height, + int& width) const; + std::vector<int> TensorShape(const rknn_tensor_attr& attr) const; + size_t TensorElementCount(const rknn_tensor_attr& attr) const; + bool TryBindNativeInputMemory(const BlobDesc& desc, std::string& reason); + bool TryBindRgaInputMemory(int height, int width, std::string& reason); + bool AllocateAndBindInputMemory(rknn_tensor_attr attr, BoundInputMode mode, std::string& reason); + void PublishRgaBoundInputTarget(); + void ClearRgaBoundInputTarget(); + void DestroyContext(); + + rknn_context context_{0}; + rknn_input_output_num io_count_{}; + std::vector<rknn_tensor_attr> input_attrs_; + std::vector<rknn_tensor_attr> output_attrs_; + std::vector<rknn_output> runtime_outputs_; + std::vector<RknnYolov8Head> float_yolov8_heads_; + std::vector<RknnYolov8QuantizedHead> quantized_yolov8_heads_; + RknnYolov8CandidateScratch yolov8_candidate_scratch_; + RknnOutputAdapterContract output_adapter_contract_; + rknn_tensor_attr bound_input_attr_{}; + rknn_tensor_mem* bound_input_memory_{nullptr}; + std::vector<unsigned char> model_data_; + std::vector<float> input_nhwc_; + std::vector<uint8_t> input_uint8_; + bool yolov8_heads_{false}; + bool native_yolov8_outputs_{false}; + bool detector_model_{false}; + bool bound_input_eligible_{true}; + bool rga_bound_input_eligible_{true}; + BoundInputMode bound_input_mode_{BoundInputMode::None}; + uint64_t bound_input_generation_{0}; + int yolov8_class_count_{0}; + int yolov8_point_count_{0}; + mutable std::mutex mutex_; +}; + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/src/nn/device/rknn/rknn_node_creator.cc b/src/nn/device/rknn/rknn_node_creator.cc new file mode 100644 index 000000000..09d72d096 --- /dev/null +++ b/src/nn/device/rknn/rknn_node_creator.cc @@ -0,0 +1,33 @@ +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include "nn/device/rknn/rknn_node_creator.h" + +#include "nn/device/host/host_node_factory.h" +#include "nn/device/rknn/rknn_net_node.h" +#if defined(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) +#include "nn/device/rknn/rknn_preprocess_node.h" +#endif + +namespace cosmo::nn { + +RknnNodeCreator::RknnNodeCreator(DeviceType device_type) : NodeCreator(device_type) {} + +std::unique_ptr<Node> RknnNodeCreator::CreateNode(NodeType type) { + if (type == NODE_NET) + return std::make_unique<RknnNetNode>(); +#if defined(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + if (RknnFastPreprocessEnabled()) { + if (type == NODE_RESIZE) + return std::make_unique<RknnResizeNode>(); + if (type == NODE_NORMALIZE) + return std::make_unique<RknnNormalizeNode>(); + } +#endif + return CreateHostNode(type); +} + +NodeCreatorRegister<RknnNodeCreator> g_rknn_node_creator_register(DEVICE_RKNN); + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/src/nn/device/rknn/rknn_node_creator.h b/src/nn/device/rknn/rknn_node_creator.h new file mode 100644 index 000000000..db9adf2f5 --- /dev/null +++ b/src/nn/device/rknn/rknn_node_creator.h @@ -0,0 +1,17 @@ +#pragma once + +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include "nn/node/node_creator.h" + +namespace cosmo::nn { + +class RknnNodeCreator final : public NodeCreator { +public: + explicit RknnNodeCreator(DeviceType device_type); + std::unique_ptr<Node> CreateNode(NodeType type) override; +}; + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/src/nn/device/rknn/rknn_preprocess_node.cc b/src/nn/device/rknn/rknn_preprocess_node.cc new file mode 100644 index 000000000..8e19f1011 --- /dev/null +++ b/src/nn/device/rknn/rknn_preprocess_node.cc @@ -0,0 +1,704 @@ +#if defined(COSMO_NN_USE_RKNN_BACKEND) && defined(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + +#include "nn/device/rknn/rknn_preprocess_node.h" + +#include <rga/im2d.h> + +#include <algorithm> +#include <array> +#include <atomic> +#include <cctype> +#include <chrono> +#include <cmath> +#include <cstdlib> +#include <cstring> +#include <limits> +#include <new> +#include <string> + +#include "nn/core/inference_pipeline_metrics.h" +#include "nn/device/rknn/rknn_net_node.h" +#include "nn/node/node_type_utils.h" +#include "nn/utils/op.h" +#include "util/Log.h" + +namespace cosmo::nn { +namespace { + + using MetricsClock = std::chrono::steady_clock; + + constexpr int kDetectorInputSize = 640; + constexpr float kNormalizeScale = 0.00392157f; + + uint64_t ElapsedNanoseconds(MetricsClock::time_point started_at) { + return static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::nanoseconds>(MetricsClock::now() - started_at).count()); + } + + bool EnvironmentFlag(const char* name, bool default_value) { + const char* raw = std::getenv(name); + if (!raw || *raw == '\0') + return default_value; + std::string value(raw); + std::transform(value.begin(), value.end(), value.begin(), + [](unsigned char c) { return static_cast<char>(std::tolower(c)); }); + if (value == "0" || value == "false" || value == "off" || value == "no") + return false; + if (value == "1" || value == "true" || value == "on" || value == "yes") + return true; + return default_value; + } + + bool RgaSucceeded(IM_STATUS status) { + return status == IM_STATUS_SUCCESS || status == IM_STATUS_NOERROR; + } + + class ScopedRgaHandle { + public: + ScopedRgaHandle() = default; + + ScopedRgaHandle(void* data, size_t size) { + ImportVirtual(data, size); + } + + ~ScopedRgaHandle() { + if (handle_ != 0) + releasebuffer_handle(handle_); + } + + [[nodiscard]] rga_buffer_handle_t Get() const { + return handle_; + } + + void ImportVirtual(void* data, size_t size) { + if (handle_ != 0 || !data || size == 0 || + size > static_cast<size_t>(std::numeric_limits<int>::max())) { + return; + } + handle_ = importbuffer_virtualaddr(data, static_cast<int>(size)); + } + + void ImportFd(int fd, size_t size) { + if (handle_ != 0 || fd < 0 || size == 0 || + size > static_cast<size_t>(std::numeric_limits<int>::max())) { + return; + } + handle_ = importbuffer_fd(fd, static_cast<int>(size)); + } + + private: + rga_buffer_handle_t handle_{0}; + }; + + void LogRgaFallbackOnce(IM_STATUS status) { + static std::atomic_flag logged = ATOMIC_FLAG_INIT; + if (!logged.test_and_set(std::memory_order_relaxed)) { + LOG_WARN("RKNN detector RGA preprocessing failed with status {} ({}); using CPU fallback", status, + imStrError_t(status)); + } + } + + void LogRgaBoundInputFallbackOnce(const std::string& reason) { + static std::atomic_flag logged = ATOMIC_FLAG_INIT; + if (!logged.test_and_set(std::memory_order_relaxed)) { + LOG_WARN("RKNN RGA bound input unavailable; retaining the host preprocessing path: {}", reason); + } + } + + void LogMppDmaBufFallbackOnce(IM_STATUS status) { + static std::atomic_flag logged = ATOMIC_FLAG_INIT; + if (!logged.test_and_set(std::memory_order_relaxed)) { + LOG_WARN("RKNN MPP DMA-BUF preprocessing failed with status {} ({}); using host RGA input", + status, imStrError_t(status)); + } + } + + void BilinearResizePacked(const uint8_t* source, int source_width, int source_height, int channels, + uint8_t* destination, int destination_width, int destination_height, + bool swap_red_blue) { + const float x_ratio = static_cast<float>(source_width) / destination_width; + const float y_ratio = static_cast<float>(source_height) / destination_height; + for (int destination_y = 0; destination_y < destination_height; ++destination_y) { + const float source_y = (destination_y + 0.5f) * y_ratio - 0.5f; + int y0 = static_cast<int>(source_y); + const float y_part = source_y - y0; + y0 = std::max(0, std::min(y0, source_height - 1)); + const int y1 = std::min(y0 + 1, source_height - 1); + for (int destination_x = 0; destination_x < destination_width; ++destination_x) { + const float source_x = (destination_x + 0.5f) * x_ratio - 0.5f; + int x0 = static_cast<int>(source_x); + const float x_part = source_x - x0; + x0 = std::max(0, std::min(x0, source_width - 1)); + const int x1 = std::min(x0 + 1, source_width - 1); + for (int channel = 0; channel < channels; ++channel) { + const int source_channel = swap_red_blue && channel != 1 ? 2 - channel : channel; + const float v00 = source[(y0 * source_width + x0) * channels + source_channel]; + const float v01 = source[(y0 * source_width + x1) * channels + source_channel]; + const float v10 = source[(y1 * source_width + x0) * channels + source_channel]; + const float v11 = source[(y1 * source_width + x1) * channels + source_channel]; + const float value = v00 * (1 - x_part) * (1 - y_part) + v01 * x_part * (1 - y_part) + + v10 * (1 - x_part) * y_part + v11 * x_part * y_part; + destination[(destination_y * destination_width + destination_x) * channels + channel] = + static_cast<uint8_t>(std::min(255.0f, std::max(0.0f, value + 0.5f))); + } + } + } + } + + size_t PackedByteCount(int width, int height) { + if (width <= 0 || height <= 0) + return 0; + const auto pixels = static_cast<size_t>(width) * static_cast<size_t>(height); + if (pixels > std::numeric_limits<size_t>::max() / 3) + return 0; + return pixels * 3; + } + +} // namespace + +bool RknnFastPreprocessEnabled() { + return EnvironmentFlag("COSMO_RKNN_FAST_PREPROCESS", true); +} + +bool RknnForceRgaFailure() { + return EnvironmentFlag("COSMO_RKNN_RGA_FORCE_FAIL", false); +} + +bool RknnMppDmaBufEnabled() { + return EnvironmentFlag("COSMO_RKNN_MPP_DMABUF", true); +} + +bool RknnForceMppDmaBufFailure() { + return EnvironmentFlag("COSMO_RKNN_MPP_DMABUF_FORCE_FAIL", false); +} + +bool IsRknnDetectorResizeContract(int out_height, int out_width, int gravity, + const std::vector<int>& padding_color) { + return out_height == kDetectorInputSize && out_width == kDetectorInputSize && gravity == 1 && + padding_color.size() >= 3 && padding_color[0] == 114 && padding_color[1] == 114 && + padding_color[2] == 114; +} + +bool IsRknnNativeNormalizeContract(const std::vector<float>& mean, const std::vector<float>& std_dev, + float scale, const DimsVector& input_dims) { + if (input_dims.size() != 4 || input_dims[0] <= 0 || input_dims[1] != kDetectorInputSize || + input_dims[2] != kDetectorInputSize || input_dims[3] != 3 || mean.size() < 3 || !std_dev.empty() || + std::fabs(scale - kNormalizeScale) > 1e-8f) { + return false; + } + return std::all_of(mean.begin(), mean.begin() + 3, [](float value) { return std::fabs(value) <= 1e-8f; }); +} + +void MapPackedU8ToNativeInt8(const uint8_t* source, int8_t* destination, size_t pixels, bool swap_red_blue) { + if (!source || !destination) + return; + for (size_t pixel = 0; pixel < pixels; ++pixel) { + const auto source_offset = pixel * 3; + const auto destination_offset = pixel * 3; + for (size_t channel = 0; channel < 3; ++channel) { + const size_t source_channel = swap_red_blue && channel != 1 ? 2 - channel : channel; + destination[destination_offset + channel] = + static_cast<int8_t>(static_cast<int>(source[source_offset + source_channel]) - 128); + } + } +} + +RknnResizeNode::RknnResizeNode() : Node() { + node_type = NodeType::NODE_RESIZE; + name = NodeTypeUtils::NodeTypeToStr(NODE_RESIZE).append("_0"); + one_blob_only = true; +} + +RknnResizeNode::~RknnResizeNode() { + ReleaseRgaBoundTarget(); +} + +void RknnResizeNode::LoadParam(Op* op) { + const auto* resize = dynamic_cast<Resize*>(op); + if (!resize) + return; + if (resize->dsize.size() >= 2) { + out_height_ = resize->dsize[0]; + out_width_ = resize->dsize[1]; + } + gravity_ = resize->gravity; + padding_color_ = resize->color; + detector_contract_ = IsRknnDetectorResizeContract(out_height_, out_width_, gravity_, padding_color_); +} + +DeviceType RknnResizeNode::GetTopBlobDeviceType() { + return DeviceType::DEVICE_NAIVE; +} + +Status RknnResizeNode::InferTopShapes() { + if (out_height_ <= 0 || out_width_ <= 0) + return Status(COSMO_NN_ERR_INVALID_CFG, "RKNN resize output dimensions must be positive"); + shared_resource->net_input_w = out_width_; + shared_resource->net_input_h = out_height_; + top_blob_shapes = {{1, out_height_, out_width_, 3}}; + top_blob_data_types = {DataType::DATA_TYPE_UINT8}; + return COSMO_NN_OK; +} + +size_t RknnResizeNode::GetBottomCount() { + return 1; +} + +size_t RknnResizeNode::GetTopCount() { + return 1; +} + +void RknnResizeNode::ReleaseRgaBoundTarget() { + if (rga_bound_target_handle_ != 0) { + releasebuffer_handle(static_cast<rga_buffer_handle_t>(rga_bound_target_handle_)); + rga_bound_target_handle_ = 0; + rga_bound_target_generation_ = 0; + } +} + +bool RknnResizeNode::AcquireRgaBoundTarget(uint32_t& handle) { + handle = 0; + if (!detector_contract_ || rga_bound_target_unavailable_ || !RknnRgaBoundInputEnabled() || + !shared_resource || !shared_resource->rknn_bound_input_provider) { + return false; + } + std::string reason; + auto* provider = shared_resource->rknn_bound_input_provider; + if (!provider->EnsureRgaBoundInput(out_height_, out_width_, reason)) { + rga_bound_target_unavailable_ = true; + LogRgaBoundInputFallbackOnce(reason); + return false; + } + const auto& target = shared_resource->rknn_bound_input_target; + if (target.owner != provider || !target.Matches(out_height_, out_width_) || + target.bytes > static_cast<size_t>(std::numeric_limits<int>::max())) { + rga_bound_target_unavailable_ = true; + LogRgaBoundInputFallbackOnce("provider returned an incompatible target"); + return false; + } + if (rga_bound_target_handle_ != 0 && rga_bound_target_generation_ == target.generation) { + handle = rga_bound_target_handle_; + return true; + } + ReleaseRgaBoundTarget(); + const auto import_started = MetricsClock::now(); + const auto imported = importbuffer_fd(target.fd, static_cast<int>(target.bytes)); + GetInferencePipelineMetrics().RecordRknnRgaBoundInputImport(ElapsedNanoseconds(import_started), + imported != 0); + if (imported == 0) { + rga_bound_target_unavailable_ = true; + GetInferencePipelineMetrics().RecordRknnRgaFailure(); + LogRgaBoundInputFallbackOnce("RGA could not import the RKNN DMA-BUF fd"); + return false; + } + rga_bound_target_handle_ = static_cast<uint32_t>(imported); + rga_bound_target_generation_ = target.generation; + handle = rga_bound_target_handle_; + return true; +} + +bool RknnResizeNode::ResizeWithRga(const Blob& bottom, Blob& top, bool allow_bound_target) { + if (!detector_contract_ || RknnForceRgaFailure()) { + if (detector_contract_ && RknnForceRgaFailure()) + GetInferencePipelineMetrics().RecordRknnRgaFailure(); + return false; + } + + auto& mutable_bottom = const_cast<Blob&>(bottom); + auto bottom_desc = mutable_bottom.GetBlobDesc(); + auto bottom_handle = mutable_bottom.GetHandle(); + auto top_handle = top.GetHandle(); + if (!bottom_handle.base || !top_handle.base || bottom_desc.dims.size() != 4 || bottom_desc.dims[0] != 1 || + bottom_desc.dims[3] != 3 || + (bottom_desc.image_format != IMAGE_BGR && bottom_desc.image_format != IMAGE_RGB)) { + GetInferencePipelineMetrics().RecordRknnRgaFailure(); + return false; + } + + const int source_height = bottom_desc.dims[1]; + const int source_width = bottom_desc.dims[2]; + const auto source_size = PackedByteCount(source_width, source_height); + const auto target_size = PackedByteCount(out_width_, out_height_); + ScopedRgaHandle host_target_handle; + uint32_t target_handle = 0; + const bool bound_target = allow_bound_target && AcquireRgaBoundTarget(target_handle); + if (!bound_target) { + host_target_handle.ImportVirtual(top_handle.base, target_size); + target_handle = host_target_handle.Get(); + } + if (target_handle == 0) { + GetInferencePipelineMetrics().RecordRknnRgaFailure(); + LogRgaFallbackOnce(IM_STATUS_OUT_OF_MEMORY); + return false; + } + + int target_width_stride = out_width_; + if (bound_target) + target_width_stride = shared_resource->rknn_bound_input_target.width_stride; + auto target = wrapbuffer_handle_t(static_cast<rga_buffer_handle_t>(target_handle), out_width_, + out_height_, target_width_stride, out_height_, RK_FORMAT_RGB_888); + + IM_STATUS last_status = IM_STATUS_FAILED; + const auto run_resize = [&](rga_buffer_handle_t source_handle, int visible_width, int visible_height, + int width_stride, int height_stride, int source_format, bool yuv_source) { + auto source = wrapbuffer_handle_t(source_handle, visible_width, visible_height, width_stride, + height_stride, source_format); + if (yuv_source) + source.color_space_mode = IM_YUV_TO_RGB_BT601_LIMIT; + + const auto fill_started = MetricsClock::now(); + const im_rect full_target{0, 0, out_width_, out_height_}; + const int fill_color = (padding_color_[0] << 16) | (padding_color_[1] << 8) | padding_color_[2]; + last_status = imfill_t(target, full_target, fill_color, 1); + GetInferencePipelineMetrics().RecordRknnRgaFill(ElapsedNanoseconds(fill_started)); + if (!RgaSucceeded(last_status)) + return false; + + const float scale = std::min(static_cast<float>(out_width_) / visible_width, + static_cast<float>(out_height_) / visible_height); + const int resized_width = static_cast<int>(visible_width * scale); + const int resized_height = static_cast<int>(visible_height * scale); + const int offset_x = (out_width_ - resized_width) / 2; + const int offset_y = (out_height_ - resized_height) / 2; + const im_rect source_rect{0, 0, visible_width, visible_height}; + const im_rect target_rect{offset_x, offset_y, resized_width, resized_height}; + const im_rect empty_rect{}; + const rga_buffer_t empty_buffer{}; + const auto resize_started = MetricsClock::now(); + last_status = improcess(source, target, empty_buffer, source_rect, target_rect, empty_rect, IM_SYNC); + GetInferencePipelineMetrics().RecordRknnRgaResizeColor(ElapsedNanoseconds(resize_started)); + return RgaSucceeded(last_status); + }; + + const auto& native = bottom_handle.native_image; + const bool native_compatible = RknnMppDmaBufEnabled() && native.Valid() && native.width == source_width && + native.height == source_height && + (native.format == IMAGE_NV12 || native.format == IMAGE_I420); + if (native_compatible) { + bool native_success = false; + ScopedRgaHandle native_source_handle; + if (!RknnForceMppDmaBufFailure()) { + const auto import_started = MetricsClock::now(); + native_source_handle.ImportFd(native.fd, native.bytes); + GetInferencePipelineMetrics().RecordRknnMppDmaBufImport(ElapsedNanoseconds(import_started), + native_source_handle.Get() != 0); + if (native_source_handle.Get() != 0) { + const int native_format = + native.format == IMAGE_NV12 ? RK_FORMAT_YCbCr_420_SP : RK_FORMAT_YCbCr_420_P; + native_success = run_resize(native_source_handle.Get(), native.width, native.height, + native.width_stride, native.height_stride, native_format, true); + } + } + if (native_success) { + GetInferencePipelineMetrics().RecordRknnMppDmaBufFrame(native.bytes); + } else { + GetInferencePipelineMetrics().RecordRknnMppDmaBufFallback(); + LogMppDmaBufFallbackOnce(last_status); + } + if (native_success) { + if (bound_target) { + auto& bound_input = shared_resource->rknn_bound_input_target; + if (bound_input.owner == shared_resource->rknn_bound_input_provider && + bound_input.generation == rga_bound_target_generation_) { + bound_input.frame_ready = true; + } + } + return true; + } + } + + ScopedRgaHandle host_source_handle(bottom_handle.base, source_size); + const int host_source_format = + bottom_desc.image_format == IMAGE_RGB ? RK_FORMAT_RGB_888 : RK_FORMAT_BGR_888; + if (host_source_handle.Get() == 0 || + !run_resize(host_source_handle.Get(), source_width, source_height, source_width, source_height, + host_source_format, false)) { + GetInferencePipelineMetrics().RecordRknnRgaFailure(); + LogRgaFallbackOnce(host_source_handle.Get() == 0 ? IM_STATUS_OUT_OF_MEMORY : last_status); + return false; + } + if (bound_target) { + auto& bound_input = shared_resource->rknn_bound_input_target; + if (bound_input.owner == shared_resource->rknn_bound_input_provider && + bound_input.generation == rga_bound_target_generation_) { + bound_input.frame_ready = true; + } + } + return true; +} + +void RknnResizeNode::ResizeWithCpu(const Blob& bottom, Blob& top, bool output_rgb) const { + auto& mutable_bottom = const_cast<Blob&>(bottom); + auto bottom_desc = mutable_bottom.GetBlobDesc(); + const int source_height = bottom_desc.dims[1]; + const int source_width = bottom_desc.dims[2]; + const int channels = bottom_desc.dims[3]; + const auto* source = static_cast<const uint8_t*>(mutable_bottom.GetHandle().base); + auto* destination = static_cast<uint8_t*>(top.GetHandle().base); + const bool swap_red_blue = output_rgb && bottom_desc.image_format != IMAGE_RGB; + + if (gravity_ == 0) { + BilinearResizePacked(source, source_width, source_height, channels, destination, out_width_, + out_height_, swap_red_blue); + return; + } + + const float scale = std::min(static_cast<float>(out_width_) / source_width, + static_cast<float>(out_height_) / source_height); + const int resized_width = static_cast<int>(source_width * scale); + const int resized_height = static_cast<int>(source_height * scale); + const uint8_t padding = static_cast<uint8_t>(padding_color_.empty() ? 114 : padding_color_[0]); + std::memset(destination, padding, PackedByteCount(out_width_, out_height_)); + std::vector<uint8_t> resized(PackedByteCount(resized_width, resized_height)); + BilinearResizePacked(source, source_width, source_height, channels, resized.data(), resized_width, + resized_height, swap_red_blue); + int offset_x = 0; + int offset_y = 0; + if (gravity_ == 1) { + offset_x = (out_width_ - resized_width) / 2; + offset_y = (out_height_ - resized_height) / 2; + } + for (int row = 0; row < resized_height; ++row) { + std::memcpy(destination + ((offset_y + row) * out_width_ + offset_x) * channels, + resized.data() + row * resized_width * channels, + static_cast<size_t>(resized_width) * channels); + } +} + +Status RknnResizeNode::ResizeSingle(const std::shared_ptr<Blob>& bottom, const std::shared_ptr<Blob>& top, + bool allow_bound_target) { + if (!bottom || !top || !bottom->GetHandle().base || !top->GetHandle().base) + return Status(COSMO_NN_ERR_NULL_PARAM, "RKNN resize input or output is null"); + const auto bottom_desc = bottom->GetBlobDesc(); + if (bottom_desc.data_type != DATA_TYPE_UINT8 || bottom_desc.data_format != DATA_FORMAT_NHWC || + bottom_desc.dims.size() != 4 || bottom_desc.dims[0] != 1 || bottom_desc.dims[1] <= 0 || + bottom_desc.dims[2] <= 0 || bottom_desc.dims[3] != 3) { + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN detector resize requires packed batch-1 uint8 input"); + } + + bool rga_success = false; + if (detector_contract_) + rga_success = ResizeWithRga(*bottom, *top, allow_bound_target); + if (!rga_success) { + const auto cpu_started = MetricsClock::now(); + try { + ResizeWithCpu(*bottom, *top, detector_contract_); + } catch (const std::bad_alloc&) { + return Status(COSMO_NN_ERR_OUT_OF_MEMORY, "RKNN CPU resize fallback allocation failed"); + } + if (detector_contract_) + GetInferencePipelineMetrics().RecordRknnCpuResizeFallback(ElapsedNanoseconds(cpu_started)); + } + + auto top_desc = top->GetBlobDesc(); + top_desc.data_format = DATA_FORMAT_NHWC; + top_desc.image_format = detector_contract_ ? IMAGE_RGB : bottom_desc.image_format; + top->SetBlobDesc(top_desc); + return COSMO_NN_OK; +} + +Status RknnResizeNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blobs, + std::vector<std::shared_ptr<Blob>>& top_blobs) { + timer.Start(); + if (top_blobs.size() != 1 || !top_blobs[0]) + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN resize requires exactly one output"); + const int batch = static_cast<int>(bottom_blobs.size()); + if (batch <= 0 || batch > max_batch) + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN resize batch size is invalid"); + + auto top_desc = top_blobs[0]->GetBlobDesc(); + top_desc.dims[0] = batch; + top_blobs[0]->SetBlobDesc(top_desc); + const size_t slice_size = PackedByteCount(out_width_, out_height_); + if (shared_resource && + shared_resource->rknn_bound_input_target.owner == shared_resource->rknn_bound_input_provider) { + shared_resource->rknn_bound_input_target.frame_ready = false; + } + for (int index = 0; index < batch; ++index) { + BlobDesc slice_desc = top_desc; + slice_desc.dims[0] = 1; + BlobHandle slice_handle; + slice_handle.base = + static_cast<uint8_t*>(top_blobs[0]->GetHandle().base) + static_cast<size_t>(index) * slice_size; + auto slice = std::make_shared<Blob>(slice_desc, slice_handle); + RETURN_ON_FAIL(ResizeSingle(bottom_blobs[index], slice, batch == 1)); + top_desc.image_format = slice->GetBlobDesc().image_format; + top_desc.data_format = slice->GetBlobDesc().data_format; + } + top_blobs[0]->SetBlobDesc(top_desc); + timer.Stop(); + return COSMO_NN_OK; +} + +RknnNormalizeNode::RknnNormalizeNode() : Node() { + node_type = NodeType::NODE_NORMALIZE; + name = NodeTypeUtils::NodeTypeToStr(NODE_NORMALIZE).append("_0"); + one_blob_only = true; +} + +void RknnNormalizeNode::LoadParam(Op* op) { + const auto* normalize = dynamic_cast<Normalize*>(op); + if (!normalize) + return; + mean_ = normalize->mean; + std_dev_ = normalize->std; + uniform_scale_ = normalize->scale; + is_bgr_ = normalize->is_bgr; + if (std_dev_.empty()) { + scale_.assign(mean_.size(), uniform_scale_); + } else { + scale_.resize(std_dev_.size()); + std::transform(std_dev_.begin(), std_dev_.end(), scale_.begin(), + [](float value) { return 1.0f / value; }); + } +} + +DeviceType RknnNormalizeNode::GetTopBlobDeviceType() { + return DeviceType::DEVICE_NAIVE; +} + +bool RknnNormalizeNode::NeedBottomShapesInfered() { + return true; +} + +Status RknnNormalizeNode::InferTopShapesWithBottoms(std::vector<DimsVector> dims, + std::vector<DataType> types) { + if (dims.size() != 1 || types.size() != 1 || dims[0].size() != 4) + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN normalize input shape is invalid"); + detector_sized_ = dims[0][1] == kDetectorInputSize && dims[0][2] == kDetectorInputSize && dims[0][3] == 3; + native_contract_ = types[0] == DATA_TYPE_UINT8 && + IsRknnNativeNormalizeContract(mean_, std_dev_, uniform_scale_, dims[0]); + if (native_contract_) { + top_blob_shapes = {dims[0]}; + top_blob_data_types = {DataType::DATA_TYPE_INT8}; + } else { + top_blob_shapes = {{dims[0][0], dims[0][3], dims[0][1], dims[0][2]}}; + top_blob_data_types = {DataType::DATA_TYPE_FLOAT}; + } + return COSMO_NN_OK; +} + +size_t RknnNormalizeNode::GetBottomCount() { + return 1; +} + +size_t RknnNormalizeNode::GetTopCount() { + return 1; +} + +bool RknnNormalizeNode::NeedSwapRedBlue(ImageFormat format) const { + if (format == IMAGE_BGR || format == IMAGE_BGRA) + return !is_bgr_; + if (format == IMAGE_RGB || format == IMAGE_RGBA) + return is_bgr_; + return false; +} + +bool RknnNormalizeNode::CanBypassBoundInput(const Blob& bottom) const { + if (!native_contract_ || !shared_resource || !shared_resource->rknn_bound_input_provider) { + return false; + } + const auto& target = shared_resource->rknn_bound_input_target; + const auto desc = const_cast<Blob&>(bottom).GetBlobDesc(); + return target.frame_ready && target.owner == shared_resource->rknn_bound_input_provider && + desc.data_type == DATA_TYPE_UINT8 && desc.data_format == DATA_FORMAT_NHWC && + desc.image_format == IMAGE_RGB && desc.dims.size() == 4 && desc.dims[0] == 1 && + target.Matches(desc.dims[1], desc.dims[2]) && !NeedSwapRedBlue(desc.image_format); +} + +Status RknnNormalizeNode::ForwardNative(const Blob& bottom, Blob& top) { + auto& mutable_bottom = const_cast<Blob&>(bottom); + const auto bottom_desc = mutable_bottom.GetBlobDesc(); + auto top_desc = top.GetBlobDesc(); + if (bottom_desc.data_type != DATA_TYPE_UINT8 || bottom_desc.data_format != DATA_FORMAT_NHWC || + top_desc.data_type != DATA_TYPE_INT8 || top_desc.data_format != DATA_FORMAT_NHWC) { + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN native preprocessing blob contract mismatch"); + } + const size_t pixels = + static_cast<size_t>(bottom_desc.dims[0]) * bottom_desc.dims[1] * bottom_desc.dims[2]; + const auto started = MetricsClock::now(); + MapPackedU8ToNativeInt8(static_cast<const uint8_t*>(mutable_bottom.GetHandle().base), + static_cast<int8_t*>(top.GetHandle().base), pixels, + NeedSwapRedBlue(bottom_desc.image_format)); + GetInferencePipelineMetrics().RecordRknnNativeInputMap(ElapsedNanoseconds(started)); + GetInferencePipelineMetrics().RecordRknnPreprocessFastHit(); + top_desc.image_format = is_bgr_ ? IMAGE_BGR : IMAGE_RGB; + top.SetBlobDesc(top_desc); + return COSMO_NN_OK; +} + +Status RknnNormalizeNode::ForwardFloat(const Blob& bottom, Blob& top) { + auto& mutable_bottom = const_cast<Blob&>(bottom); + const auto bottom_desc = mutable_bottom.GetBlobDesc(); + const auto top_desc = top.GetBlobDesc(); + if (bottom_desc.data_type != DATA_TYPE_UINT8 || top_desc.data_type != DATA_TYPE_FLOAT || + top_desc.data_format != DATA_FORMAT_NCHW || mean_.size() < 3 || scale_.size() < 3) { + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN float normalize blob contract mismatch"); + } + const int batch = bottom_desc.dims[0]; + const int height = bottom_desc.dims[1]; + const int width = bottom_desc.dims[2]; + const int channels = bottom_desc.dims[3]; + const int plane = height * width; + const bool swap_red_blue = NeedSwapRedBlue(bottom_desc.image_format); + const auto* source = static_cast<const uint8_t*>(mutable_bottom.GetHandle().base); + auto* destination = static_cast<float*>(top.GetHandle().base); + for (int batch_index = 0; batch_index < batch; ++batch_index) { + const auto* batch_source = source + batch_index * plane * channels; + auto* batch_destination = destination + batch_index * plane * 3; + for (int pixel = 0; pixel < plane; ++pixel) { + const int source_offset = pixel * channels; + const int first_channel = swap_red_blue ? 2 : 0; + const int third_channel = swap_red_blue ? 0 : 2; + batch_destination[pixel] = + (static_cast<float>(batch_source[source_offset + first_channel]) - mean_[0]) * scale_[0]; + batch_destination[plane + pixel] = + (static_cast<float>(batch_source[source_offset + 1]) - mean_[1]) * scale_[1]; + batch_destination[2 * plane + pixel] = + (static_cast<float>(batch_source[source_offset + third_channel]) - mean_[2]) * scale_[2]; + } + } + return COSMO_NN_OK; +} + +Status RknnNormalizeNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blobs, + std::vector<std::shared_ptr<Blob>>& top_blobs) { + timer.Start(); + if (bottom_blobs.size() != 1 || top_blobs.size() != 1 || !bottom_blobs[0] || !top_blobs[0] || + !bottom_blobs[0]->GetHandle().base || !top_blobs[0]->GetHandle().base) { + return Status(COSMO_NN_ERR_INVALID_INPUT, + "RKNN normalize requires exactly one valid input and output"); + } + const auto bottom_desc = bottom_blobs[0]->GetBlobDesc(); + if (bottom_desc.dims.size() != 4 || bottom_desc.dims[0] <= 0 || bottom_desc.dims[0] > max_batch) { + return Status(COSMO_NN_ERR_INVALID_INPUT, "RKNN normalize batch size is invalid"); + } + SetCurrentBatch(top_blobs[0], bottom_desc.dims[0]); + auto runtime_top_desc = top_blobs[0]->GetBlobDesc(); + runtime_top_desc.data_format = native_contract_ ? DATA_FORMAT_NHWC : DATA_FORMAT_NCHW; + top_blobs[0]->SetBlobDesc(runtime_top_desc); + Status status; + if (native_contract_) { + if (CanBypassBoundInput(*bottom_blobs[0])) { + runtime_top_desc.image_format = is_bgr_ ? IMAGE_BGR : IMAGE_RGB; + top_blobs[0]->SetBlobDesc(runtime_top_desc); + GetInferencePipelineMetrics().RecordRknnPreprocessFastHit(); + GetInferencePipelineMetrics().RecordRknnRgaBoundInputNormalizeBypass(); + status = COSMO_NN_OK; + } else { + status = ForwardNative(*bottom_blobs[0], *top_blobs[0]); + } + } else { + const auto fallback_started = MetricsClock::now(); + status = ForwardFloat(*bottom_blobs[0], *top_blobs[0]); + if (detector_sized_) + GetInferencePipelineMetrics().RecordRknnCpuNormalizeFallback( + ElapsedNanoseconds(fallback_started)); + } + timer.Stop(); + return status; +} + +} // namespace cosmo::nn + +#endif diff --git a/src/nn/device/rknn/rknn_preprocess_node.h b/src/nn/device/rknn/rknn_preprocess_node.h new file mode 100644 index 000000000..47ba89852 --- /dev/null +++ b/src/nn/device/rknn/rknn_preprocess_node.h @@ -0,0 +1,85 @@ +#pragma once + +#if defined(COSMO_NN_USE_RKNN_BACKEND) && defined(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + +#include <cstddef> +#include <cstdint> +#include <vector> + +#include "nn/node/node.h" + +namespace cosmo::nn { + +bool RknnFastPreprocessEnabled(); +bool RknnForceRgaFailure(); +bool RknnMppDmaBufEnabled(); +bool RknnForceMppDmaBufFailure(); +bool IsRknnDetectorResizeContract(int out_height, int out_width, int gravity, + const std::vector<int>& padding_color); +bool IsRknnNativeNormalizeContract(const std::vector<float>& mean, const std::vector<float>& std_dev, + float scale, const DimsVector& input_dims); +void MapPackedU8ToNativeInt8(const uint8_t* source, int8_t* destination, size_t pixels, bool swap_red_blue); + +class RknnResizeNode final : public Node { +public: + RknnResizeNode(); + ~RknnResizeNode() override; + + void LoadParam(Op* op) override; + DeviceType GetTopBlobDeviceType() override; + Status InferTopShapes() override; + size_t GetBottomCount() override; + size_t GetTopCount() override; + Status Forward(std::vector<std::shared_ptr<Blob>>& bottom_blobs, + std::vector<std::shared_ptr<Blob>>& top_blobs) override; + +private: + Status ResizeSingle(const std::shared_ptr<Blob>& bottom, const std::shared_ptr<Blob>& top, + bool allow_bound_target); + bool ResizeWithRga(const Blob& bottom, Blob& top, bool allow_bound_target); + bool AcquireRgaBoundTarget(uint32_t& handle); + void ReleaseRgaBoundTarget(); + void ResizeWithCpu(const Blob& bottom, Blob& top, bool output_rgb) const; + + int out_height_{0}; + int out_width_{0}; + int gravity_{0}; + std::vector<int> padding_color_{114, 114, 114}; + bool detector_contract_{false}; + uint32_t rga_bound_target_handle_{0}; + uint64_t rga_bound_target_generation_{0}; + bool rga_bound_target_unavailable_{false}; +}; + +class RknnNormalizeNode final : public Node { +public: + RknnNormalizeNode(); + ~RknnNormalizeNode() override = default; + + void LoadParam(Op* op) override; + DeviceType GetTopBlobDeviceType() override; + bool NeedBottomShapesInfered() override; + Status InferTopShapesWithBottoms(std::vector<DimsVector> dims, std::vector<DataType> types) override; + size_t GetBottomCount() override; + size_t GetTopCount() override; + Status Forward(std::vector<std::shared_ptr<Blob>>& bottom_blobs, + std::vector<std::shared_ptr<Blob>>& top_blobs) override; + +private: + bool NeedSwapRedBlue(ImageFormat format) const; + bool CanBypassBoundInput(const Blob& bottom) const; + Status ForwardNative(const Blob& bottom, Blob& top); + Status ForwardFloat(const Blob& bottom, Blob& top); + + std::vector<float> mean_{}; + std::vector<float> std_dev_{}; + std::vector<float> scale_{}; + float uniform_scale_{1.0f}; + bool is_bgr_{true}; + bool native_contract_{false}; + bool detector_sized_{false}; +}; + +} // namespace cosmo::nn + +#endif diff --git a/src/nn/device/rknn/rknn_yolov8_adapter.cc b/src/nn/device/rknn/rknn_yolov8_adapter.cc new file mode 100644 index 000000000..3f90c4bd0 --- /dev/null +++ b/src/nn/device/rknn/rknn_yolov8_adapter.cc @@ -0,0 +1,528 @@ +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include "nn/device/rknn/rknn_yolov8_adapter.h" + +#include <algorithm> +#include <array> +#include <chrono> +#include <cmath> +#include <limits> + +namespace cosmo::nn { +namespace { + + constexpr std::array<RknnOutputAdapterRegistryEntry, 7> kOutputAdapterRegistry{{ + {RknnOutputAdapterKind::GenericTensorV1, "generic_tensor_v1", true, true}, + {RknnOutputAdapterKind::YoloAnchor3HeadV1, "yolo_anchor_3head_v1", false, false}, + {RknnOutputAdapterKind::YoloDfl6HeadV1, "yolo_dfl_6head_v1", true, true}, + {RknnOutputAdapterKind::YoloDfl9HeadScoreSumV1, "yolo_dfl_9head_score_sum_v1", true, true}, + {RknnOutputAdapterKind::YoloPoseV1, "yolo_pose_v1", false, false}, + {RknnOutputAdapterKind::YoloSegV1, "yolo_seg_v1", false, false}, + {RknnOutputAdapterKind::YoloObbV1, "yolo_obb_v1", false, false}, + }}; + + bool ParseNchw(const std::vector<int>& shape, int& channels, int& height, int& width) { + if (shape.size() != 4 || shape[0] != 1 || shape[1] <= 0 || shape[2] <= 0 || shape[3] <= 0) + return false; + channels = shape[1]; + height = shape[2]; + width = shape[3]; + return true; + } + + size_t ShapeCount(const std::vector<int>& shape) { + size_t count = 1; + for (int dim : shape) { + if (dim <= 0 || count > std::numeric_limits<size_t>::max() / static_cast<size_t>(dim)) + return 0; + count *= static_cast<size_t>(dim); + } + return count; + } + + float Sigmoid(float value) { + if (value >= 0.0f) + return 1.0f / (1.0f + std::exp(-value)); + const float exponential = std::exp(value); + return exponential / (1.0f + exponential); + } + + float ClassScore(const RknnOutputAdapterContract& contract, float value) { + return contract.class_scores_are_probabilities ? std::clamp(value, 0.0f, 1.0f) : Sigmoid(value); + } + + uint64_t ElapsedNanoseconds(std::chrono::steady_clock::time_point started_at) { + return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>( + std::chrono::steady_clock::now() - started_at) + .count()); + } + + size_t QuantizedIndex(int8_t value) { + return static_cast<size_t>(static_cast<int>(value) + 128); + } + + bool DetectYolov8DflContract(const std::vector<std::vector<int>>& shapes, size_t outputs_per_branch, + RknnOutputAdapterContract& contract, std::string& error) { + if (shapes.size() != outputs_per_branch * 3) + return false; + + const bool has_score_sum = outputs_per_branch == 3; + int class_count = 0; + int point_count = 0; + int previous_height = std::numeric_limits<int>::max(); + for (size_t branch_index = 0; branch_index < 3; ++branch_index) { + const size_t base = branch_index * outputs_per_branch; + int box_channels = 0, box_height = 0, box_width = 0; + int cls_channels = 0, cls_height = 0, cls_width = 0; + if (!ParseNchw(shapes[base], box_channels, box_height, box_width) || + !ParseNchw(shapes[base + 1], cls_channels, cls_height, cls_width)) { + error = "YOLOv8 RKNN heads must be static NCHW tensors with batch 1"; + return false; + } + if (box_channels != 64 || box_height != cls_height || box_width != cls_width) { + error = "YOLOv8 RKNN box/class head dimensions do not match"; + return false; + } + if (cls_channels <= 0 || (class_count != 0 && cls_channels != class_count)) { + error = "YOLOv8 RKNN class counts are inconsistent"; + return false; + } + if (has_score_sum) { + int sum_channels = 0, sum_height = 0, sum_width = 0; + if (!ParseNchw(shapes[base + 2], sum_channels, sum_height, sum_width) || sum_channels != 1 || + sum_height != box_height || sum_width != box_width) { + error = "YOLOv8 RKNN score-sum head dimensions do not match"; + return false; + } + } + if (box_height >= previous_height) { + error = "YOLOv8 RKNN heads must be ordered from fine to coarse stride"; + return false; + } + if (box_height > std::numeric_limits<int>::max() / box_width || + point_count > std::numeric_limits<int>::max() - box_height * box_width) { + error = "YOLOv8 RKNN point count overflows"; + return false; + } + + auto& branch = contract.branches[branch_index]; + branch.box_index = base; + branch.class_index = base + 1; + branch.score_sum_index = has_score_sum ? base + 2 : RknnYolov8BranchContract::kNoTensor; + branch.height = box_height; + branch.width = box_width; + class_count = cls_channels; + point_count += box_height * box_width; + previous_height = box_height; + } + + contract.kind = has_score_sum ? RknnOutputAdapterKind::YoloDfl9HeadScoreSumV1 + : RknnOutputAdapterKind::YoloDfl6HeadV1; + contract.class_count = class_count; + contract.point_count = point_count; + contract.logical_shape = {1, 4 + class_count, point_count}; + contract.class_scores_are_probabilities = has_score_sum; + error.clear(); + return true; + } + +} // namespace + +const std::array<RknnOutputAdapterRegistryEntry, 7>& RknnOutputAdapterRegistry() { + return kOutputAdapterRegistry; +} + +const char* RknnOutputAdapterName(RknnOutputAdapterKind kind) { + const auto found = + std::find_if(kOutputAdapterRegistry.begin(), kOutputAdapterRegistry.end(), + [kind](const RknnOutputAdapterRegistryEntry& entry) { return entry.kind == kind; }); + return found == kOutputAdapterRegistry.end() ? "unknown" : found->name; +} + +bool IsRknnYolov8DflAdapter(RknnOutputAdapterKind kind) { + return kind == RknnOutputAdapterKind::YoloDfl6HeadV1 || + kind == RknnOutputAdapterKind::YoloDfl9HeadScoreSumV1; +} + +bool ResolveRknnOutputAdapter(const std::vector<std::vector<int>>& shapes, + RknnOutputAdapterContract& contract, std::string& error) { + contract = {}; + std::string ignored_error; + if ((shapes.size() == 6 && DetectYolov8DflContract(shapes, 2, contract, ignored_error)) || + (shapes.size() == 9 && DetectYolov8DflContract(shapes, 3, contract, ignored_error))) { + error.clear(); + return true; + } + contract = {}; + contract.kind = RknnOutputAdapterKind::GenericTensorV1; + error.clear(); + return true; +} + +bool DetectRknnYolov8Layout(const std::vector<std::vector<int>>& shapes, RknnYolov8Layout& layout, + std::string& error) { + layout = {}; + if (shapes.size() == 6) + return DetectYolov8DflContract(shapes, 2, layout, error); + if (shapes.size() == 9) + return DetectYolov8DflContract(shapes, 3, layout, error); + error = "YOLOv8 RKNN adapter requires six or nine ordered DFL outputs"; + return false; +} + +bool ReconstructRknnYolov8(const std::vector<RknnYolov8Head>& heads, int input_height, int input_width, + float* output, size_t output_count, std::string& error) { + std::vector<std::vector<int>> shapes; + shapes.reserve(heads.size()); + for (const auto& head : heads) + shapes.push_back(head.shape); + + RknnYolov8Layout layout; + if (!DetectRknnYolov8Layout(shapes, layout, error)) + return false; + if (!output || input_height <= 0 || input_width <= 0) { + error = "YOLOv8 RKNN adapter received an invalid output or input size"; + return false; + } + const size_t required = + static_cast<size_t>(4 + layout.class_count) * static_cast<size_t>(layout.point_count); + if (output_count < required) { + error = "YOLOv8 RKNN logical output buffer is too small"; + return false; + } + + int point_offset = 0; + for (const auto& branch : layout.branches) { + const auto& box_head = heads[branch.box_index]; + const auto& cls_head = heads[branch.class_index]; + int box_channels = 0, height = 0, width = 0; + int cls_channels = 0, cls_height = 0, cls_width = 0; + ParseNchw(box_head.shape, box_channels, height, width); + ParseNchw(cls_head.shape, cls_channels, cls_height, cls_width); + if (!box_head.data || !cls_head.data || box_head.element_count != ShapeCount(box_head.shape) || + cls_head.element_count != ShapeCount(cls_head.shape)) { + error = "YOLOv8 RKNN output byte count does not match the queried head shape"; + return false; + } + + const int spatial_count = height * width; + const float stride_x = static_cast<float>(input_width) / static_cast<float>(width); + const float stride_y = static_cast<float>(input_height) / static_cast<float>(height); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + const int spatial_index = y * width + x; + float distance[4]{}; + for (int side = 0; side < 4; ++side) { + float maximum = -std::numeric_limits<float>::infinity(); + for (int bin = 0; bin < 16; ++bin) { + const int channel = side * 16 + bin; + maximum = std::max(maximum, box_head.data[channel * spatial_count + spatial_index]); + } + float denominator = 0.0f; + float numerator = 0.0f; + for (int bin = 0; bin < 16; ++bin) { + const int channel = side * 16 + bin; + const float value = + std::exp(box_head.data[channel * spatial_count + spatial_index] - maximum); + denominator += value; + numerator += value * static_cast<float>(bin); + } + if (!(denominator > 0.0f) || !std::isfinite(denominator)) { + error = "YOLOv8 RKNN DFL softmax produced an invalid denominator"; + return false; + } + distance[side] = numerator / denominator; + } + + const float left = (static_cast<float>(x) + 0.5f - distance[0]) * stride_x; + const float top = (static_cast<float>(y) + 0.5f - distance[1]) * stride_y; + const float right = (static_cast<float>(x) + 0.5f + distance[2]) * stride_x; + const float bottom = (static_cast<float>(y) + 0.5f + distance[3]) * stride_y; + const int logical_index = point_offset + spatial_index; + output[logical_index] = (left + right) * 0.5f; + output[layout.point_count + logical_index] = (top + bottom) * 0.5f; + output[2 * layout.point_count + logical_index] = right - left; + output[3 * layout.point_count + logical_index] = bottom - top; + for (int cls = 0; cls < layout.class_count; ++cls) { + output[(4 + cls) * layout.point_count + logical_index] = + ClassScore(layout, cls_head.data[cls * spatial_count + spatial_index]); + } + } + } + point_offset += spatial_count; + } + return true; +} + +bool ReconstructRknnYolov8Quantized(const std::vector<RknnYolov8QuantizedHead>& heads, int input_height, + int input_width, float* output, size_t output_count, std::string& error, + RknnYolov8TransformTiming* timing) { + std::vector<std::vector<int>> shapes; + shapes.reserve(heads.size()); + for (const auto& head : heads) + shapes.push_back(head.shape); + + RknnYolov8Layout layout; + if (!DetectRknnYolov8Layout(shapes, layout, error)) + return false; + if (!output || input_height <= 0 || input_width <= 0) { + error = "YOLOv8 RKNN quantized adapter received an invalid output or input size"; + return false; + } + const size_t required = + static_cast<size_t>(4 + layout.class_count) * static_cast<size_t>(layout.point_count); + if (output_count < required) { + error = "YOLOv8 RKNN logical output buffer is too small"; + return false; + } + if (timing) + *timing = {}; + + int point_offset = 0; + for (const auto& branch : layout.branches) { + const auto& box_head = heads[branch.box_index]; + const auto& cls_head = heads[branch.class_index]; + int box_channels = 0, height = 0, width = 0; + int cls_channels = 0, cls_height = 0, cls_width = 0; + ParseNchw(box_head.shape, box_channels, height, width); + ParseNchw(cls_head.shape, cls_channels, cls_height, cls_width); + if (!box_head.data || !cls_head.data || box_head.element_count != ShapeCount(box_head.shape) || + cls_head.element_count != ShapeCount(cls_head.shape)) { + error = "YOLOv8 RKNN quantized output byte count does not match the queried head shape"; + return false; + } + if (!std::isfinite(box_head.scale) || !(box_head.scale > 0.0f) || !std::isfinite(cls_head.scale) || + !(cls_head.scale > 0.0f) || box_head.zero_point < -128 || box_head.zero_point > 127 || + cls_head.zero_point < -128 || cls_head.zero_point > 127) { + error = "YOLOv8 RKNN quantized output parameters are invalid"; + return false; + } + + std::array<float, 256> dfl_exp_lut{}; + std::array<float, 256> class_score_lut{}; + for (size_t index = 0; index < dfl_exp_lut.size(); ++index) { + dfl_exp_lut[index] = std::exp(-static_cast<float>(index) * box_head.scale); + const int quantized = static_cast<int>(index) - 128; + class_score_lut[index] = + ClassScore(layout, (static_cast<float>(quantized) - cls_head.zero_point) * cls_head.scale); + } + + const int spatial_count = height * width; + const float stride_x = static_cast<float>(input_width) / static_cast<float>(width); + const float stride_y = static_cast<float>(input_height) / static_cast<float>(height); + const auto dfl_started = std::chrono::steady_clock::now(); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + const int spatial_index = y * width + x; + float distance[4]{}; + for (int side = 0; side < 4; ++side) { + int maximum = -128; + for (int bin = 0; bin < 16; ++bin) { + const int channel = side * 16 + bin; + maximum = std::max( + maximum, + static_cast<int>(box_head.data[channel * spatial_count + spatial_index])); + } + float denominator = 0.0f; + float numerator = 0.0f; + for (int bin = 0; bin < 16; ++bin) { + const int channel = side * 16 + bin; + const int quantized = + static_cast<int>(box_head.data[channel * spatial_count + spatial_index]); + const float value = dfl_exp_lut[static_cast<size_t>(maximum - quantized)]; + denominator += value; + numerator += value * static_cast<float>(bin); + } + distance[side] = numerator / denominator; + } + + const float left = (static_cast<float>(x) + 0.5f - distance[0]) * stride_x; + const float top = (static_cast<float>(y) + 0.5f - distance[1]) * stride_y; + const float right = (static_cast<float>(x) + 0.5f + distance[2]) * stride_x; + const float bottom = (static_cast<float>(y) + 0.5f + distance[3]) * stride_y; + const int logical_index = point_offset + spatial_index; + output[logical_index] = (left + right) * 0.5f; + output[layout.point_count + logical_index] = (top + bottom) * 0.5f; + output[2 * layout.point_count + logical_index] = right - left; + output[3 * layout.point_count + logical_index] = bottom - top; + } + } + if (timing) + timing->dfl_nanoseconds += ElapsedNanoseconds(dfl_started); + + const auto class_started = std::chrono::steady_clock::now(); + for (int cls = 0; cls < layout.class_count; ++cls) { + const auto* source = cls_head.data + cls * spatial_count; + auto* destination = output + (4 + cls) * layout.point_count + point_offset; + for (int spatial_index = 0; spatial_index < spatial_count; ++spatial_index) + destination[spatial_index] = class_score_lut[QuantizedIndex(source[spatial_index])]; + } + if (timing) + timing->class_nanoseconds += ElapsedNanoseconds(class_started); + point_offset += spatial_count; + } + return true; +} + +bool DecodeRknnYolov8QuantizedCandidates(const std::vector<RknnYolov8QuantizedHead>& heads, int input_height, + int input_width, float confidence_threshold, + RknnYolov8CandidateScratch& scratch, + std::vector<Yolov8Candidate>& candidates, std::string& error, + RknnYolov8CandidateTiming* timing) { + candidates.clear(); + if (timing) + *timing = {}; + + std::vector<std::vector<int>> shapes; + shapes.reserve(heads.size()); + for (const auto& head : heads) + shapes.push_back(head.shape); + + RknnYolov8Layout layout; + if (!DetectRknnYolov8Layout(shapes, layout, error)) + return false; + if (input_height <= 0 || input_width <= 0 || !std::isfinite(confidence_threshold)) { + error = "RKNN YOLOv8 candidate adapter received an invalid input contract"; + return false; + } + const auto initial_capacity = static_cast<size_t>(std::min(layout.point_count, 1024)); + if (candidates.capacity() < initial_capacity) + candidates.reserve(initial_capacity); + + for (const auto& branch : layout.branches) { + const auto& box_head = heads[branch.box_index]; + const auto& cls_head = heads[branch.class_index]; + const RknnYolov8QuantizedHead* score_sum_head = + branch.HasScoreSum() ? &heads[branch.score_sum_index] : nullptr; + int box_channels = 0, height = 0, width = 0; + int cls_channels = 0, cls_height = 0, cls_width = 0; + ParseNchw(box_head.shape, box_channels, height, width); + ParseNchw(cls_head.shape, cls_channels, cls_height, cls_width); + if (!box_head.data || !cls_head.data || box_head.element_count != ShapeCount(box_head.shape) || + cls_head.element_count != ShapeCount(cls_head.shape)) { + error = "RKNN YOLOv8 candidate head byte count does not match its shape"; + candidates.clear(); + return false; + } + if (score_sum_head && + (!score_sum_head->data || score_sum_head->element_count != ShapeCount(score_sum_head->shape) || + !std::isfinite(score_sum_head->scale) || !(score_sum_head->scale > 0.0f) || + score_sum_head->zero_point < -128 || score_sum_head->zero_point > 127)) { + error = "RKNN YOLOv8 score-sum output parameters are invalid"; + candidates.clear(); + return false; + } + if (!std::isfinite(box_head.scale) || !(box_head.scale > 0.0f) || !std::isfinite(cls_head.scale) || + !(cls_head.scale > 0.0f) || box_head.zero_point < -128 || box_head.zero_point > 127 || + cls_head.zero_point < -128 || cls_head.zero_point > 127) { + error = "RKNN YOLOv8 candidate quantization parameters are invalid"; + candidates.clear(); + return false; + } + + std::array<float, 256> dfl_exp_lut{}; + std::array<float, 256> class_score_lut{}; + for (size_t index = 0; index < dfl_exp_lut.size(); ++index) { + dfl_exp_lut[index] = std::exp(-static_cast<float>(index) * box_head.scale); + const int quantized = static_cast<int>(index) - 128; + class_score_lut[index] = + ClassScore(layout, (static_cast<float>(quantized) - cls_head.zero_point) * cls_head.scale); + } + + const int spatial_count = height * width; + const auto class_started = std::chrono::steady_clock::now(); + scratch.class_max.assign(static_cast<size_t>(spatial_count), std::numeric_limits<int8_t>::min()); + scratch.class_ids.assign(static_cast<size_t>(spatial_count), -1); + scratch.active_points.clear(); + if (score_sum_head) { + if (scratch.active_points.capacity() < static_cast<size_t>(spatial_count)) + scratch.active_points.reserve(static_cast<size_t>(spatial_count)); + for (int spatial_index = 0; spatial_index < spatial_count; ++spatial_index) { + const float score_sum = + (static_cast<float>(score_sum_head->data[spatial_index]) - score_sum_head->zero_point) * + score_sum_head->scale; + if (score_sum >= confidence_threshold) { + scratch.active_points.push_back(spatial_index); + } else if (timing) { + ++timing->score_sum_points_rejected; + } + } + } + for (int cls = 0; cls < cls_channels; ++cls) { + const auto* source = cls_head.data + cls * spatial_count; + const auto update_max = [&](int spatial_index) { + if (scratch.class_ids[spatial_index] < 0 || + source[spatial_index] > scratch.class_max[spatial_index]) { + scratch.class_max[spatial_index] = source[spatial_index]; + scratch.class_ids[spatial_index] = cls; + } + }; + if (score_sum_head) { + for (int spatial_index : scratch.active_points) + update_max(spatial_index); + } else { + for (int spatial_index = 0; spatial_index < spatial_count; ++spatial_index) + update_max(spatial_index); + } + } + if (timing) { + timing->class_nanoseconds += ElapsedNanoseconds(class_started); + timing->points_scanned += static_cast<uint64_t>(spatial_count); + } + + const float stride_x = static_cast<float>(input_width) / static_cast<float>(width); + const float stride_y = static_cast<float>(input_height) / static_cast<float>(height); + const auto dfl_started = std::chrono::steady_clock::now(); + for (int spatial_index = 0; spatial_index < spatial_count; ++spatial_index) { + if (scratch.class_ids[spatial_index] < 0) + continue; + const float confidence = class_score_lut[QuantizedIndex(scratch.class_max[spatial_index])]; + if (confidence < confidence_threshold) + continue; + + float distance[4]{}; + for (int side = 0; side < 4; ++side) { + int maximum = -128; + for (int bin = 0; bin < 16; ++bin) { + const int channel = side * 16 + bin; + maximum = std::max( + maximum, static_cast<int>(box_head.data[channel * spatial_count + spatial_index])); + } + float denominator = 0.0f; + float numerator = 0.0f; + for (int bin = 0; bin < 16; ++bin) { + const int channel = side * 16 + bin; + const int quantized = + static_cast<int>(box_head.data[channel * spatial_count + spatial_index]); + const float value = dfl_exp_lut[static_cast<size_t>(maximum - quantized)]; + denominator += value; + numerator += value * static_cast<float>(bin); + } + if (!(denominator > 0.0f) || !std::isfinite(denominator)) { + error = "RKNN YOLOv8 candidate DFL produced an invalid denominator"; + candidates.clear(); + return false; + } + distance[side] = numerator / denominator; + } + + const int x = spatial_index % width; + const int y = spatial_index / width; + const float left = (static_cast<float>(x) + 0.5f - distance[0]) * stride_x; + const float top = (static_cast<float>(y) + 0.5f - distance[1]) * stride_y; + const float right = (static_cast<float>(x) + 0.5f + distance[2]) * stride_x; + const float bottom = (static_cast<float>(y) + 0.5f + distance[3]) * stride_y; + candidates.push_back({(left + right) * 0.5f, (top + bottom) * 0.5f, right - left, bottom - top, + confidence, scratch.class_ids[spatial_index]}); + if (timing) + ++timing->points_decoded; + } + if (timing) + timing->dfl_nanoseconds += ElapsedNanoseconds(dfl_started); + } + return true; +} + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/src/nn/device/rknn/rknn_yolov8_adapter.h b/src/nn/device/rknn/rknn_yolov8_adapter.h new file mode 100644 index 000000000..6611768a2 --- /dev/null +++ b/src/nn/device/rknn/rknn_yolov8_adapter.h @@ -0,0 +1,115 @@ +#pragma once + +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include <array> +#include <cstddef> +#include <cstdint> +#include <limits> +#include <string> +#include <vector> + +#include "nn/core/shared_resource.h" + +namespace cosmo::nn { + +enum class RknnOutputAdapterKind : uint8_t { + GenericTensorV1 = 0, + YoloAnchor3HeadV1, + YoloDfl6HeadV1, + YoloDfl9HeadScoreSumV1, + YoloPoseV1, + YoloSegV1, + YoloObbV1, +}; + +struct RknnOutputAdapterRegistryEntry { + RknnOutputAdapterKind kind{RknnOutputAdapterKind::GenericTensorV1}; + const char* name{nullptr}; + bool implemented{false}; + bool auto_detect{false}; +}; + +struct RknnYolov8BranchContract { + static constexpr size_t kNoTensor = std::numeric_limits<size_t>::max(); + + size_t box_index{kNoTensor}; + size_t class_index{kNoTensor}; + size_t score_sum_index{kNoTensor}; + int height{0}; + int width{0}; + + [[nodiscard]] bool HasScoreSum() const { + return score_sum_index != kNoTensor; + } +}; + +struct RknnOutputAdapterContract { + RknnOutputAdapterKind kind{RknnOutputAdapterKind::GenericTensorV1}; + int class_count{0}; + int point_count{0}; + std::vector<int> logical_shape; + std::array<RknnYolov8BranchContract, 3> branches{}; + bool class_scores_are_probabilities{false}; +}; + +const std::array<RknnOutputAdapterRegistryEntry, 7>& RknnOutputAdapterRegistry(); +const char* RknnOutputAdapterName(RknnOutputAdapterKind kind); +bool ResolveRknnOutputAdapter(const std::vector<std::vector<int>>& shapes, + RknnOutputAdapterContract& contract, std::string& error); +bool IsRknnYolov8DflAdapter(RknnOutputAdapterKind kind); + +struct RknnYolov8Head { + const float* data{nullptr}; + size_t element_count{0}; + std::vector<int> shape; +}; + +struct RknnYolov8QuantizedHead { + const int8_t* data{nullptr}; + size_t element_count{0}; + std::vector<int> shape; + int32_t zero_point{0}; + float scale{0.0f}; +}; + +struct RknnYolov8TransformTiming { + uint64_t dfl_nanoseconds{0}; + uint64_t class_nanoseconds{0}; +}; + +struct RknnYolov8CandidateTiming { + uint64_t dfl_nanoseconds{0}; + uint64_t class_nanoseconds{0}; + uint64_t points_scanned{0}; + uint64_t points_decoded{0}; + uint64_t score_sum_points_rejected{0}; +}; + +struct RknnYolov8CandidateScratch { + std::vector<int8_t> class_max; + std::vector<int> class_ids; + std::vector<int> active_points; +}; + +using RknnYolov8Layout = RknnOutputAdapterContract; + +bool DetectRknnYolov8Layout(const std::vector<std::vector<int>>& shapes, RknnYolov8Layout& layout, + std::string& error); + +bool ReconstructRknnYolov8(const std::vector<RknnYolov8Head>& heads, int input_height, int input_width, + float* output, size_t output_count, std::string& error); + +bool ReconstructRknnYolov8Quantized(const std::vector<RknnYolov8QuantizedHead>& heads, int input_height, + int input_width, float* output, size_t output_count, std::string& error, + RknnYolov8TransformTiming* timing = nullptr); + +bool DecodeRknnYolov8QuantizedCandidates(const std::vector<RknnYolov8QuantizedHead>& heads, int input_height, + int input_width, float confidence_threshold, + RknnYolov8CandidateScratch& scratch, + std::vector<Yolov8Candidate>& candidates, std::string& error, + RknnYolov8CandidateTiming* timing = nullptr); + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/src/nn/device/sophon/qwen3_5/qwen3_5_model.cc b/src/nn/device/sophon/qwen3_5/qwen3_5_model.cc index e1939d383..f149aefbb 100644 --- a/src/nn/device/sophon/qwen3_5/qwen3_5_model.cc +++ b/src/nn/device/sophon/qwen3_5/qwen3_5_model.cc @@ -250,16 +250,12 @@ namespace qwen3_5 { if (bm_handle_ != nullptr || p_bmrt_ != nullptr || model_path.empty()) { throw safety::RuntimeError("initialize model", "already initialized or empty model path"); } + + const RawBmodelLoadPlan load_plan = safety::AuthorizeRawBmodel(model_path); + try { safety::CheckStatus(bm_dev_request(&bm_handle_, dev_id), "request device"); - p_bmrt_ = bmrt_create(bm_handle_); - if (p_bmrt_ == nullptr) { - throw safety::RuntimeError("create runtime"); - } - bmrt_set_flags(p_bmrt_, BM_RUNTIME_SHARE_MEM); - if (!bmrt_load_bmodel(p_bmrt_, model_path.c_str())) { - throw safety::RuntimeError("load model", model_path); - } + p_bmrt_ = safety::LoadSingleAuthorizedRawBmodel(load_plan, bm_handle_); safety::CheckStatus(bm_thread_sync(bm_handle_), "synchronize model load"); init_by_names(); const size_t token_capacity = static_cast<size_t>(std::max(SEQLEN, MAX_INPUT_LENGTH)) + 1U; diff --git a/src/nn/device/sophon/qwen3_5/qwen3_5_model.h b/src/nn/device/sophon/qwen3_5/qwen3_5_model.h index 288df7163..34c514e90 100644 --- a/src/nn/device/sophon/qwen3_5/qwen3_5_model.h +++ b/src/nn/device/sophon/qwen3_5/qwen3_5_model.h @@ -29,7 +29,7 @@ namespace qwen3_5 { ~Qwen3_5Model(); void init(int dev_id, const std::string& model_path, bool do_sample, - const std::string& model_config_json_path = ""); + const std::string& model_config_json_path); void deinit(); void forward_embed(const ArrayInt& tokens); void forward_vit(const float* pixel_values, const ArrayInt& position_ids, const ArrayInt& pos_idx, diff --git a/src/nn/device/sophon/qwen3vl/qwen3vl_model.cc b/src/nn/device/sophon/qwen3vl/qwen3vl_model.cc index 0269f06af..e0605239d 100644 --- a/src/nn/device/sophon/qwen3vl/qwen3vl_model.cc +++ b/src/nn/device/sophon/qwen3vl/qwen3vl_model.cc @@ -338,19 +338,12 @@ namespace qwen3vl { if (bm_handle_ != nullptr || p_bmrt_ != nullptr || model_path.empty()) { throw safety::RuntimeError("initialize model", "already initialized or empty model path"); } + + const RawBmodelLoadPlan load_plan = safety::AuthorizeRawBmodel(model_path); + try { safety::CheckStatus(bm_dev_request(&bm_handle_, dev_id), "request device"); - p_bmrt_ = bmrt_create(bm_handle_); - if (p_bmrt_ == nullptr) { - throw safety::RuntimeError("create runtime"); - } - bmrt_set_flags(p_bmrt_, BM_RUNTIME_SHARE_MEM); - /* Qwen3VL model file: uses .nn extension, content is raw bmodel without extra header, loaded - * directly as bmodel to save memory and storage - */ - if (!bmrt_load_bmodel(p_bmrt_, model_path.c_str())) { - throw safety::RuntimeError("load model", model_path); - } + p_bmrt_ = safety::LoadSingleAuthorizedRawBmodel(load_plan, bm_handle_); safety::CheckStatus(bm_thread_sync(bm_handle_), "synchronize model load"); init_by_names(); const size_t token_capacity = static_cast<size_t>(std::max(SEQLEN, MAX_INPUT_LENGTH)) + 1U; diff --git a/src/nn/device/sophon/qwen3vl/qwen3vl_model.h b/src/nn/device/sophon/qwen3vl/qwen3vl_model.h index 572366f33..89b46d9f9 100644 --- a/src/nn/device/sophon/qwen3vl/qwen3vl_model.h +++ b/src/nn/device/sophon/qwen3vl/qwen3vl_model.h @@ -6,7 +6,6 @@ #include "bmlib_runtime.h" #include "bmruntime_interface.h" - namespace cosmo::nn { namespace qwen3vl { @@ -35,7 +34,7 @@ namespace qwen3vl { * reads from config.generation for generation params; tokenizer etc. loaded by runner from * config_dir, no directory passed here */ void init(int dev_id, const std::string& model_path, bool do_sample, - const std::string& model_config_json_path = ""); + const std::string& model_config_json_path); void deinit(); void forward_embed(const ArrayInt& tokens); void forward_vit(const float* pixel_values, const ArrayInt& position_ids, const ArrayInt& pos_idx, diff --git a/src/nn/device/sophon/qwen_runtime_safety.h b/src/nn/device/sophon/qwen_runtime_safety.h index 5634e6f6b..7d02702b2 100644 --- a/src/nn/device/sophon/qwen_runtime_safety.h +++ b/src/nn/device/sophon/qwen_runtime_safety.h @@ -2,11 +2,13 @@ #include <cstdio> #include <limits> +#include <new> #include <stdexcept> #include <string> #include "bmlib_runtime.h" #include "bmruntime_interface.h" +#include "nn/guard/CemV2SophonLoader.h" namespace cosmo::nn::qwen_runtime_safety { @@ -144,4 +146,41 @@ inline void FreeHandleNoThrow(bm_handle_t* handle) noexcept { *handle = nullptr; } +inline RawBmodelLoadPlan RequireAuthorizedRawBmodel(RawBmodelLoadPlan plan) { + switch (plan.error) { + case RawBmodelAuthorizationError::kNone: + return plan; + case RawBmodelAuthorizationError::kPolicyRejected: + default: + throw RuntimeError("authorize model", "format rejected"); + } +} + +inline RawBmodelLoadPlan AuthorizeRawBmodel(const std::string& model_path) { + return RequireAuthorizedRawBmodel(PrepareRawBmodelLoad(ModelLoadPolicy::Production(), model_path)); +} + +inline void* LoadSingleAuthorizedRawBmodel(const RawBmodelLoadPlan& plan, const CemV2Api& guard_api, + const SophonRuntimeApi& runtime_api, bm_handle_t bm_handle) { + SophonModelLoadResult loaded = LoadRawBmodelByPlan(plan, guard_api, runtime_api, bm_handle); + if (!loaded.IsSuccess() || loaded.runtimes.size() != 1) { + if (loaded.IsOutOfMemory()) { + throw std::bad_alloc(); + } + if (loaded.error == SophonModelLoadError::kNativeRuntimeCreateFailed) { + throw RuntimeError("create runtime"); + } + if (loaded.error == SophonModelLoadError::kNativeLoadFailed && + plan.decision.action == ModelLoadAction::kNativeRawBmodel) { + throw RuntimeError("load model", plan.decision.model_path); + } + throw RuntimeError("load authorized model"); + } + return loaded.runtimes.front().release(); +} + +inline void* LoadSingleAuthorizedRawBmodel(const RawBmodelLoadPlan& plan, bm_handle_t bm_handle) { + return LoadSingleAuthorizedRawBmodel(plan, FrozenCemV2Api(), NativeSophonRuntimeApi(), bm_handle); +} + } // namespace cosmo::nn::qwen_runtime_safety diff --git a/src/nn/device/sophon/sophon_net_node.cc b/src/nn/device/sophon/sophon_net_node.cc index e2ae65c52..4d0e1a3d7 100644 --- a/src/nn/device/sophon/sophon_net_node.cc +++ b/src/nn/device/sophon/sophon_net_node.cc @@ -181,6 +181,10 @@ namespace { } } // namespace +void BmrtDeleter::operator()(void* runtime) const noexcept { + DestroyBmRuntime(&runtime); +} + std::mutex SophonNetNode::sophon_net_mutex; SophonNetNode::SophonNetNode() : NetNode() {} @@ -436,9 +440,9 @@ Status SophonNetNode::LoadWeight(const char* data, size_t size) { } } -Status SophonNetNode::AttachBmrt(void* bmrt_handle) { +Status SophonNetNode::AttachOwnedBmrt(OwnedBmrt bmrt_handle) { if (!bmrt_handle) - return Status(COSMO_NN_ERR_LOAD_MODEL, "AttachBmrt: bmrt handle is null"); + return Status(COSMO_NN_ERR_LOAD_MODEL, "AttachOwnedBmrt: bmrt handle is null"); if (shared_resource == nullptr) { return Status(COSMO_NN_ERR_GRAPH_NOT_INIT, "Sophon shared resource is null"); @@ -450,12 +454,10 @@ Status SophonNetNode::AttachBmrt(void* bmrt_handle) { std::unique_lock<std::mutex> lck(sophon_net_mutex); if (m_bmrt != nullptr) { - return Status(COSMO_NN_ERR_LOAD_MODEL, "AttachBmrt: runtime is already attached"); + return Status(COSMO_NN_ERR_LOAD_MODEL, "AttachOwnedBmrt: runtime is already attached"); } - // Take ownership of the externally-created bmrt. - // The .so has already completed bmrt_create + bmrt_load_bmodel_data. - m_bmrt = bmrt_handle; + m_bmrt = bmrt_handle.release(); try { Status status = SetupNetworkAfterBmrt(); @@ -472,6 +474,10 @@ Status SophonNetNode::AttachBmrt(void* bmrt_handle) { DestroyBmRuntime(&m_bmrt); m_netinfo = nullptr; return Status(COSMO_NN_ERR_LOAD_MODEL, error.what()); + } catch (...) { + DestroyBmRuntime(&m_bmrt); + m_netinfo = nullptr; + return Status(COSMO_NN_ERR_LOAD_MODEL, "Sophon model setup failed with an unknown error"); } } diff --git a/src/nn/device/sophon/sophon_net_node.h b/src/nn/device/sophon/sophon_net_node.h index 0339225b8..bd8bfe4da 100644 --- a/src/nn/device/sophon/sophon_net_node.h +++ b/src/nn/device/sophon/sophon_net_node.h @@ -1,5 +1,6 @@ #pragma once +#include <memory> #include <mutex> #include <vector> @@ -11,6 +12,12 @@ namespace cosmo::nn { +struct BmrtDeleter { + void operator()(void* runtime) const noexcept; +}; + +using OwnedBmrt = std::unique_ptr<void, BmrtDeleter>; + typedef struct _netInfos { std::vector<std::vector<int>> inPuts; std::vector<std::vector<int>> outPuts; @@ -30,11 +37,9 @@ class SophonNetNode : public NetNode { virtual Status LoadWeight(const char* data, size_t size) override; - /// Attach an externally-created bmrt handle (from model guard .so). - /// The bmrt must already have bmodel data loaded via bmrt_load_bmodel_data. - /// Skips bmrt_create + bmrt_load_bmodel_data, but performs all subsequent - /// setup: network info, input/output tensors, device memory allocation. - Status AttachBmrt(void* bmrt_handle); + /// Consume an externally-created bmrt handle whose model data is already loaded. + /// The handle is destroyed on every failure path or retained by the node on success. + Status AttachOwnedBmrt(OwnedBmrt bmrt_handle); virtual size_t GetBottomCount() override; diff --git a/src/nn/guard/CemV2SophonLoader.cc b/src/nn/guard/CemV2SophonLoader.cc new file mode 100644 index 000000000..0b9f0c8d4 --- /dev/null +++ b/src/nn/guard/CemV2SophonLoader.cc @@ -0,0 +1,296 @@ +#include "nn/guard/CemV2SophonLoader.h" + +#ifdef COSMO_NN_USE_SOPHON_BACKEND + +#include <cstdio> +#include <new> +#include <utility> + +#include "bmruntime_interface.h" + +namespace cosmo::nn { +namespace { + + class ArtifactOwner final { + public: + ArtifactOwner(CmgV2Artifact* artifact, const CemV2Api& api) noexcept + : artifact_(artifact), api_(api) {} + + ~ArtifactOwner() { + Reset(); + } + + ArtifactOwner(const ArtifactOwner&) = delete; + ArtifactOwner& operator=(const ArtifactOwner&) = delete; + + ArtifactOwner(ArtifactOwner&& other) noexcept + : artifact_(std::exchange(other.artifact_, nullptr)), api_(other.api_) {} + + ArtifactOwner& operator=(ArtifactOwner&& other) noexcept { + if (this != &other) { + Reset(); + artifact_ = std::exchange(other.artifact_, nullptr); + api_ = other.api_; + } + return *this; + } + + [[nodiscard]] CmgV2Artifact* Get() const noexcept { + return artifact_; + } + + private: + void Reset() noexcept { + if (artifact_ == nullptr) { + return; + } + api_.close_artifact(api_.context, artifact_); + artifact_ = nullptr; + } + + CmgV2Artifact* artifact_ = nullptr; + CemV2Api api_{}; + }; + + bool IsGuardApiAvailable(const CemV2Api& api) noexcept { + return api.abi_major == CMG_V2_ABI_MAJOR && api.open_artifact != nullptr && + api.get_artifact_info != nullptr && api.load_sophon_segment != nullptr && + api.close_artifact != nullptr; + } + + bool IsRuntimeDestroyAvailable(const SophonRuntimeApi& api) noexcept { + return api.destroy != nullptr; + } + + bool IsValidArtifactInfo(const CmgV2ArtifactInfo& info, + CmgV2SourceFormat expected_source_format) noexcept { + return info.struct_size == CMG_V2_ARTIFACT_INFO_SIZE && info.reserved == 0 && + info.source_format == expected_source_format && info.segment_count > 0; + } + + SophonModelLoadResult Failure(SophonModelLoadError error, CmgV2Status guard_status) { + SophonModelLoadResult result; + result.error = error; + result.guard_status = guard_status; + return result; + } + +#ifdef COSMO_HAS_MODEL_GUARD + CmgV2Status OpenFrozenArtifact(void*, const char* path, CmgV2SourceFormat source_format, + CmgV2Artifact** out_artifact) { + return CmgV2OpenArtifact(path, source_format, out_artifact); + } + + CmgV2Status GetFrozenArtifactInfo(void*, const CmgV2Artifact* artifact, CmgV2ArtifactInfo* out_info) { + return CmgV2GetArtifactInfo(artifact, out_info); + } + + CmgV2Status LoadFrozenSophonSegment(void*, CmgV2Artifact* artifact, bm_handle_t bm_handle, + std::uint32_t segment_index, const CmgV2SophonLoadOptions* options, + void** out_bmrt) { + return CmgV2LoadSophonSegment(artifact, bm_handle, segment_index, options, out_bmrt); + } + + void CloseFrozenArtifact(void*, CmgV2Artifact* artifact) noexcept { + CmgV2CloseArtifact(artifact); + } +#endif + + void* CreateNativeRuntime(void*, bm_handle_t bm_handle) { + return bmrt_create(bm_handle); + } + + void SetNativeRuntimeFlags(void*, void* runtime, std::uint32_t flags) { + bmrt_set_flags(runtime, flags); + } + + bool LoadNativeRuntimeFile(void*, void* runtime, const char* model_path) { + return bmrt_load_bmodel(runtime, model_path); + } + + void DestroyNativeRuntime(void*, void* runtime) noexcept { + if (runtime == nullptr) { + return; + } + try { + bmrt_destroy(runtime); + } catch (...) { + std::fputs("[ModelLoader] bmrt_destroy failed during cleanup\n", stderr); + } + } + + bool IsProtectedRawDecision(const ModelLoadDecision& decision) noexcept { + return decision.action == ModelLoadAction::kGuardV2 && decision.magic == ModelMagic::kCemc && + !decision.model_path.empty(); + } + + bool IsNativeRawDecision(const ModelLoadDecision& decision) noexcept { + return decision.action == ModelLoadAction::kNativeRawBmodel && + decision.magic == ModelMagic::kUnknown && !decision.model_path.empty(); + } + +} // namespace + +void SophonRuntimeDeleter::operator()(void* runtime) const noexcept { + if (runtime != nullptr && destroy != nullptr) { + destroy(context, runtime); + } +} + +const CemV2Api& FrozenCemV2Api() noexcept { +#ifdef COSMO_HAS_MODEL_GUARD + static const CemV2Api api{CMG_V2_ABI_MAJOR, nullptr, + OpenFrozenArtifact, GetFrozenArtifactInfo, + LoadFrozenSophonSegment, CloseFrozenArtifact}; +#else + static const CemV2Api api{CMG_V2_ABI_MAJOR, nullptr, nullptr, nullptr, nullptr, nullptr}; +#endif + return api; +} + +const SophonRuntimeApi& NativeSophonRuntimeApi() noexcept { + static const SophonRuntimeApi api{nullptr, CreateNativeRuntime, SetNativeRuntimeFlags, + LoadNativeRuntimeFile, DestroyNativeRuntime}; + return api; +} + +RawBmodelLoadPlan PrepareRawBmodelLoad(const ModelLoadPolicy& policy, const std::string& model_path) { + RawBmodelLoadPlan plan; + plan.decision = policy.Evaluate(model_path, ModelLoadIntent::kRawBmodel); + if (!plan.decision.IsAllowed() || (plan.decision.action != ModelLoadAction::kGuardV2 && + plan.decision.action != ModelLoadAction::kNativeRawBmodel)) { + return plan; + } + + plan.error = RawBmodelAuthorizationError::kNone; + return plan; +} + +SophonModelLoadResult LoadCemV2SophonArtifact(const CemV2Api& guard_api, const SophonRuntimeApi& runtime_api, + const std::string& model_path, + CmgV2SourceFormat expected_source_format, bm_handle_t bm_handle, + CmgV2SophonLoadFlags flags) { + if (model_path.empty() || bm_handle == nullptr || (flags & ~CMG_V2_SOPHON_SHARE_MEM) != 0) { + return Failure(SophonModelLoadError::kInvalidArgument, CMG_V2_RESOURCE_INVALID_ARGUMENT); + } + if (expected_source_format != CMG_V2_SOURCE_COSMO_NN_V1 && + expected_source_format != CMG_V2_SOURCE_RAW_BMODEL) { + return Failure(SophonModelLoadError::kInvalidArgument, CMG_V2_RESOURCE_INVALID_ARGUMENT); + } + if (!IsGuardApiAvailable(guard_api)) { + return Failure(SophonModelLoadError::kAbiUnavailable, CMG_V2_RESOURCE_ABI_MISMATCH); + } + if (!IsRuntimeDestroyAvailable(runtime_api)) { + return Failure(SophonModelLoadError::kNativeRuntimeUnavailable, CMG_V2_RESOURCE_INVALID_STATE); + } + + CmgV2Artifact* raw_artifact = nullptr; + const CmgV2Status open_status = + guard_api.open_artifact(guard_api.context, model_path.c_str(), expected_source_format, &raw_artifact); + if (open_status != CMG_V2_OK) { + if (raw_artifact != nullptr) { + ArtifactOwner invalid_artifact(raw_artifact, guard_api); + return Failure(SophonModelLoadError::kAbiContractViolation, CMG_V2_RESOURCE_INTERNAL); + } + return Failure(SophonModelLoadError::kArtifactOpenFailed, open_status); + } + if (raw_artifact == nullptr) { + return Failure(SophonModelLoadError::kAbiContractViolation, CMG_V2_RESOURCE_INTERNAL); + } + ArtifactOwner artifact(raw_artifact, guard_api); + + CmgV2ArtifactInfo info{}; + info.struct_size = CMG_V2_ARTIFACT_INFO_SIZE; + const CmgV2Status info_status = guard_api.get_artifact_info(guard_api.context, artifact.Get(), &info); + if (info_status != CMG_V2_OK) { + return Failure(SophonModelLoadError::kArtifactInfoFailed, info_status); + } + if (!IsValidArtifactInfo(info, expected_source_format)) { + return Failure(SophonModelLoadError::kArtifactInfoInvalid, CMG_V2_RESOURCE_INTERNAL); + } + SophonModelLoadResult result; + try { + result.runtimes.reserve(info.segment_count); + } catch (const std::bad_alloc&) { + return Failure(SophonModelLoadError::kNoMemory, CMG_V2_RESOURCE_NO_MEMORY); + } + + CmgV2SophonLoadOptions options{}; + options.struct_size = CMG_V2_SOPHON_LOAD_OPTIONS_SIZE; + options.flags = flags; + + for (std::uint32_t index = 0; index < info.segment_count; ++index) { + void* raw_runtime = nullptr; + const CmgV2Status load_status = guard_api.load_sophon_segment( + guard_api.context, artifact.Get(), bm_handle, index, &options, &raw_runtime); + GuardOwnedBmrt owned_runtime(raw_runtime, {runtime_api.context, runtime_api.destroy}); + if (load_status != CMG_V2_OK) { + if (raw_runtime != nullptr) { + return Failure(SophonModelLoadError::kAbiContractViolation, CMG_V2_RESOURCE_INTERNAL); + } + return Failure(SophonModelLoadError::kSegmentLoadFailed, load_status); + } + if (raw_runtime == nullptr) { + return Failure(SophonModelLoadError::kAbiContractViolation, CMG_V2_RESOURCE_INTERNAL); + } + try { + result.runtimes.push_back(std::move(owned_runtime)); + } catch (const std::bad_alloc&) { + return Failure(SophonModelLoadError::kNoMemory, CMG_V2_RESOURCE_NO_MEMORY); + } + } + + return result; +} + +SophonModelLoadResult LoadRawBmodelByPolicy(const ModelLoadDecision& decision, const CemV2Api& guard_api, + const SophonRuntimeApi& runtime_api, bm_handle_t bm_handle) { + if (bm_handle == nullptr) { + return Failure(SophonModelLoadError::kInvalidArgument, CMG_V2_RESOURCE_INVALID_ARGUMENT); + } + if (IsProtectedRawDecision(decision)) { + return LoadCemV2SophonArtifact(guard_api, runtime_api, decision.model_path, CMG_V2_SOURCE_RAW_BMODEL, + bm_handle, CMG_V2_SOPHON_SHARE_MEM); + } + if (!IsNativeRawDecision(decision)) { + return Failure(SophonModelLoadError::kPolicyRejected, CMG_V2_FORMAT_SOURCE_MISMATCH); + } + if (runtime_api.create == nullptr || runtime_api.set_flags == nullptr || + runtime_api.load_file == nullptr || runtime_api.destroy == nullptr) { + return Failure(SophonModelLoadError::kNativeRuntimeUnavailable, CMG_V2_RESOURCE_INVALID_STATE); + } + + void* raw_runtime = runtime_api.create(runtime_api.context, bm_handle); + GuardOwnedBmrt owned_runtime(raw_runtime, {runtime_api.context, runtime_api.destroy}); + if (raw_runtime == nullptr) { + return Failure(SophonModelLoadError::kNativeRuntimeCreateFailed, CMG_V2_BACKEND_FAILED); + } + try { + runtime_api.set_flags(runtime_api.context, raw_runtime, BM_RUNTIME_SHARE_MEM); + if (!runtime_api.load_file(runtime_api.context, raw_runtime, decision.model_path.c_str())) { + return Failure(SophonModelLoadError::kNativeLoadFailed, CMG_V2_BACKEND_FAILED); + } + } catch (...) { + return Failure(SophonModelLoadError::kNativeLoadFailed, CMG_V2_BACKEND_FAILED); + } + + SophonModelLoadResult result; + try { + result.runtimes.push_back(std::move(owned_runtime)); + } catch (const std::bad_alloc&) { + return Failure(SophonModelLoadError::kNoMemory, CMG_V2_RESOURCE_NO_MEMORY); + } + return result; +} + +SophonModelLoadResult LoadRawBmodelByPlan(const RawBmodelLoadPlan& plan, const CemV2Api& guard_api, + const SophonRuntimeApi& runtime_api, bm_handle_t bm_handle) { + if (!plan.IsAuthorized()) { + return Failure(SophonModelLoadError::kPolicyRejected, CMG_V2_FORMAT_SOURCE_MISMATCH); + } + return LoadRawBmodelByPolicy(plan.decision, guard_api, runtime_api, bm_handle); +} + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_SOPHON_BACKEND diff --git a/src/nn/guard/CemV2SophonLoader.h b/src/nn/guard/CemV2SophonLoader.h new file mode 100644 index 000000000..310a86e28 --- /dev/null +++ b/src/nn/guard/CemV2SophonLoader.h @@ -0,0 +1,144 @@ +#pragma once + +#ifdef COSMO_NN_USE_SOPHON_BACKEND + +#include <cosmo_model_guard_v2.h> + +#include <cstdint> +#include <memory> +#include <string> +#include <vector> + +#include "nn/guard/ModelLoadPolicy.h" + +namespace cosmo::nn { + +static_assert(CMG_V2_ABI_MAJOR == UINT32_C(2), "CosmoEdge requires model-guard ABI major 2"); + +/// Adapter for the four frozen model-guard v2 entry points. The context is +/// opaque so focused tests can provide deterministic C-ABI mocks without +/// changing the production ABI. +struct CemV2Api { + using OpenArtifact = CmgV2Status (*)(void* context, const char* installed_model_path, + CmgV2SourceFormat expected_source_format, + CmgV2Artifact** out_artifact); + using GetArtifactInfo = CmgV2Status (*)(void* context, const CmgV2Artifact* artifact, + CmgV2ArtifactInfo* out_info); + using LoadSophonSegment = CmgV2Status (*)(void* context, CmgV2Artifact* artifact, bm_handle_t bm_handle, + std::uint32_t segment_index, + const CmgV2SophonLoadOptions* options, void** out_bmrt); + using CloseArtifact = void (*)(void* context, CmgV2Artifact* artifact) noexcept; + + std::uint32_t abi_major = 0; + void* context = nullptr; + OpenArtifact open_artifact{}; + GetArtifactInfo get_artifact_info{}; + LoadSophonSegment load_sophon_segment{}; + CloseArtifact close_artifact{}; +}; + +/// Minimal Sophon runtime surface needed for native user-model loading and +/// bmrt ownership cleanup. Protected CEMC loading never calls create/load_file. +struct SophonRuntimeApi { + using Create = void* (*)(void* context, bm_handle_t bm_handle); + using SetFlags = void (*)(void* context, void* bmrt, std::uint32_t flags); + using LoadFile = bool (*)(void* context, void* bmrt, const char* model_path); + using Destroy = void (*)(void* context, void* bmrt) noexcept; + + void* context = nullptr; + Create create{}; + SetFlags set_flags{}; + LoadFile load_file{}; + Destroy destroy{}; +}; + +struct SophonRuntimeDeleter { + void* context = nullptr; + SophonRuntimeApi::Destroy destroy = nullptr; + + void operator()(void* runtime) const noexcept; +}; + +using GuardOwnedBmrt = std::unique_ptr<void, SophonRuntimeDeleter>; + +enum class SophonModelLoadError { + kNone, + kInvalidArgument, + kPolicyRejected, + kAbiUnavailable, + kArtifactOpenFailed, + kArtifactInfoFailed, + kArtifactInfoInvalid, + kSegmentLoadFailed, + kAbiContractViolation, + kNativeRuntimeUnavailable, + kNativeRuntimeCreateFailed, + kNativeLoadFailed, + kNoMemory, +}; + +struct SophonModelLoadResult { + SophonModelLoadError error = SophonModelLoadError::kNone; + CmgV2Status guard_status = CMG_V2_OK; + std::vector<GuardOwnedBmrt> runtimes; + + [[nodiscard]] bool IsSuccess() const noexcept { + return error == SophonModelLoadError::kNone; + } + + [[nodiscard]] bool IsOutOfMemory() const noexcept { + return error == SophonModelLoadError::kNoMemory || guard_status == CMG_V2_RESOURCE_NO_MEMORY; + } +}; + +enum class RawBmodelAuthorizationError { + kNone, + kPolicyRejected, +}; + +/// Authorization state resolved before a Sophon device is requested. +struct RawBmodelLoadPlan { + RawBmodelAuthorizationError error = RawBmodelAuthorizationError::kPolicyRejected; + ModelLoadDecision decision; + + [[nodiscard]] bool IsAuthorized() const noexcept { + return error == RawBmodelAuthorizationError::kNone; + } +}; + +/// Production adapters. The guard adapter binds directly to the four frozen +/// CmgV2* symbols when model-guard is enabled; no dynamic lookup or fallback is +/// used. The build compatibility gate is responsible for supplying ABI major 2. +[[nodiscard]] const CemV2Api& FrozenCemV2Api() noexcept; +[[nodiscard]] const SophonRuntimeApi& NativeSophonRuntimeApi() noexcept; + +/// Resolve raw-bmodel format routing. Call this before acquiring device +/// resources. +[[nodiscard]] RawBmodelLoadPlan PrepareRawBmodelLoad(const ModelLoadPolicy& policy, + const std::string& model_path); + +/// Open one authenticated artifact, validate its immutable info, load every +/// segment through the same handle, then close it exactly once. Partial failure +/// destroys every bmrt already returned by the guard. +[[nodiscard]] SophonModelLoadResult LoadCemV2SophonArtifact( + const CemV2Api& guard_api, const SophonRuntimeApi& runtime_api, const std::string& model_path, + CmgV2SourceFormat expected_source_format, bm_handle_t bm_handle, CmgV2SophonLoadFlags flags); + +/// Dispatch a raw-bmodel decision already produced by ModelLoadPolicy. CEMC +/// decisions can only use the guard path; any guard failure is final. Native +/// loading is available only for an explicit kNativeRawBmodel decision. +[[nodiscard]] SophonModelLoadResult LoadRawBmodelByPolicy(const ModelLoadDecision& decision, + const CemV2Api& guard_api, + const SophonRuntimeApi& runtime_api, + bm_handle_t bm_handle); + +/// Execute a previously authorized plan. An unauthorized plan is rejected +/// without touching either the guard ABI or the native BMRuntime API. +[[nodiscard]] SophonModelLoadResult LoadRawBmodelByPlan(const RawBmodelLoadPlan& plan, + const CemV2Api& guard_api, + const SophonRuntimeApi& runtime_api, + bm_handle_t bm_handle); + +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_SOPHON_BACKEND diff --git a/src/nn/guard/ModelLoadPolicy.cc b/src/nn/guard/ModelLoadPolicy.cc new file mode 100644 index 000000000..bd07b40c0 --- /dev/null +++ b/src/nn/guard/ModelLoadPolicy.cc @@ -0,0 +1,88 @@ +#include "nn/guard/ModelLoadPolicy.h" + +#include <filesystem> +#include <fstream> +#include <system_error> +#include <utility> + +namespace cosmo::nn { +namespace { + + namespace fs = std::filesystem; + + constexpr std::array<std::uint8_t, 4> kCemcMagic = {'C', 'E', 'M', 'C'}; + constexpr std::array<std::uint8_t, 4> kCennMagic = {'C', 'E', 'N', 'N'}; + constexpr std::array<std::uint8_t, 4> kLegacyEncryptedMagic = {0x01, 0x00, 0x01, 0xec}; + + bool ReadModelMagic(const fs::path& model_path, ModelMagic& magic) { + std::ifstream input(model_path, std::ios::binary); + std::array<std::uint8_t, 4> bytes{}; + if (!input.read(reinterpret_cast<char*>(bytes.data()), static_cast<std::streamsize>(bytes.size()))) { + return false; + } + magic = DetectModelMagic(bytes); + return true; + } + + ModelLoadDecision Reject(ModelLoadDecision decision, ModelPolicyError error) { + decision.action = ModelLoadAction::kReject; + decision.error = error; + return decision; + } + +} // namespace + +ModelMagic DetectModelMagic(const std::array<std::uint8_t, 4>& bytes) noexcept { + if (bytes == kCemcMagic) { + return ModelMagic::kCemc; + } + if (bytes == kCennMagic) { + return ModelMagic::kCenn; + } + if (bytes == kLegacyEncryptedMagic) { + return ModelMagic::kLegacyEncrypted; + } + return ModelMagic::kUnknown; +} + +ModelLoadPolicy ModelLoadPolicy::Production() { + return ModelLoadPolicy(); +} + +ModelLoadDecision ModelLoadPolicy::Evaluate(const std::string& model_path, ModelLoadIntent intent) const { + ModelLoadDecision decision; + if (model_path.empty()) { + return Reject(std::move(decision), ModelPolicyError::kPathNotRegularFile); + } + + std::error_code error; + const fs::path input_path(model_path); + if (!fs::is_regular_file(fs::status(input_path, error)) || error) { + return Reject(std::move(decision), ModelPolicyError::kPathNotRegularFile); + } + + const fs::path absolute_path = fs::absolute(input_path, error).lexically_normal(); + if (error || absolute_path.empty()) { + return Reject(std::move(decision), ModelPolicyError::kPathNotRegularFile); + } + decision.model_path = absolute_path.string(); + if (!ReadModelMagic(absolute_path, decision.magic)) { + return Reject(std::move(decision), ModelPolicyError::kHeaderReadFailed); + } + + if (decision.magic == ModelMagic::kCemc) { + decision.action = ModelLoadAction::kGuardV2; + return decision; + } + if (decision.magic == ModelMagic::kCenn && intent == ModelLoadIntent::kCosmoNn) { + decision.action = ModelLoadAction::kNativeCenn; + return decision; + } + if (decision.magic == ModelMagic::kUnknown && intent == ModelLoadIntent::kRawBmodel) { + decision.action = ModelLoadAction::kNativeRawBmodel; + return decision; + } + return Reject(std::move(decision), ModelPolicyError::kFormatRejected); +} + +} // namespace cosmo::nn diff --git a/src/nn/guard/ModelLoadPolicy.h b/src/nn/guard/ModelLoadPolicy.h new file mode 100644 index 000000000..c6fbf880c --- /dev/null +++ b/src/nn/guard/ModelLoadPolicy.h @@ -0,0 +1,66 @@ +#pragma once + +#include <array> +#include <cstdint> +#include <string> + +namespace cosmo::nn { + +/// Format selected solely from the first four bytes of a model file. +enum class ModelMagic { + kUnknown, + kCemc, + kCenn, + kLegacyEncrypted, +}; + +/// Native loader selected by the model consumer. +enum class ModelLoadIntent { + kCosmoNn, + kRawBmodel, +}; + +/// Loader action selected from the file format and consumer intent. +enum class ModelLoadAction { + kReject, + kGuardV2, + kNativeCenn, + kNativeRawBmodel, +}; + +/// Stable reason for a rejected decision. +enum class ModelPolicyError { + kNone, + kPathNotRegularFile, + kHeaderReadFailed, + kFormatRejected, +}; + +/// Result of inspecting one model file. +struct ModelLoadDecision { + ModelMagic magic = ModelMagic::kUnknown; + ModelLoadAction action = ModelLoadAction::kReject; + ModelPolicyError error = ModelPolicyError::kNone; + std::string model_path; + + [[nodiscard]] bool IsAllowed() const { + return action != ModelLoadAction::kReject; + } +}; + +/// Detect reserved model formats without host-endian integer conversion. +[[nodiscard]] ModelMagic DetectModelMagic(const std::array<std::uint8_t, 4>& bytes) noexcept; + +/// Minimal format router. CEMC always goes through Guard, while native CENN and +/// raw bmodel loading follow the caller's already selected model type. +class ModelLoadPolicy final { +public: + [[nodiscard]] static ModelLoadPolicy Production(); + + [[nodiscard]] ModelLoadDecision Evaluate(const std::string& model_path, ModelLoadIntent intent) const; + +private: + ModelLoadPolicy() = default; +}; + +} // namespace cosmo::nn diff --git a/src/nn/guard/cosmo_model_guard.h b/src/nn/guard/cosmo_model_guard.h deleted file mode 100644 index c1e829afd..000000000 --- a/src/nn/guard/cosmo_model_guard.h +++ /dev/null @@ -1,58 +0,0 @@ -/// @file cosmo_model_guard.h -/// @brief Public interface for the model guard library. - -#pragma once -#include <cstddef> -#include <cstdint> - -#ifdef COSMO_NN_USE_SOPHON_BACKEND -#include "bmruntime_interface.h" -#endif - -#ifndef GUARD_EXPORT -#define GUARD_EXPORT __attribute__((visibility("default"))) -#endif - -namespace cosmo::guard { - -/// Magic number identifying an encrypted model file. -static constexpr uint32_t kEncryptedMagic = 0xEC010001; - -/// Check whether the file-header magic indicates an encrypted model. -inline bool IsEncryptedModel(uint32_t magic) { - return magic == kEncryptedMagic; -} - -#ifdef COSMO_NN_USE_SOPHON_BACKEND - -/// Error codes returned by guard functions. -enum class GuardError : int { - kSuccess = 0, - kInvalidMagic = -1, - kDecryptFailed = -2, - kLoadFailed = -3, - kHandleNull = -4, - kSegmentOutOfRange = -5, - kFileOpenFailed = -6, - kGuardNotAvailable = -10, -}; - -/// Decrypt and load a single segment from an encrypted model file. -/// -/// @param enc_file_path Path to the encrypted model file. -/// @param bm_handle Sophon device handle. -/// @param segment_index 0-based segment index. -/// @param out_bmrt [out] Created bmrt handle; caller manages lifetime via bmrt_destroy. -/// @return 0 on success, negative GuardError code on failure. -GUARD_EXPORT int DecryptAndLoadSegmentFromFile(const char* enc_file_path, bm_handle_t bm_handle, - uint32_t segment_index, void** out_bmrt); - -/// Query the number of encrypted segments in a model file. -/// -/// @param enc_file_path Path to the encrypted model file. -/// @return Segment count (>0) on success, negative GuardError code on failure. -GUARD_EXPORT int GetEncryptedSegmentCountFromFile(const char* enc_file_path); - -#endif // COSMO_NN_USE_SOPHON_BACKEND - -} // namespace cosmo::guard diff --git a/src/nn/node/net_node.cc b/src/nn/node/net_node.cc index 0f18506b4..bc7ce3d11 100644 --- a/src/nn/node/net_node.cc +++ b/src/nn/node/net_node.cc @@ -1,5 +1,7 @@ #include "nn/node/net_node.h" +#include <utility> + #include "nn/node/node_type_utils.h" namespace cosmo::nn { @@ -31,6 +33,10 @@ void NetNode::SetNetworkOutputNames(std::vector<std::string> names) { top_count = names.size(); } +void NetNode::SetInputContract(std::string contract) { + input_contract_ = std::move(contract); +} + Status NetNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blob, std::vector<std::shared_ptr<Blob>>& params, std::vector<std::shared_ptr<Blob>>& top_blobs) { @@ -42,4 +48,4 @@ Status NetNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blob, return COSMO_NN_OK; } -} // namespace cosmo::nn \ No newline at end of file +} // namespace cosmo::nn diff --git a/src/nn/node/net_node.h b/src/nn/node/net_node.h index b39943c8c..360586422 100644 --- a/src/nn/node/net_node.h +++ b/src/nn/node/net_node.h @@ -33,6 +33,8 @@ class NetNode : public Node { void SetNetworkOutputNames(std::vector<std::string> names); + void SetInputContract(std::string contract); + void SetOutputToCpu(bool v) { output_to_cpu_ = v; } @@ -45,6 +47,7 @@ class NetNode : public Node { // network actual input/output names std::vector<std::string> network_input_names{}; std::vector<std::string> network_output_names{}; + std::string input_contract_{}; }; } // namespace cosmo::nn diff --git a/src/nn/node/yolov8_decode_node.cc b/src/nn/node/yolov8_decode_node.cc index 50d0a1ca0..9a66e5cf5 100644 --- a/src/nn/node/yolov8_decode_node.cc +++ b/src/nn/node/yolov8_decode_node.cc @@ -1,14 +1,37 @@ #include "nn/node/yolov8_decode_node.h" #include <algorithm> +#include <chrono> #include <cmath> +#include "nn/core/inference_pipeline_metrics.h" #include "nn/node/node_type_utils.h" #include "nn/utils/dims_vector_utils.h" #include "nn/utils/op.h" #include "util/Log.h" namespace cosmo::nn { +namespace { + + using MetricsClock = std::chrono::steady_clock; + + uint64_t ElapsedNanoseconds(MetricsClock::time_point started_at) { + return static_cast<uint64_t>( + std::chrono::duration_cast<std::chrono::nanoseconds>(MetricsClock::now() - started_at).count()); + } + + class ScopedPostprocessMetric { + public: + ScopedPostprocessMetric() : started_at_(MetricsClock::now()) {} + ~ScopedPostprocessMetric() { + GetInferencePipelineMetrics().RecordYolov8Postprocess(ElapsedNanoseconds(started_at_)); + } + + private: + MetricsClock::time_point started_at_; + }; + +} // namespace YoloV8DecodeNode::YoloV8DecodeNode() : Node() { node_type = NodeType::NODE_YOLOV8_DECODE; @@ -36,6 +59,10 @@ Status YoloV8DecodeNode::InferTopShapes() { top_blob_shapes = {{max_batch, top_k, top_col}}; top_blob_data_types = {DataType::DATA_TYPE_FLOAT}; + if (shared_resource) { + shared_resource->yolov8_direct_postprocess = {true, base_conf, input_width_, input_height_}; + } + return COSMO_NN_OK; } @@ -49,6 +76,7 @@ size_t YoloV8DecodeNode::GetTopCount() { Status YoloV8DecodeNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blobs, std::vector<std::shared_ptr<Blob>>& top_blobs) { + ScopedPostprocessMetric postprocess_metric; timer.Start(); auto bottom_blob = bottom_blobs.at(0); @@ -56,6 +84,12 @@ Status YoloV8DecodeNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blob ResetTopBlob(top_blob); RETURN_ON_FAIL(CheckNodeInputOutput(bottom_blob, top_blob, true)); + if (shared_resource && shared_resource->yolov8_candidate_batch.ready) { + const auto status = ForwardDirectCandidates(top_blob); + timer.Stop(); + return status; + } + auto bottom_desc = bottom_blob->GetBlobDesc(); auto bottom_handle = bottom_blob->GetHandle(); auto bottom_dim = bottom_desc.dims; @@ -108,52 +142,63 @@ Status YoloV8DecodeNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blob auto top_ptr_i = top_ptr + i * top_row * top_col; std::vector<std::tuple<int, float, int, bool>> conf_list; + conf_list.reserve(static_cast<size_t>(num_boxes)); float global_max_conf = -1.0f; - for (int j = 0; j < num_boxes; j++) { - float* box_data; - float* conf_start; - - if (is_format1) { - // Format 1: [batch, num_boxes, num_features] - // Data layout: box0_features, box1_features, ... - box_data = bottom_ptr_i + j * num_features; - conf_start = box_data + 4; - } else { - // Format 2: [batch, num_features, num_boxes] - // Data layout: feature0_all_boxes, feature1_all_boxes, ... - // For box j: x=bottom_ptr_i[0*num_boxes+j], y=bottom_ptr_i[1*num_boxes+j], ... - box_data = nullptr; // Will access per-feature - conf_start = bottom_ptr_i + 4 * num_boxes + j; // Start of class scores for box j + const bool class_major_scan = + !is_format1 && shared_resource && shared_resource->prefer_yolov8_class_major_scan; + if (class_major_scan) { + class_max_scratch_.assign(static_cast<size_t>(num_boxes), -1.0f); + class_id_scratch_.assign(static_cast<size_t>(num_boxes), -1); + for (int c = 0; c < class_num; ++c) { + const float* scores = bottom_ptr_i + (4 + c) * num_boxes; + for (int j = 0; j < num_boxes; ++j) { + if (scores[j] > class_max_scratch_[j]) { + class_max_scratch_[j] = scores[j]; + class_id_scratch_[j] = c; + } + } } - - // Find max confidence and class_id - float max_conf = -1.0f; - int class_id = -1; - for (int c = 0; c < class_num; c++) { - float conf; + for (int j = 0; j < num_boxes; ++j) { + const float confidence = class_max_scratch_[j]; + global_max_conf = std::max(global_max_conf, confidence); + if (!std::isnan(confidence) && confidence >= base_conf) { + conf_list.emplace_back(j, confidence, class_id_scratch_[j], true); + } + } + } else { + for (int j = 0; j < num_boxes; j++) { if (is_format1) { - conf = conf_start[c]; + // Format 1: [batch, num_boxes, num_features] + // Data layout: box0_features, box1_features, ... + float* box_data = bottom_ptr_i + j * num_features; + float* conf_start = box_data + 4; + float max_conf = -1.0f; + int class_id = -1; + for (int c = 0; c < class_num; c++) { + if (conf_start[c] > max_conf) { + max_conf = conf_start[c]; + class_id = c; + } + } + global_max_conf = std::max(global_max_conf, max_conf); + if (!std::isnan(max_conf) && max_conf >= base_conf) + conf_list.emplace_back(j, max_conf, class_id, true); } else { - conf = bottom_ptr_i[(4 + c) * num_boxes + j]; - } - if (conf > max_conf) { - max_conf = conf; - class_id = c; + // Established format-2 path, retained for non-capable producers. + float max_conf = -1.0f; + int class_id = -1; + for (int c = 0; c < class_num; c++) { + const float conf = bottom_ptr_i[(4 + c) * num_boxes + j]; + if (conf > max_conf) { + max_conf = conf; + class_id = c; + } + } + global_max_conf = std::max(global_max_conf, max_conf); + if (!std::isnan(max_conf) && max_conf >= base_conf) + conf_list.emplace_back(j, max_conf, class_id, true); } } - - float confidence = max_conf; - if (confidence > global_max_conf) { - global_max_conf = confidence; - } - - if (std::isnan(confidence)) - continue; - - if (confidence < base_conf) - continue; - - conf_list.push_back(std::make_tuple(j, confidence, class_id, true)); } LOG_DEBUG( @@ -190,7 +235,9 @@ Status YoloV8DecodeNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blob p, idx, conf, cid, x, y, w, h); } + const auto nms_started = MetricsClock::now(); NMS(conf_list, bottom_ptr_i, num_features, num_boxes, is_format1); + GetInferencePipelineMetrics().RecordYolov8Nms(ElapsedNanoseconds(nms_started)); // Auto-detect normalized coordinates: if all box values are in [0, 1], // the model outputs normalized coords and we need to scale by input_size. @@ -276,6 +323,58 @@ Status YoloV8DecodeNode::Forward(std::vector<std::shared_ptr<Blob>>& bottom_blob return COSMO_NN_OK; } +Status YoloV8DecodeNode::ForwardDirectCandidates(std::shared_ptr<Blob>& top_blob) { + auto& batch = shared_resource->yolov8_candidate_batch; + batch.ready = false; + auto& candidates = batch.candidates; + SetCurrentBatch(top_blob, 1); + + std::sort(candidates.begin(), candidates.end(), + [](const Yolov8Candidate& lhs, const Yolov8Candidate& rhs) { + return lhs.confidence > rhs.confidence; + }); + const auto nms_started = MetricsClock::now(); + NmsDirectCandidates(candidates); + GetInferencePipelineMetrics().RecordYolov8Nms(ElapsedNanoseconds(nms_started)); + + auto* output = static_cast<float*>(top_blob->GetHandle().base); + if (!output) + return Status(COSMO_NN_ERR_NULL_PARAM, "YOLOv8 direct candidate output is null"); + const int limit = std::min(top_k, static_cast<int>(candidates.size())); + int valid_count = 0; + for (const auto& candidate : candidates) { + if (valid_count >= limit) + break; + if (!std::isfinite(candidate.confidence) || candidate.confidence < 0.0f) + continue; + output[valid_count * top_col + 0] = candidate.x; + output[valid_count * top_col + 1] = candidate.y; + output[valid_count * top_col + 2] = candidate.width; + output[valid_count * top_col + 3] = candidate.height; + output[valid_count * top_col + 4] = candidate.confidence; + output[valid_count * top_col + 5] = static_cast<float>(candidate.class_id); + ++valid_count; + } + return COSMO_NN_OK; +} + +void YoloV8DecodeNode::NmsDirectCandidates(std::vector<Yolov8Candidate>& candidates) { + for (size_t i = 0; i < candidates.size(); ++i) { + auto& lhs = candidates[i]; + if (lhs.confidence < 0.0f) + continue; + for (size_t j = i + 1; j < candidates.size(); ++j) { + auto& rhs = candidates[j]; + if (rhs.confidence < 0.0f || lhs.class_id != rhs.class_id) + continue; + float lhs_box[4]{lhs.x, lhs.y, lhs.width, lhs.height}; + float rhs_box[4]{rhs.x, rhs.y, rhs.width, rhs.height}; + if (IOU(lhs_box, rhs_box) >= nms_threshold) + rhs.confidence = -1.0f; + } + } +} + void YoloV8DecodeNode::NMS(std::vector<std::tuple<int, float, int, bool>>& conf_list, float* bottom, int num_features, int num_boxes, bool is_format1) { std::sort(conf_list.begin(), conf_list.end(), diff --git a/src/nn/node/yolov8_decode_node.h b/src/nn/node/yolov8_decode_node.h index 8b0aa976d..10edf31f5 100644 --- a/src/nn/node/yolov8_decode_node.h +++ b/src/nn/node/yolov8_decode_node.h @@ -39,6 +39,10 @@ class YoloV8DecodeNode : public Node { private: void ResetTopBlob(std::shared_ptr<Blob> top); + Status ForwardDirectCandidates(std::shared_ptr<Blob>& top_blob); + + void NmsDirectCandidates(std::vector<Yolov8Candidate>& candidates); + void NMS(std::vector<std::tuple<int, float, int, bool>>& list, float* bottom, int num_features, int num_boxes, bool is_format1); @@ -54,6 +58,8 @@ class YoloV8DecodeNode : public Node { // Net input dimensions for denormalizing coordinates int input_width_ = 0; int input_height_ = 0; + std::vector<float> class_max_scratch_; + std::vector<int> class_id_scratch_; }; } // namespace cosmo::nn diff --git a/src/nn/pipeline/detection_pipeline.cc b/src/nn/pipeline/detection_pipeline.cc index b342d2961..8f07e2c8b 100644 --- a/src/nn/pipeline/detection_pipeline.cc +++ b/src/nn/pipeline/detection_pipeline.cc @@ -99,11 +99,12 @@ Status YoloV5DetPipeline::Init(const PipelineConfig& config, const std::string& for (auto& mc : config.models) { nlohmann::json p = pipeline_utils::ParseJsonObject(mc.params_json); ModelInfo model; - model.name = mc.name; - model.filename = mc.file_name; - model.file_md5 = mc.file_md5; - model.max_batch = mc.max_batch; - max_batch_ = mc.max_batch; + model.name = mc.name; + model.filename = mc.file_name; + model.file_md5 = mc.file_md5; + model.input_contract = pipeline_utils::ReadString(p, "rknn_input_contract", std::string()); + model.max_batch = mc.max_batch; + max_batch_ = mc.max_batch; for (auto& in_def : mc.inputs) { InputNodeInfo input; @@ -191,11 +192,12 @@ Status YoloV8DetPipeline::Init(const PipelineConfig& config, const std::string& for (auto& mc : config.models) { nlohmann::json p = pipeline_utils::ParseJsonObject(mc.params_json); ModelInfo model; - model.name = mc.name; - model.filename = mc.file_name; - model.file_md5 = mc.file_md5; - model.max_batch = mc.max_batch; - max_batch_ = mc.max_batch; + model.name = mc.name; + model.filename = mc.file_name; + model.file_md5 = mc.file_md5; + model.input_contract = pipeline_utils::ReadString(p, "rknn_input_contract", std::string()); + model.max_batch = mc.max_batch; + max_batch_ = mc.max_batch; for (auto& in_def : mc.inputs) { InputNodeInfo input; diff --git a/src/nn/utils/default_component.cc b/src/nn/utils/default_component.cc index c0aeaaa5e..8ffffbdce 100644 --- a/src/nn/utils/default_component.cc +++ b/src/nn/utils/default_component.cc @@ -3,11 +3,26 @@ #include <cstdio> #include <cstring> #include <stdexcept> +#include <utility> #include "nn/pipeline/model_pipeline.h" #include "nn/pipeline/pipeline_utils.h" namespace cosmo::nn { +namespace { + + DefaultComponent::Options MakeOptions(IProfiler* profiler, std::string tokenizer_path, + std::string word_table_path, int device_id, bool use_skip) { + DefaultComponent::Options options; + options.profiler = profiler; + options.tokenizer_path = std::move(tokenizer_path); + options.word_table_path = std::move(word_table_path); + options.device_id = device_id; + options.use_skip = use_skip; + return options; + } + +} // namespace std::mutex DefaultComponent::mutex; @@ -15,7 +30,13 @@ std::mutex DefaultComponent::mutex; DefaultComponent::DefaultComponent(std::string json_path, std::string model_path, DeviceType device_type, IProfiler* profiler, std::string tokenizer_path, - std::string word_table_path, int device_id, bool use_skip) { + std::string word_table_path, int device_id, bool use_skip) + : DefaultComponent( + MakeOptions(profiler, std::move(tokenizer_path), std::move(word_table_path), device_id, use_skip), + std::move(json_path), std::move(model_path), device_type) {} + +DefaultComponent::DefaultComponent(const Options& options, std::string json_path, std::string model_path, + DeviceType device_type) { std::unique_lock<std::mutex> lock(mutex); std::string json_content; @@ -44,8 +65,8 @@ DefaultComponent::DefaultComponent(std::string json_path, std::string model_path if (!pipeline_) throw std::runtime_error("Failed to create pipeline for: " + config.model_type); - status = pipeline_->Init(config, model_path, device_type, device_id, profiler, tokenizer_path, - word_table_path, use_skip); + status = pipeline_->Init(config, model_path, device_type, options.device_id, options.profiler, + options.tokenizer_path, options.word_table_path, options.use_skip); if (!bool(status)) throw std::runtime_error("Pipeline init failed: " + std::string(status.description())); } diff --git a/src/nn/utils/default_component.h b/src/nn/utils/default_component.h index d46ebef8d..1ceb54baf 100644 --- a/src/nn/utils/default_component.h +++ b/src/nn/utils/default_component.h @@ -15,11 +15,24 @@ class ModelPipeline; class PUBLIC DefaultComponent { public: + struct Options { + IProfiler* profiler = nullptr; + std::string tokenizer_path; + std::string word_table_path; + int device_id = 0; + bool use_skip = false; + }; + DefaultComponent(std::string json_path, std::string model_path, DeviceType device_type, IProfiler* profiler = nullptr, std::string tokenizer_path = std::string(), std::string word_table_path = std::string(), int device_id = 0, bool use_skip = false) noexcept(false); + /// Options-first form remains unambiguous with the legacy constructor's + /// optional profiler argument. + DefaultComponent(const Options& options, std::string json_path, std::string model_path, + DeviceType device_type) noexcept(false); + ~DefaultComponent(); DefaultComponent(DefaultComponent const& other) = delete; diff --git a/src/nn/utils/model_info_utils.h b/src/nn/utils/model_info_utils.h index 30c9a7813..db8cad3f9 100644 --- a/src/nn/utils/model_info_utils.h +++ b/src/nn/utils/model_info_utils.h @@ -34,11 +34,12 @@ struct PUBLIC OutputNodeInfo { }; struct PUBLIC ModelInfo { - std::string description = {}; - std::string name = {}; - std::string filename = {}; - std::string file_md5 = {}; - int max_batch = 0; + std::string description = {}; + std::string name = {}; + std::string filename = {}; + std::string file_md5 = {}; + std::string input_contract = {}; + int max_batch = 0; std::vector<InputNodeInfo> input_node_infos = {}; std::vector<OutputNodeInfo> output_node_infos = {}; diff --git a/src/nn/utils/string_format.cc b/src/nn/utils/string_format.cc index ad500327f..c62c5752a 100644 --- a/src/nn/utils/string_format.cc +++ b/src/nn/utils/string_format.cc @@ -28,6 +28,10 @@ std::string DeviceTypeToString(DeviceType val) { return "NAIVE"; case DEVICE_SOPHON_TPU: return "SOPHON_TPU"; + case DEVICE_CPU: + return "CPU"; + case DEVICE_RKNN: + return "RKNN"; default: return "UNKNOWN"; } @@ -50,4 +54,4 @@ std::string VectorToString(std::vector<int8_t> val) { return stream.str(); } -} // namespace cosmo::nn \ No newline at end of file +} // namespace cosmo::nn diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt index 63f232959..b4ccd4c9f 100644 --- a/src/platform/CMakeLists.txt +++ b/src/platform/CMakeLists.txt @@ -22,3 +22,9 @@ if(COSMO_NN_USE_CPU_BACKEND) COSMO_NN_USE_HOST_BACKEND COSMO_NN_USE_ONNX_BACKEND) endif() +if(COSMO_NN_USE_RKNN_BACKEND) + target_compile_definitions(cosmo_platform PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) +endif() diff --git a/src/platform/SystemReboot.cc b/src/platform/SystemReboot.cc index 51102cac4..eec68f1b4 100644 --- a/src/platform/SystemReboot.cc +++ b/src/platform/SystemReboot.cc @@ -13,6 +13,8 @@ namespace { +constexpr char kModelAuthorizationDirectory[] = "model-guard"; + // Execute an immediate system reboot via the `reboot` command. void ImmReboot() { #ifndef COSMO_NN_USE_SOPHON_BACKEND @@ -29,6 +31,18 @@ void ImmReboot() { namespace cosmo::platform { +std::error_code ClearFactoryResetData(const std::string& baseDir) { + std::error_code ec; + for (std::filesystem::directory_iterator entry(baseDir, ec), end; !ec && entry != end;) { + const auto path = entry->path(); + entry.increment(ec); + if (!ec && path.filename() != kModelAuthorizationDirectory) { + std::filesystem::remove_all(path, ec); + } + } + return ec; +} + RebootManager::~RebootManager() { std::lock_guard<std::mutex> lock(mtx_); JoinPendingLocked(); @@ -67,11 +81,10 @@ void RebootManager::Reset(const std::string& reason, const std::string& baseDir) baseDir); return; #else - LOG_INFO("Removing base dir: {}", baseDir); - std::error_code ec; - std::filesystem::remove_all(baseDir, ec); + LOG_INFO("Clearing factory-resettable data in: {}", baseDir); + const auto ec = ClearFactoryResetData(baseDir); if (ec) { - LOG_ERRO("Failed to remove {}: {}", baseDir, ec.message()); + LOG_ERRO("Failed to clear resettable data in {}: {}", baseDir, ec.message()); } ImmReboot(); diff --git a/src/platform/SystemReboot.h b/src/platform/SystemReboot.h index 217700d5d..c6a5f6076 100644 --- a/src/platform/SystemReboot.h +++ b/src/platform/SystemReboot.h @@ -7,10 +7,14 @@ #include <mutex> #include <string> +#include <system_error> #include <thread> namespace cosmo::platform { +// Remove factory-resettable data while retaining the top-level model-guard directory. +std::error_code ClearFactoryResetData(const std::string& baseDir); + // Manages system reboot and factory-reset operations. // Thread-safe: all public methods serialize on an internal mutex to prevent // concurrent reboot thread re-assignment. @@ -26,9 +30,9 @@ class RebootManager { // reason: Human-readable reason for the reboot (logged). void Reboot(const std::string& reason); - // Schedule a factory reset (delete baseDir then reboot). + // Schedule a factory reset (clear resettable entries in baseDir then reboot). // reason: Human-readable reason for the reset (logged). - // baseDir: Absolute path to the data directory to remove. + // baseDir: Absolute path containing resettable data. void Reset(const std::string& reason, const std::string& baseDir); private: diff --git a/src/service/CMakeLists.txt b/src/service/CMakeLists.txt index d15acfdcf..d0c444d25 100644 --- a/src/service/CMakeLists.txt +++ b/src/service/CMakeLists.txt @@ -30,3 +30,11 @@ if(COSMO_NN_USE_CPU_BACKEND) COSMO_NN_USE_HOST_BACKEND COSMO_NN_USE_ONNX_BACKEND) endif() + +if(COSMO_NN_USE_RKNN_BACKEND) + target_link_libraries(cosmo_service PRIVATE rknnrt) + target_compile_definitions(cosmo_service PRIVATE + COSMO_NN_USE_RKNN_BACKEND + COSMO_NN_USE_HOST_BACKEND + COSMO_NN_USE_RAW_MODEL_BACKEND) +endif() diff --git a/src/service/ai/impl/LlmInferServiceImpl.cc b/src/service/ai/impl/LlmInferServiceImpl.cc index 85451971a..b3038f71a 100644 --- a/src/service/ai/impl/LlmInferServiceImpl.cc +++ b/src/service/ai/impl/LlmInferServiceImpl.cc @@ -13,7 +13,8 @@ static constexpr const char* kTag = "LlmInferService "; namespace cosmo::service { bool LlmInferServiceImpl::EnsureInit(const std::string& atomic_code) { -#ifdef COSMO_NN_USE_HOST_BACKEND +#if (defined(COSMO_NN_USE_HOST_BACKEND) && !defined(COSMO_NN_USE_RKNN_BACKEND)) || \ + (defined(COSMO_NN_USE_RKNN_BACKEND) && !defined(COSMO_NN_USE_RKLLM_BACKEND)) // LLM inference (Qwen3VL/Qwen3.5) is not supported on x86 platform LOG_WARN("{}EnsureInit: LLM inference is not supported on x86 platform (atomicCode: {})", kTag, atomic_code); @@ -60,7 +61,7 @@ bool LlmInferServiceImpl::EnsureInit(const std::string& atomic_code) { atomic_code_ = atomic_code; LOG_INFO("{}EnsureInit: Qwen3VL shared instance created. AtomicCode:{}", kTag, atomic_code); return true; -#endif // COSMO_NN_USE_HOST_BACKEND +#endif } bool LlmInferServiceImpl::IsInitialized() const { diff --git a/src/service/algorithm/impl/AlgorithmLayoutMng.cc b/src/service/algorithm/impl/AlgorithmLayoutMng.cc index 9a9ff8f31..7599f0367 100644 --- a/src/service/algorithm/impl/AlgorithmLayoutMng.cc +++ b/src/service/algorithm/impl/AlgorithmLayoutMng.cc @@ -54,7 +54,18 @@ bool AlgorithmLayoutMng::ResolveLayoutDirectory(const std::string& requested_pat return false; } - const std::string& selected_path = requested_path.empty() ? algorithm_path : requested_path; + // The Web client must not need to know the device's configured app-data + // root. An empty value means the writable algorithm root, while the + // stable logical name selects the read-only template root. Legacy + // absolute paths remain accepted when they resolve inside this runtime. + std::string selected_path; + if (requested_path.empty()) { + selected_path = algorithm_path; + } else if (requested_path == "algorithm_template") { + selected_path = (std::filesystem::path(resolved_resource) / "algorithm_template").string(); + } else { + selected_path = requested_path; + } if (!cosmo::path::ResolveExistingPathWithinRoot(resolved_resource, selected_path, cosmo::path::PathEntryType::kDirectory, resolved_path)) { return false; diff --git a/src/service/camera/ICameraTaskConfig.h b/src/service/camera/ICameraTaskConfig.h index 0c72a4077..049b483db 100644 --- a/src/service/camera/ICameraTaskConfig.h +++ b/src/service/camera/ICameraTaskConfig.h @@ -139,6 +139,17 @@ class ICameraTaskConfig { /// @return true if at least one task references this schedule. virtual bool ScheduleInUse(const std::string& scheduleId) = 0; + /// Keep the camera channel active while a live-preview publisher exists. + /// The first lease starts the channel on demand; later leases share it. + /// @param cameraId Camera identifier. + /// @return ErrorEnum::Success when the channel is running or its start was accepted. + virtual cosmo::util::ErrorEnum AcquirePreviewChannel(const std::string& cameraId) = 0; + + /// Release one live-preview lease. The last release allows the channel to + /// stop again when no analysis task or image capture still needs it. + /// @param cameraId Camera identifier. + virtual void ReleasePreviewChannel(const std::string& cameraId) = 0; + /// Capture a single image frame from a camera channel. /// @param channelId Channel identifier. /// @param timeOutMs Timeout in milliseconds (default: 3000). diff --git a/src/service/camera/impl/CameraServiceImpl.cc b/src/service/camera/impl/CameraServiceImpl.cc index 5eeeffd5c..20633b7a5 100644 --- a/src/service/camera/impl/CameraServiceImpl.cc +++ b/src/service/camera/impl/CameraServiceImpl.cc @@ -20,6 +20,7 @@ #include <regex> #include "flow/channel/AlgChannel.h" +#include "flow/channel/VideoEofPolicy.h" #include "flow/common/AlgDataRecord.h" #include "flow/common/FlowTaskUtil.h" #include "service/algorithm/IAlgorithmQuery.h" @@ -581,11 +582,17 @@ void CameraServiceImpl::MonitorCameraEntity(const CameraEntityPtr& camera, bool MsgCameraAttr attr; if (ServiceRegistry::Instance().Get<ITaskChannel>().GetChannelAttr(camera->videoChannelId, attr)) { - bool isReadEnd = + const bool isReadEnd = (attr.dataStatus == static_cast<int>(camera::AlgDemuxStatus::AlgDemuxReadEnd)); + const bool isTerminalReadEnd = + flow::IsTerminalOfflineReadEnd(isReadEnd, attr.repeatPending); + if (isReadEnd && attr.repeatPending) { + LOG_ERRO("[{}/{}] Refusing task auto-stop: local video is reopening", + camera->videoChannelId, task->task_id_); + } // Channel has finished reading and no active data remains (queue fully consumed) - if (isReadEnd && !ServiceRegistry::Instance().Get<ITaskChannel>().TaskDataActive( - camera->videoChannelId)) { + if (isTerminalReadEnd && !ServiceRegistry::Instance().Get<ITaskChannel>().TaskDataActive( + camera->videoChannelId)) { LOG_INFO("[{}/{}] Offline video completed, auto-stopping task to release resources", camera->videoChannelId, task->task_id_); ServiceRegistry::Instance().Get<ITaskLifecycle>().TaskStop(task->task_id_); @@ -642,7 +649,8 @@ void CameraServiceImpl::UpdateChannelState(const CameraEntityPtr& camera) { camera->videoChannelId); ServiceRegistry::Instance().Get<ITaskLifecycle>().TaskStart(camera->videoChannelId, camera->channel_task_); - } else if (!anyTaskRunning && channelRunning && !camera->is_capturing_image_.load()) { + } else if (!anyTaskRunning && channelRunning && !camera->is_capturing_image_.load() && + camera->preview_lease_count_.load(std::memory_order_acquire) == 0) { // Cache video attributes before stopping the channel MsgCameraAttr attr; if (ServiceRegistry::Instance().Get<ITaskChannel>().GetChannelAttr(camera->videoChannelId, attr)) { diff --git a/src/service/camera/impl/CameraServiceImpl.h b/src/service/camera/impl/CameraServiceImpl.h index 2024f6ea5..34536759a 100644 --- a/src/service/camera/impl/CameraServiceImpl.h +++ b/src/service/camera/impl/CameraServiceImpl.h @@ -64,6 +64,7 @@ class CameraEntity { std::string channel_url_{}; // Stream URL std::atomic<bool> is_capturing_image_{false}; + std::atomic<size_t> preview_lease_count_{0}; std::atomic<ChannelStatus> probed_status_{ChannelStatus::ChannelStatusOffline}; mutable std::mutex attr_mtx_; @@ -130,6 +131,8 @@ class CameraServiceImpl : public ICameraService { bool IsAlgorithmInUse(const std::string& algorithmId) const override; bool ScheduleInUse(const std::string& scheduleId) override; + util::ErrorEnum AcquirePreviewChannel(const std::string& cameraId) override; + void ReleasePreviewChannel(const std::string& cameraId) override; VideoFramePtr CaptureImage(const std::string& channelId, int timeOutMs = 3000) override; util::ErrorEnum BindTaskLibPara(const std::string& cameraId, const std::string& algorithmCode, const std::vector<std::string>& bindLibs, diff --git a/src/service/camera/impl/CameraTaskConfig.cc b/src/service/camera/impl/CameraTaskConfig.cc index e91fef7c4..a058dad60 100644 --- a/src/service/camera/impl/CameraTaskConfig.cc +++ b/src/service/camera/impl/CameraTaskConfig.cc @@ -47,7 +47,7 @@ namespace { // ============================================================ util::ErrorEnum CameraServiceImpl::CheckTaskStartResource() const { -#ifdef COSMO_NN_USE_SOPHON_BACKEND +#if defined(COSMO_NN_USE_SOPHON_BACKEND) || defined(COSMO_NN_USE_RKNN_BACKEND) if (!ServiceRegistry::Instance().Get<IConfigReadService>().GetResourceLimit()) { return util::ErrorEnum::Success; } @@ -414,6 +414,65 @@ util::ErrorEnum CameraServiceImpl::QuerySwitch(const std::string& cameraId, cons }); } +util::ErrorEnum CameraServiceImpl::AcquirePreviewChannel(const std::string& cameraId) { + auto camera = GetCamera(cameraId); + if (!camera) { + LOG_INFO("{} Not Exist", cameraId); + return util::ErrorEnum::CameraNotExist; + } + + std::lock_guard<std::mutex> command_lock(camera->command_mtx_); + if (camera->deleting_) { + return util::ErrorEnum::CameraNotExist; + } + + const size_t previous = camera->preview_lease_count_.fetch_add(1, std::memory_order_acq_rel); + if (previous > 0) { + return util::ErrorEnum::Success; + } + + auto& lifecycle = ServiceRegistry::Instance().Get<ITaskLifecycle>(); + if (lifecycle.TaskIsStart(camera->channel_task_)) { + return util::ErrorEnum::Success; + } + + LOG_INFO("[{}] Auto-starting ChannelTask for live preview", cameraId); + if (!lifecycle.TaskStart(cameraId, camera->channel_task_)) { + camera->preview_lease_count_.fetch_sub(1, std::memory_order_acq_rel); + LOG_WARN("[{}] Failed to auto-start ChannelTask for live preview", cameraId); + return util::ErrorEnum::DemuxNoData; + } + return util::ErrorEnum::Success; +} + +void CameraServiceImpl::ReleasePreviewChannel(const std::string& cameraId) { + auto camera = GetCamera(cameraId); + if (!camera) { + return; + } + + std::lock_guard<std::mutex> command_lock(camera->command_mtx_); + if (camera->deleting_) { + return; + } + + size_t current = camera->preview_lease_count_.load(std::memory_order_acquire); + while (current > 0 && !camera->preview_lease_count_.compare_exchange_weak( + current, current - 1, std::memory_order_acq_rel, std::memory_order_acquire)) { + } + if (current == 0) { + LOG_WARN("[{}] Live preview lease release ignored because no lease is active", cameraId); + return; + } + if (current > 1) { + return; + } + + // UpdateChannelState reads the count again, so a concurrent acquire cannot + // have its channel stopped by this final release. + UpdateChannelState(camera); +} + VideoFramePtr CameraServiceImpl::CaptureImage(const std::string& cameraId, int timeOutMs) { auto camera = GetCamera(cameraId); if (!camera) { diff --git a/src/service/event/impl/AlarmPushServiceImpl.cc b/src/service/event/impl/AlarmPushServiceImpl.cc index dd4809233..3e08f19b1 100644 --- a/src/service/event/impl/AlarmPushServiceImpl.cc +++ b/src/service/event/impl/AlarmPushServiceImpl.cc @@ -291,24 +291,23 @@ bool AlarmPushServiceImpl::Submit(std::string url, IN& rgtIn, OUT& rgtOut, int t AppendHeader(http_req); std::string json_result{}; if (!cosmo::util::EncodeJson(rgtIn, json_result)) { - LOG_ERRO("Msg:{} Enc Json failed", url); + LOG_ERRO("{}", "Alarm HTTP request EncodeJson failed"); return false; } - LOG_INFO("Msg:{} Content:{:.2048}{}", url, json_result, json_result.size() > 2048 ? " ..." : ""); + LOG_DEBUG("Alarm HTTP request_bytes:{}", json_result.size()); http_req.SetData(json_result); http_req.SetTimeout(timeout_sec); auto ret = http_req.Submit(cosmo::network::http::HttpRequestMethod::kPost); if (200 != ret) { - LOG_ERRO("Msg:{} Submit Failed, Error Code:{}, Response:{:.2048}{}", url, ret, http_handler.GetData(), - http_handler.GetData().size() > 2048 ? " ..." : ""); + LOG_ERRO("Alarm HTTP submit failed, status:{} response_bytes:{}", ret, http_handler.GetData().size()); return false; } - LOG_INFO("Msg:{} Get Response is:{}", url, http_handler.GetData()); + LOG_DEBUG("Alarm HTTP completed, status:{} response_bytes:{}", ret, http_handler.GetData().size()); if (!cosmo::util::DecodeJson(http_handler.GetData(), rgtOut)) { - LOG_ERRO("Msg:{} Get Response is:{} ", url, http_handler.GetData()); + LOG_ERRO("Alarm HTTP response DecodeJson failed, response_bytes:{}", http_handler.GetData().size()); return false; } return true; @@ -348,10 +347,10 @@ bool AlarmPushServiceImpl::OnEvents(cosmo::CMsgOnEventsReq&& reqEvent) { reqEvent.property.recognition.LibImage = ReadFileBase64(reqEvent.property.recognition.LibImage); if (!Submit(url, reqEvent, rsp)) { - LOG_WARN("Msg:{} recordId:{} Push To {} Failed", reqEvent.messageId, reqEvent.recordId, url); + LOG_WARN("Msg:{} recordId:{} alarm push failed", reqEvent.messageId, reqEvent.recordId); return false; } - LOG_INFO("Msg:{} recordId:{} Push To {} Ok", reqEvent.messageId, reqEvent.recordId, url); + LOG_INFO("Msg:{} recordId:{} alarm push OK", reqEvent.messageId, reqEvent.recordId); ServiceRegistry::Instance().Get<IAlarmRecordService>().UpdateAlarmReportStatus(reqEvent.messageId, true); return true; } diff --git a/src/service/event/impl/EventNotifierImpl.cc b/src/service/event/impl/EventNotifierImpl.cc index 619c99f99..d88a2d7f8 100644 --- a/src/service/event/impl/EventNotifierImpl.cc +++ b/src/service/event/impl/EventNotifierImpl.cc @@ -72,8 +72,12 @@ bool EventNotifierImpl::StartServer(const std::string& ip, int port) { http_app_ = std::make_unique<uWS::TemplatedApp<false>>(); http_app_ ->any("/*", - [](auto* /*res*/, auto* /*req*/) { - // placeholder – receive handler intentionally empty + [](auto* res, auto* /*req*/) { + // uWebSockets requires every ordinary HTTP handler to either + // respond or install an abort handler. Leaving this route + // empty terminates the whole engine when a browser or health + // probe reaches the WebSocket port without an Upgrade header. + res->writeStatus("404 Not Found")->end("Not Found"); }) .options("/*", [](auto* res, auto* /*req*/) { @@ -124,7 +128,7 @@ void EventNotifierImpl::InitWebSocketServer(const std::function<void(std::string {uWS::DISABLED, kMaxPayloadLength, kIdleTimeoutSec, kMaxBackpressure, // open [this](auto ws, auto req) { - LOG_INFO("Recv a websocket request, url: {}, host: {}", req->getUrl(), req->getHeader("host")); + LOG_INFO("Recv a websocket request, host: {}", req->getHeader("host")); ws_connections_[cosmo::util::ToLower(req->getUrl())].push_back(ws); ++ws_connection_count_; has_ws_connection_.store(true, std::memory_order_release); @@ -147,7 +151,7 @@ void EventNotifierImpl::InitWebSocketServer(const std::function<void(std::string it_map.second.erase(it_vec); --ws_connection_count_; has_ws_connection_.store(ws_connection_count_ != 0, std::memory_order_release); - LOG_INFO("Remove a websocket connection, Url: {}", it_map.first); + LOG_INFO("{}", "Remove a websocket connection"); break; } } diff --git a/src/service/infra/impl/LinkageCrud.cc b/src/service/infra/impl/LinkageCrud.cc index abc850b49..b084efdbc 100644 --- a/src/service/infra/impl/LinkageCrud.cc +++ b/src/service/infra/impl/LinkageCrud.cc @@ -75,8 +75,8 @@ cosmo::util::ErrorEnum LinkageServiceImpl::Add(const std::string& name, const st if (!cosmo::util::DecodeJson(normalized_workflow, storage.workflow)) { return cosmo::util::ErrorEnum::Failed; } - auto task = MakeTask(name, storage); - if (!task) { + auto task = storage.workflow.empty() ? nullptr : MakeTask(name, storage); + if (!storage.workflow.empty() && !task) { return cosmo::util::ErrorEnum::ParameterException; } const std::string new_id = cosmo::util::GenerateUUID(); diff --git a/src/service/infra/impl/LinkageServiceImpl.cc b/src/service/infra/impl/LinkageServiceImpl.cc index 08d2ace9a..5002b5b75 100644 --- a/src/service/infra/impl/LinkageServiceImpl.cc +++ b/src/service/infra/impl/LinkageServiceImpl.cc @@ -110,8 +110,9 @@ void LinkageServiceImpl::LoadConfig() { LOG_WARN("Read strategy {}/{} failed", strategy.strategy_id, strategy.name); continue; } - strategy.task = MakeTask(strategy.name, strategy.strategy); - if (!strategy.task) { + strategy.task = + strategy.strategy.workflow.empty() ? nullptr : MakeTask(strategy.name, strategy.strategy); + if (!strategy.strategy.workflow.empty() && !strategy.task) { LOG_WARN("Reject invalid linkage strategy {}/{}", strategy.strategy_id, strategy.name); continue; } diff --git a/src/service/media/dto/AudioDto.h b/src/service/media/dto/AudioDto.h index e37a5957a..aef31122a 100644 --- a/src/service/media/dto/AudioDto.h +++ b/src/service/media/dto/AudioDto.h @@ -74,7 +74,7 @@ namespace Audio { }; // Audio device modify struct MsgModifyAudioDeviceRecv : public MsgRecvHead { - util::RangeInt<1, 2> devOperation{0}; + util::RangeInt<1, 2> devOperation{1}; MsgBaseAudioDeviceInfo audioDev; }; @@ -140,7 +140,7 @@ namespace Audio { // Audio device test struct MsgTestAudioDeviceRecv : public MsgRecvHead { - util::RangeInt<1, 2> operation{0}; // 1: File test, 2: Text test + util::RangeInt<1, 2> operation{1}; // 1: File test, 2: Text test std::string devSn; // Audio device ID std::string data; // Text or file ID util::RangeInt<0, 100> volume{50}; // Volume diff --git a/src/service/media/impl/AudioServiceImpl.cc b/src/service/media/impl/AudioServiceImpl.cc index 86f9942b2..6f1b62075 100644 --- a/src/service/media/impl/AudioServiceImpl.cc +++ b/src/service/media/impl/AudioServiceImpl.cc @@ -25,7 +25,8 @@ static constexpr const char* kTag = "AudioServiceImpl"; AudioServiceImpl::AudioServiceImpl() : audio_db_file_(cosmo::path::GetCfgPath() + "/audioMng.json"), device_db_file_(cosmo::path::GetCfgPath() + "/AudioDeviceMng.json") { - audio_file_path_ = cosmo::path::GetBaseDir() + audio_relative_path_; + default_audio_file_name_ = cosmo::path::GetAppBaseDir() + "/files/Audio/beep.ogg"; + audio_file_path_ = cosmo::path::GetBaseDir() + audio_relative_path_; LOG_INFO("Init Cfg:{} FilePath:{}", audio_db_file_, audio_file_path_); { std::error_code err; diff --git a/src/service/media/impl/AudioServiceImpl.h b/src/service/media/impl/AudioServiceImpl.h index b4c666626..e1657848e 100644 --- a/src/service/media/impl/AudioServiceImpl.h +++ b/src/service/media/impl/AudioServiceImpl.h @@ -72,11 +72,11 @@ class AudioServiceImpl : public IAudioService { std::string audio_file_path_; size_t max_audio_count_{1000}; std::vector<cosmo::AlarmAudioInfo> audio_info_list_; - std::string audio_relative_path_ = "/audioMng/"; - std::string default_audio_name_ = "默认"; // Default audio (business label) - std::string default_audio_id_ = "1234567890"; // Default audio ID - std::string default_audio_file_name_ = "./media/audio/beep.ogg"; // Default audio file - std::string default_audio_web_file_ = "/audioMng/beep.ogg"; + std::string audio_relative_path_ = "/audioMng/"; + std::string default_audio_name_ = "默认"; // Default audio (business label) + std::string default_audio_id_ = "1234567890"; // Default audio ID + std::string default_audio_file_name_; // Packaged default audio file + std::string default_audio_web_file_ = "/audioMng/beep.ogg"; // :: AudioDevice state mutable std::shared_mutex device_mtx_; diff --git a/src/service/media/impl/AudioServicePlayback.cc b/src/service/media/impl/AudioServicePlayback.cc index 51689f6d4..661354052 100644 --- a/src/service/media/impl/AudioServicePlayback.cc +++ b/src/service/media/impl/AudioServicePlayback.cc @@ -251,20 +251,21 @@ struct AudioDeviceRsp { bool AudioServiceImpl::HttpSubmit(const std::string& url, const std::string& data) { auto response = ServiceRegistry::Instance().Get<cosmo::service::IHttpClient>().Post(url, data); if (response.statusCode != 200) { - LOG_ERRO("Request {} , data:{} status: {}", url, data, response.statusCode); + LOG_ERRO("Audio HTTP request failed, status:{} request_bytes:{} response_bytes:{}", + response.statusCode, data.size(), response.body.size()); return false; } // Get result auto ret_json = response.body; - // Print result - LOG_INFO("From {} Submit {} Get : {}", url, data, ret_json); + LOG_DEBUG("Audio HTTP completed, status:{} request_bytes:{} response_bytes:{}", response.statusCode, + data.size(), ret_json.size()); AudioDeviceRsp rsp; try { auto j = nlohmann::json::parse(ret_json); j.get_to(rsp); - } catch (const std::exception& e) { - LOG_ERRO("Parse:{} Get {} ", ret_json, e.what()); + } catch (const std::exception&) { + LOG_ERRO("Audio HTTP response parse failed, response_bytes:{}", ret_json.size()); return false; } diff --git a/src/service/media/impl/LiveStreamServiceImpl.cc b/src/service/media/impl/LiveStreamServiceImpl.cc index a9e1b7bff..32c2a7bc5 100644 --- a/src/service/media/impl/LiveStreamServiceImpl.cc +++ b/src/service/media/impl/LiveStreamServiceImpl.cc @@ -4,6 +4,8 @@ #include "service/media/impl/LiveStreamServiceImpl.h" #include <algorithm> +#include <thread> +#include <utility> #include "flow/stream/StreamViewer.h" #include "media/PreviewPipelineMetrics.h" @@ -37,6 +39,72 @@ namespace { return algCode.empty() ? kRawStreamReadyTimeout : kAlgStreamReadyTimeout; } + bool IsChannelStartupState(cosmo::util::ErrorEnum state) { + switch (state) { + case cosmo::util::ErrorEnum::ActionReady: + case cosmo::util::ErrorEnum::ActionStart: + case cosmo::util::ErrorEnum::ActionStop: + case cosmo::util::ErrorEnum::DemuxStreamStart: + case cosmo::util::ErrorEnum::DemuxNoData: + return true; + default: + return false; + } + } + + bool WaitForChannelReady(const cosmo::AlgChannelPtr& channel, std::chrono::milliseconds timeout, + cosmo::util::ErrorEnum& last_state) { + const auto deadline = std::chrono::steady_clock::now() + timeout; + do { + last_state = channel->GetUrlStatus(); + if (last_state == cosmo::util::ErrorEnum::Success) { + return true; + } + if (!IsChannelStartupState(last_state)) { + return false; + } + std::this_thread::sleep_for(std::chrono::milliseconds(25)); + } while (std::chrono::steady_clock::now() < deadline); + return false; + } + + class PreviewChannelLease { + public: + PreviewChannelLease(service::ICameraTaskConfig& camera_service, std::string channel_id) + : camera_service_(camera_service), channel_id_(std::move(channel_id)) {} + + cosmo::util::ErrorEnum Acquire() { + const auto result = camera_service_.AcquirePreviewChannel(channel_id_); + acquired_ = result == cosmo::util::ErrorEnum::Success; + return result; + } + + void Commit() { + acquired_ = false; + } + + ~PreviewChannelLease() { + if (acquired_) { + camera_service_.ReleasePreviewChannel(channel_id_); + } + } + + private: + service::ICameraTaskConfig& camera_service_; + std::string channel_id_; + bool acquired_{false}; + }; + + void StopViewerAndReleasePreview(const cosmo::StreamViewerPtr& viewer) { + if (!viewer) { + return; + } + const auto channel_id = viewer->GetChannelId(); + viewer->Stop(); + service::ServiceRegistry::Instance().Get<service::ICameraTaskConfig>().ReleasePreviewChannel( + channel_id); + } + std::string BuildStreamName(const std::string& channelId, const std::string& algCode) { return algCode.empty() ? channelId : COSMO_FORMAT("{}_{}", channelId, algCode); } @@ -101,6 +169,7 @@ void LiveStreamServiceImpl::Stop() { } std::vector<cosmo::StreamViewerPtr> viewers_to_stop; + std::vector<std::string> orphaned_channel_leases; { std::unique_lock<std::shared_mutex> lock(mtx_); viewers_to_stop.swap(viewers_); @@ -112,13 +181,20 @@ void LiveStreamServiceImpl::Stop() { if (gate->viewer) { viewers_to_stop.push_back(gate->viewer); gate->viewer.reset(); + } else if (gate->channel_lease_acquired) { + orphaned_channel_leases.push_back(gate->channel_id); } + gate->channel_lease_acquired = false; gate->cv.notify_all(); } starting_viewers_.clear(); } for (auto& viewer : viewers_to_stop) { - viewer->Stop(); + StopViewerAndReleasePreview(viewer); + } + for (const auto& channel_id : orphaned_channel_leases) { + service::ServiceRegistry::Instance().Get<service::ICameraTaskConfig>().ReleasePreviewChannel( + channel_id); } stopped_ = true; LOG_INFO("{}", "LiveStreamServiceImpl Delete"); @@ -162,19 +238,32 @@ cosmo::util::ErrorEnum LiveStreamServiceImpl::ViewerCreate(const std::string& ch if (!channel_inst) { return cosmo::util::ErrorEnum::CameraNotExist; } + auto& camera_task_config = service::ServiceRegistry::Instance().Get<service::ICameraTaskConfig>(); if (!algCode.empty()) { - const auto tasks = - service::ServiceRegistry::Instance().Get<service::ICameraTaskConfig>().GetTasks(channelId); - const bool task_exists = std::any_of(tasks.begin(), tasks.end(), - [&](const auto& task) { return task.algorithmCode == algCode; }); - if (!task_exists) { + const auto tasks = camera_task_config.GetTasks(channelId); + const auto task_it = std::find_if(tasks.begin(), tasks.end(), + [&](const auto& task) { return task.algorithmCode == algCode; }); + if (task_it == tasks.end()) { LOG_WARN("viewer rejected: stream={}/{} task=absent", channelId, algCode); return cosmo::util::ErrorEnum::TaskNotExist; } + if (!task_it->enable) { + LOG_WARN("viewer rejected: stream={}/{} task=stopped", channelId, algCode); + return cosmo::util::ErrorEnum::ActionStop; + } } - cosmo::util::ErrorEnum channelState = channel_inst->GetUrlStatus(); - if (cosmo::util::ErrorEnum::Success != channelState) { - LOG_WARN("Channel Stream State {}", channelState); + + const auto ready_timeout = StreamReadyTimeout(algCode); + PreviewChannelLease channel_lease(camera_task_config, channelId); + const auto lease_result = channel_lease.Acquire(); + if (lease_result != cosmo::util::ErrorEnum::Success) { + return lease_result; + } + + cosmo::util::ErrorEnum channel_state = channel_inst->GetUrlStatus(); + if (!WaitForChannelReady(channel_inst, ready_timeout, channel_state)) { + LOG_WARN("viewer channel startup failed: stream={}/{} state={}", channelId, algCode, + cosmo::util::ErrorEnumName(channel_state)); return cosmo::util::ErrorEnum::DemuxNoData; } @@ -188,7 +277,6 @@ cosmo::util::ErrorEnum LiveStreamServiceImpl::ViewerCreate(const std::string& ch const bool requires_encoder = !(algCode.empty() && attr.codec == "H264"); const std::string viewer_key = BuildViewerKey(channelId, algCode); - const auto ready_timeout = StreamReadyTimeout(algCode); std::shared_ptr<ViewerStartGate> gate; bool start_owner = false; @@ -228,16 +316,19 @@ cosmo::util::ErrorEnum LiveStreamServiceImpl::ViewerCreate(const std::string& ch return cosmo::util::ErrorEnum::EncodeFailed; } } - gate = std::make_shared<ViewerStartGate>(); - gate->requires_encoder = requires_encoder; + gate = std::make_shared<ViewerStartGate>(); + gate->channel_id = channelId; + gate->requires_encoder = requires_encoder; + gate->channel_lease_acquired = true; starting_viewers_.emplace(viewer_key, gate); + channel_lease.Commit(); start_owner = true; LOG_INFO("viewer startup reserved: stream={}/{} encoder={}", channelId, algCode, requires_encoder); } } if (failed_viewer) { - failed_viewer->Stop(); + StopViewerAndReleasePreview(failed_viewer); LOG_INFO("viewer failed publisher released before restart: stream={}/{}", channelId, algCode); } @@ -264,16 +355,22 @@ cosmo::util::ErrorEnum LiveStreamServiceImpl::ViewerCreate(const std::string& ch if (viewer) { viewer->Stop(); } + bool release_channel_lease = false; { std::unique_lock<std::shared_mutex> lock(mtx_); gate->viewer.reset(); - gate->result = result; - gate->finished = true; - auto it = starting_viewers_.find(viewer_key); + gate->result = result; + gate->finished = true; + release_channel_lease = gate->channel_lease_acquired; + gate->channel_lease_acquired = false; + auto it = starting_viewers_.find(viewer_key); if (it != starting_viewers_.end() && it->second == gate) { starting_viewers_.erase(it); } } + if (release_channel_lease) { + camera_task_config.ReleasePreviewChannel(channelId); + } gate->cv.notify_all(); cosmo::media::GetPreviewPipelineMetrics().PreviewFailed(); LOG_ERRO("viewer startup failed: stream={}/{} stage={} error={} publisher=released", channelId, @@ -338,8 +435,9 @@ cosmo::util::ErrorEnum LiveStreamServiceImpl::ViewerCreate(const std::string& ch viewer->MarkReady(std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::steady_clock::now() - request_started_at)); viewers_.push_back(viewer); - gate->result = cosmo::util::ErrorEnum::Success; - gate->finished = true; + gate->result = cosmo::util::ErrorEnum::Success; + gate->finished = true; + gate->channel_lease_acquired = false; gate->viewer.reset(); auto it = starting_viewers_.find(viewer_key); if (it != starting_viewers_.end() && it->second == gate) { @@ -365,6 +463,7 @@ bool LiveStreamServiceImpl::ViewerDelete(const std::string& channelId, const std } cosmo::StreamViewerPtr viewer_to_stop; + std::string channel_lease_to_release; { std::unique_lock<std::shared_mutex> lock(mtx_); auto it = FindViewer(channelId, algCode); @@ -387,6 +486,10 @@ bool LiveStreamServiceImpl::ViewerDelete(const std::string& channelId, const std if (gate->participants == 0) { gate->cancelled = true; viewer_to_stop = gate->viewer; + if (gate->channel_lease_acquired) { + channel_lease_to_release = gate->channel_id; + gate->channel_lease_acquired = false; + } LOG_INFO("viewer startup cancel requested: stream={}/{} waiters=0", channelId, algCode); } else { LOG_INFO("viewer startup participant released: stream={}/{} waiters_remaining={}", @@ -400,6 +503,10 @@ bool LiveStreamServiceImpl::ViewerDelete(const std::string& channelId, const std if (viewer_to_stop) { viewer_to_stop->Stop(); } + if (!channel_lease_to_release.empty()) { + service::ServiceRegistry::Instance().Get<service::ICameraTaskConfig>().ReleasePreviewChannel( + channel_lease_to_release); + } return true; } @@ -418,11 +525,6 @@ cosmo::util::ErrorEnum LiveStreamServiceImpl::ViewerHeartBeat(const std::string& if (!channel_inst) { return cosmo::util::ErrorEnum::CameraNotExist; } - cosmo::util::ErrorEnum channelState = channel_inst->GetUrlStatus(); - if (cosmo::util::ErrorEnum::Success != channelState) { - LOG_WARN("Channel Stream State {}", channelState); - return channelState; - } std::shared_lock<std::shared_mutex> lock(mtx_); LOG_DEBUG("alive channel size {} {}", viewers_.size(), channelId); auto it = FindViewer(channelId, algCode); @@ -438,7 +540,15 @@ cosmo::util::ErrorEnum LiveStreamServiceImpl::ViewerHeartBeat(const std::string& // A successful keepalive for a missing viewer leaves the browser believing // that a stream removed by the watchdog (or a service restart) is still - // healthy. Return a normal stream error so the client can recreate it. + // healthy. Return the source error when one exists, otherwise a normal + // no-data error so the client can recreate it. An existing publisher is + // deliberately checked before source state: a short RTSP outage must not + // tear down a healthy viewer that can resume as soon as demux reconnects. + const cosmo::util::ErrorEnum channelState = channel_inst->GetUrlStatus(); + if (cosmo::util::ErrorEnum::Success != channelState) { + LOG_WARN("Channel Stream State {}", channelState); + return channelState; + } return cosmo::util::ErrorEnum::DemuxNoData; } @@ -488,7 +598,7 @@ void LiveStreamServiceImpl::CheckAliveTasks() { } } for (auto& viewer : viewers_to_stop) { - viewer->Stop(); + StopViewerAndReleasePreview(viewer); } } diff --git a/src/service/media/impl/LiveStreamServiceImpl.h b/src/service/media/impl/LiveStreamServiceImpl.h index ad6aaab97..025808ddc 100644 --- a/src/service/media/impl/LiveStreamServiceImpl.h +++ b/src/service/media/impl/LiveStreamServiceImpl.h @@ -43,7 +43,9 @@ class LiveStreamServiceImpl : public ILiveStreamService { cosmo::StreamViewerPtr viewer; cosmo::util::ErrorEnum result{cosmo::util::ErrorEnum::NotInit}; size_t participants{1}; + std::string channel_id; bool requires_encoder{false}; + bool channel_lease_acquired{false}; bool finished{false}; bool cancelled{false}; }; diff --git a/src/service/model/impl/ModelAddModel.cc b/src/service/model/impl/ModelAddModel.cc index e052715d5..189592d6e 100644 --- a/src/service/model/impl/ModelAddModel.cc +++ b/src/service/model/impl/ModelAddModel.cc @@ -179,6 +179,19 @@ util::ErrorEnum ModelImportExporter::ValidateAddModelInputs( std::string& resolved_model_code, std::vector<std::string>& bmodel_paths) { namespace fs = std::filesystem; +#ifdef COSMO_NN_USE_RKNN_BACKEND + static const std::vector<std::string> kSupportedRknnModelTypes = { + // Expose only model types verified end-to-end on a real RK3576 device. + // Keypoints, feature extraction, OCR and Grounding DINO remain disabled + // until their matching RKNN models pass runtime validation. + "yolov8_det", "classify", "qwen3_5"}; + if (std::find(kSupportedRknnModelTypes.begin(), kSupportedRknnModelTypes.end(), modelType) == + kSupportedRknnModelTypes.end()) { + LOG_WARN("[AddModel] Unsupported RK3576 model type: {}", modelType); + return util::ErrorEnum::InvalidParam; + } +#endif + resolved_model_code = generate_unique_model_code_(); LOG_INFO("[AddModel] Using resolved model code: {} (request code: {})", resolved_model_code, modelCode); if (resolved_model_code.empty()) @@ -203,11 +216,20 @@ util::ErrorEnum ModelImportExporter::ValidateAddModelInputs( } bool is_sam2 = (modelType == "sam2"); +#ifdef COSMO_NN_USE_RKNN_BACKEND + const bool is_rkllm_qwen35 = (modelType == "qwen3_5"); + if (is_rkllm_qwen35 && bmodel_files.size() != 2) { + LOG_WARN("{}", "[AddModel] RK3576 Qwen3.5 requires model.rkllm and vision.rknn"); + return util::ErrorEnum::InvalidParam; + } +#else + const bool is_rkllm_qwen35 = false; +#endif if (is_sam2 && bmodel_files.size() != 2) { LOG_WARN("{}", "[AddModel] SAM2 model requires exactly 2 bmodel files (encoder and decoder)"); return util::ErrorEnum::InvalidParam; } - if (!is_sam2 && bmodel_files.size() != 1) { + if (!is_sam2 && !is_rkllm_qwen35 && bmodel_files.size() != 1) { LOG_WARN("{}", "[AddModel] Non-SAM2 model must have exactly 1 bmodel file"); return util::ErrorEnum::InvalidParam; } @@ -243,15 +265,40 @@ util::ErrorEnum ModelImportExporter::ValidateAddModelInputs( return util::ErrorEnum::InvalidParam; } - // Check all bmodel files exist - for (const auto& bmodelFile : bmodel_files) { + // Check all model files exist. Keep RKLLM files in a deterministic language/vision order. + std::vector<const cosmo::Model::BmodelFileInfo*> ordered_model_files; + ordered_model_files.reserve(bmodel_files.size()); +#ifdef COSMO_NN_USE_RKNN_BACKEND + if (is_rkllm_qwen35) { + const cosmo::Model::BmodelFileInfo* language_model = nullptr; + const cosmo::Model::BmodelFileInfo* vision_model = nullptr; + for (const auto& file : bmodel_files) { + if (file.role == "language") + language_model = &file; + else if (file.role == "vision") + vision_model = &file; + } + if (!language_model || !vision_model) { + LOG_WARN("{}", "[AddModel] RK3576 Qwen3.5 model roles must be language and vision"); + return util::ErrorEnum::InvalidParam; + } + // Staged upload paths are opaque and intentionally do not preserve client filenames. + // The authenticated frontend validates the extensions; roles keep the server copy order safe. + ordered_model_files = {language_model, vision_model}; + } else +#endif + { + for (const auto& file : bmodel_files) + ordered_model_files.push_back(&file); + } + for (const auto* bmodelFile : ordered_model_files) { std::string resolved_path; - if (!ResolveManagedUploadFile(bmodelFile.filePath, resolved_path)) { - LOG_WARN("[AddModel] bmodel file is not a managed upload: {}", bmodelFile.filePath); + if (!ResolveManagedUploadFile(bmodelFile->filePath, resolved_path)) { + LOG_WARN("[AddModel] model file is not a managed upload: {}", bmodelFile->filePath); return util::ErrorEnum::FileNotExist; } bmodel_paths.push_back(std::move(resolved_path)); - LOG_INFO("[AddModel] bmodel file: role={}, path={}", bmodelFile.role, bmodel_paths.back()); + LOG_INFO("[AddModel] model file: role={}, path={}", bmodelFile->role, bmodel_paths.back()); } return util::ErrorEnum::Success; @@ -326,7 +373,36 @@ util::ErrorEnum ModelImportExporter::WriteNnFile(const std::string& modelType, const std::string& model_dir) { namespace fs = std::filesystem; -#ifdef COSMO_NN_USE_ONNX_BACKEND +#ifdef COSMO_NN_USE_RKNN_BACKEND + std::string convert_error; + if (modelType == "qwen3_5") { + if (bmodel_paths.size() != 2) { + convert_error = "RK3576 Qwen3.5 requires one RKLLM file and one vision RKNN file"; + } else { + const std::vector<std::string> destination_names = {"model.rkllm", "vision.rknn"}; + for (size_t i = 0; i < destination_names.size(); ++i) { + std::error_code ec; + const auto destination = (fs::path(model_dir) / destination_names[i]).string(); + fs::copy_file(bmodel_paths[i], destination, fs::copy_options::overwrite_existing, ec); + if (ec) { + convert_error = "Failed to copy RKLLM component to " + destination + ": " + ec.message(); + break; + } + LOG_INFO("[AddModel] RKLLM: copied component to {}", destination); + } + } + } else if (bmodel_paths.size() != 1) { + convert_error = "RKNN add-model requires exactly one model file"; + } else { + const std::string model_file_path = model_dir + "/model.rknn"; + std::error_code ec; + fs::copy_file(bmodel_paths[0], model_file_path, fs::copy_options::overwrite_existing, ec); + if (ec) + convert_error = "Failed to copy RKNN model to " + model_file_path + ": " + ec.message(); + else + LOG_INFO("[AddModel] RKNN: copied model file to {}", model_file_path); + } +#elif defined(COSMO_NN_USE_ONNX_BACKEND) // CPU/x86: copy .onnx file directly; no Sophon wrapper needed. std::string convert_error; if (modelType == "sam2") { diff --git a/src/service/model/impl/ModelImporter.cc b/src/service/model/impl/ModelImporter.cc index 171270333..4a4d1b0e3 100644 --- a/src/service/model/impl/ModelImporter.cc +++ b/src/service/model/impl/ModelImporter.cc @@ -293,7 +293,8 @@ util::ErrorEnum ModelImportExporter::ImportDirectoryArchive(const std::string& t has_model = std::any_of(fs::directory_iterator(sub_dir), fs::directory_iterator(), [](const auto& f) { return f.path().extension() == cosmo::util::kModelFileExt || - f.path().extension() == ".bmodel" || f.path().extension() == ".onnx"; + f.path().extension() == ".bmodel" || f.path().extension() == ".onnx" || + f.path().extension() == ".rknn"; }); } if (!has_model) { @@ -424,7 +425,7 @@ util::ErrorEnum ModelImportExporter::ImportModel(const std::string& archivePath) if (!f.is_regular_file()) continue; auto ext = f.path().extension().string(); - if (ext == cosmo::util::kModelFileExt || ext == ".bmodel" || ext == ".onnx") { + if (ext == cosmo::util::kModelFileExt || ext == ".bmodel" || ext == ".onnx" || ext == ".rknn") { flat_structure = true; break; } diff --git a/src/service/model/impl/ModelServiceImpl.cc b/src/service/model/impl/ModelServiceImpl.cc index 89b6bcd94..8812a983d 100644 --- a/src/service/model/impl/ModelServiceImpl.cc +++ b/src/service/model/impl/ModelServiceImpl.cc @@ -256,7 +256,7 @@ cosmo::util::ErrorEnum ModelServiceImpl::CheckModelValid(std::string un_zip_file for (const auto& file : files) { if (file.find(cosmo::util::kModelFileExt) != std::string::npos || - file.find(".onnx") != std::string::npos) { + file.find(".onnx") != std::string::npos || file.find(".rknn") != std::string::npos) { found_model = true; } if (file.find(".json") != std::string::npos) { diff --git a/src/service/modelguard/IModelAuthorizationService.h b/src/service/modelguard/IModelAuthorizationService.h new file mode 100644 index 000000000..9cf77bf78 --- /dev/null +++ b/src/service/modelguard/IModelAuthorizationService.h @@ -0,0 +1,23 @@ +#pragma once + +#include <string> + +#include "util/ErrorCode.h" + +namespace cosmo::service { + +struct ModelAuthorizationStatus { + bool supported{false}; + bool authorized{false}; + std::string state{"unsupported"}; +}; + +class IModelAuthorizationService { +public: + virtual ~IModelAuthorizationService() = default; + virtual ModelAuthorizationStatus Status() = 0; + virtual util::ErrorEnum CreateDeviceRequest(std::string& file_path, std::string& file_name) = 0; + virtual util::ErrorEnum InstallCertificate(const std::string& file_path) = 0; +}; + +} // namespace cosmo::service diff --git a/src/service/modelguard/impl/ModelAuthorizationServiceImpl.cc b/src/service/modelguard/impl/ModelAuthorizationServiceImpl.cc new file mode 100644 index 000000000..e5c71af10 --- /dev/null +++ b/src/service/modelguard/impl/ModelAuthorizationServiceImpl.cc @@ -0,0 +1,83 @@ +#include "service/modelguard/impl/ModelAuthorizationServiceImpl.h" + +#include <filesystem> +#include <utility> + +#include "util/Exec.h" +#include "util/PathUtil.h" +#include "util/UuidUtil.h" + +namespace cosmo::service { +namespace { + constexpr std::uintmax_t kDeviceRequestSize = 48; + constexpr std::uintmax_t kCertificateSize = 236; +} // namespace + +ModelAuthorizationServiceImpl::ModelAuthorizationServiceImpl(std::string provision_tool) + : provision_tool_(std::move(provision_tool)) {} + +bool ModelAuthorizationServiceImpl::ToolAvailable() const { + std::error_code ec; + const auto status = std::filesystem::status(provision_tool_, ec); + return !ec && std::filesystem::is_regular_file(status) && + (status.permissions() & std::filesystem::perms::owner_exec) != std::filesystem::perms::none; +} + +ModelAuthorizationStatus ModelAuthorizationServiceImpl::Status() { + if (!ToolAvailable()) { + return {}; + } + std::string output; + const int result = util::Exec({provision_tool_, "status"}, output); + if (result == 0 && output.rfind("valid ", 0) == 0) { + return {true, true, "valid"}; + } + for (const auto* state : {"certificate_unavailable", "certificate_rejected", "device_mismatch", + "identity_rejected", "resource_failure"}) { + if (output.find(state) != std::string::npos) { + return {true, false, state}; + } + } + return {true, false, "unknown"}; +} + +util::ErrorEnum ModelAuthorizationServiceImpl::CreateDeviceRequest(std::string& file_path, + std::string& file_name) { + file_path.clear(); + file_name.clear(); + if (!ToolAvailable()) { + return util::ErrorEnum::OperationNotSupport; + } + const auto candidate = std::filesystem::path(path::GetTemporaryDirPath()) / + ("model-authorization-request-" + util::GenerateUUID() + ".cmpr"); + std::string output; + if (util::Exec({provision_tool_, "request", "--output", candidate.string()}, output) != 0) { + return util::ErrorEnum::Failed; + } + std::error_code ec; + if (!std::filesystem::is_regular_file(candidate, ec) || ec || + std::filesystem::file_size(candidate, ec) != kDeviceRequestSize || ec) { + std::filesystem::remove(candidate, ec); + return util::ErrorEnum::FileAnalysisFailed; + } + file_path = candidate.string(); + file_name = "device-request.cmpr"; + return util::ErrorEnum::Success; +} + +util::ErrorEnum ModelAuthorizationServiceImpl::InstallCertificate(const std::string& file_path) { + if (!ToolAvailable()) { + return util::ErrorEnum::OperationNotSupport; + } + std::error_code ec; + if (!std::filesystem::is_regular_file(file_path, ec) || ec || + std::filesystem::file_size(file_path, ec) != kCertificateSize || ec) { + return util::ErrorEnum::FileAnalysisFailed; + } + std::string output; + return util::Exec({provision_tool_, "install", "--certificate", file_path}, output) == 0 + ? util::ErrorEnum::Success + : util::ErrorEnum::Failed; +} + +} // namespace cosmo::service diff --git a/src/service/modelguard/impl/ModelAuthorizationServiceImpl.h b/src/service/modelguard/impl/ModelAuthorizationServiceImpl.h new file mode 100644 index 000000000..00480dc8b --- /dev/null +++ b/src/service/modelguard/impl/ModelAuthorizationServiceImpl.h @@ -0,0 +1,23 @@ +#pragma once + +#include <string> + +#include "service/modelguard/IModelAuthorizationService.h" + +namespace cosmo::service { + +class ModelAuthorizationServiceImpl final : public IModelAuthorizationService { +public: + explicit ModelAuthorizationServiceImpl( + std::string provision_tool = "/appfs/cosmo_wander/cwai_data/bin/cosmo-model-provision"); + + ModelAuthorizationStatus Status() override; + util::ErrorEnum CreateDeviceRequest(std::string& file_path, std::string& file_name) override; + util::ErrorEnum InstallCertificate(const std::string& file_path) override; + +private: + bool ToolAvailable() const; + std::string provision_tool_; +}; + +} // namespace cosmo::service diff --git a/src/service/network/impl/MqttLifecycleServiceImpl.cc b/src/service/network/impl/MqttLifecycleServiceImpl.cc index f0450f648..b8a78ea46 100644 --- a/src/service/network/impl/MqttLifecycleServiceImpl.cc +++ b/src/service/network/impl/MqttLifecycleServiceImpl.cc @@ -220,12 +220,12 @@ void MqttLifecycleServiceImpl::MqttStart() { client_id = mqtt_param.clientId; user_name = mqtt_param.userName; passwd = mqtt_param.passwd; - LOG_INFO("RunMode StandAlone {}:{}", url, port); + LOG_INFO("RunMode StandAlone MQTT port:{}", port); } else if (RunMode::RunModeIotNetwork == run_mode) { auto iot_param = ServiceRegistry::Instance().Get<IConfigNetworkService>().GetIotNetworkParam(); url = iot_param.mqttIp; port = iot_param.mqttPort; - LOG_INFO("RunMode IOTNetwork {}:{}", url, port); + LOG_INFO("RunMode IOTNetwork MQTT port:{}", port); } else { LOG_ERRO("RunMode ({}) Un-Support", run_mode); Disconnect(); @@ -373,12 +373,12 @@ bool MqttLifecycleServiceImpl::MqttClientConnect(const std::string& sn, const st opts.client_id = sn; opts.username = "aibox::" + sn; } - LOG_INFO("MLINK CONNECT To {}", url); + LOG_INFO("{}", "MLINK CONNECT requested"); opts.device_sn = sn; LOG_INFO("Before MQTTClientCreate, MQTTClient State: [{}]", mqtt_client_->MQTTClientIsConnected()); if (mqtt_client_->MQTTClientCreate(opts)) { - LOG_ERRO("MQTTClientCreate Failed, SN: [{}], serverURI: [{}]", sn, url); + LOG_ERRO("MQTTClientCreate Failed, SN: [{}]", sn); return false; } if (!connect_running_.load(std::memory_order_acquire)) { @@ -646,9 +646,9 @@ void MqttLifecycleServiceImpl::HandleMessage(mqtt::MqttCommonMsgDl&& msg) { std::string res_string; (void)cosmo::util::EncodeJson(response, res_string); - LOG_INFO("Handle:{} With {} Ms Rsp: {:.4096}{}", msg.head.action, - chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - time_start).count(), - res_string, res_string.size() > 4096 ? " ..." : ""); + LOG_DEBUG("Handle:{} elapsed_ms:{} response_bytes:{}", msg.head.action, + chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - time_start).count(), + res_string.size()); SendAsyncData(k_device_to_platform, res_string); } diff --git a/src/service/path/IUploadStagingService.h b/src/service/path/IUploadStagingService.h index 60c022036..bc598cf8a 100644 --- a/src/service/path/IUploadStagingService.h +++ b/src/service/path/IUploadStagingService.h @@ -20,6 +20,7 @@ enum class UploadPurpose { kAlgorithm, kUpgrade, kImage, + kModelAuthorizationCertificate, }; [[nodiscard]] std::string_view UploadPurposeName(UploadPurpose purpose); diff --git a/src/service/path/impl/FileServiceImpl.cc b/src/service/path/impl/FileServiceImpl.cc index e02ba684d..89c411122 100644 --- a/src/service/path/impl/FileServiceImpl.cc +++ b/src/service/path/impl/FileServiceImpl.cc @@ -309,13 +309,13 @@ bool FileServiceImpl::DownloadFile(const std::string& url, std::vector<uint8_t>& http_req.SetTimeout(200); auto ret_code = static_cast<int>(http_req.Submit(cosmo::network::http::HttpRequestMethod::kGet)); if (ret_code != 200) { - LOG_ERRO("{} Download[{}] Fail! curl return [{}]", kTag, url, ret_code); + LOG_ERRO("{} Download failed, status:{}", kTag, ret_code); return false; } data = http_hnd.GetImageData(); if (data.empty()) { - LOG_WARN("{} Download[{}] returned an empty body", kTag, url); + LOG_WARN("{} Download returned an empty body", kTag); return false; } return true; diff --git a/src/service/path/impl/UploadStagingServiceImpl.cc b/src/service/path/impl/UploadStagingServiceImpl.cc index c7980d2a4..e20834a6b 100644 --- a/src/service/path/impl/UploadStagingServiceImpl.cc +++ b/src/service/path/impl/UploadStagingServiceImpl.cc @@ -304,14 +304,17 @@ std::string_view UploadPurposeName(UploadPurpose purpose) { return "upgrade"; case UploadPurpose::kImage: return "image"; + case UploadPurpose::kModelAuthorizationCertificate: + return "model-authorization-certificate"; } return {}; } bool ParseUploadPurpose(std::string_view value, UploadPurpose& purpose) { - for (auto candidate : {UploadPurpose::kModelComponent, UploadPurpose::kModelArchive, - UploadPurpose::kVideo, UploadPurpose::kFaceImport, UploadPurpose::kAudio, - UploadPurpose::kAlgorithm, UploadPurpose::kUpgrade, UploadPurpose::kImage}) { + for (auto candidate : + {UploadPurpose::kModelComponent, UploadPurpose::kModelArchive, UploadPurpose::kVideo, + UploadPurpose::kFaceImport, UploadPurpose::kAudio, UploadPurpose::kAlgorithm, + UploadPurpose::kUpgrade, UploadPurpose::kImage, UploadPurpose::kModelAuthorizationCertificate}) { if (value == UploadPurposeName(candidate)) { purpose = candidate; return true; @@ -1086,6 +1089,7 @@ bool UploadStagingServiceImpl::IsPurposeValid(UploadPurpose purpose) { case UploadPurpose::kAlgorithm: case UploadPurpose::kUpgrade: case UploadPurpose::kImage: + case UploadPurpose::kModelAuthorizationCertificate: return true; } return false; diff --git a/src/service/path/impl/file/HttpFileServerCli.cc b/src/service/path/impl/file/HttpFileServerCli.cc index b46b61378..77ba85f52 100644 --- a/src/service/path/impl/file/HttpFileServerCli.cc +++ b/src/service/path/impl/file/HttpFileServerCli.cc @@ -131,7 +131,7 @@ bool HttpFileServerCli::HttpclientSubmit(FileServerClientType type, cosmo::FMsgR } std::string json_str = FileServerRespTrim(http_req.GetContent()); if (!cosmo::util::DecodeJson(json_str, rgtOut)) { - LOG_ERRO("{} DecodeJson failed: {}", kTag, json_str); + LOG_ERRO("{} DecodeJson failed, response_bytes:{}", kTag, json_str.size()); return false; } return true; @@ -164,7 +164,7 @@ bool HttpFileServerCli::HttpclientSubmit(FileServerClientType type, const std::s http_post_req.AppendHeader("token", token); http_post_req.AppendHeader("isHttps", is_https ? "true" : "false"); - LOG_INFO("{} HttpclientSubmit fileUrl[{}]", kTag, fileUrl); + LOG_DEBUG("{} HttpclientSubmit file_url_bytes:{}", kTag, fileUrl.size()); http_post_req.AppendHeader("fileUrl", fileUrl); http_post_req.SetTimeout(200); if (!http_req.SetFile("file", rgtIn, "application/octet-stream")) { @@ -183,7 +183,7 @@ bool HttpFileServerCli::HttpclientSubmit(FileServerClientType type, const std::s } std::string json_str = FileServerRespTrim(http_req.GetContent()); if (!cosmo::util::DecodeJson(json_str, rgtOut)) { - LOG_ERRO("{} DecodeJson failed: {}", kTag, json_str); + LOG_ERRO("{} DecodeJson failed, response_bytes:{}", kTag, json_str.size()); return false; } return true; diff --git a/src/service/system/IDeviceInfoService.h b/src/service/system/IDeviceInfoService.h index 464309543..30f1b84d7 100644 --- a/src/service/system/IDeviceInfoService.h +++ b/src/service/system/IDeviceInfoService.h @@ -26,12 +26,13 @@ struct DeviceBasicInfo { /// Hardware resource utilization item for dashboard display. struct HwResourceItem { - std::string key; ///< Resource key identifier. - std::string name; ///< Human-readable resource name. - int usedPercent{0}; ///< Usage percentage (0–100). - std::string usedSize; ///< Used capacity string (e.g. "2.1 GB"). - std::string unusedSize; ///< Free capacity string. - int available{0}; ///< Available units. + std::string key; ///< Resource key identifier. + std::string name; ///< Human-readable resource name. + int usedPercent{0}; ///< Usage percentage (0–100). + std::string usedSize; ///< Used capacity string (e.g. "2.1 GiB"). + std::string unusedSize; ///< Free capacity string. + int available{0}; ///< Available units. + std::string memoryDomain; ///< Physical memory pool identity; empty for non-memory resources. }; /// Aggregate device info service providing device identity diff --git a/src/service/system/ISystemOperationService.h b/src/service/system/ISystemOperationService.h index 448c8652a..14bfcceea 100644 --- a/src/service/system/ISystemOperationService.h +++ b/src/service/system/ISystemOperationService.h @@ -6,6 +6,7 @@ #include <string> #include "service/detail/ServiceRegistry.h" +#include "service/system/UpgradeSpace.h" #include "util/ErrorCode.h" namespace cosmo::service { @@ -39,6 +40,12 @@ class ISystemOperationService { /// @return ErrorEnum::kSuccess on success. virtual cosmo::util::ErrorEnum Upgrade(const std::string& filePath) = 0; + /// Check the data-volume budget required for an upgrade package. When + /// explicitly confirmed, event images and videos may be removed before + /// the budget is inspected again. + virtual cosmo::util::ErrorEnum CheckUpgradeSpace(std::uint64_t packageSizeBytes, bool cleanupEventMedia, + UpgradeSpaceStatus& status) = 0; + // ── Debug Tools ── /// Dump thread status information to the log for debugging. diff --git a/src/service/system/UpgradeSpace.h b/src/service/system/UpgradeSpace.h new file mode 100644 index 000000000..c1d5713a5 --- /dev/null +++ b/src/service/system/UpgradeSpace.h @@ -0,0 +1,16 @@ +#pragma once + +#include <cstdint> + +namespace cosmo::service { + +struct UpgradeSpaceStatus { + bool sufficient{false}; + std::uint64_t required_bytes{0}; + std::uint64_t available_bytes{0}; + std::uint64_t event_media_bytes{0}; + std::uint64_t deleted_media_bytes{0}; + std::uint64_t deleted_media_files{0}; +}; + +} // namespace cosmo::service diff --git a/src/service/system/dto/SystemDeviceDto.cc b/src/service/system/dto/SystemDeviceDto.cc index c044a5a83..1548af669 100644 --- a/src/service/system/dto/SystemDeviceDto.cc +++ b/src/service/system/dto/SystemDeviceDto.cc @@ -54,15 +54,17 @@ void from_json(const nlohmann::json& j, MsgQueryHardwareResourceSend::Item& v) { JSON_OPT(j, v, usedSize); JSON_OPT(j, v, unusedSize); JSON_OPT(j, v, available); + JSON_OPT(j, v, memoryDomain); } void to_json(nlohmann::json& j, const MsgQueryHardwareResourceSend::Item& v) { - j["key"] = v.key; - j["name"] = v.name; - j["usedPercent"] = v.usedPercent; - j["usedSize"] = v.usedSize; - j["unusedSize"] = v.unusedSize; - j["available"] = v.available; + j["key"] = v.key; + j["name"] = v.name; + j["usedPercent"] = v.usedPercent; + j["usedSize"] = v.usedSize; + j["unusedSize"] = v.unusedSize; + j["available"] = v.available; + j["memoryDomain"] = v.memoryDomain; } void from_json(const nlohmann::json& j, MsgQueryHardwareResourceSend::ResData& v) { diff --git a/src/service/system/dto/SystemDeviceDto.h b/src/service/system/dto/SystemDeviceDto.h index 3ace6d2eb..e497eda2a 100644 --- a/src/service/system/dto/SystemDeviceDto.h +++ b/src/service/system/dto/SystemDeviceDto.h @@ -30,6 +30,7 @@ struct MsgQueryHardwareResourceSend : public MsgSendHead { std::string usedSize; std::string unusedSize; int available{0}; + std::string memoryDomain; friend void to_json(nlohmann::json& j, const Item& v); friend void from_json(const nlohmann::json& j, Item& v); }; diff --git a/src/service/system/dto/SystemMaintainDto.cc b/src/service/system/dto/SystemMaintainDto.cc index 0432c3c6c..ac585d013 100644 --- a/src/service/system/dto/SystemMaintainDto.cc +++ b/src/service/system/dto/SystemMaintainDto.cc @@ -67,6 +67,86 @@ void from_json(const nlohmann::json& j, MsgUpgradeRecv& v) { JSON_OPT(j, v, fileUrl); } +void to_json(nlohmann::json& j, const MsgCheckUpgradeSpaceRecv& v) { + to_json(j, static_cast<const MsgRecvHead&>(v)); + j["packageSizeBytes"] = v.packageSizeBytes; + j["cleanupEventMedia"] = v.cleanupEventMedia; +} + +void from_json(const nlohmann::json& j, MsgCheckUpgradeSpaceRecv& v) { + from_json(j, static_cast<MsgRecvHead&>(v)); + JSON_OPT(j, v, packageSizeBytes); + JSON_OPT(j, v, cleanupEventMedia); +} + +void to_json(nlohmann::json& j, const MsgCheckUpgradeSpaceSend& v) { + to_json(j, static_cast<const MsgSendHead&>(v)); + j["resData"] = v.resData; +} + +void from_json(const nlohmann::json& j, MsgCheckUpgradeSpaceSend& v) { + from_json(j, static_cast<MsgSendHead&>(v)); + JSON_OPT(j, v, resData); +} + +void to_json(nlohmann::json& j, const MsgCheckUpgradeSpaceSend::ResData& v) { + j = nlohmann::json{{"sufficient", v.sufficient}, + {"requiredBytes", v.requiredBytes}, + {"availableBytes", v.availableBytes}, + {"eventMediaBytes", v.eventMediaBytes}, + {"deletedMediaBytes", v.deletedMediaBytes}, + {"deletedMediaFiles", v.deletedMediaFiles}}; +} + +void from_json(const nlohmann::json& j, MsgCheckUpgradeSpaceSend::ResData& v) { + JSON_OPT(j, v, sufficient); + JSON_OPT(j, v, requiredBytes); + JSON_OPT(j, v, availableBytes); + JSON_OPT(j, v, eventMediaBytes); + JSON_OPT(j, v, deletedMediaBytes); + JSON_OPT(j, v, deletedMediaFiles); +} + +void to_json(nlohmann::json& j, const MsgQueryModelAuthorizationSend& v) { + to_json(j, static_cast<const MsgSendHead&>(v)); + j["resData"] = v.resData; +} +void from_json(const nlohmann::json& j, MsgQueryModelAuthorizationSend& v) { + from_json(j, static_cast<MsgSendHead&>(v)); + JSON_OPT(j, v, resData); +} +void to_json(nlohmann::json& j, const MsgQueryModelAuthorizationSend::ResData& v) { + j = nlohmann::json{{"supported", v.supported}, {"authorized", v.authorized}, {"state", v.state}}; +} +void from_json(const nlohmann::json& j, MsgQueryModelAuthorizationSend::ResData& v) { + if (j.contains("supported")) + j.at("supported").get_to(v.supported); + if (j.contains("authorized")) + j.at("authorized").get_to(v.authorized); + if (j.contains("state")) + j.at("state").get_to(v.state); +} +void to_json(nlohmann::json& j, const MsgDownloadModelAuthorizationRequestSend& v) { + to_json(j, static_cast<const MsgSendHead&>(v)); + j["filePath"] = v.filePath; + j["fileName"] = v.fileName; +} +void from_json(const nlohmann::json& j, MsgDownloadModelAuthorizationRequestSend& v) { + from_json(j, static_cast<MsgSendHead&>(v)); + JSON_OPT(j, v, filePath); + JSON_OPT(j, v, fileName); +} +void to_json(nlohmann::json& j, const MsgInstallModelAuthorizationRecv& v) { + to_json(j, static_cast<const MsgRecvHead&>(v)); + j["uploadId"] = v.uploadId; + j["filePath"] = v.filePath; +} +void from_json(const nlohmann::json& j, MsgInstallModelAuthorizationRecv& v) { + from_json(j, static_cast<MsgRecvHead&>(v)); + JSON_OPT(j, v, uploadId); + JSON_OPT(j, v, filePath); +} + void to_json(nlohmann::json& j, const MsgQueryDocumentUrlRecv& v) { to_json(j, static_cast<const MsgRecvHead&>(v)); j["type"] = v.type; diff --git a/src/service/system/dto/SystemMaintainDto.h b/src/service/system/dto/SystemMaintainDto.h index 77a8d85e9..c1f59659c 100644 --- a/src/service/system/dto/SystemMaintainDto.h +++ b/src/service/system/dto/SystemMaintainDto.h @@ -1,5 +1,6 @@ #pragma once +#include <cstdint> #include <system_error> #include "util/dto/ServerMsgTypes.h" @@ -62,6 +63,59 @@ void from_json(const nlohmann::json& j, MsgUpgradeRecv& v); // struct MsgUpgradeSend : public MsgSendHead {}; +struct MsgCheckUpgradeSpaceRecv : public MsgRecvHead { + std::uint64_t packageSizeBytes{0}; + bool cleanupEventMedia{false}; +}; + +void to_json(nlohmann::json& j, const MsgCheckUpgradeSpaceRecv& v); +void from_json(const nlohmann::json& j, MsgCheckUpgradeSpaceRecv& v); + +struct MsgCheckUpgradeSpaceSend : public MsgSendHead { + struct ResData { + bool sufficient{false}; + std::uint64_t requiredBytes{0}; + std::uint64_t availableBytes{0}; + std::uint64_t eventMediaBytes{0}; + std::uint64_t deletedMediaBytes{0}; + std::uint64_t deletedMediaFiles{0}; + friend void to_json(nlohmann::json& j, const ResData& v); + friend void from_json(const nlohmann::json& j, ResData& v); + } resData; +}; + +void to_json(nlohmann::json& j, const MsgCheckUpgradeSpaceSend& v); +void from_json(const nlohmann::json& j, MsgCheckUpgradeSpaceSend& v); + +struct MsgQueryModelAuthorizationRecv : public MsgRecvHead {}; +struct MsgQueryModelAuthorizationSend : public MsgSendHead { + struct ResData { + bool supported{false}; + bool authorized{false}; + std::string state; + friend void to_json(nlohmann::json& j, const ResData& v); + friend void from_json(const nlohmann::json& j, ResData& v); + } resData; +}; +void to_json(nlohmann::json& j, const MsgQueryModelAuthorizationSend& v); +void from_json(const nlohmann::json& j, MsgQueryModelAuthorizationSend& v); + +struct MsgDownloadModelAuthorizationRequestRecv : public MsgRecvHead {}; +struct MsgDownloadModelAuthorizationRequestSend : public MsgSendHead { + std::string filePath; + std::string fileName; +}; +void to_json(nlohmann::json& j, const MsgDownloadModelAuthorizationRequestSend& v); +void from_json(const nlohmann::json& j, MsgDownloadModelAuthorizationRequestSend& v); + +struct MsgInstallModelAuthorizationRecv : public MsgRecvHead { + std::string uploadId; + std::string filePath; +}; +void to_json(nlohmann::json& j, const MsgInstallModelAuthorizationRecv& v); +void from_json(const nlohmann::json& j, MsgInstallModelAuthorizationRecv& v); +struct MsgInstallModelAuthorizationSend : public MsgSendHead {}; + // Document download address request struct MsgQueryDocumentUrlRecv : public MsgRecvHead { int type{0}; diff --git a/src/service/system/dto/SystemMsgTypes.cc b/src/service/system/dto/SystemMsgTypes.cc index e0b2c7788..8c7cc9f9f 100644 --- a/src/service/system/dto/SystemMsgTypes.cc +++ b/src/service/system/dto/SystemMsgTypes.cc @@ -49,6 +49,10 @@ void to_json(nlohmann::json& j, const MsgGpuDevUsage& v) { void from_json(const nlohmann::json& j, MsgGpuInfo& v) { JSON_OPT(j, v, gpuusage); + JSON_OPT(j, v, gpuusageAvailable); + JSON_OPT(j, v, utilizationMetric); + JSON_OPT(j, v, coreUtilizations); + JSON_OPT(j, v, memoryDomain); JSON_OPT(j, v, gpumemusage); JSON_OPT(j, v, gpumemtotal); JSON_OPT(j, v, gpumemavailable); @@ -68,29 +72,291 @@ void from_json(const nlohmann::json& j, MsgGpuInfo& v) { JSON_OPT(j, v, firstFrames); JSON_OPT(j, v, firstFrameMs); JSON_OPT(j, v, firstFrameMaxMs); + JSON_OPT(j, v, videoEncoderAvailable); + JSON_OPT(j, v, videoEncoderBackend); + JSON_OPT(j, v, videoEncoderImplementation); + JSON_OPT(j, v, videoEncoderDetail); + JSON_OPT(j, v, videoDecoderAvailable); + JSON_OPT(j, v, videoDecoderBackend); + JSON_OPT(j, v, videoDecoderImplementation); + JSON_OPT(j, v, videoDecoderDetail); + JSON_OPT(j, v, rgaFrames); + JSON_OPT(j, v, rgaMs); + JSON_OPT(j, v, rgaFailures); + JSON_OPT(j, v, mppEncodedFrames); + JSON_OPT(j, v, mppEncodeMs); + JSON_OPT(j, v, mppEncodeFailures); + JSON_OPT(j, v, mppDecodedFrames); + JSON_OPT(j, v, mppDecodeMs); + JSON_OPT(j, v, mppDecodeFailures); + JSON_OPT(j, v, mppDecodeFallbacks); + JSON_OPT(j, v, mppCopyOutFrames); + JSON_OPT(j, v, mppCopyOutMs); + JSON_OPT(j, v, mppCopyOutFailures); + JSON_OPT(j, v, mppEarlyDroppedFrames); + JSON_OPT(j, v, colorConvertFrames); + JSON_OPT(j, v, colorConvertMs); + JSON_OPT(j, v, blobConvertFrames); + JSON_OPT(j, v, blobConvertMs); + JSON_OPT(j, v, graphForwardFrames); + JSON_OPT(j, v, graphForwardMs); + JSON_OPT(j, v, graphForwardFailures); + JSON_OPT(j, v, resultParseFrames); + JSON_OPT(j, v, resultParseMs); + JSON_OPT(j, v, resultParseFailures); + JSON_OPT(j, v, rknnForwards); + JSON_OPT(j, v, rknnForwardMs); + JSON_OPT(j, v, rknnForwardFailures); + JSON_OPT(j, v, rknnPrepareCalls); + JSON_OPT(j, v, rknnPrepareMs); + JSON_OPT(j, v, rknnInputsSetCalls); + JSON_OPT(j, v, rknnInputsSetMs); + JSON_OPT(j, v, rknnRunCalls); + JSON_OPT(j, v, rknnRunMs); + JSON_OPT(j, v, rknnOutputsGetCalls); + JSON_OPT(j, v, rknnOutputsGetMs); + JSON_OPT(j, v, rknnOutputsReleaseCalls); + JSON_OPT(j, v, rknnOutputsReleaseMs); + JSON_OPT(j, v, rknnOutputTransformCalls); + JSON_OPT(j, v, rknnOutputTransformMs); + JSON_OPT(j, v, rknnMutexWaitCalls); + JSON_OPT(j, v, rknnMutexWaitMs); + JSON_OPT(j, v, rknnDetectorForwards); + JSON_OPT(j, v, rknnDetectorForwardMs); + JSON_OPT(j, v, rknnDetectorForwardFailures); + JSON_OPT(j, v, rknnDetectorPrepareCalls); + JSON_OPT(j, v, rknnDetectorPrepareMs); + JSON_OPT(j, v, rknnDetectorInputsSetCalls); + JSON_OPT(j, v, rknnDetectorInputsSetMs); + JSON_OPT(j, v, rknnDetectorRunCalls); + JSON_OPT(j, v, rknnDetectorRunMs); + JSON_OPT(j, v, rknnDetectorOutputsGetCalls); + JSON_OPT(j, v, rknnDetectorOutputsGetMs); + JSON_OPT(j, v, rknnDetectorOutputsReleaseCalls); + JSON_OPT(j, v, rknnDetectorOutputsReleaseMs); + JSON_OPT(j, v, rknnDetectorOutputTransformCalls); + JSON_OPT(j, v, rknnDetectorOutputTransformMs); + JSON_OPT(j, v, rknnDetectorMutexWaitCalls); + JSON_OPT(j, v, rknnDetectorMutexWaitMs); + JSON_OPT(j, v, rknnPreprocessFastHits); + JSON_OPT(j, v, rknnRgaFillCalls); + JSON_OPT(j, v, rknnRgaFillMs); + JSON_OPT(j, v, rknnRgaResizeColorCalls); + JSON_OPT(j, v, rknnRgaResizeColorMs); + JSON_OPT(j, v, rknnRgaFailures); + JSON_OPT(j, v, rknnCpuResizeFallbackCalls); + JSON_OPT(j, v, rknnCpuResizeFallbackMs); + JSON_OPT(j, v, rknnCpuNormalizeFallbackCalls); + JSON_OPT(j, v, rknnCpuNormalizeFallbackMs); + JSON_OPT(j, v, rknnNativeInputMapCalls); + JSON_OPT(j, v, rknnNativeInputMapMs); + JSON_OPT(j, v, rknnNativeInt8Inputs); + JSON_OPT(j, v, rknnFloatInputs); + JSON_OPT(j, v, rknnUint8ContractInputs); + JSON_OPT(j, v, rknnInputCompatibilityFallbacks); + JSON_OPT(j, v, rknnBoundInputBindAttempts); + JSON_OPT(j, v, rknnBoundInputBindFailures); + JSON_OPT(j, v, rknnBoundInputCopyCalls); + JSON_OPT(j, v, rknnBoundInputCopyMs); + JSON_OPT(j, v, rknnBoundInputCopyBytes); + JSON_OPT(j, v, rknnBoundInputCopyFailures); + JSON_OPT(j, v, rknnBoundInputSyncCalls); + JSON_OPT(j, v, rknnBoundInputSyncMs); + JSON_OPT(j, v, rknnBoundInputSyncFailures); + JSON_OPT(j, v, rknnBoundInputFrames); + JSON_OPT(j, v, rknnRgaBoundInputBindAttempts); + JSON_OPT(j, v, rknnRgaBoundInputBindFailures); + JSON_OPT(j, v, rknnRgaBoundInputImportCalls); + JSON_OPT(j, v, rknnRgaBoundInputImportMs); + JSON_OPT(j, v, rknnRgaBoundInputImportFailures); + JSON_OPT(j, v, rknnRgaBoundInputFrames); + JSON_OPT(j, v, rknnRgaBoundUint8Frames); + JSON_OPT(j, v, rknnRgaBoundNativeInt8Frames); + JSON_OPT(j, v, rknnRgaBoundRequantizeCalls); + JSON_OPT(j, v, rknnRgaBoundRequantizeMs); + JSON_OPT(j, v, rknnRgaBoundRequantizeFailures); + JSON_OPT(j, v, rknnRgaBoundInputNormalizeBypasses); + JSON_OPT(j, v, rknnMppDmaBufImportCalls); + JSON_OPT(j, v, rknnMppDmaBufImportMs); + JSON_OPT(j, v, rknnMppDmaBufImportFailures); + JSON_OPT(j, v, rknnMppDmaBufFrames); + JSON_OPT(j, v, rknnMppDmaBufFallbacks); + JSON_OPT(j, v, rknnMppDmaBufSourceBytes); + JSON_OPT(j, v, rknnNativeInt8Outputs); + JSON_OPT(j, v, rknnFloatOutputs); + JSON_OPT(j, v, rknnOutputCompatibilityFallbacks); + JSON_OPT(j, v, rknnNativeOutputBytes); + JSON_OPT(j, v, rknnFloatOutputBytes); + JSON_OPT(j, v, rknnYolov8DflCalls); + JSON_OPT(j, v, rknnYolov8DflMs); + JSON_OPT(j, v, rknnYolov8ClassCalls); + JSON_OPT(j, v, rknnYolov8ClassMs); + JSON_OPT(j, v, rknnYolov8DirectCandidateCalls); + JSON_OPT(j, v, rknnYolov8DirectCandidateFailures); + JSON_OPT(j, v, rknnYolov8DirectPointsScanned); + JSON_OPT(j, v, rknnYolov8DirectPointsDecoded); + JSON_OPT(j, v, rknnYolov8ScoreSumPointsRejected); + JSON_OPT(j, v, rknnYolov8LogicalFloatBytesAvoided); + JSON_OPT(j, v, yolov8PostprocessCalls); + JSON_OPT(j, v, yolov8PostprocessMs); + JSON_OPT(j, v, yolov8NmsCalls); + JSON_OPT(j, v, yolov8NmsMs); } void to_json(nlohmann::json& j, const MsgGpuInfo& v) { - j["gpuusage"] = v.gpuusage; - j["gpumemusage"] = v.gpumemusage; - j["gpumemtotal"] = v.gpumemtotal; - j["gpumemavailable"] = v.gpumemavailable; - j["gpudevusage"] = v.gpudevusage; - j["gpuCapacity"] = v.gpuCapacity; - j["activePreviewPublishers"] = v.activePreviewPublishers; - j["activePreviewStreams"] = v.activePreviewStreams; - j["activeRawPreviewStreams"] = v.activeRawPreviewStreams; - j["activeAlgorithmPreviewStreams"] = v.activeAlgorithmPreviewStreams; - j["previewStreamStarts"] = v.previewStreamStarts; - j["previewStreamStops"] = v.previewStreamStops; - j["previewStreamFailures"] = v.previewStreamFailures; - j["osdFrames"] = v.osdFrames; - j["osdMs"] = v.osdMs; - j["publishedFrames"] = v.publishedFrames; - j["publishMs"] = v.publishMs; - j["firstFrames"] = v.firstFrames; - j["firstFrameMs"] = v.firstFrameMs; - j["firstFrameMaxMs"] = v.firstFrameMaxMs; + j["gpuusage"] = v.gpuusage; + j["gpuusageAvailable"] = v.gpuusageAvailable; + j["utilizationMetric"] = v.utilizationMetric; + j["coreUtilizations"] = v.coreUtilizations; + j["memoryDomain"] = v.memoryDomain; + j["gpumemusage"] = v.gpumemusage; + j["gpumemtotal"] = v.gpumemtotal; + j["gpumemavailable"] = v.gpumemavailable; + j["gpudevusage"] = v.gpudevusage; + j["gpuCapacity"] = v.gpuCapacity; + j["activePreviewPublishers"] = v.activePreviewPublishers; + j["activePreviewStreams"] = v.activePreviewStreams; + j["activeRawPreviewStreams"] = v.activeRawPreviewStreams; + j["activeAlgorithmPreviewStreams"] = v.activeAlgorithmPreviewStreams; + j["previewStreamStarts"] = v.previewStreamStarts; + j["previewStreamStops"] = v.previewStreamStops; + j["previewStreamFailures"] = v.previewStreamFailures; + j["osdFrames"] = v.osdFrames; + j["osdMs"] = v.osdMs; + j["publishedFrames"] = v.publishedFrames; + j["publishMs"] = v.publishMs; + j["firstFrames"] = v.firstFrames; + j["firstFrameMs"] = v.firstFrameMs; + j["firstFrameMaxMs"] = v.firstFrameMaxMs; + j["videoEncoderAvailable"] = v.videoEncoderAvailable; + j["videoEncoderBackend"] = v.videoEncoderBackend; + j["videoEncoderImplementation"] = v.videoEncoderImplementation; + j["videoEncoderDetail"] = v.videoEncoderDetail; + j["videoDecoderAvailable"] = v.videoDecoderAvailable; + j["videoDecoderBackend"] = v.videoDecoderBackend; + j["videoDecoderImplementation"] = v.videoDecoderImplementation; + j["videoDecoderDetail"] = v.videoDecoderDetail; + j["rgaFrames"] = v.rgaFrames; + j["rgaMs"] = v.rgaMs; + j["rgaFailures"] = v.rgaFailures; + j["mppEncodedFrames"] = v.mppEncodedFrames; + j["mppEncodeMs"] = v.mppEncodeMs; + j["mppEncodeFailures"] = v.mppEncodeFailures; + j["mppDecodedFrames"] = v.mppDecodedFrames; + j["mppDecodeMs"] = v.mppDecodeMs; + j["mppDecodeFailures"] = v.mppDecodeFailures; + j["mppDecodeFallbacks"] = v.mppDecodeFallbacks; + j["mppCopyOutFrames"] = v.mppCopyOutFrames; + j["mppCopyOutMs"] = v.mppCopyOutMs; + j["mppCopyOutFailures"] = v.mppCopyOutFailures; + j["mppEarlyDroppedFrames"] = v.mppEarlyDroppedFrames; + j["colorConvertFrames"] = v.colorConvertFrames; + j["colorConvertMs"] = v.colorConvertMs; + j["blobConvertFrames"] = v.blobConvertFrames; + j["blobConvertMs"] = v.blobConvertMs; + j["graphForwardFrames"] = v.graphForwardFrames; + j["graphForwardMs"] = v.graphForwardMs; + j["graphForwardFailures"] = v.graphForwardFailures; + j["resultParseFrames"] = v.resultParseFrames; + j["resultParseMs"] = v.resultParseMs; + j["resultParseFailures"] = v.resultParseFailures; + j["rknnForwards"] = v.rknnForwards; + j["rknnForwardMs"] = v.rknnForwardMs; + j["rknnForwardFailures"] = v.rknnForwardFailures; + j["rknnPrepareCalls"] = v.rknnPrepareCalls; + j["rknnPrepareMs"] = v.rknnPrepareMs; + j["rknnInputsSetCalls"] = v.rknnInputsSetCalls; + j["rknnInputsSetMs"] = v.rknnInputsSetMs; + j["rknnRunCalls"] = v.rknnRunCalls; + j["rknnRunMs"] = v.rknnRunMs; + j["rknnOutputsGetCalls"] = v.rknnOutputsGetCalls; + j["rknnOutputsGetMs"] = v.rknnOutputsGetMs; + j["rknnOutputsReleaseCalls"] = v.rknnOutputsReleaseCalls; + j["rknnOutputsReleaseMs"] = v.rknnOutputsReleaseMs; + j["rknnOutputTransformCalls"] = v.rknnOutputTransformCalls; + j["rknnOutputTransformMs"] = v.rknnOutputTransformMs; + j["rknnMutexWaitCalls"] = v.rknnMutexWaitCalls; + j["rknnMutexWaitMs"] = v.rknnMutexWaitMs; + j["rknnDetectorForwards"] = v.rknnDetectorForwards; + j["rknnDetectorForwardMs"] = v.rknnDetectorForwardMs; + j["rknnDetectorForwardFailures"] = v.rknnDetectorForwardFailures; + j["rknnDetectorPrepareCalls"] = v.rknnDetectorPrepareCalls; + j["rknnDetectorPrepareMs"] = v.rknnDetectorPrepareMs; + j["rknnDetectorInputsSetCalls"] = v.rknnDetectorInputsSetCalls; + j["rknnDetectorInputsSetMs"] = v.rknnDetectorInputsSetMs; + j["rknnDetectorRunCalls"] = v.rknnDetectorRunCalls; + j["rknnDetectorRunMs"] = v.rknnDetectorRunMs; + j["rknnDetectorOutputsGetCalls"] = v.rknnDetectorOutputsGetCalls; + j["rknnDetectorOutputsGetMs"] = v.rknnDetectorOutputsGetMs; + j["rknnDetectorOutputsReleaseCalls"] = v.rknnDetectorOutputsReleaseCalls; + j["rknnDetectorOutputsReleaseMs"] = v.rknnDetectorOutputsReleaseMs; + j["rknnDetectorOutputTransformCalls"] = v.rknnDetectorOutputTransformCalls; + j["rknnDetectorOutputTransformMs"] = v.rknnDetectorOutputTransformMs; + j["rknnDetectorMutexWaitCalls"] = v.rknnDetectorMutexWaitCalls; + j["rknnDetectorMutexWaitMs"] = v.rknnDetectorMutexWaitMs; + j["rknnPreprocessFastHits"] = v.rknnPreprocessFastHits; + j["rknnRgaFillCalls"] = v.rknnRgaFillCalls; + j["rknnRgaFillMs"] = v.rknnRgaFillMs; + j["rknnRgaResizeColorCalls"] = v.rknnRgaResizeColorCalls; + j["rknnRgaResizeColorMs"] = v.rknnRgaResizeColorMs; + j["rknnRgaFailures"] = v.rknnRgaFailures; + j["rknnCpuResizeFallbackCalls"] = v.rknnCpuResizeFallbackCalls; + j["rknnCpuResizeFallbackMs"] = v.rknnCpuResizeFallbackMs; + j["rknnCpuNormalizeFallbackCalls"] = v.rknnCpuNormalizeFallbackCalls; + j["rknnCpuNormalizeFallbackMs"] = v.rknnCpuNormalizeFallbackMs; + j["rknnNativeInputMapCalls"] = v.rknnNativeInputMapCalls; + j["rknnNativeInputMapMs"] = v.rknnNativeInputMapMs; + j["rknnNativeInt8Inputs"] = v.rknnNativeInt8Inputs; + j["rknnFloatInputs"] = v.rknnFloatInputs; + j["rknnUint8ContractInputs"] = v.rknnUint8ContractInputs; + j["rknnInputCompatibilityFallbacks"] = v.rknnInputCompatibilityFallbacks; + j["rknnBoundInputBindAttempts"] = v.rknnBoundInputBindAttempts; + j["rknnBoundInputBindFailures"] = v.rknnBoundInputBindFailures; + j["rknnBoundInputCopyCalls"] = v.rknnBoundInputCopyCalls; + j["rknnBoundInputCopyMs"] = v.rknnBoundInputCopyMs; + j["rknnBoundInputCopyBytes"] = v.rknnBoundInputCopyBytes; + j["rknnBoundInputCopyFailures"] = v.rknnBoundInputCopyFailures; + j["rknnBoundInputSyncCalls"] = v.rknnBoundInputSyncCalls; + j["rknnBoundInputSyncMs"] = v.rknnBoundInputSyncMs; + j["rknnBoundInputSyncFailures"] = v.rknnBoundInputSyncFailures; + j["rknnBoundInputFrames"] = v.rknnBoundInputFrames; + j["rknnRgaBoundInputBindAttempts"] = v.rknnRgaBoundInputBindAttempts; + j["rknnRgaBoundInputBindFailures"] = v.rknnRgaBoundInputBindFailures; + j["rknnRgaBoundInputImportCalls"] = v.rknnRgaBoundInputImportCalls; + j["rknnRgaBoundInputImportMs"] = v.rknnRgaBoundInputImportMs; + j["rknnRgaBoundInputImportFailures"] = v.rknnRgaBoundInputImportFailures; + j["rknnRgaBoundInputFrames"] = v.rknnRgaBoundInputFrames; + j["rknnRgaBoundUint8Frames"] = v.rknnRgaBoundUint8Frames; + j["rknnRgaBoundNativeInt8Frames"] = v.rknnRgaBoundNativeInt8Frames; + j["rknnRgaBoundRequantizeCalls"] = v.rknnRgaBoundRequantizeCalls; + j["rknnRgaBoundRequantizeMs"] = v.rknnRgaBoundRequantizeMs; + j["rknnRgaBoundRequantizeFailures"] = v.rknnRgaBoundRequantizeFailures; + j["rknnRgaBoundInputNormalizeBypasses"] = v.rknnRgaBoundInputNormalizeBypasses; + j["rknnMppDmaBufImportCalls"] = v.rknnMppDmaBufImportCalls; + j["rknnMppDmaBufImportMs"] = v.rknnMppDmaBufImportMs; + j["rknnMppDmaBufImportFailures"] = v.rknnMppDmaBufImportFailures; + j["rknnMppDmaBufFrames"] = v.rknnMppDmaBufFrames; + j["rknnMppDmaBufFallbacks"] = v.rknnMppDmaBufFallbacks; + j["rknnMppDmaBufSourceBytes"] = v.rknnMppDmaBufSourceBytes; + j["rknnNativeInt8Outputs"] = v.rknnNativeInt8Outputs; + j["rknnFloatOutputs"] = v.rknnFloatOutputs; + j["rknnOutputCompatibilityFallbacks"] = v.rknnOutputCompatibilityFallbacks; + j["rknnNativeOutputBytes"] = v.rknnNativeOutputBytes; + j["rknnFloatOutputBytes"] = v.rknnFloatOutputBytes; + j["rknnYolov8DflCalls"] = v.rknnYolov8DflCalls; + j["rknnYolov8DflMs"] = v.rknnYolov8DflMs; + j["rknnYolov8ClassCalls"] = v.rknnYolov8ClassCalls; + j["rknnYolov8ClassMs"] = v.rknnYolov8ClassMs; + j["rknnYolov8DirectCandidateCalls"] = v.rknnYolov8DirectCandidateCalls; + j["rknnYolov8DirectCandidateFailures"] = v.rknnYolov8DirectCandidateFailures; + j["rknnYolov8DirectPointsScanned"] = v.rknnYolov8DirectPointsScanned; + j["rknnYolov8DirectPointsDecoded"] = v.rknnYolov8DirectPointsDecoded; + j["rknnYolov8ScoreSumPointsRejected"] = v.rknnYolov8ScoreSumPointsRejected; + j["rknnYolov8LogicalFloatBytesAvoided"] = v.rknnYolov8LogicalFloatBytesAvoided; + j["yolov8PostprocessCalls"] = v.yolov8PostprocessCalls; + j["yolov8PostprocessMs"] = v.yolov8PostprocessMs; + j["yolov8NmsCalls"] = v.yolov8NmsCalls; + j["yolov8NmsMs"] = v.yolov8NmsMs; } void from_json(const nlohmann::json& j, MsgDiskInfo& v) { diff --git a/src/service/system/dto/SystemMsgTypes.h b/src/service/system/dto/SystemMsgTypes.h index a011c3a62..7a66362cf 100644 --- a/src/service/system/dto/SystemMsgTypes.h +++ b/src/service/system/dto/SystemMsgTypes.h @@ -34,6 +34,10 @@ struct MsgGpuDevUsage { struct MsgGpuInfo { double gpuusage{0.0}; + bool gpuusageAvailable{true}; + std::string utilizationMetric; + std::vector<double> coreUtilizations; + std::string memoryDomain; double gpumemusage{0.0}; int64_t gpumemtotal{0}; int64_t gpumemavailable{0}; @@ -53,6 +57,135 @@ struct MsgGpuInfo { uint64_t firstFrames{0}; double firstFrameMs{0.0}; double firstFrameMaxMs{0.0}; + bool videoEncoderAvailable{false}; + std::string videoEncoderBackend; + std::string videoEncoderImplementation; + std::string videoEncoderDetail; + bool videoDecoderAvailable{false}; + std::string videoDecoderBackend; + std::string videoDecoderImplementation; + std::string videoDecoderDetail; + uint64_t rgaFrames{0}; + double rgaMs{0.0}; + uint64_t rgaFailures{0}; + uint64_t mppEncodedFrames{0}; + double mppEncodeMs{0.0}; + uint64_t mppEncodeFailures{0}; + uint64_t mppDecodedFrames{0}; + double mppDecodeMs{0.0}; + uint64_t mppDecodeFailures{0}; + uint64_t mppDecodeFallbacks{0}; + uint64_t mppCopyOutFrames{0}; + double mppCopyOutMs{0.0}; + uint64_t mppCopyOutFailures{0}; + uint64_t mppEarlyDroppedFrames{0}; + uint64_t colorConvertFrames{0}; + double colorConvertMs{0.0}; + uint64_t blobConvertFrames{0}; + double blobConvertMs{0.0}; + uint64_t graphForwardFrames{0}; + double graphForwardMs{0.0}; + uint64_t graphForwardFailures{0}; + uint64_t resultParseFrames{0}; + double resultParseMs{0.0}; + uint64_t resultParseFailures{0}; + uint64_t rknnForwards{0}; + double rknnForwardMs{0.0}; + uint64_t rknnForwardFailures{0}; + uint64_t rknnPrepareCalls{0}; + double rknnPrepareMs{0.0}; + uint64_t rknnInputsSetCalls{0}; + double rknnInputsSetMs{0.0}; + uint64_t rknnRunCalls{0}; + double rknnRunMs{0.0}; + uint64_t rknnOutputsGetCalls{0}; + double rknnOutputsGetMs{0.0}; + uint64_t rknnOutputsReleaseCalls{0}; + double rknnOutputsReleaseMs{0.0}; + uint64_t rknnOutputTransformCalls{0}; + double rknnOutputTransformMs{0.0}; + uint64_t rknnMutexWaitCalls{0}; + double rknnMutexWaitMs{0.0}; + uint64_t rknnDetectorForwards{0}; + double rknnDetectorForwardMs{0.0}; + uint64_t rknnDetectorForwardFailures{0}; + uint64_t rknnDetectorPrepareCalls{0}; + double rknnDetectorPrepareMs{0.0}; + uint64_t rknnDetectorInputsSetCalls{0}; + double rknnDetectorInputsSetMs{0.0}; + uint64_t rknnDetectorRunCalls{0}; + double rknnDetectorRunMs{0.0}; + uint64_t rknnDetectorOutputsGetCalls{0}; + double rknnDetectorOutputsGetMs{0.0}; + uint64_t rknnDetectorOutputsReleaseCalls{0}; + double rknnDetectorOutputsReleaseMs{0.0}; + uint64_t rknnDetectorOutputTransformCalls{0}; + double rknnDetectorOutputTransformMs{0.0}; + uint64_t rknnDetectorMutexWaitCalls{0}; + double rknnDetectorMutexWaitMs{0.0}; + uint64_t rknnPreprocessFastHits{0}; + uint64_t rknnRgaFillCalls{0}; + double rknnRgaFillMs{0.0}; + uint64_t rknnRgaResizeColorCalls{0}; + double rknnRgaResizeColorMs{0.0}; + uint64_t rknnRgaFailures{0}; + uint64_t rknnCpuResizeFallbackCalls{0}; + double rknnCpuResizeFallbackMs{0.0}; + uint64_t rknnCpuNormalizeFallbackCalls{0}; + double rknnCpuNormalizeFallbackMs{0.0}; + uint64_t rknnNativeInputMapCalls{0}; + double rknnNativeInputMapMs{0.0}; + uint64_t rknnNativeInt8Inputs{0}; + uint64_t rknnFloatInputs{0}; + uint64_t rknnUint8ContractInputs{0}; + uint64_t rknnInputCompatibilityFallbacks{0}; + uint64_t rknnBoundInputBindAttempts{0}; + uint64_t rknnBoundInputBindFailures{0}; + uint64_t rknnBoundInputCopyCalls{0}; + double rknnBoundInputCopyMs{0.0}; + uint64_t rknnBoundInputCopyBytes{0}; + uint64_t rknnBoundInputCopyFailures{0}; + uint64_t rknnBoundInputSyncCalls{0}; + double rknnBoundInputSyncMs{0.0}; + uint64_t rknnBoundInputSyncFailures{0}; + uint64_t rknnBoundInputFrames{0}; + uint64_t rknnRgaBoundInputBindAttempts{0}; + uint64_t rknnRgaBoundInputBindFailures{0}; + uint64_t rknnRgaBoundInputImportCalls{0}; + double rknnRgaBoundInputImportMs{0.0}; + uint64_t rknnRgaBoundInputImportFailures{0}; + uint64_t rknnRgaBoundInputFrames{0}; + uint64_t rknnRgaBoundUint8Frames{0}; + uint64_t rknnRgaBoundNativeInt8Frames{0}; + uint64_t rknnRgaBoundRequantizeCalls{0}; + double rknnRgaBoundRequantizeMs{0.0}; + uint64_t rknnRgaBoundRequantizeFailures{0}; + uint64_t rknnRgaBoundInputNormalizeBypasses{0}; + uint64_t rknnMppDmaBufImportCalls{0}; + double rknnMppDmaBufImportMs{0.0}; + uint64_t rknnMppDmaBufImportFailures{0}; + uint64_t rknnMppDmaBufFrames{0}; + uint64_t rknnMppDmaBufFallbacks{0}; + uint64_t rknnMppDmaBufSourceBytes{0}; + uint64_t rknnNativeInt8Outputs{0}; + uint64_t rknnFloatOutputs{0}; + uint64_t rknnOutputCompatibilityFallbacks{0}; + uint64_t rknnNativeOutputBytes{0}; + uint64_t rknnFloatOutputBytes{0}; + uint64_t rknnYolov8DflCalls{0}; + double rknnYolov8DflMs{0.0}; + uint64_t rknnYolov8ClassCalls{0}; + double rknnYolov8ClassMs{0.0}; + uint64_t rknnYolov8DirectCandidateCalls{0}; + uint64_t rknnYolov8DirectCandidateFailures{0}; + uint64_t rknnYolov8DirectPointsScanned{0}; + uint64_t rknnYolov8DirectPointsDecoded{0}; + uint64_t rknnYolov8ScoreSumPointsRejected{0}; + uint64_t rknnYolov8LogicalFloatBytesAvoided{0}; + uint64_t yolov8PostprocessCalls{0}; + double yolov8PostprocessMs{0.0}; + uint64_t yolov8NmsCalls{0}; + double yolov8NmsMs{0.0}; friend void to_json(nlohmann::json& j, const MsgGpuInfo& v); friend void from_json(const nlohmann::json& j, MsgGpuInfo& v); }; diff --git a/src/service/system/impl/AcceleratorMetricsProviderCpu.cc b/src/service/system/impl/AcceleratorMetricsProviderCpu.cc index f4cdc6048..5ae66d58e 100644 --- a/src/service/system/impl/AcceleratorMetricsProviderCpu.cc +++ b/src/service/system/impl/AcceleratorMetricsProviderCpu.cc @@ -8,7 +8,9 @@ namespace { class CpuAcceleratorMetricsProvider final : public AcceleratorMetricsProvider { public: cosmo::MsgGpuInfo QueryUtilization() override { - return {}; + cosmo::MsgGpuInfo result; + result.memoryDomain = "none"; + return result; } int64_t QueryAvailableMemoryMB() override { diff --git a/src/service/system/impl/AcceleratorMetricsProviderRknn.cc b/src/service/system/impl/AcceleratorMetricsProviderRknn.cc new file mode 100644 index 000000000..4ad99d65f --- /dev/null +++ b/src/service/system/impl/AcceleratorMetricsProviderRknn.cc @@ -0,0 +1,165 @@ +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include <algorithm> +#include <array> +#include <charconv> +#include <cstdlib> +#include <fstream> +#include <limits> +#include <map> +#include <optional> +#include <regex> +#include <sstream> +#include <string> +#include <vector> + +#include "service/system/impl/AcceleratorMetricsProvider.h" + +namespace cosmo::service::detail { +namespace { + + struct MemorySnapshot { + int64_t total_mb{0}; + int64_t available_mb{0}; + }; + + struct NpuLoadSnapshot { + double aggregate{0.0}; + std::vector<double> cores; + }; + + std::optional<unsigned int> ParseUnsigned(const std::ssub_match& match) { + const auto text = match.str(); + unsigned int value{0}; + const auto [end, error] = std::from_chars(text.data(), text.data() + text.size(), value); + if (error != std::errc{} || end != text.data() + text.size()) + return std::nullopt; + return value; + } + + std::optional<NpuLoadSnapshot> ParseNpuLoad(const std::string& text) { + static const std::regex core_pattern(R"(Core\s*([0-9]+)\s*:\s*([0-9]+)\s*%)"); + std::map<unsigned int, double> cores_by_id; + for (auto it = std::sregex_iterator(text.begin(), text.end(), core_pattern); + it != std::sregex_iterator(); ++it) { + const auto core_id = ParseUnsigned((*it)[1]); + const auto percent = ParseUnsigned((*it)[2]); + if (!core_id || !percent || *percent > 100) + return std::nullopt; + cores_by_id[*core_id] = static_cast<double>(*percent) / 100.0; + } + if (cores_by_id.empty()) + return std::nullopt; + + NpuLoadSnapshot result; + result.cores.reserve(cores_by_id.size()); + for (const auto& [core_id, load] : cores_by_id) { + (void)core_id; + result.cores.push_back(load); + result.aggregate = std::max(result.aggregate, load); + } + return result; + } + + std::optional<NpuLoadSnapshot> ReadNpuLoadFile(const std::string& path) { + std::ifstream stream(path); + if (!stream) + return std::nullopt; + const std::string text((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>()); + return ParseNpuLoad(text); + } + + std::optional<NpuLoadSnapshot> ReadNpuLoad() { + if (const char* configured_path = std::getenv("COSMO_RKNPU_LOAD_PATH"); + configured_path && *configured_path) { + return ReadNpuLoadFile(configured_path); + } + + static const std::array<const char*, 2> load_paths{ + "/run/cosmo-edge/metrics/rknpu-load", + "/sys/kernel/debug/rknpu/load", + }; + for (const auto* path : load_paths) { + if (auto load = ReadNpuLoadFile(path)) + return load; + } + return std::nullopt; + } + + MemorySnapshot ReadSharedMemory() { + MemorySnapshot result; + std::ifstream stream("/proc/meminfo"); + std::string key; + uint64_t value_kib = 0; + std::string unit; + while (stream >> key >> value_kib >> unit) { + const auto value_mb = value_kib / 1024; + if (value_mb > static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) + continue; + if (key == "MemTotal:") + result.total_mb = static_cast<int64_t>(value_mb); + else if (key == "MemAvailable:") + result.available_mb = static_cast<int64_t>(value_mb); + } + result.available_mb = std::clamp<int64_t>(result.available_mb, 0, result.total_mb); + return result; + } + + std::string ReadNpuFrequency() { + std::ifstream stream("/sys/class/devfreq/27700000.npu/cur_freq"); + uint64_t hz = 0; + if (!(stream >> hz)) + return "RK3576 shared-memory NPU"; + std::ostringstream text; + text << (hz / 1000000) << " MHz"; + return text.str(); + } + + class RknnAcceleratorMetricsProvider final : public AcceleratorMetricsProvider { + public: + cosmo::MsgGpuInfo QueryUtilization() override { + const auto memory = ReadSharedMemory(); + cosmo::MsgGpuInfo result; + result.utilizationMetric = "busy-time-load"; + result.memoryDomain = "shared-system"; + if (const auto load = ReadNpuLoad()) { + // The dashboard uses the busiest core as the device health + // signal while preserving all per-core values in telemetry. + result.gpuusage = load->aggregate; + result.gpuusageAvailable = true; + result.coreUtilizations = load->cores; + } else { + result.gpuusage = 0.0; + result.gpuusageAvailable = false; + } + result.gpumemtotal = memory.total_mb; + result.gpumemavailable = memory.available_mb; + result.gpumemusage = memory.total_mb > 0 + ? static_cast<double>(memory.total_mb - memory.available_mb) / + static_cast<double>(memory.total_mb) + : 0.0; + result.gpuCapacity = ReadNpuFrequency(); + + cosmo::MsgGpuDevUsage shared; + shared.gpuusage = result.gpuusage; + shared.gpumemtotal = result.gpumemtotal; + shared.gpumemavailable = result.gpumemavailable; + shared.gpumemusage = result.gpumemusage; + result.gpudevusage.push_back(shared); + return result; + } + + int64_t QueryAvailableMemoryMB() override { + return ReadSharedMemory().available_mb; + } + }; + +} // namespace + +std::unique_ptr<AcceleratorMetricsProvider> CreateAcceleratorMetricsProvider() { + return std::make_unique<RknnAcceleratorMetricsProvider>(); +} + +} // namespace cosmo::service::detail + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/src/service/system/impl/AcceleratorMetricsProviderSophon.cc b/src/service/system/impl/AcceleratorMetricsProviderSophon.cc index 978d6b403..f1ff08f27 100644 --- a/src/service/system/impl/AcceleratorMetricsProviderSophon.cc +++ b/src/service/system/impl/AcceleratorMetricsProviderSophon.cc @@ -13,6 +13,7 @@ namespace { public: cosmo::MsgGpuInfo QueryUtilization() override { cosmo::MsgGpuInfo result; + result.memoryDomain = "dedicated-accelerator"; bm_handle_t handle{}; auto status = bm_dev_request(&handle, 0); if (status != BM_SUCCESS) { diff --git a/src/service/system/impl/DeviceInfoServiceImpl.cc b/src/service/system/impl/DeviceInfoServiceImpl.cc index 54a9eaf1d..5442d8a98 100644 --- a/src/service/system/impl/DeviceInfoServiceImpl.cc +++ b/src/service/system/impl/DeviceInfoServiceImpl.cc @@ -54,6 +54,20 @@ namespace { return result; } + std::string FormatBinaryBytes(int64_t bytes) { + constexpr double kMebibyte = 1024.0 * 1024.0; + constexpr double kGibibyte = 1024.0 * kMebibyte; + if (bytes >= static_cast<int64_t>(kGibibyte)) + return COSMO_FORMAT("{:.2f} GiB", static_cast<double>(bytes) / kGibibyte); + return COSMO_FORMAT("{:.2f} MiB", static_cast<double>(bytes) / kMebibyte); + } + + std::string FormatBinaryMebibytes(int64_t mebibytes) { + if (mebibytes >= 1024) + return COSMO_FORMAT("{:.2f} GiB", static_cast<double>(mebibytes) / 1024.0); + return COSMO_FORMAT("{:.2f} MiB", static_cast<double>(mebibytes)); + } + } // namespace // Hardware info state (migrated from HwInfo singleton). @@ -198,46 +212,60 @@ std::vector<HwResourceItem> DeviceInfoServiceImpl::GetHardwareResource(double& c const auto cpu_utl = ClampRatio(raw_cpu_utl); items.push_back({"cpuUtilization", "CPU使用率", static_cast<int>(std::lround(cpu_utl * 100)), COSMO_FORMAT("{:.0f}%", cpu_utl * 100), COSMO_FORMAT("{:.0f}%", (1 - cpu_utl) * 100), - std::isfinite(raw_cpu_utl) && raw_cpu_utl >= 0.0 ? 1 : 0}); + std::isfinite(raw_cpu_utl) && raw_cpu_utl >= 0.0 ? 1 : 0, ""}); // Memory const auto mem_utl = hw_res_state_->GetMemoryUtilization(); const auto mem_usage = GetCapacityUsage(mem_utl.memtotal, mem_utl.memavailable); - items.push_back({"generalMemoryUtilization", "业务内存使用率", mem_usage.percent, - COSMO_FORMAT("{:.2f} MB", static_cast<double>(mem_usage.used) / 1024 / 1024), - COSMO_FORMAT("{:.2f} MB", static_cast<double>(mem_usage.available) / 1024 / 1024), - mem_usage.valid ? 1 : 0}); + items.push_back({"generalMemoryUtilization", "系统内存使用率", mem_usage.percent, + FormatBinaryBytes(mem_usage.used), FormatBinaryBytes(mem_usage.available), + mem_usage.valid ? 1 : 0, "system"}); // GPU/NPU auto gpu_utl = hw_res_state_->GetGpuUtilization(); const auto raw_gpu_usage = gpu_utl.gpuusage; const auto gpu_usage = ClampRatio(raw_gpu_usage); gpu_utl.gpuusage = gpu_usage; - items.push_back({"npuUtilization", "NPU使用率", static_cast<int>(std::lround(gpu_usage * 100)), - COSMO_FORMAT("{:.0f}%", gpu_usage * 100), COSMO_FORMAT("{:.0f}%", (1 - gpu_usage) * 100), - std::isfinite(raw_gpu_usage) && raw_gpu_usage >= 0.0 ? 1 : 0}); + if (gpu_utl.gpuusageAvailable) { + items.push_back({"npuUtilization", "NPU负载", static_cast<int>(std::lround(gpu_usage * 100)), + COSMO_FORMAT("{:.0f}%", gpu_usage * 100), + COSMO_FORMAT("{:.0f}%", (1 - gpu_usage) * 100), + std::isfinite(raw_gpu_usage) && raw_gpu_usage >= 0.0 ? 1 : 0, ""}); + } else { + items.push_back({"npuUtilization", "NPU负载", 0, "--", "--", 0, ""}); + } // GPU memory details - auto add_gpu_mem_item = [&](const std::string& key, const std::string& name, const auto& dev) { + auto add_gpu_mem_item = [&](const std::string& key, const std::string& name, + const std::string& memory_domain, const auto& dev) { const auto usage = GetCapacityUsage(dev.gpumemtotal, dev.gpumemavailable); - items.push_back( - {key, name, usage.percent, COSMO_FORMAT("{:.2f} GB", static_cast<double>(usage.used) / 1024), - COSMO_FORMAT("{:.2f} GB", static_cast<double>(usage.available) / 1024), usage.valid ? 1 : 0}); + items.push_back({key, name, usage.percent, FormatBinaryMebibytes(usage.used), + FormatBinaryMebibytes(usage.available), usage.valid ? 1 : 0, memory_domain}); }; - if (2 == gpu_utl.gpudevusage.size()) { - add_gpu_mem_item("modelMemoryUtilization", "模型内存使用率", gpu_utl.gpudevusage[0]); - add_gpu_mem_item("pictureMemoryUtilization", "图片内存使用率", gpu_utl.gpudevusage[1]); - } else if (3 == gpu_utl.gpudevusage.size()) { - add_gpu_mem_item("modelMemoryUtilization", "heap 0 内存使用率", gpu_utl.gpudevusage[0]); - add_gpu_mem_item("pictureMemoryUtilization", "heap 1 内存使用率", gpu_utl.gpudevusage[1]); - add_gpu_mem_item("TPPMemoryUtilization", "heap 2 内存使用率", gpu_utl.gpudevusage[2]); - } else { - const auto gpu_mem_usage = GetCapacityUsage(gpu_utl.gpumemtotal, gpu_utl.gpumemavailable); - items.push_back({"specialMemoryUtilization", "芯片内存使用率", gpu_mem_usage.percent, - COSMO_FORMAT("{:.2f} GB", static_cast<double>(gpu_mem_usage.used) / 1024), - COSMO_FORMAT("{:.2f} GB", static_cast<double>(gpu_mem_usage.available) / 1024), - gpu_mem_usage.valid ? 1 : 0}); + // RK3576 has no dedicated NPU VRAM: its legacy gpumem fields describe the + // same system DDR already represented above. Keep those fields for model + // admission and wire compatibility, but never emit a second UI capacity. + if (gpu_utl.memoryDomain != "shared-system") { + if (2 == gpu_utl.gpudevusage.size()) { + add_gpu_mem_item("modelMemoryUtilization", "模型内存使用率", "accelerator-heap-0", + gpu_utl.gpudevusage[0]); + add_gpu_mem_item("pictureMemoryUtilization", "图片内存使用率", "accelerator-heap-1", + gpu_utl.gpudevusage[1]); + } else if (3 == gpu_utl.gpudevusage.size()) { + add_gpu_mem_item("modelMemoryUtilization", "heap 0 内存使用率", "accelerator-heap-0", + gpu_utl.gpudevusage[0]); + add_gpu_mem_item("pictureMemoryUtilization", "heap 1 内存使用率", "accelerator-heap-1", + gpu_utl.gpudevusage[1]); + add_gpu_mem_item("TPPMemoryUtilization", "heap 2 内存使用率", "accelerator-heap-2", + gpu_utl.gpudevusage[2]); + } else { + const auto gpu_mem_usage = GetCapacityUsage(gpu_utl.gpumemtotal, gpu_utl.gpumemavailable); + items.push_back({"specialMemoryUtilization", "芯片内存使用率", gpu_mem_usage.percent, + FormatBinaryMebibytes(gpu_mem_usage.used), + FormatBinaryMebibytes(gpu_mem_usage.available), gpu_mem_usage.valid ? 1 : 0, + "accelerator"}); + } } // Disk @@ -247,7 +275,7 @@ std::vector<HwResourceItem> DeviceInfoServiceImpl::GetHardwareResource(double& c {"eMMCUtilization", "eMMC使用率", disk_usage.percent, COSMO_FORMAT("{:.2f} GB", static_cast<double>(disk_usage.used) / 1024 / 1024 / 1024), COSMO_FORMAT("{:.2f} GB", static_cast<double>(disk_usage.available) / 1024 / 1024 / 1024), - disk_usage.valid ? 1 : 0}); + disk_usage.valid ? 1 : 0, ""}); // Packet stats size_t packet_total = 0, packet_proc = 0, packet_discard = 0, continues_discard_sec = 0; @@ -261,8 +289,8 @@ std::vector<HwResourceItem> DeviceInfoServiceImpl::GetHardwareResource(double& c used_percent = ClampRatio(used_percent); items.push_back({"packetDiscardUtilization", "丢包率", static_cast<int>(std::lround(used_percent * 100)), COSMO_FORMAT("{}个", packet_discard), - COSMO_FORMAT("{}个", packet_total - packet_discard), 1}); - LOG_INFO("continuesDiscardSec:{} packetDiscard:{}", continues_discard_sec, packet_discard); + COSMO_FORMAT("{}个", packet_total - packet_discard), 1, ""}); + LOG_DEBUG("continuesDiscardSec:{} packetDiscard:{}", continues_discard_sec, packet_discard); std::vector<cosmo::GpuMemSnapshot> devs; devs.reserve(gpu_utl.gpudevusage.size()); diff --git a/src/service/system/impl/HardwareQueryUtil.cc b/src/service/system/impl/HardwareQueryUtil.cc index 86a2e9c77..373eb5100 100644 --- a/src/service/system/impl/HardwareQueryUtil.cc +++ b/src/service/system/impl/HardwareQueryUtil.cc @@ -7,10 +7,12 @@ #include <netinet/in.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <sys/utsname.h> #include <sys/vfs.h> #include <unistd.h> #include <algorithm> +#include <cctype> #include <cerrno> #include <climits> #include <cmath> @@ -40,6 +42,18 @@ namespace { return *provider; } + std::string ReadDeviceTreeText(const std::string& path, char separator = ' ') { + std::ifstream stream(path, std::ios::binary); + if (!stream) + return {}; + std::string value((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>()); + std::replace(value.begin(), value.end(), '\0', separator); + while (!value.empty() && std::isspace(static_cast<unsigned char>(value.back()))) + value.pop_back(); + const auto first = value.find_first_not_of(" \t\r\n"); + return first == std::string::npos ? std::string{} : value.substr(first); + } + } // namespace // ============================================================ @@ -85,7 +99,18 @@ void HardwareQueryUtil::ReadDeviceSnAndModel(std::string* device_sn, std::string if (!device_sn || !device_model) { return; } -#ifndef COSMO_NN_USE_SOPHON_BACKEND +#if defined(COSMO_NN_USE_RKNN_BACKEND) + *device_sn = ReadDeviceTreeText("/proc/device-tree/serial-number"); + if (device_sn->empty()) + *device_sn = ReadDeviceTreeText("/sys/firmware/devicetree/base/serial-number"); + if (device_sn->empty()) + *device_sn = QueryPrimaryMac(); + *device_model = ReadDeviceTreeText("/proc/device-tree/model"); + if (device_model->empty()) + *device_model = "RK3576"; + LOG_INFO("RKNN deviceSn:{} deviceModel:{}", *device_sn, *device_model); + return; +#elif !defined(COSMO_NN_USE_SOPHON_BACKEND) *device_sn = "CA16T01-X86-TRIAL"; *device_model = "X86-TRIAL"; LOG_INFO("x86 trial mode - mocked deviceSn:{}", *device_sn); @@ -121,7 +146,10 @@ void HardwareQueryUtil::ReadDeviceSnAndModel(std::string* device_sn, std::string } std::string HardwareQueryUtil::ReadHardwareSpec() { -#ifndef COSMO_NN_USE_SOPHON_BACKEND +#if defined(COSMO_NN_USE_RKNN_BACKEND) + auto compatible = ReadDeviceTreeText("/proc/device-tree/compatible", ','); + return compatible.empty() ? "rockchip,rk3576" : compatible; +#elif !defined(COSMO_NN_USE_SOPHON_BACKEND) return "X86_HARDWARE_SPEC"; #else auto hardware_info = @@ -137,7 +165,13 @@ std::string HardwareQueryUtil::ReadHardwareSpec() { } std::string HardwareQueryUtil::ReadKernelRevision() { -#ifndef COSMO_NN_USE_SOPHON_BACKEND +#if defined(COSMO_NN_USE_RKNN_BACKEND) + struct utsname system_info {}; + if (uname(&system_info) == 0) + return system_info.release; + LOG_WARN("uname failed while querying RK3576 kernel revision: {}", std::strerror(errno)); + return {}; +#elif !defined(COSMO_NN_USE_SOPHON_BACKEND) return "X86-Generic-Kernel"; #else LOG_INFO("{}", "bm_version"); diff --git a/src/service/system/impl/PacketUpgrade.cc b/src/service/system/impl/PacketUpgrade.cc index b2ee64dc3..90e6d9ff0 100644 --- a/src/service/system/impl/PacketUpgrade.cc +++ b/src/service/system/impl/PacketUpgrade.cc @@ -306,9 +306,8 @@ util::ErrorEnum PacketUpgrade(const fs::path& filePath) { } std::string file_name = absolute_file.filename().string(); std::string file_name_md5sum; - auto ret = UpgradeFileNameCheck(file_name, file_name_md5sum); - if (ret != util::ErrorEnum::Success) { - return ret; + if (UpgradeFileNameCheck(file_name, file_name_md5sum) != util::ErrorEnum::Success) { + return util::ErrorEnum::UpgradeFileVerifyFailed; } std::string resolved_file; @@ -340,9 +339,6 @@ util::ErrorEnum PacketUpgrade(const fs::path& filePath) { if (!budget.valid) { throw util::ErrorMessage(util::ErrorEnum::SysErr, "Cannot inspect upgrade extraction storage"); } - // A valid package replaces the previous prepared upgrade tree. Include - // those allocated blocks in the admission budget, while keeping the tree - // intact until all package validation above has succeeded. const auto usable_bytes = util::UsableStorageBytesAfterReclaim(budget, AllocatedTreeBytes(upgradeFileDir)); if (inspection.total_bytes > usable_bytes) { diff --git a/src/service/system/impl/SystemOperationServiceImpl.cc b/src/service/system/impl/SystemOperationServiceImpl.cc index 1a55a2de2..ecc0e5200 100644 --- a/src/service/system/impl/SystemOperationServiceImpl.cc +++ b/src/service/system/impl/SystemOperationServiceImpl.cc @@ -6,6 +6,7 @@ #include "service/detail/ServiceRegistry.h" #include "service/system/impl/PacketUpgrade.h" +#include "service/system/impl/UpgradeStorage.h" #include "util/ErrorCode.h" #include "util/Exec.h" #include "util/Log.h" @@ -76,6 +77,14 @@ cosmo::util::ErrorEnum SystemOperationServiceImpl::Upgrade(const std::string& fi return result; } +cosmo::util::ErrorEnum SystemOperationServiceImpl::CheckUpgradeSpace(std::uint64_t packageSizeBytes, + bool cleanupEventMedia, + UpgradeSpaceStatus& status) { + return cosmo::service::CheckUpgradeStorage(cosmo::path::GetBaseDir(), + cosmo::path::GetEventRootPath(false), packageSizeBytes, + cleanupEventMedia, status); +} + void SystemOperationServiceImpl::ShowThreadDebugInfo() { cosmo::util::ShowAllThreads(); } diff --git a/src/service/system/impl/SystemOperationServiceImpl.h b/src/service/system/impl/SystemOperationServiceImpl.h index 37cd2e914..19de74c94 100644 --- a/src/service/system/impl/SystemOperationServiceImpl.h +++ b/src/service/system/impl/SystemOperationServiceImpl.h @@ -17,6 +17,8 @@ class SystemOperationServiceImpl : public ISystemOperationService { void ResetDevice(const std::string& reason) override; cosmo::util::ErrorEnum ExportLogs(std::string& fileName, std::string& fileUrl) override; cosmo::util::ErrorEnum Upgrade(const std::string& filePath) override; + cosmo::util::ErrorEnum CheckUpgradeSpace(std::uint64_t packageSizeBytes, bool cleanupEventMedia, + UpgradeSpaceStatus& status) override; void ShowThreadDebugInfo() override; private: diff --git a/src/service/system/impl/UpgradeStorage.cc b/src/service/system/impl/UpgradeStorage.cc new file mode 100644 index 000000000..859ff2fe9 --- /dev/null +++ b/src/service/system/impl/UpgradeStorage.cc @@ -0,0 +1,151 @@ +#include "service/system/impl/UpgradeStorage.h" + +#include <algorithm> +#include <array> +#include <cctype> +#include <limits> +#include <string> +#include <vector> + +#include "util/Log.h" +#include "util/PathUtil.h" + +namespace cosmo::service { +namespace fs = std::filesystem; +namespace { + + struct EventMediaFile { + fs::path path; + std::uint64_t size{0}; + }; + + std::uint64_t SaturatingAdd(std::uint64_t lhs, std::uint64_t rhs) { + const auto max_value = std::numeric_limits<std::uint64_t>::max(); + return rhs > max_value - lhs ? max_value : lhs + rhs; + } + + util::ErrorEnum CollectEventMediaFiles(const fs::path& event_root, std::vector<EventMediaFile>& files, + std::uint64_t& total_bytes) { + files.clear(); + total_bytes = 0; + std::error_code ec; + const auto root_status = fs::symlink_status(event_root, ec); + if (ec == std::errc::no_such_file_or_directory || !fs::exists(root_status)) { + return util::ErrorEnum::Success; + } + if (ec || !fs::is_directory(root_status)) { + return util::ErrorEnum::SysErr; + } + + fs::recursive_directory_iterator entry(event_root, fs::directory_options::none, ec), end; + if (ec) { + return util::ErrorEnum::SysErr; + } + for (; entry != end; entry.increment(ec)) { + if (ec) { + return util::ErrorEnum::SysErr; + } + const auto file_status = entry->symlink_status(ec); + if (ec) { + return util::ErrorEnum::SysErr; + } + if (!fs::is_regular_file(file_status) || !IsEventMediaFile(entry->path())) { + continue; + } + const auto size = entry->file_size(ec); + if (ec) { + return util::ErrorEnum::SysErr; + } + files.push_back({entry->path(), size}); + total_bytes = SaturatingAdd(total_bytes, size); + } + return ec ? util::ErrorEnum::SysErr : util::ErrorEnum::Success; + } + +} // namespace + +std::uint64_t RequiredUpgradeSpaceBytes(std::uint64_t package_size_bytes) { + const auto max_value = std::numeric_limits<std::uint64_t>::max(); + if (package_size_bytes > max_value / 5) { + return max_value; + } + const auto multiplied = package_size_bytes * 5; + return multiplied / 2 + multiplied % 2; +} + +bool IsEventMediaFile(const fs::path& path) { + static constexpr std::array<const char*, 16> kMediaExtensions{ + ".jpg", ".jpeg", ".png", ".bmp", ".webp", ".gif", ".mp4", ".avi", + ".mov", ".mkv", ".webm", ".flv", ".ts", ".m4v", ".h264", ".h265"}; + auto extension = path.extension().string(); + std::transform(extension.begin(), extension.end(), extension.begin(), + [](unsigned char ch) { return static_cast<char>(std::tolower(ch)); }); + return std::find(kMediaExtensions.begin(), kMediaExtensions.end(), extension) != kMediaExtensions.end(); +} + +EventMediaCleanupResult DeleteEventMediaFiles(const fs::path& event_root) { + EventMediaCleanupResult result; + std::vector<EventMediaFile> files; + std::uint64_t total_bytes = 0; + result.error = CollectEventMediaFiles(event_root, files, total_bytes); + if (result.error != util::ErrorEnum::Success) { + return result; + } + + for (const auto& file : files) { + std::error_code ec; + if (fs::remove(file.path, ec)) { + ++result.deleted_files; + result.deleted_bytes = SaturatingAdd(result.deleted_bytes, file.size); + } else if (ec) { + LOG_WARN("Cannot remove event media {}: {}", file.path.string(), ec.message()); + result.error = util::ErrorEnum::SysErr; + } + } + return result; +} + +util::ErrorEnum CheckUpgradeStorage(const fs::path& data_root, const fs::path& event_root, + std::uint64_t package_size_bytes, bool cleanup_event_media, + UpgradeSpaceStatus& status) { + status = {}; + if (package_size_bytes == 0 || data_root.empty() || event_root.empty() || + !cosmo::path::IsWithinRoot(data_root.string(), event_root.string())) { + return util::ErrorEnum::InvalidParam; + } + + status.required_bytes = RequiredUpgradeSpaceBytes(package_size_bytes); + std::error_code ec; + auto space = fs::space(data_root, ec); + if (ec) { + return util::ErrorEnum::SysErr; + } + status.available_bytes = space.available; + status.sufficient = status.available_bytes >= status.required_bytes; + if (status.sufficient) { + return util::ErrorEnum::Success; + } + + if (!cleanup_event_media) { + std::vector<EventMediaFile> media_files; + return CollectEventMediaFiles(event_root, media_files, status.event_media_bytes); + } + + const auto cleanup = DeleteEventMediaFiles(event_root); + status.event_media_bytes = cleanup.deleted_bytes; + status.deleted_media_bytes = cleanup.deleted_bytes; + status.deleted_media_files = cleanup.deleted_files; + if (cleanup.error != util::ErrorEnum::Success) { + return cleanup.error; + } + + space = fs::space(data_root, ec); + if (ec) { + return util::ErrorEnum::SysErr; + } + status.available_bytes = space.available; + status.sufficient = status.available_bytes >= status.required_bytes; + return util::ErrorEnum::Success; +} + +} // namespace cosmo::service diff --git a/src/service/system/impl/UpgradeStorage.h b/src/service/system/impl/UpgradeStorage.h new file mode 100644 index 000000000..b592271ab --- /dev/null +++ b/src/service/system/impl/UpgradeStorage.h @@ -0,0 +1,25 @@ +#pragma once + +#include <cstdint> +#include <filesystem> + +#include "service/system/UpgradeSpace.h" +#include "util/ErrorCode.h" + +namespace cosmo::service { + +struct EventMediaCleanupResult { + util::ErrorEnum error{util::ErrorEnum::Success}; + std::uint64_t deleted_files{0}; + std::uint64_t deleted_bytes{0}; +}; + +[[nodiscard]] std::uint64_t RequiredUpgradeSpaceBytes(std::uint64_t package_size_bytes); +[[nodiscard]] bool IsEventMediaFile(const std::filesystem::path& path); +[[nodiscard]] EventMediaCleanupResult DeleteEventMediaFiles(const std::filesystem::path& event_root); +[[nodiscard]] util::ErrorEnum CheckUpgradeStorage(const std::filesystem::path& data_root, + const std::filesystem::path& event_root, + std::uint64_t package_size_bytes, bool cleanup_event_media, + UpgradeSpaceStatus& status); + +} // namespace cosmo::service diff --git a/src/service/task/impl/TaskServiceImpl.cc b/src/service/task/impl/TaskServiceImpl.cc index 85fec07c4..ad380c6a5 100644 --- a/src/service/task/impl/TaskServiceImpl.cc +++ b/src/service/task/impl/TaskServiceImpl.cc @@ -592,8 +592,8 @@ cosmo::MsgTaskCreateSend TaskServiceImpl::ProcessTaskCreate(cosmo::MsgTaskCreate LOG_WARN("{}/{} AlgCode:{} Name:{} Version:{} GetVideoPlay Failed", data.videoChannelId, data.taskId, data.algorithmCode, data.algorithmName, data.algorithmUpdateTime); } else { - LOG_INFO("{}/{} AlgCode:{} Name:{} GetVideoPlay Url:{} ", data.videoChannelId, data.taskId, - data.algorithmCode, data.algorithmName, get_video_rsp.resData.streamUrl); + LOG_INFO("{}/{} AlgCode:{} Name:{} GetVideoPlay OK", data.videoChannelId, data.taskId, + data.algorithmCode, data.algorithmName); data.streamUrl = get_video_rsp.resData.streamUrl; } } @@ -617,8 +617,8 @@ cosmo::MsgTaskCreateSend TaskServiceImpl::ProcessTaskCreate(cosmo::MsgTaskCreate return ret_data; } // 3. Set task parameters - LOG_INFO("{}/{} Create {} Task, Set Params streamUrl:{}", data.videoChannelId, data.taskId, - action_alg->algorithmName, data.streamUrl); + LOG_INFO("{}/{} Create {} Task, stream URL present:{}", data.videoChannelId, data.taskId, + action_alg->algorithmName, !data.streamUrl.empty()); if (!data.streamUrl.empty()) { cosmo::MsgDynamicKeyValue url; url.key = std::string(cosmo::key::CHANNEL_URL); diff --git a/src/service/task/impl/TaskServiceQuery.cc b/src/service/task/impl/TaskServiceQuery.cc index 53181cd4a..cc30d5cba 100644 --- a/src/service/task/impl/TaskServiceQuery.cc +++ b/src/service/task/impl/TaskServiceQuery.cc @@ -150,9 +150,9 @@ std::vector<cosmo::MsgOverviewMem> TaskServiceImpl::GetTaskLiveOverviewInfo(cons auto now = cosmo::util::GetMilliseconds(); if ((now - last_overview_log_ts_) > 1000) { last_overview_log_ts_ = now; - LOG_INFO("[TASK_OV_READ] taskId:{} channel:{} infos:{} aiData:{} aiFrames:{} aiTargets:{} alarm:{}", - taskId, task->channelId, infos.size(), ai_data_cnt, ai_frame_cnt, ai_target_cnt, - alarm_data_cnt); + LOG_DEBUG("[TASK_OV_READ] taskId:{} channel:{} infos:{} aiData:{} aiFrames:{} aiTargets:{} alarm:{}", + taskId, task->channelId, infos.size(), ai_data_cnt, ai_frame_cnt, ai_target_cnt, + alarm_data_cnt); } return infos; } diff --git a/src/util/AsyncQueue.h b/src/util/AsyncQueue.h index 46347cb75..9701a07b3 100644 --- a/src/util/AsyncQueue.h +++ b/src/util/AsyncQueue.h @@ -63,6 +63,8 @@ class AsyncQueue : public Thread { bool IsRunning() const; size_t RestSize() const; + bool CanAccept() const; + void RecordDiscard(); // Populates status snapshot; returns false if queue is stopped bool Status(AsyncQueueInfo& status); @@ -213,6 +215,25 @@ size_t AsyncQueue<DataType, QueueType>::RestSize() const { return queue_.size(); } +template <typename DataType, typename QueueType> +bool AsyncQueue<DataType, QueueType>::CanAccept() const { + std::lock_guard<std::mutex> lock(queue_mtx_); + return is_running_ && queue_.size() < max_size_; +} + +template <typename DataType, typename QueueType> +void AsyncQueue<DataType, QueueType>::RecordDiscard() { + std::lock_guard<std::mutex> lock(queue_mtx_); + status_.insertCount += 1; + status_.insertCountPeriod += 1; + status_.discardCount += 1; + status_.discardCountPeriod += 1; + status_.continuousDiscardCount += 1; + if (status_.continuousDiscardCount > status_.continuousDiscardCountMax) { + status_.continuousDiscardCountMax = status_.continuousDiscardCount; + } +} + template <typename DataType, typename QueueType> bool AsyncQueue<DataType, QueueType>::Status(AsyncQueueInfo& status) { std::lock_guard<std::mutex> lock(queue_mtx_); diff --git a/src/util/NnBackendConstants.h b/src/util/NnBackendConstants.h index 1a9082c30..e4dc5de47 100644 --- a/src/util/NnBackendConstants.h +++ b/src/util/NnBackendConstants.h @@ -47,6 +47,16 @@ static constexpr const char* kModelFileExt = ".nn"; /// Add a new chip here to support it across the model pipeline. static constexpr const char* kSupportedChips[] = {"BM1688", "CV186X"}; +#elif defined(COSMO_NN_USE_RKNN_BACKEND) + +/// Directory prefix for RK3576 RKNN model directories. +static constexpr const char* kPlatformDirPrefix = "prod_RK3576_"; +static constexpr const char* kNewDirPrefix = "prod_RK3576_"; +static constexpr const char* kPlatformDirRegex = "prod_[A-Z0-9]+_([0-9]+)_.*"; +static constexpr const char* kEngineType = "RK3576"; +static constexpr const char* kModelFileExt = ".rknn"; +static constexpr const char* kSupportedChips[] = {"RK3576"}; + #elif defined(COSMO_NN_USE_CPU_BACKEND) /// Directory prefix for CPU/x86 backend model directories: "prod_X86_". @@ -69,7 +79,7 @@ static constexpr const char* kModelFileExt = ".onnx"; static constexpr const char* kSupportedChips[] = {"X86"}; #else -#error "Either COSMO_NN_USE_SOPHON_BACKEND or COSMO_NN_USE_CPU_BACKEND must be defined" +#error "A Sophon, CPU, or RKNN backend must be defined" #endif /// Case-insensitive check whether `chip` is a supported chip/platform type for the diff --git a/src/util/PathUtil.cc b/src/util/PathUtil.cc index 84b94ccce..48a77bdc3 100644 --- a/src/util/PathUtil.cc +++ b/src/util/PathUtil.cc @@ -185,9 +185,18 @@ void Init() { EnsureDir(cwaiRuntimePath); } +void OverrideRootPaths(const std::string& dataPath, const std::string& appDataPath) { + const fs::path data_root(dataPath); + const fs::path app_data_root(appDataPath); + if (dataPath.empty() || appDataPath.empty() || !data_root.is_absolute() || !app_data_root.is_absolute()) { + throw std::invalid_argument("Cosmo data roots must be non-empty absolute paths"); + } + g_dataPath = data_root.lexically_normal().string(); + g_appDataPath = app_data_root.lexically_normal().string(); +} + void OverrideRootPathForTest(const std::string& dataPath, const std::string& appDataPath) { - g_dataPath = dataPath; - g_appDataPath = appDataPath; + OverrideRootPaths(dataPath, appDataPath); } // ── Configuration paths ─────────────────────────────────────────────────────── @@ -293,6 +302,10 @@ std::string GetBaseDir() { return g_dataPath; } +std::string GetAppBaseDir() { + return g_appDataPath; +} + [[nodiscard]] bool IsWithinRoot(const std::string& root, const std::string& candidate) { if (root.empty() || candidate.empty()) { return false; diff --git a/src/util/PathUtil.h b/src/util/PathUtil.h index 787f22eaa..af5115500 100644 --- a/src/util/PathUtil.h +++ b/src/util/PathUtil.h @@ -23,6 +23,10 @@ namespace cosmo::path { /// CWAI runtime data path. Call once from SwDevicePreInit(). void Init(); +/// Override the application data roots before Init(). Both paths must be +/// absolute. This supports isolated side-by-side deployments and containers. +void OverrideRootPaths(const std::string& dataPath, const std::string& appDataPath); + /// Test-only: override the root data paths to isolate unit tests from the /// real filesystem. Must be called before any path accessor. /// @param dataPath Replaces the default /data/cwaiuserdata @@ -64,6 +68,9 @@ std::string GetDbBackUpPath(); /// Root data directory for the application. std::string GetBaseDir(); +/// Read-only packaged application root (resource, files, font, and binaries). +std::string GetAppBaseDir(); + /// True iff @p candidate, after canonicalization, is equal to or nested under /// @p root (both canonicalized identically). Neither path is required to exist. /// diff --git a/src/util/Version.h b/src/util/Version.h index 3273387d1..7addb59fd 100644 --- a/src/util/Version.h +++ b/src/util/Version.h @@ -4,10 +4,23 @@ namespace cosmo::util { -constexpr int kVersionMajor = 1; -constexpr int kVersionMinor = 0; -constexpr int kVersionPatch = 0; -constexpr int kVersionBuild = 0; +#ifndef COSMO_VERSION_MAJOR +#define COSMO_VERSION_MAJOR 1 +#endif +#ifndef COSMO_VERSION_MINOR +#define COSMO_VERSION_MINOR 1 +#endif +#ifndef COSMO_VERSION_PATCH +#define COSMO_VERSION_PATCH 0 +#endif +#ifndef COSMO_VERSION_BUILD +#define COSMO_VERSION_BUILD 0 +#endif + +constexpr int kVersionMajor = COSMO_VERSION_MAJOR; +constexpr int kVersionMinor = COSMO_VERSION_MINOR; +constexpr int kVersionPatch = COSMO_VERSION_PATCH; +constexpr int kVersionBuild = COSMO_VERSION_BUILD; // Returns the application description string. constexpr const char* GetProgramDesc() { diff --git a/src/util/dto/CameraMsgTypes.h b/src/util/dto/CameraMsgTypes.h index 5245f820c..5f939e9a1 100644 --- a/src/util/dto/CameraMsgTypes.h +++ b/src/util/dto/CameraMsgTypes.h @@ -31,6 +31,9 @@ struct MsgCameraAttr { float fps{0.0}; ChannelStatus channelStatus{ChannelStatus::ChannelStatusOffline}; // 0: offline, 1: online, 2: auth error int dataStatus{0}; // service::camera::AlgDemuxStatus status + // Runtime-only guard. It is intentionally not serialized into the public + // camera DTO because it only coordinates the demuxer and task monitor. + bool repeatPending{false}; friend void to_json(nlohmann::json& j, const MsgCameraAttr& v); friend void from_json(const nlohmann::json& j, MsgCameraAttr& v); }; diff --git a/src/web/.npmrc b/src/web/.npmrc index 81cb45565..3e94beb74 100644 --- a/src/web/.npmrc +++ b/src/web/.npmrc @@ -1,4 +1,10 @@ -# Locked to npmmirror for install speed. -# IMPORTANT: `npm audit` must be run with `--registry=https://registry.npmjs.org` -# because npmmirror does not implement /-/npm/v1/security/*. +# This mirror is substantially faster on the supported build host. Package +# integrity remains locked in package-lock.json. Keep concurrency at one: +# npm 10.2 can otherwise retain over one hundred CDN sockets and never exit. registry=https://registry.npmmirror.com/ +maxsockets=1 +progress=false +fetch-retries=3 +fetch-timeout=120000 +prefer-offline=true +update-notifier=false diff --git a/src/web/package-lock.json b/src/web/package-lock.json index db21758e8..97c4edcc8 100644 --- a/src/web/package-lock.json +++ b/src/web/package-lock.json @@ -39,7 +39,7 @@ }, "node_modules/@babel/helper-string-parser": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@babel/helper-string-parser/7.29.7/helper-string-parser-7.29.7.tgz", "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "license": "MIT", "engines": { @@ -48,7 +48,7 @@ }, "node_modules/@babel/helper-validator-identifier": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@babel/helper-validator-identifier/7.29.7/helper-validator-identifier-7.29.7.tgz", "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { @@ -57,7 +57,7 @@ }, "node_modules/@babel/parser": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.7.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@babel/parser/7.29.7/parser-7.29.7.tgz", "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "license": "MIT", "dependencies": { @@ -72,7 +72,7 @@ }, "node_modules/@babel/types": { "version": "7.29.7", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.7.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@babel/types/7.29.7/types-7.29.7.tgz", "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "license": "MIT", "dependencies": { @@ -85,14 +85,14 @@ }, "node_modules/@bufbuild/protobuf": { "version": "2.11.0", - "resolved": "https://registry.npmmirror.com/@bufbuild/protobuf/-/protobuf-2.11.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@bufbuild/protobuf/2.11.0/protobuf-2.11.0.tgz", "integrity": "sha512-sBXGT13cpmPR5BMgHE6UEEfEaShh5Ror6rfN3yEK5si7QVrtZg8LEPQb0VVhiLRUslD2yLnXtnRzG035J/mZXQ==", "dev": true, "license": "(Apache-2.0 AND BSD-3-Clause)" }, "node_modules/@ctrl/tinycolor": { "version": "3.6.1", - "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@ctrl/tinycolor/3.6.1/tinycolor-3.6.1.tgz", "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", "license": "MIT", "engines": { @@ -101,7 +101,7 @@ }, "node_modules/@element-plus/icons-vue": { "version": "2.3.2", - "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@element-plus/icons-vue/2.3.2/icons-vue-2.3.2.tgz", "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==", "license": "MIT", "peerDependencies": { @@ -110,7 +110,7 @@ }, "node_modules/@esbuild/linux-x64": { "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@esbuild/linux-x64/0.25.12/linux-x64-0.25.12.tgz", "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", "cpu": [ "x64" @@ -127,7 +127,7 @@ }, "node_modules/@floating-ui/core": { "version": "1.7.4", - "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.4.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@floating-ui/core/1.7.4/core-1.7.4.tgz", "integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==", "license": "MIT", "dependencies": { @@ -136,7 +136,7 @@ }, "node_modules/@floating-ui/dom": { "version": "1.7.5", - "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.5.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@floating-ui/dom/1.7.5/dom-1.7.5.tgz", "integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==", "license": "MIT", "dependencies": { @@ -146,7 +146,7 @@ }, "node_modules/@floating-ui/utils": { "version": "0.2.10", - "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.10.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@floating-ui/utils/0.2.10/utils-0.2.10.tgz", "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", "license": "MIT" }, @@ -162,7 +162,9 @@ }, "funding": { "url": "https://github.com/sponsors/kazupon" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/@intlify/core-base/9.14.5/core-base-9.14.5.tgz", + "integrity": "sha512-5ah5FqZG4pOoHjkvs8mjtv+gPKYU0zCISaYNjBNNqYiaITxW8ZtVih3GS/oTOqN8d9/mDLyrjD46GBApNxmlsA==" }, "node_modules/@intlify/message-compiler": { "version": "9.14.5", @@ -176,7 +178,9 @@ }, "funding": { "url": "https://github.com/sponsors/kazupon" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/@intlify/message-compiler/9.14.5/message-compiler-9.14.5.tgz", + "integrity": "sha512-IHzgEu61/YIpQV5Pc3aRWScDcnFKWvQA9kigcINcCBXN8mbW+vk9SK+lDxA6STzKQsVJxUPg9ACC52pKKo3SVQ==" }, "node_modules/@intlify/shared": { "version": "9.14.5", @@ -186,17 +190,19 @@ }, "funding": { "url": "https://github.com/sponsors/kazupon" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/@intlify/shared/9.14.5/shared-9.14.5.tgz", + "integrity": "sha512-9gB+E53BYuAEMhbCAxVgG38EZrk59sxBtv3jSizNL2hEWlgjBjAw1AwpLHtNaeda12pe6W20OGEa0TwuMSRbyQ==" }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@jridgewell/sourcemap-codec/1.5.5/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@parcel/watcher": { "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.6.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@parcel/watcher/2.5.6/watcher-2.5.6.tgz", "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", "dev": true, "hasInstallScript": true, @@ -233,7 +239,7 @@ }, "node_modules/@parcel/watcher-linux-x64-glibc": { "version": "2.5.6", - "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@parcel/watcher-linux-x64-glibc/2.5.6/watcher-linux-x64-glibc-2.5.6.tgz", "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", "cpu": [ "x64" @@ -255,7 +261,7 @@ "node_modules/@popperjs/core": { "name": "@sxzz/popperjs-es", "version": "2.11.8", - "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@sxzz/popperjs-es/2.11.8/popperjs-es-2.11.8.tgz", "integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==", "license": "MIT", "funding": { @@ -265,7 +271,7 @@ }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@rollup/rollup-linux-x64-gnu/4.59.0/rollup-linux-x64-gnu-4.59.0.tgz", "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", "cpu": [ "x64" @@ -278,20 +284,20 @@ }, "node_modules/@types/estree": { "version": "1.0.8", - "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@types/estree/1.0.8/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, "license": "MIT" }, "node_modules/@types/lodash": { "version": "4.17.24", - "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@types/lodash/4.17.24/lodash-4.17.24.tgz", "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", "license": "MIT" }, "node_modules/@types/lodash-es": { "version": "4.17.12", - "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@types/lodash-es/4.17.12/lodash-es-4.17.12.tgz", "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", "license": "MIT", "dependencies": { @@ -300,13 +306,13 @@ }, "node_modules/@types/web-bluetooth": { "version": "0.0.20", - "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@types/web-bluetooth/0.0.20/web-bluetooth-0.0.20.tgz", "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==", "license": "MIT" }, "node_modules/@vitejs/plugin-vue": { "version": "5.2.4", - "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vitejs/plugin-vue/5.2.4/plugin-vue-5.2.4.tgz", "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", "dev": true, "license": "MIT", @@ -320,7 +326,7 @@ }, "node_modules/@vue-flow/background": { "version": "1.3.2", - "resolved": "https://registry.npmmirror.com/@vue-flow/background/-/background-1.3.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue-flow/background/1.3.2/background-1.3.2.tgz", "integrity": "sha512-eJPhDcLj1wEo45bBoqTXw1uhl0yK2RaQGnEINqvvBsAFKh/camHJd5NPmOdS1w+M9lggc9igUewxaEd3iCQX2w==", "license": "MIT", "peerDependencies": { @@ -330,7 +336,7 @@ }, "node_modules/@vue-flow/controls": { "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/@vue-flow/controls/-/controls-1.1.3.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue-flow/controls/1.1.3/controls-1.1.3.tgz", "integrity": "sha512-XCf+G+jCvaWURdFlZmOjifZGw3XMhN5hHlfMGkWh9xot+9nH9gdTZtn+ldIJKtarg3B21iyHU8JjKDhYcB6JMw==", "license": "MIT", "peerDependencies": { @@ -340,7 +346,7 @@ }, "node_modules/@vue-flow/core": { "version": "1.48.2", - "resolved": "https://registry.npmmirror.com/@vue-flow/core/-/core-1.48.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue-flow/core/1.48.2/core-1.48.2.tgz", "integrity": "sha512-raxhgKWE+G/mcEvXJjGFUDYW9rAI3GOtiHR3ZkNpwBWuIaCC1EYiBmKGwJOoNzVFgwO7COgErnK7i08i287AFA==", "license": "MIT", "dependencies": { @@ -356,7 +362,7 @@ }, "node_modules/@vue-flow/minimap": { "version": "1.5.4", - "resolved": "https://registry.npmmirror.com/@vue-flow/minimap/-/minimap-1.5.4.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue-flow/minimap/1.5.4/minimap-1.5.4.tgz", "integrity": "sha512-l4C+XTAXnRxsRpUdN7cAVFBennC1sVRzq4bDSpVK+ag7tdMczAnhFYGgbLkUw3v3sY6gokyWwMl8CDonp8eB2g==", "license": "MIT", "dependencies": { @@ -370,7 +376,7 @@ }, "node_modules/@vue/compiler-core": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/compiler-core/3.5.35/compiler-core-3.5.35.tgz", "integrity": "sha512-BUmHaR1J+O+CKZ9uJucdVTEr1LHsdyvv7vG3eNRhK3CczEHeMd/LtsHAuD7PbrxvI2envCY2v7HI1vC1aBRzKw==", "license": "MIT", "dependencies": { @@ -383,7 +389,7 @@ }, "node_modules/@vue/compiler-dom": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/compiler-dom/3.5.35/compiler-dom-3.5.35.tgz", "integrity": "sha512-k+bprkXxuqhVajgTx5mUHuir7TwQzUKOWR40ng1ncAqQRPnrLngGGgqVEEhOnTMlc8btHYVKmrP8s5Qyg0hvYA==", "license": "MIT", "dependencies": { @@ -393,7 +399,7 @@ }, "node_modules/@vue/compiler-sfc": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/compiler-sfc/3.5.35/compiler-sfc-3.5.35.tgz", "integrity": "sha512-G5VPMcXTSywXBgtFOZOnHKBxKSrwXUcvY1iaF5/hRcy7t0J6CH/d8ha9F4nzi00Fax1eLV0QHM7v4mQu68jydw==", "license": "MIT", "dependencies": { @@ -410,7 +416,7 @@ }, "node_modules/@vue/compiler-ssr": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/compiler-ssr/3.5.35/compiler-ssr-3.5.35.tgz", "integrity": "sha512-rGhAeXgdM7/ffTJGXT69rCCdTmjDewnFuUZfBQQHTdcEBeWdT5HCGY60y2ytLJr9/Dsu7IntUi5z/w0h6Rjnzw==", "license": "MIT", "dependencies": { @@ -420,13 +426,13 @@ }, "node_modules/@vue/devtools-api": { "version": "6.6.4", - "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/devtools-api/6.6.4/devtools-api-6.6.4.tgz", "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", "license": "MIT" }, "node_modules/@vue/reactivity": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/reactivity/3.5.35/reactivity-3.5.35.tgz", "integrity": "sha512-tVc+SsHConvh/Lz64qq1pP3rYArBmK42xonovEcxY74SQtvctZodG/zhq54P5dr38cVuw25d27cPNRdlMidpGQ==", "license": "MIT", "dependencies": { @@ -435,7 +441,7 @@ }, "node_modules/@vue/runtime-core": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/runtime-core/3.5.35/runtime-core-3.5.35.tgz", "integrity": "sha512-A/xFNX9loIcWDygeQuNCfKuh0CoYBzxhqEMNah5TSFg9Z53DrFYEN2qi5CU9necjM1OWYegYREUTHmXTmhfXtg==", "license": "MIT", "dependencies": { @@ -445,7 +451,7 @@ }, "node_modules/@vue/runtime-dom": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/runtime-dom/3.5.35/runtime-dom-3.5.35.tgz", "integrity": "sha512-odrJ1C391dbGnyDRh8U+rnP7J2amIEzfmRk5vXy7xi3aZhEXofTvpi0T4HJb6jlNqQZTNPR5MPHSB3RHNkIORA==", "license": "MIT", "dependencies": { @@ -457,7 +463,7 @@ }, "node_modules/@vue/server-renderer": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/server-renderer/3.5.35/server-renderer-3.5.35.tgz", "integrity": "sha512-NkebSOYdB97wi8OQcO3HqzZSlymJi/aWsN/7h74OSVhRTm6qGs3Jp3e0rCXynmWwSlKeRrnlIug+ilYoHBmQDA==", "license": "MIT", "dependencies": { @@ -470,13 +476,13 @@ }, "node_modules/@vue/shared": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vue/shared/3.5.35/shared-3.5.35.tgz", "integrity": "sha512-zSbjL7gRXwks2ZQLRGCajBtBXEOXW9Ddhn/HvSdrGkE2dqGnumzW8XtusRrxrE9LvqtiqDXQ+A60Hp6mvdYxfA==", "license": "MIT" }, "node_modules/@vueuse/core": { "version": "10.11.1", - "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-10.11.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vueuse/core/10.11.1/core-10.11.1.tgz", "integrity": "sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==", "license": "MIT", "dependencies": { @@ -491,7 +497,7 @@ }, "node_modules/@vueuse/core/node_modules/vue-demi": { "version": "0.14.10", - "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", + "resolved": "https://cdn.npmmirror.com/packages/vue-demi/0.14.10/vue-demi-0.14.10.tgz", "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", "hasInstallScript": true, "license": "MIT", @@ -517,7 +523,7 @@ }, "node_modules/@vueuse/metadata": { "version": "10.11.1", - "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-10.11.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vueuse/metadata/10.11.1/metadata-10.11.1.tgz", "integrity": "sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==", "license": "MIT", "funding": { @@ -526,7 +532,7 @@ }, "node_modules/@vueuse/shared": { "version": "10.11.1", - "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-10.11.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/@vueuse/shared/10.11.1/shared-10.11.1.tgz", "integrity": "sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==", "license": "MIT", "dependencies": { @@ -538,7 +544,7 @@ }, "node_modules/@vueuse/shared/node_modules/vue-demi": { "version": "0.14.10", - "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz", + "resolved": "https://cdn.npmmirror.com/packages/vue-demi/0.14.10/vue-demi-0.14.10.tgz", "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", "hasInstallScript": true, "license": "MIT", @@ -570,17 +576,21 @@ }, "engines": { "node": ">= 6.0.0" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/agent-base/6.0.2/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==" }, "node_modules/async-validator": { "version": "4.2.5", - "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz", + "resolved": "https://cdn.npmmirror.com/packages/async-validator/4.2.5/async-validator-4.2.5.tgz", "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", - "license": "MIT" + "license": "MIT", + "resolved": "https://cdn.npmmirror.com/packages/asynckit/0.4.0/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { "version": "1.16.1", @@ -590,7 +600,9 @@ "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/axios/1.16.1/axios-1.16.1.tgz", + "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==" }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", @@ -601,11 +613,13 @@ }, "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/call-bind-apply-helpers/1.0.2/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==" }, "node_modules/chokidar": { "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/chokidar/5.0.0/chokidar-5.0.0.tgz", "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", "dev": true, "license": "MIT", @@ -621,7 +635,7 @@ }, "node_modules/colorjs.io": { "version": "0.5.2", - "resolved": "https://registry.npmmirror.com/colorjs.io/-/colorjs.io-0.5.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/colorjs.io/0.5.2/colorjs.io-0.5.2.tgz", "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", "dev": true, "license": "MIT" @@ -634,17 +648,19 @@ }, "engines": { "node": ">= 0.8" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/combined-stream/1.0.8/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==" }, "node_modules/csstype": { "version": "3.2.3", - "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "resolved": "https://cdn.npmmirror.com/packages/csstype/3.2.3/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, "node_modules/d3-color": { "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/d3-color/-/d3-color-3.1.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-color/3.1.0/d3-color-3.1.0.tgz", "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", "license": "ISC", "engines": { @@ -653,7 +669,7 @@ }, "node_modules/d3-dispatch": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-dispatch/3.0.1/d3-dispatch-3.0.1.tgz", "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", "license": "ISC", "engines": { @@ -662,7 +678,7 @@ }, "node_modules/d3-drag": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/d3-drag/-/d3-drag-3.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-drag/3.0.0/d3-drag-3.0.0.tgz", "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", "license": "ISC", "dependencies": { @@ -675,7 +691,7 @@ }, "node_modules/d3-ease": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/d3-ease/-/d3-ease-3.0.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-ease/3.0.1/d3-ease-3.0.1.tgz", "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", "license": "BSD-3-Clause", "engines": { @@ -684,7 +700,7 @@ }, "node_modules/d3-interpolate": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-interpolate/3.0.1/d3-interpolate-3.0.1.tgz", "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", "license": "ISC", "dependencies": { @@ -696,7 +712,7 @@ }, "node_modules/d3-selection": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/d3-selection/-/d3-selection-3.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-selection/3.0.0/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", "engines": { @@ -705,7 +721,7 @@ }, "node_modules/d3-timer": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/d3-timer/-/d3-timer-3.0.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-timer/3.0.1/d3-timer-3.0.1.tgz", "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", "license": "ISC", "engines": { @@ -714,7 +730,7 @@ }, "node_modules/d3-transition": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/d3-transition/-/d3-transition-3.0.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-transition/3.0.1/d3-transition-3.0.1.tgz", "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", "license": "ISC", "dependencies": { @@ -733,7 +749,7 @@ }, "node_modules/d3-zoom": { "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/d3-zoom/-/d3-zoom-3.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/d3-zoom/3.0.0/d3-zoom-3.0.0.tgz", "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", "license": "ISC", "dependencies": { @@ -749,7 +765,7 @@ }, "node_modules/dagre": { "version": "0.8.5", - "resolved": "https://registry.npmmirror.com/dagre/-/dagre-0.8.5.tgz", + "resolved": "https://cdn.npmmirror.com/packages/dagre/0.8.5/dagre-0.8.5.tgz", "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", "license": "MIT", "dependencies": { @@ -759,7 +775,7 @@ }, "node_modules/dayjs": { "version": "1.11.19", - "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.19.tgz", + "resolved": "https://cdn.npmmirror.com/packages/dayjs/1.11.19/dayjs-1.11.19.tgz", "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "license": "MIT" }, @@ -776,18 +792,22 @@ "supports-color": { "optional": true } - } + }, + "resolved": "https://cdn.npmmirror.com/packages/debug/4.4.3/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==" }, "node_modules/delayed-stream": { "version": "1.0.0", "license": "MIT", "engines": { "node": ">=0.4.0" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/delayed-stream/1.0.0/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" }, "node_modules/detect-libc": { "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/detect-libc/2.1.2/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", @@ -806,11 +826,13 @@ }, "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/dunder-proto/1.0.1/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==" }, "node_modules/echarts": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/echarts/-/echarts-6.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/echarts/6.0.0/echarts-6.0.0.tgz", "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==", "license": "Apache-2.0", "dependencies": { @@ -820,7 +842,7 @@ }, "node_modules/element-plus": { "version": "2.13.2", - "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.13.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/element-plus/2.13.2/element-plus-2.13.2.tgz", "integrity": "sha512-Zjzm1NnFXGhV4LYZ6Ze9skPlYi2B4KAmN18FL63A3PZcjhDfroHwhtM6RE8BonlOPHXUnPQynH0BgaoEfvhrGw==", "license": "MIT", "dependencies": { @@ -845,7 +867,7 @@ }, "node_modules/entities": { "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/entities/7.0.1/entities-7.0.1.tgz", "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", "license": "BSD-2-Clause", "engines": { @@ -860,14 +882,18 @@ "license": "MIT", "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/es-define-property/1.0.1/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==" }, "node_modules/es-errors": { "version": "1.3.0", "license": "MIT", "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/es-errors/1.3.0/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, "node_modules/es-object-atoms": { "version": "1.1.2", @@ -877,7 +903,9 @@ }, "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/es-object-atoms/1.1.2/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==" }, "node_modules/es-set-tostringtag": { "version": "2.1.0", @@ -890,17 +918,19 @@ }, "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/es-set-tostringtag/2.1.0/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==" }, "node_modules/es6-promise": { "version": "4.2.8", - "resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz", + "resolved": "https://cdn.npmmirror.com/packages/es6-promise/4.2.8/es6-promise-4.2.8.tgz", "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", "license": "MIT" }, "node_modules/esbuild": { "version": "0.25.12", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.25.12.tgz", + "resolved": "https://cdn.npmmirror.com/packages/esbuild/0.25.12/esbuild-0.25.12.tgz", "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, "hasInstallScript": true, @@ -942,13 +972,13 @@ }, "node_modules/estree-walker": { "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/estree-walker/2.0.2/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "license": "MIT" }, "node_modules/fdir": { "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/fdir/6.5.0/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", @@ -966,7 +996,7 @@ }, "node_modules/flv.js": { "version": "1.6.2", - "resolved": "https://registry.npmmirror.com/flv.js/-/flv.js-1.6.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/flv.js/1.6.2/flv.js-1.6.2.tgz", "integrity": "sha512-xre4gUbX1MPtgQRKj2pxJENp/RnaHaxYvy3YToVVCrSmAWUu85b9mug6pTXF6zakUjNP2lFWZ1rkSX7gxhB/2A==", "license": "Apache-2.0", "dependencies": { @@ -990,7 +1020,9 @@ "debug": { "optional": true } - } + }, + "resolved": "https://cdn.npmmirror.com/packages/follow-redirects/1.16.0/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==" }, "node_modules/form-data": { "version": "4.0.5", @@ -1004,14 +1036,18 @@ }, "engines": { "node": ">= 6" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/form-data/4.0.5/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==" }, "node_modules/function-bind": { "version": "1.1.2", "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/function-bind/1.1.2/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" }, "node_modules/get-intrinsic": { "version": "1.3.0", @@ -1033,7 +1069,9 @@ }, "funding": { "url": "https://github.com/sponsors/ljharb" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/get-intrinsic/1.3.0/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==" }, "node_modules/get-proto": { "version": "1.0.1", @@ -1044,7 +1082,9 @@ }, "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/get-proto/1.0.1/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==" }, "node_modules/gopd": { "version": "1.2.0", @@ -1054,11 +1094,13 @@ }, "funding": { "url": "https://github.com/sponsors/ljharb" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/gopd/1.2.0/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" }, "node_modules/graphlib": { "version": "2.1.8", - "resolved": "https://registry.npmmirror.com/graphlib/-/graphlib-2.1.8.tgz", + "resolved": "https://cdn.npmmirror.com/packages/graphlib/2.1.8/graphlib-2.1.8.tgz", "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", "license": "MIT", "dependencies": { @@ -1067,7 +1109,7 @@ }, "node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/has-flag/4.0.0/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", @@ -1083,7 +1125,9 @@ }, "funding": { "url": "https://github.com/sponsors/ljharb" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/has-symbols/1.1.0/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==" }, "node_modules/has-tostringtag": { "version": "1.0.2", @@ -1096,7 +1140,9 @@ }, "funding": { "url": "https://github.com/sponsors/ljharb" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/has-tostringtag/1.0.2/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==" }, "node_modules/hasown": { "version": "2.0.4", @@ -1106,7 +1152,9 @@ }, "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/hasown/2.0.4/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==" }, "node_modules/https-proxy-agent": { "version": "5.0.1", @@ -1117,18 +1165,20 @@ }, "engines": { "node": ">= 6" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/https-proxy-agent/5.0.1/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==" }, "node_modules/immutable": { "version": "5.1.6", - "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.6.tgz", + "resolved": "https://cdn.npmmirror.com/packages/immutable/5.1.6/immutable-5.1.6.tgz", "integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==", "dev": true, "license": "MIT" }, "node_modules/is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/is-extglob/2.1.1/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", @@ -1139,7 +1189,7 @@ }, "node_modules/is-glob": { "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", + "resolved": "https://cdn.npmmirror.com/packages/is-glob/4.0.3/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", @@ -1153,25 +1203,25 @@ }, "node_modules/js-md5": { "version": "0.8.3", - "resolved": "https://registry.npmmirror.com/js-md5/-/js-md5-0.8.3.tgz", + "resolved": "https://cdn.npmmirror.com/packages/js-md5/0.8.3/js-md5-0.8.3.tgz", "integrity": "sha512-qR0HB5uP6wCuRMrWPTrkMaev7MJZwJuuw4fnwAzRgP4J4/F8RwtodOKpGp4XpqsLBFzzgqIO42efFAyz2Et6KQ==", "license": "MIT" }, "node_modules/lodash": { "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", + "resolved": "https://cdn.npmmirror.com/packages/lodash/4.17.23/lodash-4.17.23.tgz", "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash-es": { "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.17.23.tgz", + "resolved": "https://cdn.npmmirror.com/packages/lodash-es/4.17.23/lodash-es-4.17.23.tgz", "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==", "license": "MIT" }, "node_modules/lodash-unified": { "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz", + "resolved": "https://cdn.npmmirror.com/packages/lodash-unified/1.0.3/lodash-unified-1.0.3.tgz", "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", "license": "MIT", "peerDependencies": { @@ -1182,7 +1232,7 @@ }, "node_modules/magic-string": { "version": "0.30.21", - "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "resolved": "https://cdn.npmmirror.com/packages/magic-string/0.30.21/magic-string-0.30.21.tgz", "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { @@ -1194,11 +1244,13 @@ "license": "MIT", "engines": { "node": ">= 0.4" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/math-intrinsics/1.1.0/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==" }, "node_modules/memoize-one": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/memoize-one/6.0.0/memoize-one-6.0.0.tgz", "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", "license": "MIT" }, @@ -1207,7 +1259,9 @@ "license": "MIT", "engines": { "node": ">= 0.6" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/mime-db/1.52.0/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, "node_modules/mime-types": { "version": "2.1.35", @@ -1217,17 +1271,19 @@ }, "engines": { "node": ">= 0.6" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/mime-types/2.1.35/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==" }, "node_modules/mitt": { "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/mitt/3.0.1/mitt-3.0.1.tgz", "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", "license": "MIT" }, "node_modules/moment": { "version": "2.30.1", - "resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/moment/2.30.1/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", "license": "MIT", "engines": { @@ -1236,11 +1292,13 @@ }, "node_modules/ms": { "version": "2.1.3", - "license": "MIT" + "license": "MIT", + "resolved": "https://cdn.npmmirror.com/packages/ms/2.1.3/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/nanoid": { "version": "3.3.12", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz", + "resolved": "https://cdn.npmmirror.com/packages/nanoid/3.3.12/nanoid-3.3.12.tgz", "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { @@ -1258,7 +1316,7 @@ }, "node_modules/node-addon-api": { "version": "7.1.1", - "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/node-addon-api/7.1.1/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "dev": true, "license": "MIT", @@ -1266,19 +1324,19 @@ }, "node_modules/normalize-wheel-es": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/normalize-wheel-es/1.2.0/normalize-wheel-es-1.2.0.tgz", "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", "license": "BSD-3-Clause" }, "node_modules/picocolors": { "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/picocolors/1.1.1/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "license": "ISC" }, "node_modules/picomatch": { "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", + "resolved": "https://cdn.npmmirror.com/packages/picomatch/4.0.3/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", @@ -1291,7 +1349,7 @@ }, "node_modules/postcss": { "version": "8.5.15", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz", + "resolved": "https://cdn.npmmirror.com/packages/postcss/8.5.15/postcss-8.5.15.tgz", "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "funding": [ { @@ -1322,11 +1380,13 @@ "license": "MIT", "engines": { "node": ">=10" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/proxy-from-env/2.1.0/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==" }, "node_modules/readdirp": { "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/readdirp/5.0.0/readdirp-5.0.0.tgz", "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", "dev": true, "license": "MIT", @@ -1340,7 +1400,7 @@ }, "node_modules/rollup": { "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.59.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/rollup/4.59.0/rollup-4.59.0.tgz", "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", "dev": true, "license": "MIT", @@ -1385,7 +1445,7 @@ }, "node_modules/rxjs": { "version": "7.8.2", - "resolved": "https://registry.npmmirror.com/rxjs/-/rxjs-7.8.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/rxjs/7.8.2/rxjs-7.8.2.tgz", "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dev": true, "license": "Apache-2.0", @@ -1395,7 +1455,7 @@ }, "node_modules/sass": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass/-/sass-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass/1.100.0/sass-1.100.0.tgz", "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==", "dev": true, "license": "MIT", @@ -1416,7 +1476,7 @@ }, "node_modules/sass-embedded": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded/-/sass-embedded-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded/1.100.0/sass-embedded-1.100.0.tgz", "integrity": "sha512-Ut8wlQSk19tm7jMK6mz6cF1+e+E7tUnW2tM02zQDPnOTcVbV8qCQG8UWxZkkNlY50+hV3hqP24OOkUlMz8xBpw==", "dev": true, "license": "MIT", @@ -1458,7 +1518,7 @@ }, "node_modules/sass-embedded-all-unknown": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-all-unknown/-/sass-embedded-all-unknown-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-all-unknown/1.100.0/sass-embedded-all-unknown-1.100.0.tgz", "integrity": "sha512-auFtXY/kwYILmSVjtBDwyj0axcLbYYiffOKWoaXHnI5bsYwiRbBh3EneR1rpbX2ZIZCrwX93i5pxKLTZF/662Q==", "cpu": [ "!arm", @@ -1475,7 +1535,7 @@ }, "node_modules/sass-embedded-android-arm": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-android-arm/-/sass-embedded-android-arm-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-android-arm/1.100.0/sass-embedded-android-arm-1.100.0.tgz", "integrity": "sha512-70f3HgX2pFNmzpGQ86n5e6QfWn2fP4QUQGfFQK0P1XH73ZLIzLo2YqygrGKGKeeqtc5eU2Wl1/xQzhzuKnO4kw==", "cpu": [ "arm" @@ -1492,7 +1552,7 @@ }, "node_modules/sass-embedded-android-arm64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-android-arm64/-/sass-embedded-android-arm64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-android-arm64/1.100.0/sass-embedded-android-arm64-1.100.0.tgz", "integrity": "sha512-W+Ru9JwTnfU0UX3jSZcbqFdtKFMcYdfFwytc57h2DgnqCOIiAqI2E06mABZBZC+r3LwXCBuS5GbXAGeVgvVDkA==", "cpu": [ "arm64" @@ -1509,7 +1569,7 @@ }, "node_modules/sass-embedded-android-riscv64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-android-riscv64/-/sass-embedded-android-riscv64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-android-riscv64/1.100.0/sass-embedded-android-riscv64-1.100.0.tgz", "integrity": "sha512-icU3o0V/uCSytSpf+tX5Lf51BvyQEbLzDUJfUi9etSauYBGHpPKkdtdZH0si4v98phq11Kl8rSV1SggksxF1Hg==", "cpu": [ "riscv64" @@ -1526,7 +1586,7 @@ }, "node_modules/sass-embedded-android-x64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-android-x64/-/sass-embedded-android-x64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-android-x64/1.100.0/sass-embedded-android-x64-1.100.0.tgz", "integrity": "sha512-mevF9VQk6gEYByy8+jusaHGmd7Usb2ytX/DsEOd0JtOGCtcf1kh575xJ6OUBDIcJ15uLnbau/0iy1eP6WVBvWA==", "cpu": [ "x64" @@ -1543,7 +1603,7 @@ }, "node_modules/sass-embedded-darwin-arm64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-darwin-arm64/-/sass-embedded-darwin-arm64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-darwin-arm64/1.100.0/sass-embedded-darwin-arm64-1.100.0.tgz", "integrity": "sha512-1PVlYi61POo93IT/FfrG1mc1tAHxeSTyUALF2aOFmXGWjVXr3bQzEQiBGCOvQbj/ix+5hNyXFXcEMEyKvtUJJA==", "cpu": [ "arm64" @@ -1560,7 +1620,7 @@ }, "node_modules/sass-embedded-darwin-x64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-darwin-x64/-/sass-embedded-darwin-x64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-darwin-x64/1.100.0/sass-embedded-darwin-x64-1.100.0.tgz", "integrity": "sha512-x97o3JnGyImZNCIVs9wQHJUE5QCvmVIKaH1cwrz/5dK7OT1FpeNiW+u9TUomP9hG6Ekjd8EL8NBHpxTfIhdjmg==", "cpu": [ "x64" @@ -1577,7 +1637,7 @@ }, "node_modules/sass-embedded-linux-arm": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-linux-arm/-/sass-embedded-linux-arm-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-linux-arm/1.100.0/sass-embedded-linux-arm-1.100.0.tgz", "integrity": "sha512-9Ul7O1eKrc5YlhwWjkp8tZPSe3UEwSZ1uwUZOQom1HL0pRlBA6F/IlGZYFTLwnHMIP1fc77MMNaBRfc05mKMpw==", "cpu": [ "arm" @@ -1594,7 +1654,7 @@ }, "node_modules/sass-embedded-linux-arm64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-linux-arm64/-/sass-embedded-linux-arm64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-linux-arm64/1.100.0/sass-embedded-linux-arm64-1.100.0.tgz", "integrity": "sha512-Dwjmj8Z6VRy7rAi53JAdEwIyUjpfl7PhpSc2/LpQPQx+aO5Dp7Spaipkax0ufJl1SoDUdchCsM4y/88YaluorQ==", "cpu": [ "arm64" @@ -1611,7 +1671,7 @@ }, "node_modules/sass-embedded-linux-musl-arm": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-linux-musl-arm/-/sass-embedded-linux-musl-arm-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-linux-musl-arm/1.100.0/sass-embedded-linux-musl-arm-1.100.0.tgz", "integrity": "sha512-sl0JgbGloPyJg66XXx5UDSDScZ0oU85DpMQU4JU/sCUCFj1Z8zZ69SJWKTCNE4/jwnce7WI2zPCV5AG+RHOZJw==", "cpu": [ "arm" @@ -1628,7 +1688,7 @@ }, "node_modules/sass-embedded-linux-musl-arm64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-linux-musl-arm64/-/sass-embedded-linux-musl-arm64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-linux-musl-arm64/1.100.0/sass-embedded-linux-musl-arm64-1.100.0.tgz", "integrity": "sha512-XpACJB2KjSLjf2e9uuvGVdOURsoNrFqgRiihhXyUHK9W0t3LIHb7z5MA/7XGPIT9bWSOO2zyw+rH/FHtDV/Yrg==", "cpu": [ "arm64" @@ -1645,7 +1705,7 @@ }, "node_modules/sass-embedded-linux-musl-riscv64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-linux-musl-riscv64/-/sass-embedded-linux-musl-riscv64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-linux-musl-riscv64/1.100.0/sass-embedded-linux-musl-riscv64-1.100.0.tgz", "integrity": "sha512-ShvI0Kx04mwoCARwZ0UjiT97isQvzO80tAt91zmFyHLN9kelc/IrQi940farSm2xQVPCKdeVyeG0ekBsokSpYQ==", "cpu": [ "riscv64" @@ -1662,7 +1722,7 @@ }, "node_modules/sass-embedded-linux-musl-x64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-linux-musl-x64/-/sass-embedded-linux-musl-x64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-linux-musl-x64/1.100.0/sass-embedded-linux-musl-x64-1.100.0.tgz", "integrity": "sha512-TDBCRWNuS4RDLQXvRc1gjZlWiWTWaWGp0Bwu/IKwJxov81lsvrCs3TihTyNXtW7V5aoN4Ky3r0QOkNb3mwmBnA==", "cpu": [ "x64" @@ -1679,7 +1739,7 @@ }, "node_modules/sass-embedded-linux-riscv64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-linux-riscv64/-/sass-embedded-linux-riscv64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-linux-riscv64/1.100.0/sass-embedded-linux-riscv64-1.100.0.tgz", "integrity": "sha512-j4ENJGOheO+fm3j/yorLxCjBP6/XskrZx7dTLlT+lXYwN/qqCqoA/gsNLI0McS3DFM6GBwPiffzWsdWS8t6sEQ==", "cpu": [ "riscv64" @@ -1696,7 +1756,7 @@ }, "node_modules/sass-embedded-linux-x64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-linux-x64/-/sass-embedded-linux-x64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-linux-x64/1.100.0/sass-embedded-linux-x64-1.100.0.tgz", "integrity": "sha512-0vUSN8j0WGtCJIOPh//EmUvYGHW0QOe5iul8qyhPk50MAcw49MA0r34AhftjDdx94ILPF6vApFs0gwHPQRlpVA==", "cpu": [ "x64" @@ -1713,7 +1773,7 @@ }, "node_modules/sass-embedded-unknown-all": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-unknown-all/-/sass-embedded-unknown-all-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-unknown-all/1.100.0/sass-embedded-unknown-all-1.100.0.tgz", "integrity": "sha512-c+naBgWId4MIpToXcI0DgqetjdAkwTTAxFAuOaBz7HUXLdyG1oZRrEvSsbe41nEdQOKH0vgofVFCeSQgoXOG9A==", "dev": true, "license": "MIT", @@ -1730,7 +1790,7 @@ }, "node_modules/sass-embedded-win32-arm64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-win32-arm64/-/sass-embedded-win32-arm64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-win32-arm64/1.100.0/sass-embedded-win32-arm64-1.100.0.tgz", "integrity": "sha512-iE+yxj+hUXwwbqpHkXxgAWTzeRfcWxJ7SSTQEPMk48lwq3oCrWLlz5sQuWHbuTK/i0GKQfROdP+hOmPi89yjUg==", "cpu": [ "arm64" @@ -1747,7 +1807,7 @@ }, "node_modules/sass-embedded-win32-x64": { "version": "1.100.0", - "resolved": "https://registry.npmmirror.com/sass-embedded-win32-x64/-/sass-embedded-win32-x64-1.100.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sass-embedded-win32-x64/1.100.0/sass-embedded-win32-x64-1.100.0.tgz", "integrity": "sha512-qI4F8MI7/KYoy9NdjJfhSspG42WPkADSNDvwEV7qWvCSFC83koJssRsKO2/PfY+niZz6BG65Ic/D+A11h959hw==", "cpu": [ "x64" @@ -1764,7 +1824,7 @@ }, "node_modules/source-map-js": { "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/source-map-js/1.2.1/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "license": "BSD-3-Clause", "engines": { @@ -1773,7 +1833,7 @@ }, "node_modules/supports-color": { "version": "8.1.1", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", + "resolved": "https://cdn.npmmirror.com/packages/supports-color/8.1.1/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", @@ -1789,7 +1849,7 @@ }, "node_modules/sync-child-process": { "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/sync-child-process/-/sync-child-process-1.0.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sync-child-process/1.0.2/sync-child-process-1.0.2.tgz", "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", "dev": true, "license": "MIT", @@ -1802,7 +1862,7 @@ }, "node_modules/sync-message-port": { "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/sync-message-port/-/sync-message-port-1.2.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/sync-message-port/1.2.0/sync-message-port-1.2.0.tgz", "integrity": "sha512-gAQ9qrUN/UCypHtGFbbe7Rc/f9bzO88IwrG8TDo/aMKAApKyD6E3W4Cm0EfhfBb6Z6SKt59tTCTfD+n1xmAvMg==", "dev": true, "license": "MIT", @@ -1812,7 +1872,7 @@ }, "node_modules/tinyglobby": { "version": "0.2.15", - "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz", + "resolved": "https://cdn.npmmirror.com/packages/tinyglobby/0.2.15/tinyglobby-0.2.15.tgz", "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", @@ -1829,7 +1889,7 @@ }, "node_modules/tree-transfer-vue3": { "version": "1.2.2", - "resolved": "https://registry.npmmirror.com/tree-transfer-vue3/-/tree-transfer-vue3-1.2.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/tree-transfer-vue3/1.2.2/tree-transfer-vue3-1.2.2.tgz", "integrity": "sha512-+jBDjXeHSay9PcKJqVwluHWaM6dlnLDtJGhsZ9bp7FKTYA7hNV13/amDjlsHY8OO675/ysrvBm1wJBtNvfKQVQ==", "license": "ISC", "dependencies": { @@ -1839,13 +1899,13 @@ }, "node_modules/tslib": { "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/tslib/2.3.0/tslib-2.3.0.tgz", "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", "license": "0BSD" }, "node_modules/uuid": { "version": "13.0.2", - "resolved": "https://registry.npmmirror.com/uuid/-/uuid-13.0.2.tgz", + "resolved": "https://cdn.npmmirror.com/packages/uuid/13.0.2/uuid-13.0.2.tgz", "integrity": "sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==", "funding": [ "https://github.com/sponsors/broofa", @@ -1858,14 +1918,14 @@ }, "node_modules/varint": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/varint/-/varint-6.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/varint/6.0.0/varint-6.0.0.tgz", "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", "dev": true, "license": "MIT" }, "node_modules/vite": { "version": "6.3.5", - "resolved": "https://registry.npmmirror.com/vite/-/vite-6.3.5.tgz", + "resolved": "https://cdn.npmmirror.com/packages/vite/6.3.5/vite-6.3.5.tgz", "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dev": true, "license": "MIT", @@ -1940,7 +2000,7 @@ }, "node_modules/vue": { "version": "3.5.35", - "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.35.tgz", + "resolved": "https://cdn.npmmirror.com/packages/vue/3.5.35/vue-3.5.35.tgz", "integrity": "sha512-cx89fnr+0kVGHiNFG6y6s0bdjypJRFNZn6x3WPstNdQR1bi1mbB7h4v5IBGTsPJU3nK1+0Iqj3Zf+hZWMieR4Q==", "license": "MIT", "dependencies": { @@ -1975,11 +2035,13 @@ }, "peerDependencies": { "vue": "^3.0.0" - } + }, + "resolved": "https://cdn.npmmirror.com/packages/vue-i18n/9.14.5/vue-i18n-9.14.5.tgz", + "integrity": "sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g==" }, "node_modules/vue-router": { "version": "4.6.4", - "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz", + "resolved": "https://cdn.npmmirror.com/packages/vue-router/4.6.4/vue-router-4.6.4.tgz", "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", "license": "MIT", "dependencies": { @@ -1994,13 +2056,13 @@ }, "node_modules/webworkify-webpack": { "version": "2.1.5", - "resolved": "https://registry.npmmirror.com/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz", + "resolved": "https://cdn.npmmirror.com/packages/webworkify-webpack/2.1.5/webworkify-webpack-2.1.5.tgz", "integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==", "license": "MIT" }, "node_modules/zrender": { "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/zrender/-/zrender-6.0.0.tgz", + "resolved": "https://cdn.npmmirror.com/packages/zrender/6.0.0/zrender-6.0.0.tgz", "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==", "license": "BSD-3-Clause", "dependencies": { diff --git a/src/web/package.json b/src/web/package.json index 05fb48b69..5145c4360 100644 --- a/src/web/package.json +++ b/src/web/package.json @@ -11,7 +11,10 @@ "i18n:check-dialogs": "node scripts/i18n_check_dialog_actions.mjs", "i18n:check-used-keys": "node scripts/i18n_check_used_keys.mjs", "i18n:check": "npm run i18n:check-scopes && npm run i18n:check-glossary && npm run i18n:check-locales && npm run i18n:check-dialogs && npm run i18n:check-used-keys", - "prebuild": "npm run i18n:check", + "upgrade-package:check": "node scripts/upgrade_package_pattern_check.mjs", + "linkage-flow:check": "node scripts/linkage_flow_layout_check.mjs", + "linkage-form:check": "node scripts/linkage_form_compatibility_check.mjs", + "prebuild": "npm run upgrade-package:check && npm run linkage-flow:check && npm run linkage-form:check && npm run i18n:check", "build": "vite build", "preview": "vite preview", "resource-i18n:check": "node scripts/resource_i18n_sync.mjs --check", diff --git a/src/web/scripts/linkage_flow_layout_check.mjs b/src/web/scripts/linkage_flow_layout_check.mjs new file mode 100644 index 000000000..b49913c7a --- /dev/null +++ b/src/web/scripts/linkage_flow_layout_check.mjs @@ -0,0 +1,31 @@ +import assert from 'node:assert/strict' +import { + DETAIL_PANEL_GAP, + DETAIL_PANEL_SIZE, + ALARM_DETAIL_PANEL_SIZE, + FLOW_NODE_SIZE, + getDetailPanelAnchor, + getDetailPanelSize, + getFlowLayoutSpacing +} from '../src/views/gam/countManagement/arrangeDetail/flow/layoutGeometry.js' + +const spacing = getFlowLayoutSpacing(FLOW_NODE_SIZE) +assert.deepEqual(FLOW_NODE_SIZE, { width: 76, height: 96 }) +assert.deepEqual(spacing, { nodesep: 48, ranksep: 50 }) + +// Start + one linkage action + end should remain a compact horizontal flow. +const compactWidth = FLOW_NODE_SIZE.width * 3 + spacing.ranksep * 2 +assert.ok(compactWidth < 400, `three-node flow is too wide: ${compactWidth}px`) + +const node = { position: { x: 500, y: 200 } } +const panel = getDetailPanelAnchor(node) +assert.equal(panel.x, 500 + FLOW_NODE_SIZE.width / 2 - DETAIL_PANEL_SIZE.width / 2) +assert.equal(panel.y, 200 + FLOW_NODE_SIZE.height + DETAIL_PANEL_GAP) + +const alarmPanelSize = getDetailPanelSize('LA_AlarmData_Code') +assert.deepEqual(alarmPanelSize, ALARM_DETAIL_PANEL_SIZE) +assert.ok(alarmPanelSize.width >= DETAIL_PANEL_SIZE.width * 2) +const alarmPanel = getDetailPanelAnchor(node, FLOW_NODE_SIZE, alarmPanelSize) +assert.equal(alarmPanel.x, 500 + FLOW_NODE_SIZE.width / 2 - alarmPanelSize.width / 2) + +console.log('linkage flow layout checks passed') diff --git a/src/web/scripts/linkage_form_compatibility_check.mjs b/src/web/scripts/linkage_form_compatibility_check.mjs new file mode 100644 index 000000000..9aae6de74 --- /dev/null +++ b/src/web/scripts/linkage_form_compatibility_check.mjs @@ -0,0 +1,24 @@ +import assert from 'node:assert/strict' +import { + collectAlarmAlgorithms, + isAlarmAlgorithmsKey +} from '../src/views/gam/countManagement/arrangeDetail/flow/linkageFormCompatibility.js' + +assert.equal(isAlarmAlgorithmsKey('algs'), true) +assert.equal(isAlarmAlgorithmsKey('strageAlgorithms'), true) +assert.equal(isAlarmAlgorithmsKey('audioDeviceId'), false) + +assert.deepEqual( + collectAlarmAlgorithms([ + { + id: 'channel-1', + children: [{ algorithmId: 'algorithm-1' }, { algorithmId: 'algorithm-2' }] + } + ]), + [ + { channelId: 'channel-1', algorithmId: 'algorithm-1' }, + { channelId: 'channel-1', algorithmId: 'algorithm-2' } + ] +) + +console.log('linkage form compatibility checks passed') diff --git a/src/web/scripts/upgrade_package_pattern_check.mjs b/src/web/scripts/upgrade_package_pattern_check.mjs new file mode 100644 index 000000000..367d0edc4 --- /dev/null +++ b/src/web/scripts/upgrade_package_pattern_check.mjs @@ -0,0 +1,25 @@ +import assert from 'node:assert/strict' + +import { isSupportedUpgradePackageName } from '../src/utils/upgradePackage.js' + +const accepted = [ + 'cosmo-V1.0.0-0123456789abcdef0123456789abcdef.tar.gz', + 'cosmo-v1.0.0-0123456789ABCDEF0123456789ABCDEF.tar.gz' +] + +const rejected = [ + '', + 'cosmo-V1.0.0.tar.gz', + 'cosmo-V1.0.0-0123456789abcdef0123456789abcde.tar.gz', + 'cosmo-release-a.tar.gz', + 'cosmo-release-Ab.tar.gz', + 'cosmo-release-../escape.tar.gz', + `cosmo-release-${'a'.repeat(65)}.tar.gz` +] + +for (const name of accepted) { + assert.equal(isSupportedUpgradePackageName(name), true, `expected accepted: ${name}`) +} +for (const name of rejected) { + assert.equal(isSupportedUpgradePackageName(name), false, `expected rejected: ${name}`) +} diff --git a/src/web/src/api/box.js b/src/web/src/api/box.js index 500a2013a..66304c894 100644 --- a/src/web/src/api/box.js +++ b/src/web/src/api/box.js @@ -130,6 +130,14 @@ const system = { data, }) }, + // 升级前检查 /data 空间;cleanupEventMedia=true 时清理事件图片和视频后复检 + boxCheckUpgradeSpace(data) { + return request({ + url: '/gtw/cwai/System/CheckUpgradeSpace', + method: 'post', + data, + }) + }, // 检测主机状态 boxCheckDeviceStatus(data) { return request({ @@ -215,6 +223,12 @@ const system = { method: 'post', }) }, + queryModelAuthorization() { + return request({ url: '/gtw/cwai/System/QueryModelAuthorization', method: 'post', data: {} }) + }, + installModelAuthorization(data) { + return request({ url: '/gtw/cwai/System/InstallModelAuthorization', method: 'post', data }) + }, // 网络设置 // 网卡查询 diff --git a/src/web/src/i18n/locales/en-US.js b/src/web/src/i18n/locales/en-US.js index 6f32f2858..0e21f9240 100644 --- a/src/web/src/i18n/locales/en-US.js +++ b/src/web/src/i18n/locales/en-US.js @@ -82,6 +82,7 @@ export default { batchUpdate: 'Batch Update', editModel: 'Edit Model', configure: 'Config', + deleteAndContinue: 'Delete and Continue', resetOnboarding: 'Reset Guide' }, short: { @@ -890,7 +891,8 @@ export default { resource: { cpuUsage: 'CPU Usage', memoryUsage: 'Memory Usage', - npuUsage: 'NPU Usage', + systemMemoryUsage: 'System Memory Usage', + npuUsage: 'NPU Load', emmcUsage: 'eMMC Usage', packetLoss: 'Packet Loss', noPacketLoss: 'No loss', @@ -902,12 +904,13 @@ export default { mediumLoad: 'Medium', highUsage: 'High', nearLimit: 'Near limit', + unavailable: 'Unavailable', packetLost: 'Lost: {value}', used: 'Used {value}', packetKept: 'Kept: {value}', available: 'Avail. {value}', usedLabel: 'Used', - unusedLabel: 'Unused', + unusedLabel: 'Available', packetLostCount: 'Lost', totalPacketCount: 'Total', systemHealthScore: 'System Health', @@ -918,8 +921,8 @@ export default { poor: 'Poor', // Backend hardware resource item names (resolved by item.key) itemCpuUtilization: 'CPU Usage', - itemGeneralMemory: 'App Memory Usage', - itemNpuUtilization: 'NPU Usage', + itemGeneralMemory: 'System Memory Usage', + itemNpuUtilization: 'NPU Load', itemModelMemory: 'Model Memory Usage', itemPictureMemory: 'Image Memory Usage', itemSpecialMemory: 'Chip Memory Usage', @@ -1137,6 +1140,16 @@ export default { clear: 'Clear' }, systemManage: { + modelAuthorization: 'Model Authorization', + authorizationStatus: 'Authorization Status', + authorized: 'Authorized', + notAuthorized: 'Not Authorized', + downloadAuthorizationRequest: 'Download Device Request', + uploadAuthorizationFile: 'Upload Authorization File', + authorizationRequestFailed: 'Failed to create the device request', + invalidAuthorizationFile: 'Invalid authorization file', + authorizationInstalled: 'Authorization installed', + authorizationInstallFailed: 'Authorization installation failed', // Network Port Settings networkPortSettings: 'Network Port Settings', dnsSettings: 'DNS Settings', @@ -1264,9 +1277,13 @@ export default { upgradeTip1: '1. The device restarts during upgrade; keep power and network connected.', upgradeTip2: '2. The package name must match cosmo-Vversion-md5.tar.gz.', upgradeConfirm: 'Upgrade the device with {fileName}? The device will restart and this page will disconnect temporarily.', + upgradeSpaceCheckFailed: 'Unable to check data-volume space required for the upgrade. Try again later.', + upgradeSpaceCleanupConfirm: 'Insufficient data-volume space: {available} available and at least {required} required. Continuing permanently deletes images and videos under the event-record directory (estimated reclaimable space: {reclaimable}). Delete them and continue the upgrade?', + upgradeEventCleanupFailed: 'Failed to clear event images and videos. The upgrade was stopped.', + upgradeSpaceStillInsufficient: 'Space is still insufficient after cleanup: {available} available and at least {required} required.', restoreFactory: 'Restore Factory Settings', downloadDeviceLog: 'Download Device Log', - invalidUpgradeFile: 'Only cosmo-Vversion-md5.tar.gz format files are supported!', + invalidUpgradeFile: 'Only cosmo-Vversion-md5.tar.gz files are supported!', fileTransferring: 'File transferring', fileTransferringProgress: 'File transferring {percent}%', upgradePreparing: 'File uploaded; validating the package and preparing to restart', diff --git a/src/web/src/i18n/locales/zh-CN.js b/src/web/src/i18n/locales/zh-CN.js index b92c2a152..ee8d4ed12 100644 --- a/src/web/src/i18n/locales/zh-CN.js +++ b/src/web/src/i18n/locales/zh-CN.js @@ -82,6 +82,7 @@ export default { batchUpdate: '批量更新', editModel: '修改模型', configure: '配置', + deleteAndContinue: '删除并继续', resetOnboarding: '重置引导' }, short: { @@ -889,8 +890,9 @@ export default { }, resource: { cpuUsage: 'CPU使用率', - memoryUsage: '显存使用率', - npuUsage: 'NPU使用率', + memoryUsage: '内存使用率', + systemMemoryUsage: '系统内存使用率', + npuUsage: 'NPU负载', emmcUsage: 'eMMC使用率', packetLoss: '丢包率', noPacketLoss: '无丢包', @@ -902,12 +904,13 @@ export default { mediumLoad: '中负载', highUsage: '高占用', nearLimit: '接近上限', + unavailable: '不可用', packetLost: '丢包 {value}', used: '已用 {value}', packetKept: '未丢 {value}', available: '可用 {value}', usedLabel: '已使用', - unusedLabel: '未使用', + unusedLabel: '可用', packetLostCount: '丢包数', totalPacketCount: '总包数', systemHealthScore: '系统健康评分', @@ -918,8 +921,8 @@ export default { poor: '较差', // Backend hardware resource item names (resolved by item.key) itemCpuUtilization: 'CPU使用率', - itemGeneralMemory: '业务内存使用率', - itemNpuUtilization: 'NPU使用率', + itemGeneralMemory: '系统内存使用率', + itemNpuUtilization: 'NPU负载', itemModelMemory: '模型内存使用率', itemPictureMemory: '图片内存使用率', itemSpecialMemory: '芯片内存使用率', @@ -1137,6 +1140,16 @@ export default { clear: '清空' }, systemManage: { + modelAuthorization: '模型授权', + authorizationStatus: '授权状态', + authorized: '已授权', + notAuthorized: '未授权', + downloadAuthorizationRequest: '下载设备请求文件', + uploadAuthorizationFile: '上传授权文件', + authorizationRequestFailed: '生成设备请求文件失败', + invalidAuthorizationFile: '授权文件无效', + authorizationInstalled: '授权安装成功', + authorizationInstallFailed: '授权安装失败', // 网口设置 networkPortSettings: '网口设置', dnsSettings: 'DNS设置', @@ -1264,6 +1277,10 @@ export default { upgradeTip1: '1.升级期间设备会自动重启,请保持供电和网络连接。', upgradeTip2: '2.仅支持文件名为cosmo-V版本号-md5.tar.gz的安装包。', upgradeConfirm: '将使用 {fileName} 升级设备。设备会自动重启,管理页面将暂时断开,是否继续?', + upgradeSpaceCheckFailed: '无法检查升级所需的数据盘空间,请稍后重试', + upgradeSpaceCleanupConfirm: '数据盘空间不足:当前可用 {available},升级至少需要 {required}。继续操作将永久删除事件记录目录中的图片和视频(预计可释放 {reclaimable}),是否删除并继续升级?', + upgradeEventCleanupFailed: '事件图片和视频清理失败,升级已停止', + upgradeSpaceStillInsufficient: '清理后空间仍不足:当前可用 {available},升级至少需要 {required}', restoreFactory: '恢复出厂设置', downloadDeviceLog: '下载设备日志', invalidUpgradeFile: '只能上传cosmo-V版本号-md5.tar.gz格式的文件!', diff --git a/src/web/src/utils/chunkUpload.js b/src/web/src/utils/chunkUpload.js index 837b69541..e6727eb9b 100644 --- a/src/web/src/utils/chunkUpload.js +++ b/src/web/src/utils/chunkUpload.js @@ -12,7 +12,8 @@ export const UploadPurpose = Object.freeze({ AUDIO: 'audio', ALGORITHM: 'algorithm', UPGRADE: 'upgrade', - IMAGE: 'image' + IMAGE: 'image', + MODEL_AUTHORIZATION_CERTIFICATE: 'model-authorization-certificate' }) const validPurposes = new Set(Object.values(UploadPurpose)) diff --git a/src/web/src/utils/request.js b/src/web/src/utils/request.js index e72635def..b903cc90d 100644 --- a/src/web/src/utils/request.js +++ b/src/web/src/utils/request.js @@ -6,6 +6,7 @@ import { formatActionableApiError, normalizeApiError } from '@/utils/apiError' const longTimeoutApi = [ '/gtw/cwai/System/Upgrade', + '/gtw/cwai/System/CheckUpgradeSpace', '/gtw/cwai/File/ImportFile', '/gtw/cwai/Camera/AddVideo', '/gtw/cwai/atomic/model/uploadTemp', @@ -18,6 +19,7 @@ const longTimeoutApi = [ const silentApi = [ '/gtw/cwai/System/Upgrade', + '/gtw/cwai/System/CheckUpgradeSpace', '/gtw/cwai/System/QueryHardwareResource', '/gtw/cwai/network/IpAccessibleCheck', '/gtw/cwai/System/QueryDeviceStatus', diff --git a/src/web/src/utils/upgradePackage.js b/src/web/src/utils/upgradePackage.js new file mode 100644 index 000000000..b423e0fc1 --- /dev/null +++ b/src/web/src/utils/upgradePackage.js @@ -0,0 +1,5 @@ +const upgradePackagePattern = + /^cosmo-[Vv]\d+\.\d+\.\d+-[0-9a-fA-F]{32}\.tar\.gz$/ + +export const isSupportedUpgradePackageName = name => + typeof name === 'string' && upgradePackagePattern.test(name) diff --git a/src/web/src/views/box/bigScreen/warnningScreen/index.vue b/src/web/src/views/box/bigScreen/warnningScreen/index.vue index 15a99e48e..a23b09d1e 100644 --- a/src/web/src/views/box/bigScreen/warnningScreen/index.vue +++ b/src/web/src/views/box/bigScreen/warnningScreen/index.vue @@ -499,6 +499,15 @@ const handleVideoFullScreen = (index) => { } } +const getDefaultOverlayAlgorithmId = (taskList) => { + const enabledTasks = Array.isArray(taskList) + ? taskList.filter((task) => task.enableStatus == 1) + : [] + return enabledTasks.length === 1 + ? String(enabledTasks[0].algorithmId || '') + : '' +} + const handleCameraNodeClick = (node) => { if (node.labelI18nKey === 'common.all' || node.label === '全部') return if (node.channelType == 0 && node.status == 0) @@ -508,7 +517,9 @@ const handleCameraNodeClick = (node) => { id: node.id, name: node.label, taskList: node.taskList, - runAlgorithmId: '' + // A single enabled task is unambiguous: request its OSD stream directly + // instead of opening a raw player only to tear it down immediately. + runAlgorithmId: getDefaultOverlayAlgorithmId(node.taskList) } if (screenType.value == 1) return @@ -643,7 +654,8 @@ const initPlayedCamera = (childCameras) => { ? requestedCamera.taskList : [] const requestedTask = taskList.find( - (task) => String(task.algorithmId) === String(requestedAlgorithmId || '') + (task) => task.enableStatus == 1 && + String(task.algorithmId) === String(requestedAlgorithmId || '') ) playedCameraList.value[0] = { diff --git a/src/web/src/views/box/strategyManagement/components/ArrangeFlow.vue b/src/web/src/views/box/strategyManagement/components/ArrangeFlow.vue index 57b51a3e3..bec683f1d 100644 --- a/src/web/src/views/box/strategyManagement/components/ArrangeFlow.vue +++ b/src/web/src/views/box/strategyManagement/components/ArrangeFlow.vue @@ -1,11 +1,20 @@ <template> <div class="page"> <main class="page-main" :style="{ width: `${width}px`, height: `${height}px` }"> - <VueFlow v-model:nodes="nodes" v-model:edges="edges" :node-types="nodeTypes" :edge-types="edgeTypes"> + <VueFlow v-model:nodes="nodes" v-model:edges="edges" :node-types="nodeTypes" :edge-types="edgeTypes" @node-click="handleNodeClick" @pane-click="closeDetailPanel" @move="handleViewportMove"> <Background pattern-color="#e5e7eb" gap="16" /> <Controls :show-interactive="false" /> <!-- <MiniMap /> --> </VueFlow> + <NodeDetailPanel + v-if="detailPanelNodeId" + ref="detailPanelRef" + :node-id="detailPanelNodeId" + :node-data="detailPanelNodeData" + :position="screenPanelPosition" + @close="closeDetailPanel" + @config-change="handlePanelConfigChange" + /> </main> <teleport to="body"> @@ -20,7 +29,7 @@ <script setup> -import { ref, markRaw, watch, nextTick } from 'vue' +import { ref, markRaw, watch, nextTick, computed, onBeforeUnmount } from 'vue' import { VueFlow, useVueFlow } from '@vue-flow/core' import { Background } from '@vue-flow/background' import { Controls } from '@vue-flow/controls' @@ -39,6 +48,13 @@ import CustomFormNode from '@/views/gam/countManagement/arrangeDetail/flow/Custo import StartNode from '@/views/gam/countManagement/arrangeDetail/flow/StartNode.vue' import EndNode from '@/views/gam/countManagement/arrangeDetail/flow/EndNode.vue' import ActionEdge from '@/views/gam/countManagement/arrangeDetail/flow/ActionEdge.vue' +import NodeDetailPanel from '@/views/gam/countManagement/arrangeDetail/flow/NodeDetailPanel.vue' +import { + getDetailPanelAnchor, + getDetailPanelSize, + getFlowLayoutSpacing, + getFlowNodeDimensions +} from '@/views/gam/countManagement/arrangeDetail/flow/layoutGeometry.js' const props = defineProps({ width: { @@ -49,6 +65,10 @@ const props = defineProps({ type: Number, default: 0 }, + strategyId: { + type: [String, Number], + default: '' + }, actionList: { type: Array, default: () => [] @@ -71,13 +91,14 @@ const nodeTypes = { const edgeTypes = { action: markRaw(ActionEdge) } - const { setNodes, setEdges, addNodes, onPaneReady, getEdges } = useVueFlow() const flowInstance = ref(null) onPaneReady((instance) => { flowInstance.value = instance - // 设置默认视口,不使用自动适应 - instance.setViewport({ x: 100, y: 200, zoom: 0.6 }) + requestAnimationFrame(() => { + centerView() + centeredStrategyId.value = String(props.strategyId || '') + }) }) const addDialogVisible = ref(false) @@ -87,11 +108,23 @@ const addDialogY = ref(0) const addDialogMode = ref('insert') // insert | branch const addDialogSourceId = ref('') -const nodeWidth = 260 -const nodeHeight = 160 const layoutDirection = 'LR' const newFlowData = ref([]) const atomicList = ref([]) +const centeredStrategyId = ref(null) +const detailPanelRef = ref(null) +const detailPanelNodeId = ref(null) +const detailPanelNodeData = ref(null) +const detailPanelPosition = ref({ x: 0, y: 0 }) +const currentViewport = ref({ x: 0, y: 0, zoom: 1 }) +const screenPanelPosition = computed(() => ({ + x: + detailPanelPosition.value.x * currentViewport.value.zoom + + currentViewport.value.x, + y: + detailPanelPosition.value.y * currentViewport.value.zoom + + currentViewport.value.y +})) const parseArray = (val) => { if (Array.isArray(val)) return val if (typeof val === 'string' && val.trim()) { @@ -106,23 +139,32 @@ const parseArray = (val) => { } const getNodeDimensions = (node) => { - if (node.type === 'detection') { - return { width: 550, height: 450 } - } - if (node.type === 'customForm') { - return { width: 550, height: 450 } - } - return { width: nodeWidth, height: nodeHeight } + // Keep the linkage graph on the same fixed card geometry as algorithm + // orchestration. Configuration is rendered in the floating panel and must + // not inflate Dagre's node bounds. + return getFlowNodeDimensions(node) +} + +const getLayoutSpacing = () => { + let maxW = 0 + let maxH = 0 + nodes.value.forEach((node) => { + const dimensions = getNodeDimensions(node) + maxW = Math.max(maxW, dimensions.width) + maxH = Math.max(maxH, dimensions.height) + }) + return getFlowLayoutSpacing({ width: maxW, height: maxH }) } const applyLayout = () => { const dagreGraph = new dagre.graphlib.Graph() dagreGraph.setDefaultEdgeLabel(() => ({})) + const spacing = getLayoutSpacing() dagreGraph.setGraph({ rankdir: layoutDirection, - nodesep: 150, - ranksep: 150 + nodesep: spacing.nodesep, + ranksep: spacing.ranksep }) nodes.value.forEach((node) => { @@ -150,12 +192,17 @@ const applyLayout = () => { } }) + nodes.value = positioned setNodes(positioned) - // 布局完成后居中显示 - // requestAnimationFrame(() => { - // centerView() - // }) + const strategyId = String(props.strategyId || '') + if (centeredStrategyId.value !== strategyId) { + requestAnimationFrame(() => { + if (!flowInstance.value) return + centerView() + centeredStrategyId.value = strategyId + }) + } } const focusNode = (nodeId) => { @@ -201,10 +248,160 @@ const centerView = () => { flowInstance.value && typeof flowInstance.value.setCenter === 'function' ) { - flowInstance.value.setCenter(cx, cy, { zoom: 0.8, duration: 300 }) + flowInstance.value.setCenter(cx, cy, { zoom: 1.0, duration: 300 }) + } +} + +const updateNodeConfig = (nodeId, config) => { + if (!nodeId || !config) return + nodes.value = nodes.value.map((node) => { + if (String(node.id) !== String(nodeId)) return node + const flowData = { + ...(node.data?.flowData || {}), + configObject: config + } + return { + ...node, + data: { + ...node.data, + flowData, + actionDetail: { + ...(node.data?.actionDetail || {}), + configObject: config + } + } + } + }) + setNodes(nodes.value) + detailPanelNodeData.value = + nodes.value.find((node) => String(node.id) === String(nodeId))?.data || null +} + +const collectCurrentPanelConfig = () => { + if (!detailPanelNodeId.value || !detailPanelRef.value) return + updateNodeConfig( + detailPanelNodeId.value, + detailPanelRef.value.submitForm?.() + ) +} + +const handlePanelConfigChange = (config) => { + updateNodeConfig(detailPanelNodeId.value, config) +} + +const handleViewportMove = (transform) => { + if (!transform) return + currentViewport.value = { + x: transform.x, + y: transform.y, + zoom: transform.zoom } } +const markNodeSelected = (nodeId) => { + const nextNodes = nodes.value.map((node) => ({ + ...node, + data: { + ...(node.data || {}), + selected: String(node.id) === String(nodeId) + } + })) + nodes.value = nextNodes + setNodes(nextNodes) +} + +const clearNodeSelected = () => { + const nextNodes = nodes.value.map((node) => ({ + ...node, + data: { + ...(node.data || {}), + selected: false + } + })) + nodes.value = nextNodes + setNodes(nextNodes) +} + +const handleNodeClick = ({ node } = {}) => { + if (!node || node.type === 'start' || node.type === 'end') return + if (detailPanelNodeId.value && detailPanelNodeId.value !== String(node.id)) { + collectCurrentPanelConfig() + } + const dimensions = getNodeDimensions(node) + const panelSize = getDetailPanelSize(node.data?.actionId) + const panelWidth = panelSize.width + const panelHeight = panelSize.height + const { x: panelX, y: panelY } = getDetailPanelAnchor( + node, + dimensions, + panelSize + ) + detailPanelNodeId.value = String(node.id) + detailPanelNodeData.value = node.data + detailPanelPosition.value = { + x: panelX, + y: panelY + } + markNodeSelected(node.id) + + nextTick(() => { + detailPanelRef.value?.resetDragOffset?.() + if (!flowInstance.value?.setCenter) return + + const bounds = nodes.value.reduce( + (acc, item) => { + const size = getNodeDimensions(item) + return { + minX: Math.min(acc.minX, item.position.x), + minY: Math.min(acc.minY, item.position.y), + maxX: Math.max(acc.maxX, item.position.x + size.width), + maxY: Math.max(acc.maxY, item.position.y + size.height) + } + }, + { minX: panelX, minY: panelY, maxX: panelX + panelWidth, maxY: panelY + panelHeight } + ) + const viewport = flowInstance.value.getViewport?.() + const zoom = Math.min(viewport?.zoom || 1, 0.75) + flowInstance.value.setCenter( + (bounds.minX + bounds.maxX) / 2, + (bounds.minY + bounds.maxY) / 2, + { zoom, duration: 280 } + ) + setTimeout(() => { + const viewportAfter = flowInstance.value?.getViewport?.() + if (viewportAfter) currentViewport.value = viewportAfter + }, 300) + }) +} + +const closeDetailPanel = () => { + collectCurrentPanelConfig() + detailPanelNodeId.value = null + detailPanelNodeData.value = null + clearNodeSelected() + nextTick(centerView) +} + +const handleOpenDetailPanel = (nodeId) => { + const node = nodes.value.find((item) => String(item.id) === String(nodeId)) + if (node) handleNodeClick({ node }) +} + +const handleCloseDetailPanel = (nodeId) => { + if (String(detailPanelNodeId.value) === String(nodeId)) { + detailPanelNodeId.value = null + detailPanelNodeData.value = null + } +} + +EventBus.$on('flow:openDetailPanel', handleOpenDetailPanel) +EventBus.$on('flow:closeDetailPanel', handleCloseDetailPanel) + +onBeforeUnmount(() => { + EventBus.$off('flow:openDetailPanel', handleOpenDetailPanel) + EventBus.$off('flow:closeDetailPanel', handleCloseDetailPanel) +}) + EventBus.$on('edgeMenu:focus', (nodeId) => { // requestAnimationFrame(() => { // focusNode(nodeId) @@ -340,7 +537,7 @@ const addComponentFromDialog = (type, label, action) => { actionName: action?.actionName, actionType: action?.actionType, // businessCategory: action?.businessCategory, - description: action?.description, + description: action?.description ?? action?.remark, atomicList: atomicList.value || [], flowData: flowItem || {}, actionDetail: { @@ -580,6 +777,7 @@ const saveMetaDataParams = () => { } const saveFlowData = () => { + collectCurrentPanelConfig() EventBus.$emit('flow:collectConfigs') const incomingMap = new Map() edges.value.forEach((e) => { @@ -652,6 +850,8 @@ const saveFlowData = () => { // Expose functions to parent component const clearFlow = () => { + detailPanelNodeId.value = null + detailPanelNodeData.value = null setNodes([]) setEdges([]) nodes.value = [] @@ -680,8 +880,10 @@ const branchInputParamConfig = ref( '[{"type":"condition","defaultValue":"","description":"配置条件使其结果为真,并运行下面的动作","failedTip":"请选择","key":"condition","name":"条件配置","level":"1","regexpr":""}]' ) watch( - () => props.workFlow, - (newVal) => { + [() => props.strategyId, () => props.workFlow], + ([, newVal]) => { + detailPanelNodeId.value = null + detailPanelNodeData.value = null newFlowData.value = parseArray(newVal) atomicList.value = [] if (newFlowData.value) { @@ -736,6 +938,7 @@ watch( flex: none; min-height: 0; overflow: hidden; + position: relative; } .page-main :deep(.vue-flow) { diff --git a/src/web/src/views/box/strategyManagement/linkageStrategy/index.vue b/src/web/src/views/box/strategyManagement/linkageStrategy/index.vue index 0550846da..e962c80fa 100644 --- a/src/web/src/views/box/strategyManagement/linkageStrategy/index.vue +++ b/src/web/src/views/box/strategyManagement/linkageStrategy/index.vue @@ -38,7 +38,7 @@ </aside> <div class="flow-container" ref="containerRef"> - <ArrangeFlow ref="flowRef" :width="width" :height="height" :workFlow="currentStrategy.workFlow" :actionList="actionList" :atomicCode="''" @onMetadata="onMetadata" /> + <ArrangeFlow ref="flowRef" :width="width" :height="height" :strategyId="currentStrategy.id" :workFlow="currentStrategy.workFlow" :actionList="actionList" :atomicCode="''" @onMetadata="onMetadata" /> </div> <el-dialog :title="strategyMode === 'edit' ? t('linkageStrategy.editStrategy') : t('linkageStrategy.addStrategy')" v-model="strategyDialogVisible" center width="420px" @close="onDialogClose"> <el-form ref="strategyFormRef" :model="strategyForm" :rules="strategyRules" :label-width="currentLocale === 'en-US' ? '170px' : '120px'" label-position="right"> @@ -121,7 +121,10 @@ onMounted(() => { window.addEventListener('resize', handleResize) // 加载可编排动作 $API.boxActionList({}).then((res) => { - actionList.value = res?.resData?.strages || [] + actionList.value = (res?.resData?.strages || []).map((item) => ({ + ...item, + actionType: item.actionType || item.businessCategory + })) queryStrategyList() }) }) diff --git a/src/web/src/views/box/systemManagement/systemMaintain/index.vue b/src/web/src/views/box/systemManagement/systemMaintain/index.vue index 9b88d9208..eebc31867 100644 --- a/src/web/src/views/box/systemManagement/systemMaintain/index.vue +++ b/src/web/src/views/box/systemManagement/systemMaintain/index.vue @@ -32,6 +32,23 @@ <el-button type="primary" size="small" @click="downloadLog">{{ t('systemManage.downloadDeviceLog') }}</el-button> </div> </el-tab-pane> + <el-tab-pane v-if="authorization.supported" :label="t('systemManage.modelAuthorization')" name="authorization"> + <div class="authorization-container"> + <el-descriptions :column="1" border> + <el-descriptions-item :label="t('systemManage.authorizationStatus')"> + <el-tag :type="authorization.authorized ? 'success' : 'warning'"> + {{ authorization.authorized ? t('systemManage.authorized') : t('systemManage.notAuthorized') }} + </el-tag> + </el-descriptions-item> + </el-descriptions> + <div class="authorization-actions"> + <el-button @click="downloadAuthorizationRequest">{{ t('systemManage.downloadAuthorizationRequest') }}</el-button> + <el-upload action="#" :auto-upload="false" :show-file-list="false" :on-change="handleCertificateChange" accept=".bin"> + <el-button type="primary">{{ t('systemManage.uploadAuthorizationFile') }}</el-button> + </el-upload> + </div> + </div> + </el-tab-pane> <el-tab-pane :label="t('systemManage.taskRunningDetail')" name="task"> <running-detail v-if="activeTab==='task'" /> </el-tab-pane> @@ -40,11 +57,12 @@ </template> <script setup> -import { ref, watch, onBeforeUnmount, getCurrentInstance } from 'vue' +import { ref, watch, onBeforeUnmount, onMounted, getCurrentInstance } from 'vue' import { ElMessage, ElMessageBox, ElLoading } from 'element-plus' import RunningDetail from './components/RunningDetail.vue' import { t } from '@/i18n' -import { normalizeApiError } from '@/utils/apiError' +import { formatBytes, normalizeApiError } from '@/utils/apiError' +import { isSupportedUpgradePackageName } from '@/utils/upgradePackage' import { uploadFileInChunks, UploadPurpose @@ -58,14 +76,70 @@ const uploadFile = ref(null) const fileName = ref('') const upload = ref(null) const checkTimer = ref(null) -const upgradePackagePattern = /^cosmo-[Vv]\d+\.\d+\.\d+-[0-9a-fA-F]{32}\.tar\.gz$/ const upgradeStatusPollIntervalMs = 5000 const upgradeRecoveryTimeoutMs = 15 * 60 * 1000 let upgradeLoading = null +const authorization = ref({ supported: false, authorized: false, state: 'unsupported' }) + +const refreshAuthorization = async () => { + try { + const response = await $API.queryModelAuthorization() + authorization.value = response?.resData?.resData || response?.resData || authorization.value + } catch (_) { + authorization.value = { supported: false, authorized: false, state: 'unsupported' } + } +} + +const downloadAuthorizationRequest = async () => { + const response = await fetch('/gtw/cwai/System/DownloadModelAuthorizationRequest', { + method: 'POST', + headers: { 'Content-Type': 'application/json', token: localStorage.getItem('mtk') || '', mtk: localStorage.getItem('mtk') || '' }, + body: '{}' + }) + if (!response.ok) throw new Error(t('systemManage.authorizationRequestFailed')) + const blob = await response.blob() + const url = URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = 'device-request.cmpr' + link.click() + URL.revokeObjectURL(url) +} + +const handleCertificateChange = async file => { + const rawFile = file?.raw || file + if (!rawFile || rawFile.size !== 236) { + ElMessage.error(t('systemManage.invalidAuthorizationFile')) + return + } + try { + const staged = await uploadFileInChunks(rawFile, { + purpose: UploadPurpose.MODEL_AUTHORIZATION_CERTIFICATE, + uploadChunk: formData => $API.uploadAtomicModelTemp(formData), + cancelUpload: data => $API.cancelAtomicModelUpload(data), + getCapabilities: () => $API.getUploadCapabilities() + }) + await $API.installModelAuthorization({ uploadId: staged.uploadId }) + ElMessage.success(t('systemManage.authorizationInstalled')) + await refreshAuthorization() + } catch (_) { + ElMessage.error(t('systemManage.authorizationInstallFailed')) + } +} + +onMounted(refreshAuthorization) const extractDeviceStatus = response => response?.resData?.resData || response?.resData || {} +const checkUpgradeSpace = async cleanupEventMedia => { + const response = await $API.boxCheckUpgradeSpace({ + packageSizeBytes: uploadFile.value.size, + cleanupEventMedia + }) + return extractDeviceStatus(response) +} + const delay = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds)) @@ -94,7 +168,9 @@ const finishUpgradeRecovery = async (loading) => { await delay(400) localStorage.removeItem('token') localStorage.removeItem('mtk') - window.location.replace('/#/boxLogin') + // A hash-only navigation keeps the old document and its module graph alive. + // Changing the query forces a fresh index.html request after the upgrade. + window.location.replace(`/?upgrade=${Date.now()}#/boxLogin`) } watch(activeTab, (newVal) => { @@ -104,7 +180,7 @@ watch(activeTab, (newVal) => { }, { immediate: true }) const beforeUpload = (file) => { - if (!upgradePackagePattern.test(file.name)) { + if (!isSupportedUpgradePackageName(file.name)) { ElMessage.error(t('systemManage.invalidUpgradeFile')) return false } @@ -120,7 +196,7 @@ const beforeUpload = (file) => { const handleFileChange = (file) => { if (file) { const rawFile = file.raw || file - if (!upgradePackagePattern.test(rawFile.name)) { + if (!isSupportedUpgradePackageName(rawFile.name)) { ElMessage.error(t('systemManage.invalidUpgradeFile')) fileName.value = '' uploadFile.value = null @@ -159,6 +235,48 @@ const handleUpgrade = async () => { return } + let spaceStatus + try { + spaceStatus = await checkUpgradeSpace(false) + } catch (_) { + ElMessage.error(t('systemManage.upgradeSpaceCheckFailed')) + return + } + + if (!spaceStatus.sufficient) { + try { + await ElMessageBox.confirm( + t('systemManage.upgradeSpaceCleanupConfirm', { + available: formatBytes(spaceStatus.availableBytes), + required: formatBytes(spaceStatus.requiredBytes), + reclaimable: formatBytes(spaceStatus.eventMediaBytes) + }), + t('common.notice'), + { + confirmButtonText: t('action.deleteAndContinue'), + cancelButtonText: t('action.cancel'), + type: 'warning' + } + ) + } catch (_) { + return + } + + try { + spaceStatus = await checkUpgradeSpace(true) + } catch (_) { + ElMessage.error(t('systemManage.upgradeEventCleanupFailed')) + return + } + if (!spaceStatus.sufficient) { + ElMessage.error(t('systemManage.upgradeSpaceStillInsufficient', { + available: formatBytes(spaceStatus.availableBytes), + required: formatBytes(spaceStatus.requiredBytes) + })) + return + } + } + clearCheckTimer() let baselineBootId = '' try { @@ -348,6 +466,9 @@ onBeforeUnmount(() => { padding: 20px; } + .authorization-container { padding: 20px; max-width: 720px; } + .authorization-actions { display: flex; gap: 12px; margin-top: 20px; } + .form-item { display: flex; align-items: center; diff --git a/src/web/src/views/gam/countManagement/algorithmicManagement/algorithmicIndex.vue b/src/web/src/views/gam/countManagement/algorithmicManagement/algorithmicIndex.vue index df4a46e74..15311b987 100644 --- a/src/web/src/views/gam/countManagement/algorithmicManagement/algorithmicIndex.vue +++ b/src/web/src/views/gam/countManagement/algorithmicManagement/algorithmicIndex.vue @@ -669,8 +669,7 @@ export default { algorithmUsage: Number(this.addAlgorithmicForm.algorithmUsage), eventType: this.addAlgorithmicForm.eventType, checkType: this.addAlgorithmicForm.checkType, - remark: this.addAlgorithmicForm.remark, - filePath: '/appfs/cosmo_wander/cwai_data/resource/algorithm' + remark: this.addAlgorithmicForm.remark } params.algorithmCategory = Number(params.algorithmCategory) params.checkType = Number(params.checkType) diff --git a/src/web/src/views/gam/countManagement/algorithmicManagement/algorithmicStatus.vue b/src/web/src/views/gam/countManagement/algorithmicManagement/algorithmicStatus.vue index aec4b3ab1..dd5687715 100644 --- a/src/web/src/views/gam/countManagement/algorithmicManagement/algorithmicStatus.vue +++ b/src/web/src/views/gam/countManagement/algorithmicManagement/algorithmicStatus.vue @@ -45,6 +45,11 @@ <span v-for="item in scope.row.envStatus.BM1688" :class="returnSpanStyle(item)" :key="item.modelCode">{{ item.modelName }}</span> </template> </el-table-column> + <el-table-column v-if="engineTypeList.includes('RK3576')" :label="'RK3576 ' + t('glossary.modelStatus')"> + <template #default="scope"> + <span v-for="item in scope.row.envStatus.RK3576" :class="returnSpanStyle(item)" :key="item.modelCode">{{ item.modelName }}</span> + </template> + </el-table-column> </template> <el-table-column v-if="platformType ==='15'" :label="t('glossary.modelStatus')"> <template #default="scope"> diff --git a/src/web/src/views/gam/countManagement/arrangeDetail/flow/ActionEdge.vue b/src/web/src/views/gam/countManagement/arrangeDetail/flow/ActionEdge.vue index fd84983cb..06e1928a7 100644 --- a/src/web/src/views/gam/countManagement/arrangeDetail/flow/ActionEdge.vue +++ b/src/web/src/views/gam/countManagement/arrangeDetail/flow/ActionEdge.vue @@ -24,6 +24,7 @@ import { BaseEdge, EdgeLabelRenderer, getBezierPath, + getSmoothStepPath, useVueFlow } from '@vue-flow/core' import EventBus from '@/components/eventBus.js' @@ -59,12 +60,17 @@ const props = defineProps({ required: true }, style: Object, - markerEnd: [String, Object] + markerEnd: [String, Object], + data: Object }) const { addNodes, setEdges, getEdges, getNodes } = useVueFlow() -const edgePath = computed(() => getBezierPath(props)) +const edgePath = computed(() => + props.data?.pathType === 'smoothstep' + ? getSmoothStepPath(props) + : getBezierPath(props) +) const path = computed(() => edgePath.value[0]) const labelX = computed(() => edgePath.value[1]) diff --git a/src/web/src/views/gam/countManagement/arrangeDetail/flow/ArrangeFlow.vue b/src/web/src/views/gam/countManagement/arrangeDetail/flow/ArrangeFlow.vue index a508cc972..931e300ef 100644 --- a/src/web/src/views/gam/countManagement/arrangeDetail/flow/ArrangeFlow.vue +++ b/src/web/src/views/gam/countManagement/arrangeDetail/flow/ArrangeFlow.vue @@ -63,6 +63,12 @@ import EndNode from './EndNode.vue' import ActionEdge from './ActionEdge.vue' import StageGroupNode from './StageGroupNode.vue' import NodeDetailPanel from './NodeDetailPanel.vue' +import { + getDetailPanelAnchor, + getDetailPanelSize, + getFlowLayoutSpacing, + getFlowNodeDimensions +} from './layoutGeometry.js' const props = defineProps({ width: { @@ -146,7 +152,7 @@ const getNodeDimensions = (node) => { } } // 所有业务节点均为固定尺寸卡片(不再有展开态) - return { width: 76, height: 96 } + return getFlowNodeDimensions(node) } const getLayoutSpacing = () => { @@ -159,9 +165,7 @@ const getLayoutSpacing = () => { if (d.height > maxH) maxH = d.height }) // LR 布局下:nodesep 控制纵向间距,ranksep 控制横向间距 - const nodesep = Math.max(40, Math.min(240, Math.round(maxH * 0.5))) - const ranksep = Math.max(50, Math.min(320, Math.round(maxW * 0.4))) - return { nodesep, ranksep } + return getFlowLayoutSpacing({ width: maxW, height: maxH }) } const applyLayout = () => { @@ -360,13 +364,12 @@ const openDetailPanel = (nodeId) => { } const dim = getNodeDimensions(node) - const panelGap = 12 // 节点底部与面板顶部之间的间距 - const panelW = 360 // 面板宽度(与 NodeDetailPanel.vue 保持一致) - const panelH = 350 // 面板最大高度 + const panelSize = getDetailPanelSize(node.data?.actionId) + const panelW = panelSize.width + const panelH = panelSize.height // 面板顶部对齐选中节点的底部,X 居中对齐节点 - const panelX = node.position.x + dim.width / 2 - panelW / 2 - const panelY = node.position.y + dim.height + panelGap + const { x: panelX, y: panelY } = getDetailPanelAnchor(node, dim, panelSize) detailPanelNodeId.value = nodeId detailPanelNodeData.value = node.data diff --git a/src/web/src/views/gam/countManagement/arrangeDetail/flow/DynamicForm.vue b/src/web/src/views/gam/countManagement/arrangeDetail/flow/DynamicForm.vue index 117f0a15b..3f924433b 100644 --- a/src/web/src/views/gam/countManagement/arrangeDetail/flow/DynamicForm.vue +++ b/src/web/src/views/gam/countManagement/arrangeDetail/flow/DynamicForm.vue @@ -303,6 +303,10 @@ import { mergeMetaParamsPreservingUnknown, mergeParamsPreservingUnknown } from './areaRuleCompatibility.js' +import { + collectAlarmAlgorithms, + isAlarmAlgorithmsKey +} from './linkageFormCompatibility.js' // Props const props = defineProps({ @@ -481,7 +485,9 @@ onMounted(() => { } item.key === 'data' && getAudioFile(index) - item.key === 'deviceSN' && getAudioDevice(index) + if (item.key === 'deviceSN' || item.key === 'audioDeviceId') { + getAudioDevice(index) + } }) if (isAreaAlarmAction.value) { @@ -799,35 +805,21 @@ const countLeafNodes = (data) => { return count } -const collectToSelection = () => { - const result = [] - const walk = (nodes) => { - ;(nodes || []).forEach((n) => { - if (n.children && n.children.length) { - walk(n.children) - } else if (n.algorithmId && n.channelId) { - result.push({ - channelId: String(n.channelId), - algorithmId: String(n.algorithmId) - }) - } - }) - } - walk(toData.value || []) - return result -} - const handleAdd = () => { - const list = collectToSelection() - const param = _.find(paramConfigs.value, { key: 'strageAlgorithms' }) + const list = collectAlarmAlgorithms(toData.value) + const param = _.find(paramConfigs.value, (item) => + isAlarmAlgorithmsKey(item?.key) + ) if (param) { param.value = JSON.stringify(list) } } const handleremove = () => { - const list = collectToSelection() - const param = _.find(paramConfigs.value, { key: 'strageAlgorithms' }) + const list = collectAlarmAlgorithms(toData.value) + const param = _.find(paramConfigs.value, (item) => + isAlarmAlgorithmsKey(item?.key) + ) if (param) { param.value = JSON.stringify(list) } @@ -1291,19 +1283,10 @@ const submitForm = ({ persist = true } = {}) => { targetLabelArr.value = [] } } else { - if (item.key === 'strageAlgorithms') { - const strageAlgorithms = [] - toData.value.forEach((item) => { - item.children.forEach((subItem) => { - strageAlgorithms.push({ - channelId: item.id, - algorithmId: subItem.algorithmId - }) - }) - }) + if (isAlarmAlgorithmsKey(item.key)) { configObject.params.push({ key: item.key, - value: JSON.stringify(strageAlgorithms) + value: JSON.stringify(collectAlarmAlgorithms(toData.value)) }) } else { configObject.params.push({ key: item.key, value: item.value }) diff --git a/src/web/src/views/gam/countManagement/arrangeDetail/flow/NodeDetailPanel.vue b/src/web/src/views/gam/countManagement/arrangeDetail/flow/NodeDetailPanel.vue index e7be2fda5..c47c4feac 100644 --- a/src/web/src/views/gam/countManagement/arrangeDetail/flow/NodeDetailPanel.vue +++ b/src/web/src/views/gam/countManagement/arrangeDetail/flow/NodeDetailPanel.vue @@ -114,6 +114,7 @@ import DynamicForm from './DynamicForm.vue' import { getIconInfo } from './iconMapping.js' import { t } from '@/i18n' import { resolveResourceActionName, resolveResourceActionRemark } from '@/utils/i18nResource' +import { getDetailPanelSize } from './layoutGeometry.js' const props = defineProps({ nodeId: { type: String, required: true }, @@ -154,7 +155,9 @@ const isDragging = ref(false) const panelStyle = computed(() => ({ left: `${props.position.x + dragOffset.value.x}px`, - top: `${props.position.y + dragOffset.value.y}px` + top: `${props.position.y + dragOffset.value.y}px`, + width: `${getDetailPanelSize(actionDetail.value?.actionId).width}px`, + maxHeight: `${getDetailPanelSize(actionDetail.value?.actionId).height}px` })) let dragStartMouse = { x: 0, y: 0 } diff --git a/src/web/src/views/gam/countManagement/arrangeDetail/flow/layoutGeometry.js b/src/web/src/views/gam/countManagement/arrangeDetail/flow/layoutGeometry.js new file mode 100644 index 000000000..3df88884f --- /dev/null +++ b/src/web/src/views/gam/countManagement/arrangeDetail/flow/layoutGeometry.js @@ -0,0 +1,25 @@ +import { isAlarmDataAction } from './linkageFormCompatibility.js' + +export const FLOW_NODE_SIZE = Object.freeze({ width: 76, height: 96 }) +export const DETAIL_PANEL_SIZE = Object.freeze({ width: 360, height: 350 }) +export const ALARM_DETAIL_PANEL_SIZE = Object.freeze({ width: 760, height: 430 }) +export const DETAIL_PANEL_GAP = 12 + +export const getFlowNodeDimensions = () => ({ ...FLOW_NODE_SIZE }) + +export const getFlowLayoutSpacing = (dimensions = FLOW_NODE_SIZE) => ({ + nodesep: Math.max(40, Math.min(240, Math.round(dimensions.height * 0.5))), + ranksep: Math.max(50, Math.min(320, Math.round(dimensions.width * 0.4))) +}) + +export const getDetailPanelSize = (actionId) => + isAlarmDataAction(actionId) ? ALARM_DETAIL_PANEL_SIZE : DETAIL_PANEL_SIZE + +export const getDetailPanelAnchor = ( + node, + dimensions = FLOW_NODE_SIZE, + panelSize = DETAIL_PANEL_SIZE +) => ({ + x: node.position.x + dimensions.width / 2 - panelSize.width / 2, + y: node.position.y + dimensions.height + DETAIL_PANEL_GAP +}) diff --git a/src/web/src/views/gam/countManagement/arrangeDetail/flow/linkageFormCompatibility.js b/src/web/src/views/gam/countManagement/arrangeDetail/flow/linkageFormCompatibility.js new file mode 100644 index 000000000..326427709 --- /dev/null +++ b/src/web/src/views/gam/countManagement/arrangeDetail/flow/linkageFormCompatibility.js @@ -0,0 +1,27 @@ +const ALARM_ALGORITHM_KEYS = new Set(['algs', 'strageAlgorithms']) +const ALARM_ACTION_IDS = new Set(['LA_AlarmData_Code', 'EVT_00001']) + +export const isAlarmAlgorithmsKey = (key) => + ALARM_ALGORITHM_KEYS.has(String(key || '')) + +export const isAlarmDataAction = (actionId) => + ALARM_ACTION_IDS.has(String(actionId || '')) + +export const collectAlarmAlgorithms = (selectedChannels = []) => { + const result = [] + const walk = (nodes, channelId = '') => { + ;(nodes || []).forEach((node) => { + const currentChannelId = node?.channelId || channelId || node?.id || '' + if (Array.isArray(node?.children) && node.children.length) { + walk(node.children, currentChannelId) + } else if (currentChannelId && node?.algorithmId) { + result.push({ + channelId: String(currentChannelId), + algorithmId: String(node.algorithmId) + }) + } + }) + } + walk(selectedChannels) + return result +} diff --git a/src/web/src/views/gam/countManagement/arrangeDetail/index.vue b/src/web/src/views/gam/countManagement/arrangeDetail/index.vue index 7522cc8fa..844c69d08 100644 --- a/src/web/src/views/gam/countManagement/arrangeDetail/index.vue +++ b/src/web/src/views/gam/countManagement/arrangeDetail/index.vue @@ -62,6 +62,7 @@ const route = useRoute() const router = useRouter() const { proxy } = getCurrentInstance() const $API = proxy.$API +const ALGORITHM_TEMPLATE_ROOT = 'algorithm_template' // Refs const flowRef = ref(null) @@ -166,8 +167,7 @@ const updateCanvasSize = () => { const getDetail = (algorithmId, isChooseModel) => { const params = { - id: algorithmId, - filePath: '/appfs/cosmo_wander/cwai_data/resource/algorithm' + id: algorithmId // id: '110020' } $API.algorithmLayoutDetail(params).then((res) => { @@ -229,7 +229,7 @@ const initMetadata = () => { const getTemplateList = () => { const params = { algorithmUsage: algorithmUsage.value ? parseInt(algorithmUsage.value) : -1, - filePath: '/appfs/cosmo_wander/cwai_data/resource/algorithm_template', + filePath: ALGORITHM_TEMPLATE_ROOT } $API.algorithmLayoutList(params).then((res) => { const { resData } = res @@ -255,7 +255,7 @@ const handleTemplateChange = (val) => { const getTemplateDetail = (algorithmId) => { const params = { id: algorithmId, - filePath: '/appfs/cosmo_wander/cwai_data/resource/algorithm_template' + filePath: ALGORITHM_TEMPLATE_ROOT } $API.algorithmLayoutDetail(params).then((res) => { const { resData } = res @@ -314,7 +314,6 @@ const saveClick = (type) => { params.algorithmUsage = algorithmData.value.algorithmUsage || params.algorithmUsage params.remark = algorithmData.value.remark || params.remark - params.filePath = '/appfs/cosmo_wander/cwai_data/resource/algorithm' params.confVersionId = algorithmData.value.confVersionId params.configVersionName = algorithmData.value.configVersionName || t('common.default') if (!showArrangeFlow.value) { diff --git a/src/web/src/views/gam/countManagement/atomicModel/index.vue b/src/web/src/views/gam/countManagement/atomicModel/index.vue index 73da66712..75bb3f992 100644 --- a/src/web/src/views/gam/countManagement/atomicModel/index.vue +++ b/src/web/src/views/gam/countManagement/atomicModel/index.vue @@ -108,29 +108,37 @@ <el-option label="BGR" value="bgr"></el-option> </el-select> </el-form-item> - <!-- 非SAM2类型:单个模型文件上传 --> + <!-- 普通类型或 RKLLM 语言模型:单个主模型文件上传 --> <el-form-item v-if="addModelForm.modelType !== 'sam2'" :label="t('glossary.modelFile')" prop="modelFile"> - <el-upload ref="uploadModelFileRef" action="#" :file-list="addModelForm.modelFileList" :limit="1" :auto-upload="false" :accept="isX86 ? '.onnx' : '.bmodel'" :on-change="handleModelFileChange" :on-remove="handleModelFileRemove"> + <el-upload ref="uploadModelFileRef" action="#" :file-list="addModelForm.modelFileList" :limit="1" :auto-upload="false" :accept="addModelPrimaryFileExtension" :on-change="handleModelFileChange" :on-remove="handleModelFileRemove"> <el-button size="small" type="primary">{{ t('action.browse') }}</el-button> <template #tip> - <div class="upload-warn">{{ t('glossary.selectModelFileTip', { ext: isX86 ? '.onnx' : '.bmodel' }) }}</div> + <div class="upload-warn">{{ t('glossary.selectModelFileTip', { ext: addModelPrimaryFileExtension }) }}</div> + </template> + </el-upload> + </el-form-item> + <el-form-item v-if="isRknn && addModelForm.modelType === 'qwen3_5'" label="vision.rknn" prop="visionFile"> + <el-upload ref="uploadVisionFileRef" action="#" :file-list="addModelForm.visionFileList" :limit="1" :auto-upload="false" accept=".rknn" :on-change="handleVisionFileChange" :on-remove="handleVisionFileRemove"> + <el-button size="small" type="primary">{{ t('action.browse') }}</el-button> + <template #tip> + <div class="upload-warn">RK3576 Qwen3.5 {{ t('glossary.selectModelFileTip', { ext: '.rknn' }) }}</div> </template> </el-upload> </el-form-item> <!-- SAM2类型:两个模型文件上传 --> <el-form-item v-if="addModelForm.modelType === 'sam2'" label="Encoder" prop="encoderFile"> - <el-upload ref="uploadEncoderFileRef" action="#" :file-list="addModelForm.encoderFileList" :limit="1" :auto-upload="false" :accept="isX86 ? '.onnx' : '.bmodel'" :on-change="handleEncoderFileChange" :on-remove="handleEncoderFileRemove"> + <el-upload ref="uploadEncoderFileRef" action="#" :file-list="addModelForm.encoderFileList" :limit="1" :auto-upload="false" :accept="modelFileExtension" :on-change="handleEncoderFileChange" :on-remove="handleEncoderFileRemove"> <el-button size="small" type="primary">{{ t('action.browse') }}</el-button> <template #tip> - <div class="upload-warn">{{ t('glossary.selectEncoderTip', { ext: isX86 ? '.onnx' : '.bmodel' }) }}</div> + <div class="upload-warn">{{ t('glossary.selectEncoderTip', { ext: modelFileExtension }) }}</div> </template> </el-upload> </el-form-item> <el-form-item v-if="addModelForm.modelType === 'sam2'" label="Decoder" prop="decoderFile"> - <el-upload ref="uploadDecoderFileRef" action="#" :file-list="addModelForm.decoderFileList" :limit="1" :auto-upload="false" :accept="isX86 ? '.onnx' : '.bmodel'" :on-change="handleDecoderFileChange" :on-remove="handleDecoderFileRemove"> + <el-upload ref="uploadDecoderFileRef" action="#" :file-list="addModelForm.decoderFileList" :limit="1" :auto-upload="false" :accept="modelFileExtension" :on-change="handleDecoderFileChange" :on-remove="handleDecoderFileRemove"> <el-button size="small" type="primary">{{ t('action.browse') }}</el-button> <template #tip> - <div class="upload-warn">{{ t('glossary.selectDecoderTip', { ext: isX86 ? '.onnx' : '.bmodel' }) }}</div> + <div class="upload-warn">{{ t('glossary.selectDecoderTip', { ext: modelFileExtension }) }}</div> </template> </el-upload> </el-form-item> @@ -308,7 +316,7 @@ <el-button size="small">{{ t('action.browse') }}</el-button> </el-upload> </div> - <div class="upload-warn" style="margin-left: 20px;">{{ t('glossary.importModelTip', { modelFile: isX86 ? 'model.onnx' : 'model.nn' }) }}</div> + <div class="upload-warn" style="margin-left: 20px;">{{ t('glossary.importModelTip', { modelFile: importedModelFileName }) }}</div> </div> <template #footer> <div class="dialog-footer"> @@ -573,6 +581,14 @@ const topBarData = computed(() => ({ ] })) const isX86 = ref(false) +const isRknn = ref(false) +const modelFileExtension = computed(() => isRknn.value ? '.rknn' : (isX86.value ? '.onnx' : '.bmodel')) +const addModelPrimaryFileExtension = computed(() => + isRknn.value && addModelForm.modelType === 'qwen3_5' + ? '.rkllm' + : modelFileExtension.value +) +const importedModelFileName = computed(() => isRknn.value ? 'model.rknn' : (isX86.value ? 'model.onnx' : 'model.nn')) const addModelDialogTitle = computed(() => addModelMode.value === 'edit' ? t('action.editModel') : t('action.addModel')) const addModelMode = ref('add') const isMultiple = ref(false) @@ -587,6 +603,7 @@ const uploadDecoderFileRef = ref(null) const uploadVocabFileRef = ref(null) const uploadCharacterTableFileRef = ref(null) const uploadTokenizerFileRef = ref(null) +const uploadVisionFileRef = ref(null) const addModelForm = reactive({ modelMainType: '', @@ -605,11 +622,14 @@ const addModelForm = reactive({ characterTableFileList: [], tokenizerFile: '', tokenizerFileList: [], + visionFile: '', + visionFileList: [], normalizationMode: '0-1', colorChannel: 'rgb' }) -const modelTypeGroups = computed(() => [ +const modelTypeGroups = computed(() => { + const groups = [ { label: t('glossary.detectAlg'), value: 'detect', @@ -652,7 +672,17 @@ const modelTypeGroups = computed(() => [ { label: 'qwen3_5', value: 'qwen3_5' } ] } -]) + ] + if (!isRknn.value) return groups + const supported = new Set([ + // RK3576 capabilities are exposed only after end-to-end validation with a + // real model on the device. Keep code-only integrations hidden for now. + 'yolov8_det', 'classify', 'qwen3_5' + ]) + return groups + .map(group => ({ ...group, children: group.children.filter(item => supported.has(item.value)) })) + .filter(group => group.children.length > 0) +}) const currentSubModelTypes = computed(() => { return ( @@ -795,6 +825,22 @@ const addModelRules = { }, trigger: 'change' } + ], + visionFile: [ + { + validator: (rule, value, callback) => { + if (!isRknn.value || addModelForm.modelType !== 'qwen3_5') { + callback() + return + } + if (!addModelForm.visionFileList || addModelForm.visionFileList.length === 0) { + callback(new Error('RK3576 Qwen3.5 需要上传 vision.rknn')) + } else { + callback() + } + }, + trigger: 'change' + } ] } @@ -1160,10 +1206,13 @@ const uploadAlgorithmicClosed = () => { addModelForm.characterTableFile = '' addModelForm.tokenizerFileList = [] addModelForm.tokenizerFile = '' + addModelForm.visionFileList = [] + addModelForm.visionFile = '' addModelForm.normalizationMode = '0-1' addModelForm.colorChannel = 'rgb' addModelFormRef.value && addModelFormRef.value.resetFields() uploadCharacterTableFileRef.value && uploadCharacterTableFileRef.value.clearFiles() + uploadVisionFileRef.value && uploadVisionFileRef.value.clearFiles() } const handleModelTypeChange = () => { @@ -1179,6 +1228,8 @@ const handleModelTypeChange = () => { addModelForm.characterTableFile = '' addModelForm.tokenizerFileList = [] addModelForm.tokenizerFile = '' + addModelForm.visionFileList = [] + addModelForm.visionFile = '' addModelForm.normalizationMode = '0-1' addModelForm.colorChannel = 'rgb' nextTick(() => { @@ -1188,6 +1239,7 @@ const handleModelTypeChange = () => { uploadVocabFileRef.value && uploadVocabFileRef.value.clearFiles() uploadCharacterTableFileRef.value && uploadCharacterTableFileRef.value.clearFiles() uploadTokenizerFileRef.value && uploadTokenizerFileRef.value.clearFiles() + uploadVisionFileRef.value && uploadVisionFileRef.value.clearFiles() }) } @@ -1266,6 +1318,19 @@ const handleTokenizerFileRemove = (file, fileList) => { fileList && fileList.length > 0 ? 'file_selected' : '' addModelFormRef.value && addModelFormRef.value.validateField('tokenizerFile') } +const handleVisionFileChange = (file, fileList) => { + addModelForm.visionFileList = + fileList.length > 0 ? [fileList[fileList.length - 1]] : [] + addModelForm.visionFile = + addModelForm.visionFileList.length > 0 ? 'file_selected' : '' + addModelFormRef.value && addModelFormRef.value.validateField('visionFile') +} +const handleVisionFileRemove = (file, fileList) => { + addModelForm.visionFileList = fileList || [] + addModelForm.visionFile = + fileList && fileList.length > 0 ? 'file_selected' : '' + addModelFormRef.value && addModelFormRef.value.validateField('visionFile') +} const uploadSingleFile = async (file, purpose = UploadPurpose.MODEL_COMPONENT) => { const result = await uploadFileInChunks(file, { @@ -1335,7 +1400,7 @@ const sureAddModel = async () => { addModelForm.encoderFileList[0].raw || addModelForm.encoderFileList[0] const decoderFile = addModelForm.decoderFileList[0].raw || addModelForm.decoderFileList[0] - const ext = isX86.value ? '.onnx' : '.bmodel' + const ext = modelFileExtension.value if (!encoderFile.name.endsWith(ext)) { proxy.$message.warning(t('validate.encoderFormatError', { ext })) return @@ -1344,6 +1409,44 @@ const sureAddModel = async () => { proxy.$message.warning(t('validate.decoderFormatError', { ext })) return } + } else if (isRknn.value && addModelForm.modelType === 'qwen3_5') { + if ( + !addModelForm.modelFileList || + addModelForm.modelFileList.length === 0 + ) { + proxy.$message.warning(t('validate.uploadModelFile')) + return + } + if ( + !addModelForm.visionFileList || + addModelForm.visionFileList.length === 0 + ) { + proxy.$message.warning('RK3576 Qwen3.5 需要上传 vision.rknn') + return + } + const languageFile = + addModelForm.modelFileList[0].raw || addModelForm.modelFileList[0] + const visionFile = + addModelForm.visionFileList[0].raw || addModelForm.visionFileList[0] + if (!languageFile.name || !languageFile.name.toLowerCase().endsWith('.rkllm')) { + proxy.$message.warning(t('validate.uploadFormatError', { ext: '.rkllm' })) + return + } + if (!visionFile.name || !visionFile.name.toLowerCase().endsWith('.rknn')) { + proxy.$message.warning(t('validate.uploadFormatError', { ext: '.rknn' })) + return + } + } else if (isRknn.value && addModelForm.modelType === 'qwen3_5') { + const languageFile = + addModelForm.modelFileList[0].raw || addModelForm.modelFileList[0] + const visionFile = + addModelForm.visionFileList[0].raw || addModelForm.visionFileList[0] + const languageUploadId = await stageForAdd(languageFile) + const visionUploadId = await stageForAdd(visionFile) + addModelParams.bmodelFiles = [ + { role: 'language', uploadId: languageUploadId }, + { role: 'vision', uploadId: visionUploadId } + ] } else { if ( !addModelForm.modelFileList || @@ -1354,7 +1457,7 @@ const sureAddModel = async () => { } const file = addModelForm.modelFileList[0].raw || addModelForm.modelFileList[0] - const ext = isX86.value ? '.onnx' : '.bmodel' + const ext = modelFileExtension.value if (!file.name.endsWith(ext)) { proxy.$message.warning(t('validate.uploadFormatError', { ext })) return @@ -1495,8 +1598,10 @@ onMounted(() => { proxy.$API.queryDeviceInfo().then(res => { const devInfoList = res?.resData?.devInfoList || [] const deviceTypeItem = devInfoList.find(item => item.key === 'deviceType') - if (deviceTypeItem && deviceTypeItem.value.toLowerCase().includes('x86')) { - isX86.value = true + if (deviceTypeItem) { + const deviceType = deviceTypeItem.value.toLowerCase() + isX86.value = deviceType.includes('x86') + isRknn.value = deviceType.includes('rk3576') || deviceType.includes('rockchip') } }).catch(() => {}) } diff --git a/src/web/src/views/gam/taskManager/index.vue b/src/web/src/views/gam/taskManager/index.vue index 8f61007cf..67ab74372 100644 --- a/src/web/src/views/gam/taskManager/index.vue +++ b/src/web/src/views/gam/taskManager/index.vue @@ -748,6 +748,7 @@ const handleBatchCommand = (command) => { const addChannelClick = () => { channelDialogMode.value = 'add' Object.assign(channelForm, { + videoChannelId: '', channelType: 0, channelName: '', url: '', diff --git a/src/web/src/views/home/components/ResourceConsume.vue b/src/web/src/views/home/components/ResourceConsume.vue index b6323997c..b6c6939fa 100644 --- a/src/web/src/views/home/components/ResourceConsume.vue +++ b/src/web/src/views/home/components/ResourceConsume.vue @@ -48,7 +48,7 @@ > <div class="chart-header"> <div class="chart-title"> - <div class="title-icon" :style="{ background: getGradientColor(item.usedPercent) }"> + <div class="title-icon" :style="{ background: getGradientColor(resourcePercent(item)) }"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"> <path v-if="item.key.includes('cpu') || item.key.includes('npu')" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 3v2m6-2v2M9 19v2m6-2v2M5 9H3m2 6H3m18-6h-2m2 6h-2M7 19h10a2 2 0 002-2V7a2 2 0 00-2-2H7a2 2 0 00-2 2v10a2 2 0 002 2zM9 9h6v6H9V9z" /> <path v-else-if="item.key.includes('Memory')" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01" /> @@ -58,8 +58,8 @@ </div> <span>{{ resolveResourceName(item) }}</span> </div> - <div class="chart-percentage" :style="{ color: getProgressColor(item.usedPercent) }"> - {{ item.usedPercent }}% + <div class="chart-percentage" :style="{ color: getProgressColor(resourcePercent(item)) }"> + {{ isResourceAvailable(item) ? `${item.usedPercent}%` : t('resource.unavailable') }} </div> </div> @@ -67,15 +67,15 @@ <div class="progress-wrapper"> <el-progress type="circle" - :percentage="item.usedPercent" - :color="getProgressColor(item.usedPercent)" + :percentage="resourcePercent(item)" + :color="getProgressColor(resourcePercent(item))" :width="110" :stroke-width="10" :show-text="false" /> <div class="progress-center"> - <div class="center-value">{{ item.usedPercent }}</div> - <div class="center-unit">%</div> + <div class="center-value">{{ isResourceAvailable(item) ? item.usedPercent : '--' }}</div> + <div v-if="isResourceAvailable(item)" class="center-unit">%</div> </div> </div> @@ -83,12 +83,12 @@ <div class="usage-stats"> <div class="stat-row"> <div class="stat-label"> - <span class="stat-dot" :style="{ background: getProgressColor(item.usedPercent) }"></span> + <span class="stat-dot" :style="{ background: getProgressColor(resourcePercent(item)) }"></span> <span v-if="item.key === 'packetDiscardUtilization'">{{ t('resource.packetLostCount') }}</span> <span v-else>{{ t('resource.usedLabel') }}</span> </div> - <div class="stat-value" :style="{ color: getProgressColor(item.usedPercent) }"> - {{ item.usedSize }} + <div class="stat-value" :style="{ color: getProgressColor(resourcePercent(item)) }"> + {{ isResourceAvailable(item) ? item.usedSize : '--' }} </div> </div> <div class="stat-row"> @@ -98,7 +98,7 @@ <span v-else>{{ t('resource.unusedLabel') }}</span> </div> <div class="stat-value stat-value-gray"> - {{ item.unusedSize }} + {{ isResourceAvailable(item) ? item.unusedSize : '--' }} </div> </div> </div> @@ -135,6 +135,9 @@ const resolveResourceName = (item) => { return i18nKey ? t(i18nKey) : item.name } +const isResourceAvailable = (item) => item?.available !== 0 +const resourcePercent = (item) => isResourceAvailable(item) ? Number(item.usedPercent) || 0 : 0 + // 查询硬件资源 const queryHardwareResource = () => { proxy.$API.queryHardwareResource().then((res) => { diff --git a/src/web/src/views/home/index.vue b/src/web/src/views/home/index.vue index b7581735c..bebda6070 100644 --- a/src/web/src/views/home/index.vue +++ b/src/web/src/views/home/index.vue @@ -27,7 +27,7 @@ </div> <div class="resource-value-row"> <span class="resource-value">{{ item.usedPercent }}</span> - <span class="resource-unit">%</span> + <span v-if="item.isAvailable" class="resource-unit">%</span> </div> <div class="resource-progress"> <div @@ -246,13 +246,14 @@ const displayResourceList = computed(() => { }) const getMergedMemoryItem = () => { - const memoryItems = resourceList.value.filter(item => MEMORY_KEYS.includes(item?.key)) + const memoryItems = dedupeMemoryItems(resourceList.value.filter(item => MEMORY_KEYS.includes(item?.key))) if (!memoryItems.length) return null const capacityItems = memoryItems .map(item => ({ - used: parseSizeToMB(item.usedSize), - unused: parseSizeToMB(item.unusedSize) + used: parseSizeToMiB(item.usedSize), + unused: parseSizeToMiB(item.unusedSize), + memoryDomain: item.memoryDomain || item.key })) .filter(item => item.used !== null && item.unused !== null) @@ -260,10 +261,11 @@ const getMergedMemoryItem = () => { const used = capacityItems.reduce((sum, item) => sum + item.used, 0) const unused = capacityItems.reduce((sum, item) => sum + item.unused, 0) const total = used + unused + const memoryDomains = new Set(capacityItems.map(item => item.memoryDomain)) return { key: 'mergedMemoryUtilization', - name: t('resource.memoryUsage'), + memoryDomain: memoryDomains.size === 1 ? capacityItems[0].memoryDomain : 'combined', usedPercent: total ? Math.round((used / total) * 100) : 0, usedSize: formatCapacity(used), unusedSize: formatCapacity(unused) @@ -273,20 +275,46 @@ const getMergedMemoryItem = () => { const percentSum = memoryItems.reduce((sum, item) => sum + toPercentNumber(item.usedPercent), 0) return { key: 'mergedMemoryUtilization', - name: t('resource.memoryUsage'), + memoryDomain: memoryItems.length === 1 ? (memoryItems[0].memoryDomain || memoryItems[0].key) : 'combined', usedPercent: Math.round(percentSum / memoryItems.length), usedSize: t('resource.usedLabel'), unusedSize: t('resource.unusedLabel') } } +const dedupeMemoryItems = (items) => { + const seenDomains = new Set() + return items.filter(item => { + if (!item?.memoryDomain) return true + if (seenDomains.has(item.memoryDomain)) return false + seenDomains.add(item.memoryDomain) + return true + }) +} + const normalizeResourceItem = (item) => { + const isAvailable = item.available !== 0 + if (!isAvailable) { + return { + ...item, + name: getResourceName(item), + isAvailable: false, + usedPercent: '--', + safePercent: 0, + level: 'unavailable', + statusText: t('resource.unavailable'), + usedLabel: t('resource.unavailable'), + unusedLabel: '' + } + } + const usedPercent = toPercentNumber(item.usedPercent) const levelInfo = getResourceLevelInfo(item.key, usedPercent) return { ...item, name: getResourceName(item), + isAvailable: true, usedPercent, safePercent: Math.min(Math.max(usedPercent, 0), 100), level: levelInfo.level, @@ -299,7 +327,9 @@ const normalizeResourceItem = (item) => { const getResourceName = (item) => { const nameMap = { cpuUtilization: t('resource.cpuUsage'), - mergedMemoryUtilization: t('resource.memoryUsage'), + mergedMemoryUtilization: item.memoryDomain === 'system' + ? t('resource.systemMemoryUsage') + : t('resource.memoryUsage'), npuUtilization: t('resource.npuUsage'), eMMCUtilization: t('resource.emmcUsage'), packetDiscardUtilization: t('resource.packetLoss') @@ -342,16 +372,19 @@ const toPercentNumber = (value) => { return Number.isNaN(number) ? 0 : Math.round(number) } -const parseSizeToMB = (value) => { +const parseSizeToMiB = (value) => { if (!value || typeof value !== 'string') return null - const match = value.trim().match(/^([\d.]+)\s*(GB|MB|KB|B)$/i) + const match = value.trim().match(/^([\d.]+)\s*(GiB|MiB|KiB|GB|MB|KB|B)$/i) if (!match) return null const number = Number(match[1]) const unit = match[2].toUpperCase() const rateMap = { + GIB: 1024, GB: 1024, + MIB: 1, MB: 1, + KIB: 1 / 1024, KB: 1 / 1024, B: 1 / 1024 / 1024 } @@ -359,9 +392,9 @@ const parseSizeToMB = (value) => { return Number.isNaN(number) ? null : number * rateMap[unit] } -const formatCapacity = (valueInMB) => { - if (valueInMB >= 1024) return `${(valueInMB / 1024).toFixed(2)} GB` - return `${valueInMB.toFixed(2)} MB` +const formatCapacity = (valueInMiB) => { + if (valueInMiB >= 1024) return `${(valueInMiB / 1024).toFixed(2)} GiB` + return `${valueInMiB.toFixed(2)} MiB` } const formatResourceTime = (date) => { @@ -810,6 +843,11 @@ onBeforeUnmount(() => { background: rgba(59, 130, 246, 0.1); } +.state-unavailable { + color: #64748b; + background: rgba(100, 116, 139, 0.12); +} + .state-low { color: #15803d; background: rgba(34, 197, 94, 0.1); @@ -834,6 +872,10 @@ onBeforeUnmount(() => { background: #3b82f6; } +.fill-unavailable { + background: #94a3b8; +} + .fill-low { background: #22c55e; } diff --git a/src/web/src/views/main/menu.js b/src/web/src/views/main/menu.js index e130de68f..b643947a8 100644 --- a/src/web/src/views/main/menu.js +++ b/src/web/src/views/main/menu.js @@ -108,7 +108,6 @@ export default [ icon: 'el-icon-mobile', section: 'system', runMode: 1, - hidden: true, children: [ { index: '/peripheralManagement/sound', @@ -121,8 +120,7 @@ export default [ titleKey: 'nav.linkageManagement', icon: 'el-icon-link', section: 'system', - runMode: 1, - hidden: true + runMode: 1 }, { index: '/systemManagement', diff --git a/test/CemV2SophonLoaderTest.cc b/test/CemV2SophonLoaderTest.cc new file mode 100644 index 000000000..8afa31bac --- /dev/null +++ b/test/CemV2SophonLoaderTest.cc @@ -0,0 +1,447 @@ +#include "catch_amalgamated.hpp" + +#ifdef COSMO_NN_USE_SOPHON_BACKEND + +#include <bmruntime_interface.h> + +#include <cstdint> +#include <string> +#include <vector> + +#include "nn/device/sophon/qwen_runtime_safety.h" +#include "nn/guard/CemV2SophonLoader.h" + +namespace cosmo::nn { +namespace { + + struct LoaderMockState { + CmgV2Status open_status = CMG_V2_OK; + CmgV2Status info_status = CMG_V2_OK; + CmgV2Status load_status = CMG_V2_OK; + std::uint32_t segment_count = 1; + std::uint32_t fail_segment = UINT32_MAX; + std::uint32_t info_source = CMG_V2_SOURCE_COSMO_NN_V1; + bool return_artifact_on_open_failure = false; + bool return_runtime_on_load_failure = false; + bool native_create_result = true; + bool native_load_result = true; + + int open_calls = 0; + int info_calls = 0; + int close_calls = 0; + int native_create_calls = 0; + int native_set_calls = 0; + int native_load_calls = 0; + std::uint32_t native_flags = 0; + std::string opened_path; + std::string native_path; + CmgV2SourceFormat opened_source = 0; + std::vector<std::uint32_t> loaded_segments; + std::vector<std::uint32_t> load_flags; + std::vector<std::uintptr_t> destroyed_runtimes; + }; + + CmgV2Artifact* MockArtifact() { + return reinterpret_cast<CmgV2Artifact*>(static_cast<std::uintptr_t>(0x7000)); + } + + void* MockRuntime(std::uint32_t index) { + return reinterpret_cast<void*>(static_cast<std::uintptr_t>(0x8000U + index)); + } + + bm_handle_t MockBmHandle() { + return reinterpret_cast<bm_handle_t>(static_cast<std::uintptr_t>(0x9000)); + } + + CmgV2Status MockOpen(void* context, const char* path, CmgV2SourceFormat source, + CmgV2Artifact** out_artifact) { + auto& state = *static_cast<LoaderMockState*>(context); + ++state.open_calls; + state.opened_path = path == nullptr ? std::string() : path; + state.opened_source = source; + *out_artifact = nullptr; + if (state.open_status != CMG_V2_OK) { + if (state.return_artifact_on_open_failure) { + *out_artifact = MockArtifact(); + } + return state.open_status; + } + *out_artifact = MockArtifact(); + return CMG_V2_OK; + } + + CmgV2Status MockInfo(void* context, const CmgV2Artifact* artifact, CmgV2ArtifactInfo* out_info) { + auto& state = *static_cast<LoaderMockState*>(context); + ++state.info_calls; + REQUIRE(artifact == MockArtifact()); + REQUIRE(out_info != nullptr); + REQUIRE(out_info->struct_size == CMG_V2_ARTIFACT_INFO_SIZE); + if (state.info_status != CMG_V2_OK) { + return state.info_status; + } + out_info->struct_size = CMG_V2_ARTIFACT_INFO_SIZE; + out_info->source_format = state.info_source; + out_info->segment_count = state.segment_count; + out_info->reserved = 0; + return CMG_V2_OK; + } + + CmgV2Status MockLoad(void* context, CmgV2Artifact* artifact, bm_handle_t bm_handle, + std::uint32_t segment_index, const CmgV2SophonLoadOptions* options, + void** out_bmrt) { + auto& state = *static_cast<LoaderMockState*>(context); + REQUIRE(artifact == MockArtifact()); + REQUIRE(bm_handle == MockBmHandle()); + REQUIRE(options != nullptr); + REQUIRE(options->struct_size == CMG_V2_SOPHON_LOAD_OPTIONS_SIZE); + REQUIRE(options->reserved[0] == 0); + REQUIRE(options->reserved[1] == 0); + state.loaded_segments.push_back(segment_index); + state.load_flags.push_back(options->flags); + *out_bmrt = nullptr; + if (segment_index == state.fail_segment) { + if (state.return_runtime_on_load_failure) { + *out_bmrt = MockRuntime(segment_index); + } + return state.load_status == CMG_V2_OK ? CMG_V2_BACKEND_FAILED : state.load_status; + } + *out_bmrt = MockRuntime(segment_index); + return CMG_V2_OK; + } + + void MockClose(void* context, CmgV2Artifact* artifact) noexcept { + auto& state = *static_cast<LoaderMockState*>(context); + CHECK(artifact == MockArtifact()); + ++state.close_calls; + } + + void* MockNativeCreate(void* context, bm_handle_t bm_handle) { + auto& state = *static_cast<LoaderMockState*>(context); + REQUIRE(bm_handle == MockBmHandle()); + ++state.native_create_calls; + return state.native_create_result ? MockRuntime(100) : nullptr; + } + + void MockNativeSetFlags(void* context, void* runtime, std::uint32_t flags) { + auto& state = *static_cast<LoaderMockState*>(context); + REQUIRE(runtime == MockRuntime(100)); + ++state.native_set_calls; + state.native_flags = flags; + } + + bool MockNativeLoad(void* context, void* runtime, const char* path) { + auto& state = *static_cast<LoaderMockState*>(context); + REQUIRE(runtime == MockRuntime(100)); + ++state.native_load_calls; + state.native_path = path == nullptr ? std::string() : path; + return state.native_load_result; + } + + void MockDestroy(void* context, void* runtime) noexcept { + auto& state = *static_cast<LoaderMockState*>(context); + state.destroyed_runtimes.push_back(reinterpret_cast<std::uintptr_t>(runtime)); + } + + CemV2Api GuardApi(LoaderMockState& state) { + return {CMG_V2_ABI_MAJOR, &state, MockOpen, MockInfo, MockLoad, MockClose}; + } + + SophonRuntimeApi RuntimeApi(LoaderMockState& state) { + return {&state, MockNativeCreate, MockNativeSetFlags, MockNativeLoad, MockDestroy}; + } + + ModelLoadDecision ProtectedRawDecision() { + ModelLoadDecision decision; + decision.magic = ModelMagic::kCemc; + decision.action = ModelLoadAction::kGuardV2; + decision.model_path = "/models/protected/model.nn"; + return decision; + } + + ModelLoadDecision NativeRawDecision() { + ModelLoadDecision decision; + decision.magic = ModelMagic::kUnknown; + decision.action = ModelLoadAction::kNativeRawBmodel; + decision.model_path = "/models/plain/model.nn"; + return decision; + } + + RawBmodelLoadPlan ProtectedRawPlan() { + RawBmodelLoadPlan plan; + plan.error = RawBmodelAuthorizationError::kNone; + plan.decision = ProtectedRawDecision(); + return plan; + } + + RawBmodelLoadPlan NativeRawPlan() { + RawBmodelLoadPlan plan; + plan.error = RawBmodelAuthorizationError::kNone; + plan.decision = NativeRawDecision(); + return plan; + } + + TEST_CASE("CEM v2 loader keeps one artifact handle through 31 segments", + "[nn][model-guard-v2][ownership]") { + for (const std::uint32_t segment_count : {1U, 2U, 8U, 31U}) { + DYNAMIC_SECTION("segment count " << segment_count) { + LoaderMockState state; + state.segment_count = segment_count; + + auto result = + LoadCemV2SophonArtifact(GuardApi(state), RuntimeApi(state), "/managed/preset/model.nn", + CMG_V2_SOURCE_COSMO_NN_V1, MockBmHandle(), 0); + + REQUIRE(result.IsSuccess()); + REQUIRE(result.runtimes.size() == segment_count); + REQUIRE(state.open_calls == 1); + REQUIRE(state.info_calls == 1); + REQUIRE(state.close_calls == 1); + REQUIRE(state.opened_source == CMG_V2_SOURCE_COSMO_NN_V1); + REQUIRE(state.loaded_segments.size() == segment_count); + for (std::uint32_t index = 0; index < segment_count; ++index) { + REQUIRE(state.loaded_segments[index] == index); + REQUIRE(state.load_flags[index] == 0); + } + + result.runtimes.clear(); + REQUIRE(state.destroyed_runtimes.size() == segment_count); + } + } + } + + TEST_CASE("CEM v2 partial segment failure destroys prior runtimes and closes once", + "[nn][model-guard-v2][ownership][security]") { + LoaderMockState state; + state.segment_count = 8; + state.fail_segment = 3; + state.load_status = CMG_V2_BACKEND_FAILED; + + const auto result = + LoadCemV2SophonArtifact(GuardApi(state), RuntimeApi(state), "/managed/preset/model.nn", + CMG_V2_SOURCE_COSMO_NN_V1, MockBmHandle(), 0); + + REQUIRE_FALSE(result.IsSuccess()); + REQUIRE(result.error == SophonModelLoadError::kSegmentLoadFailed); + const std::vector<std::uint32_t> expected_segments{0, 1, 2, 3}; + REQUIRE(state.loaded_segments == expected_segments); + REQUIRE(state.destroyed_runtimes.size() == 3); + REQUIRE(state.close_calls == 1); + } + + TEST_CASE("protected raw path delegates authorization directly to Guard", + "[nn][model-guard-v2][qwen][security]") { + LoaderMockState state; + state.info_source = CMG_V2_SOURCE_RAW_BMODEL; + + auto result = + LoadRawBmodelByPolicy(ProtectedRawDecision(), GuardApi(state), RuntimeApi(state), MockBmHandle()); + + REQUIRE(result.IsSuccess()); + REQUIRE(result.runtimes.size() == 1); + REQUIRE(state.open_calls == 1); + REQUIRE(state.loaded_segments == std::vector<std::uint32_t>{0}); + REQUIRE(state.native_create_calls == 0); + REQUIRE(state.native_load_calls == 0); + } + + TEST_CASE("CEM v2 contract violations reclaim unexpected resources", + "[nn][model-guard-v2][ownership][security]") { + SECTION("failed open returned an artifact") { + LoaderMockState state; + state.open_status = CMG_V2_FORMAT_INVALID; + state.return_artifact_on_open_failure = true; + + const auto result = + LoadCemV2SophonArtifact(GuardApi(state), RuntimeApi(state), "/managed/preset/model.nn", + CMG_V2_SOURCE_COSMO_NN_V1, MockBmHandle(), 0); + + REQUIRE(result.error == SophonModelLoadError::kAbiContractViolation); + REQUIRE(state.close_calls == 1); + } + + SECTION("failed load returned a runtime") { + LoaderMockState state; + state.fail_segment = 0; + state.load_status = CMG_V2_CRYPTO_FAILED; + state.return_runtime_on_load_failure = true; + + const auto result = + LoadCemV2SophonArtifact(GuardApi(state), RuntimeApi(state), "/managed/preset/model.nn", + CMG_V2_SOURCE_COSMO_NN_V1, MockBmHandle(), 0); + + REQUIRE(result.error == SophonModelLoadError::kAbiContractViolation); + REQUIRE(state.destroyed_runtimes.size() == 1); + REQUIRE(state.close_calls == 1); + } + } + + TEST_CASE("protected raw bmodel failures never invoke plaintext native loading", + "[nn][model-guard-v2][qwen][security]") { + for (const CmgV2Status failure : {CMG_V2_FORMAT_INVALID, CMG_V2_LICENSE_UNAVAILABLE, + CMG_V2_LICENSE_REJECTED, CMG_V2_CRYPTO_FAILED}) { + DYNAMIC_SECTION("guard failure " << failure) { + LoaderMockState state; + state.open_status = failure; + + const auto result = LoadRawBmodelByPolicy(ProtectedRawDecision(), GuardApi(state), + RuntimeApi(state), MockBmHandle()); + + REQUIRE_FALSE(result.IsSuccess()); + REQUIRE(result.error == SophonModelLoadError::kArtifactOpenFailed); + REQUIRE(result.guard_status == failure); + REQUIRE(state.native_create_calls == 0); + REQUIRE(state.native_load_calls == 0); + } + } + + SECTION("ABI unavailable") { + LoaderMockState state; + CemV2Api unavailable{CMG_V2_ABI_MAJOR, &state, nullptr, nullptr, nullptr, nullptr}; + + const auto result = + LoadRawBmodelByPolicy(ProtectedRawDecision(), unavailable, RuntimeApi(state), MockBmHandle()); + + REQUIRE(result.error == SophonModelLoadError::kAbiUnavailable); + REQUIRE(state.native_create_calls == 0); + REQUIRE(state.native_load_calls == 0); + } + + SECTION("guard resource exhaustion remains distinguishable internally") { + LoaderMockState state; + state.open_status = CMG_V2_RESOURCE_NO_MEMORY; + + const auto result = LoadRawBmodelByPolicy(ProtectedRawDecision(), GuardApi(state), + RuntimeApi(state), MockBmHandle()); + + REQUIRE_FALSE(result.IsSuccess()); + REQUIRE(result.IsOutOfMemory()); + REQUIRE(state.native_create_calls == 0); + REQUIRE(state.native_load_calls == 0); + } + } + + TEST_CASE("protected Qwen path uses v2 raw source and guard share-memory option", + "[nn][model-guard-v2][qwen][ownership]") { + LoaderMockState state; + state.info_source = CMG_V2_SOURCE_RAW_BMODEL; + + auto result = + LoadRawBmodelByPlan(ProtectedRawPlan(), GuardApi(state), RuntimeApi(state), MockBmHandle()); + + REQUIRE(result.IsSuccess()); + REQUIRE(result.runtimes.size() == 1); + REQUIRE(state.opened_source == CMG_V2_SOURCE_RAW_BMODEL); + const std::vector<std::uint32_t> expected_flags{CMG_V2_SOPHON_SHARE_MEM}; + REQUIRE(state.load_flags == expected_flags); + REQUIRE(state.native_create_calls == 0); + REQUIRE(state.native_load_calls == 0); + REQUIRE(state.close_calls == 1); + } + + TEST_CASE("explicit raw format decision may use native Qwen loader", + "[nn][model-guard-v2][qwen][security]") { + LoaderMockState state; + + auto result = + LoadRawBmodelByPlan(NativeRawPlan(), GuardApi(state), RuntimeApi(state), MockBmHandle()); + + REQUIRE(result.IsSuccess()); + REQUIRE(result.runtimes.size() == 1); + REQUIRE(state.open_calls == 0); + REQUIRE(state.native_create_calls == 1); + REQUIRE(state.native_set_calls == 1); + REQUIRE(state.native_load_calls == 1); + REQUIRE(state.native_flags == BM_RUNTIME_SHARE_MEM); + REQUIRE(state.native_path == "/models/plain/model.nn"); + + ModelLoadDecision rejected = NativeRawDecision(); + rejected.action = ModelLoadAction::kReject; + const auto rejected_result = + LoadRawBmodelByPolicy(rejected, GuardApi(state), RuntimeApi(state), MockBmHandle()); + REQUIRE(rejected_result.error == SophonModelLoadError::kPolicyRejected); + REQUIRE(state.native_create_calls == 1); + REQUIRE(state.native_load_calls == 1); + } + + TEST_CASE("native user-model failure destroys its runtime without touching guard", + "[nn][model-guard-v2][qwen][ownership]") { + LoaderMockState state; + state.native_load_result = false; + + const auto result = + LoadRawBmodelByPolicy(NativeRawDecision(), GuardApi(state), RuntimeApi(state), MockBmHandle()); + + REQUIRE(result.error == SophonModelLoadError::kNativeLoadFailed); + REQUIRE(state.open_calls == 0); + REQUIRE(state.native_create_calls == 1); + REQUIRE(state.native_load_calls == 1); + REQUIRE(state.destroyed_runtimes.size() == 1); + } + + TEST_CASE("shared Qwen helpers preserve authorization and load error mapping", + "[nn][model-guard-v2][qwen][errors]") { + SECTION("one authorized runtime is transferred to the Qwen owner") { + LoaderMockState state; + state.info_source = CMG_V2_SOURCE_RAW_BMODEL; + + void* runtime = qwen_runtime_safety::LoadSingleAuthorizedRawBmodel( + ProtectedRawPlan(), GuardApi(state), RuntimeApi(state), MockBmHandle()); + + REQUIRE(runtime == MockRuntime(0)); + REQUIRE(state.destroyed_runtimes.empty()); + MockDestroy(&state, runtime); + } + + SECTION("policy rejection keeps the public Qwen error text") { + RawBmodelLoadPlan plan; + plan.error = RawBmodelAuthorizationError::kPolicyRejected; + + REQUIRE_THROWS_WITH(qwen_runtime_safety::RequireAuthorizedRawBmodel(plan), + "Qwen Sophon runtime operation failed: authorize model (format rejected)"); + } + + SECTION("guard resource exhaustion remains bad_alloc") { + LoaderMockState state; + state.open_status = CMG_V2_RESOURCE_NO_MEMORY; + + REQUIRE_THROWS_AS(qwen_runtime_safety::LoadSingleAuthorizedRawBmodel( + ProtectedRawPlan(), GuardApi(state), RuntimeApi(state), MockBmHandle()), + std::bad_alloc); + REQUIRE(state.native_create_calls == 0); + REQUIRE(state.native_load_calls == 0); + } + + SECTION("other load failures keep the public Qwen error text") { + LoaderMockState state; + state.open_status = CMG_V2_LICENSE_REJECTED; + + REQUIRE_THROWS_WITH(qwen_runtime_safety::LoadSingleAuthorizedRawBmodel( + ProtectedRawPlan(), GuardApi(state), RuntimeApi(state), MockBmHandle()), + "Qwen Sophon runtime operation failed: load authorized model"); + REQUIRE(state.native_create_calls == 0); + REQUIRE(state.native_load_calls == 0); + } + + SECTION("native runtime creation failure keeps the public Qwen error text") { + LoaderMockState state; + state.native_create_result = false; + + REQUIRE_THROWS_WITH(qwen_runtime_safety::LoadSingleAuthorizedRawBmodel( + NativeRawPlan(), GuardApi(state), RuntimeApi(state), MockBmHandle()), + "Qwen Sophon runtime operation failed: create runtime"); + } + + SECTION("native model load failure keeps the public Qwen error text and path") { + LoaderMockState state; + state.native_load_result = false; + + REQUIRE_THROWS_WITH(qwen_runtime_safety::LoadSingleAuthorizedRawBmodel( + NativeRawPlan(), GuardApi(state), RuntimeApi(state), MockBmHandle()), + "Qwen Sophon runtime operation failed: load model (/models/plain/model.nn)"); + } + } + +} // namespace +} // namespace cosmo::nn + +#endif // COSMO_NN_USE_SOPHON_BACKEND diff --git a/test/ModelLoadPolicyTest.cc b/test/ModelLoadPolicyTest.cc new file mode 100644 index 000000000..7a5381bc3 --- /dev/null +++ b/test/ModelLoadPolicyTest.cc @@ -0,0 +1,133 @@ +#include <unistd.h> + +#include <array> +#include <atomic> +#include <cstdint> +#include <filesystem> +#include <fstream> +#include <string> +#include <vector> + +#include "catch_amalgamated.hpp" +#include "nn/guard/ModelLoadPolicy.h" + +namespace cosmo::nn { +namespace { + + namespace fs = std::filesystem; + + class ScopedDirectory final { + public: + ScopedDirectory() { + static std::atomic<unsigned int> sequence{0}; + path_ = fs::temp_directory_path() / ("cosmo-model-load-policy-" + std::to_string(getpid()) + "-" + + std::to_string(sequence.fetch_add(1))); + fs::create_directories(path_); + } + + ~ScopedDirectory() { + std::error_code error; + fs::remove_all(path_, error); + } + + [[nodiscard]] fs::path Path(const std::string& name) const { + return path_ / name; + } + + [[nodiscard]] const fs::path& Get() const { + return path_; + } + + private: + fs::path path_; + }; + + fs::path WriteModel(const fs::path& path, const std::vector<std::uint8_t>& bytes) { + fs::create_directories(path.parent_path()); + std::ofstream stream(path, std::ios::binary | std::ios::trunc); + REQUIRE(stream.is_open()); + stream.write(reinterpret_cast<const char*>(bytes.data()), static_cast<std::streamsize>(bytes.size())); + REQUIRE(stream.good()); + return path; + } + + std::vector<std::uint8_t> ModelBytes(const std::array<std::uint8_t, 4>& magic) { + return {magic[0], magic[1], magic[2], magic[3], 0x01, 0x02, 0x03, 0x04}; + } + + constexpr std::array<std::uint8_t, 4> kCemc = {'C', 'E', 'M', 'C'}; + constexpr std::array<std::uint8_t, 4> kCenn = {'C', 'E', 'N', 'N'}; + constexpr std::array<std::uint8_t, 4> kLegacy = {0x01, 0x00, 0x01, 0xec}; + constexpr std::array<std::uint8_t, 4> kUnreserved = {0x42, 0x4d, 0x00, 0x01}; + + TEST_CASE("Model magic detection compares the raw four bytes", "[nn][model-policy]") { + REQUIRE(DetectModelMagic(kCemc) == ModelMagic::kCemc); + REQUIRE(DetectModelMagic(kCenn) == ModelMagic::kCenn); + REQUIRE(DetectModelMagic(kLegacy) == ModelMagic::kLegacyEncrypted); + REQUIRE(DetectModelMagic(kUnreserved) == ModelMagic::kUnknown); + REQUIRE(DetectModelMagic({0xec, 0x01, 0x00, 0x01}) == ModelMagic::kUnknown); + } + + TEST_CASE("CEMC always routes to Guard regardless of path metadata", + "[nn][model-policy][model-guard-v2]") { + ScopedDirectory directory; + const ModelLoadPolicy policy = ModelLoadPolicy::Production(); + const fs::path target = WriteModel(directory.Path("any/location/model.nn"), ModelBytes(kCemc)); + fs::permissions(target, fs::perms::all, fs::perm_options::replace); + const fs::path link = directory.Path("linked-model.nn"); + fs::create_symlink(target, link); + + for (const fs::path& path : {target, link}) { + for (const ModelLoadIntent intent : {ModelLoadIntent::kCosmoNn, ModelLoadIntent::kRawBmodel}) { + const ModelLoadDecision decision = policy.Evaluate(path.string(), intent); + REQUIRE(decision.action == ModelLoadAction::kGuardV2); + REQUIRE(decision.magic == ModelMagic::kCemc); + REQUIRE(decision.error == ModelPolicyError::kNone); + REQUIRE(decision.model_path == fs::absolute(path).lexically_normal().string()); + } + } + } + + TEST_CASE("Native model formats follow the selected consumer", "[nn][model-policy]") { + ScopedDirectory directory; + const ModelLoadPolicy policy = ModelLoadPolicy::Production(); + const fs::path cenn = WriteModel(directory.Path("plain-cenn.nn"), ModelBytes(kCenn)); + const fs::path raw = WriteModel(directory.Path("plain.bmodel"), ModelBytes(kUnreserved)); + + REQUIRE(policy.Evaluate(cenn.string(), ModelLoadIntent::kCosmoNn).action == + ModelLoadAction::kNativeCenn); + REQUIRE(policy.Evaluate(cenn.string(), ModelLoadIntent::kRawBmodel).error == + ModelPolicyError::kFormatRejected); + REQUIRE(policy.Evaluate(raw.string(), ModelLoadIntent::kRawBmodel).action == + ModelLoadAction::kNativeRawBmodel); + REQUIRE(policy.Evaluate(raw.string(), ModelLoadIntent::kCosmoNn).error == + ModelPolicyError::kFormatRejected); + } + + TEST_CASE("Legacy encrypted format never falls back to a native loader", + "[nn][model-policy][model-guard-v2]") { + ScopedDirectory directory; + const ModelLoadPolicy policy = ModelLoadPolicy::Production(); + const fs::path legacy = WriteModel(directory.Path("legacy.nn"), ModelBytes(kLegacy)); + + REQUIRE(policy.Evaluate(legacy.string(), ModelLoadIntent::kCosmoNn).error == + ModelPolicyError::kFormatRejected); + REQUIRE(policy.Evaluate(legacy.string(), ModelLoadIntent::kRawBmodel).error == + ModelPolicyError::kFormatRejected); + } + + TEST_CASE("Unreadable model shapes are rejected", "[nn][model-policy]") { + ScopedDirectory directory; + const ModelLoadPolicy policy = ModelLoadPolicy::Production(); + const fs::path truncated = WriteModel(directory.Path("truncated.nn"), {0x42, 0x4d, 0x00}); + + REQUIRE(policy.Evaluate(truncated.string(), ModelLoadIntent::kRawBmodel).error == + ModelPolicyError::kHeaderReadFailed); + REQUIRE(policy.Evaluate(directory.Get().string(), ModelLoadIntent::kCosmoNn).error == + ModelPolicyError::kPathNotRegularFile); + REQUIRE(policy.Evaluate(directory.Path("missing.nn").string(), ModelLoadIntent::kCosmoNn).error == + ModelPolicyError::kPathNotRegularFile); + } + +} // namespace +} // namespace cosmo::nn diff --git a/test/cmake/test_cosmo_version.cmake b/test/cmake/test_cosmo_version.cmake new file mode 100644 index 000000000..de9f90dc1 --- /dev/null +++ b/test/cmake/test_cosmo_version.cmake @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.16) + +if(NOT DEFINED COSMO_SOURCE_DIR) + message(FATAL_ERROR "COSMO_SOURCE_DIR is required") +endif() + +include("${COSMO_SOURCE_DIR}/cmake/CosmoVersion.cmake") +cosmo_resolve_version("${COSMO_SOURCE_DIR}" 1 1 0 0) + +foreach(_part MAJOR MINOR PATCH BUILD) + if(NOT COSMO_VERSION_${_part} MATCHES "^[0-9]+$") + message(FATAL_ERROR + "COSMO_VERSION_${_part} is not numeric: ${COSMO_VERSION_${_part}}") + endif() +endforeach() + +set(_package_version + "V${COSMO_VERSION_MAJOR}.${COSMO_VERSION_MINOR}.${COSMO_VERSION_PATCH}") +set(_display_version "${_package_version}.${COSMO_VERSION_BUILD}") + +if(NOT _package_version MATCHES "^V[0-9]+\\.[0-9]+\\.[0-9]+$") + message(FATAL_ERROR "Invalid package version: ${_package_version}") +endif() +if(NOT _display_version MATCHES "^V[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+$") + message(FATAL_ERROR "Invalid display version: ${_display_version}") +endif() + +message(STATUS "Package version: ${_package_version}") +message(STATUS "Display version: ${_display_version}") +message(STATUS "Version source: ${COSMO_VERSION_SOURCE}") + +# A source tree without Git metadata must retain the supplied release fallback. +cosmo_resolve_version("${COSMO_SOURCE_DIR}/path-without-git-metadata" 7 8 9 10) +if(NOT COSMO_VERSION_MAJOR EQUAL 7 OR + NOT COSMO_VERSION_MINOR EQUAL 8 OR + NOT COSMO_VERSION_PATCH EQUAL 9 OR + NOT COSMO_VERSION_BUILD EQUAL 10 OR + NOT COSMO_VERSION_SOURCE STREQUAL "fallback") + message(FATAL_ERROR "Version fallback changed unexpectedly") +endif() diff --git a/test/mock/MockCameraService.h b/test/mock/MockCameraService.h index bd0a0d338..21d00e04f 100644 --- a/test/mock/MockCameraService.h +++ b/test/mock/MockCameraService.h @@ -50,6 +50,8 @@ class MockCameraService : public cosmo::service::ICameraService { MAKE_MOCK1(NotifyAlgorithmsDeleted, void(const std::vector<std::string>&), override); MAKE_MOCK1(IsAlgorithmInUse, bool(const std::string&), const override); MAKE_MOCK1(ScheduleInUse, bool(const std::string&), override); + MAKE_MOCK1(AcquirePreviewChannel, cosmo::util::ErrorEnum(const std::string&), override); + MAKE_MOCK1(ReleasePreviewChannel, void(const std::string&), override); MAKE_MOCK2(CaptureImage, VideoFramePtr(const std::string&, int), override); MAKE_MOCK4(BindTaskLibPara, cosmo::util::ErrorEnum(const std::string&, const std::string&, const std::vector<std::string>&, diff --git a/test/mock/MockModelAuthorizationService.h b/test/mock/MockModelAuthorizationService.h new file mode 100644 index 000000000..e44a3b673 --- /dev/null +++ b/test/mock/MockModelAuthorizationService.h @@ -0,0 +1,16 @@ +#pragma once + +#include <trompeloeil.hpp> + +#include "service/modelguard/IModelAuthorizationService.h" + +namespace cosmo::test { + +class MockModelAuthorizationService : public service::IModelAuthorizationService { +public: + MAKE_MOCK0(Status, service::ModelAuthorizationStatus(), override); + MAKE_MOCK2(CreateDeviceRequest, util::ErrorEnum(std::string&, std::string&), override); + MAKE_MOCK1(InstallCertificate, util::ErrorEnum(const std::string&), override); +}; + +} // namespace cosmo::test diff --git a/test/mock/MockServiceRegistry.cc b/test/mock/MockServiceRegistry.cc index 71d859d73..7a1fde571 100644 --- a/test/mock/MockServiceRegistry.cc +++ b/test/mock/MockServiceRegistry.cc @@ -20,6 +20,7 @@ #include "mock/MockFaceLibService.h" #include "mock/MockLinkageService.h" #include "mock/MockLiveStreamService.h" +#include "mock/MockModelAuthorizationService.h" #include "mock/MockModelService.h" #include "mock/MockNetworkService.h" #include "mock/MockOnboardingService.h" @@ -40,6 +41,7 @@ struct MockServiceRegistryImpl { MockCameraService cameraSvc; MockAlgorithmService algSvc; MockModelService modelSvc; + MockModelAuthorizationService modelAuthorizationSvc; MockScheduleService scheduleSvc; MockAuthService authSvc; MockAppInfoService appInfoSvc; @@ -75,6 +77,7 @@ MockServiceRegistry::MockServiceRegistry() cameraSvc(impl->cameraSvc), algSvc(impl->algSvc), modelSvc(impl->modelSvc), + modelAuthorizationSvc(impl->modelAuthorizationSvc), scheduleSvc(impl->scheduleSvc), authSvc(impl->authSvc), appInfoSvc(impl->appInfoSvc), @@ -128,6 +131,7 @@ MockServiceRegistry::MockServiceRegistry() service::ServiceRegistry::Instance().Set<service::IAlgorithmLayout>( static_cast<service::IAlgorithmLayout*>(&algSvc)); service::ServiceRegistry::Instance().Set<service::IModelService>(&modelSvc); + service::ServiceRegistry::Instance().Set<service::IModelAuthorizationService>(&modelAuthorizationSvc); service::ServiceRegistry::Instance().Set<service::IScheduleService>(&scheduleSvc); service::ServiceRegistry::Instance().Set<service::IAuthService>(&authSvc); @@ -194,6 +198,9 @@ MockServiceRegistry::MockServiceRegistry() NAMED_ALLOW_CALL(taskSvc, SetTaskParam(trompeloeil::_, trompeloeil::_, trompeloeil::_)).RETURN(true)); expectations.push_back(NAMED_ALLOW_CALL(taskSvc, TaskIsStart(trompeloeil::_)).RETURN(false)); expectations.push_back(NAMED_ALLOW_CALL(taskSvc, TaskStart(trompeloeil::_, trompeloeil::_)).RETURN(true)); + expectations.push_back(NAMED_ALLOW_CALL(cameraSvc, AcquirePreviewChannel(trompeloeil::_)) + .RETURN(cosmo::util::ErrorEnum::Success)); + expectations.push_back(NAMED_ALLOW_CALL(cameraSvc, ReleasePreviewChannel(trompeloeil::_))); expectations.push_back(NAMED_ALLOW_CALL(taskSvc, RecordClearTaskData(trompeloeil::_))); expectations.push_back(NAMED_ALLOW_CALL(taskSvc, RecordTaskAction(trompeloeil::_, trompeloeil::_))); } @@ -212,6 +219,7 @@ MockServiceRegistry::~MockServiceRegistry() { service::ServiceRegistry::Instance().Set<service::IAlgorithmCrud>(nullptr); service::ServiceRegistry::Instance().Set<service::IAlgorithmLayout>(nullptr); service::ServiceRegistry::Instance().Set<service::IModelService>(nullptr); + service::ServiceRegistry::Instance().Set<service::IModelAuthorizationService>(nullptr); service::ServiceRegistry::Instance().Set<service::IScheduleService>(nullptr); service::ServiceRegistry::Instance().Set<service::IAuthService>(nullptr); diff --git a/test/mock/MockServiceRegistry.h b/test/mock/MockServiceRegistry.h index 3abaa87b2..8baa74eec 100644 --- a/test/mock/MockServiceRegistry.h +++ b/test/mock/MockServiceRegistry.h @@ -12,6 +12,7 @@ class MockTaskService; class MockCameraService; class MockAlgorithmService; class MockModelService; +class MockModelAuthorizationService; class MockScheduleService; class MockAuthService; class MockAppInfoService; @@ -48,6 +49,7 @@ struct MockServiceRegistry { MockCameraService& cameraSvc; MockAlgorithmService& algSvc; MockModelService& modelSvc; + MockModelAuthorizationService& modelAuthorizationSvc; MockScheduleService& scheduleSvc; MockAuthService& authSvc; MockAppInfoService& appInfoSvc; diff --git a/test/mock/MockSystemOperationService.h b/test/mock/MockSystemOperationService.h index 302542f85..ace7751a5 100644 --- a/test/mock/MockSystemOperationService.h +++ b/test/mock/MockSystemOperationService.h @@ -16,6 +16,8 @@ class MockSystemOperationService : public cosmo::service::ISystemOperationServic MAKE_MOCK1(ResetDevice, void(const std::string&), override); MAKE_MOCK2(ExportLogs, cosmo::util::ErrorEnum(std::string&, std::string&), override); MAKE_MOCK1(Upgrade, cosmo::util::ErrorEnum(const std::string&), override); + MAKE_MOCK3(CheckUpgradeSpace, + cosmo::util::ErrorEnum(std::uint64_t, bool, cosmo::service::UpgradeSpaceStatus&), override); MAKE_MOCK0(ShowThreadDebugInfo, void(), override); }; diff --git a/test/test_accelerator_metrics_provider.cc b/test/test_accelerator_metrics_provider.cc index 930337f45..4d86578ed 100644 --- a/test/test_accelerator_metrics_provider.cc +++ b/test/test_accelerator_metrics_provider.cc @@ -1,6 +1,40 @@ #include "catch_amalgamated.hpp" #include "service/system/impl/AcceleratorMetricsProvider.h" +#ifdef COSMO_NN_USE_RKNN_BACKEND +#include <cstdint> +#include <cstdlib> +#include <filesystem> +#include <fstream> +#include <string> + +namespace { + +class ScopedNpuLoadFixture { +public: + explicit ScopedNpuLoadFixture(const std::string& content) + : path_(std::filesystem::temp_directory_path() / + ("cosmo-rknpu-load-" + std::to_string(reinterpret_cast<uintptr_t>(this)))) { + std::ofstream stream(path_); + stream << content; + stream.close(); + REQUIRE(stream.good()); + REQUIRE(setenv("COSMO_RKNPU_LOAD_PATH", path_.c_str(), 1) == 0); + } + + ~ScopedNpuLoadFixture() { + unsetenv("COSMO_RKNPU_LOAD_PATH"); + std::error_code error; + std::filesystem::remove(path_, error); + } + +private: + std::filesystem::path path_; +}; + +} // namespace +#endif + #ifdef COSMO_NN_USE_CPU_BACKEND TEST_CASE("CPU accelerator metrics provider reports no accelerator", "[system][metrics]") { auto provider = cosmo::service::detail::CreateAcceleratorMetricsProvider(); @@ -10,6 +44,37 @@ TEST_CASE("CPU accelerator metrics provider reports no accelerator", "[system][m CHECK(metrics.gpuusage == 0.0); CHECK(metrics.gpumemtotal == 0); CHECK(metrics.gpudevusage.empty()); + CHECK(metrics.memoryDomain == "none"); CHECK(provider->QueryAvailableMemoryMB() == 0); } #endif + +#ifdef COSMO_NN_USE_RKNN_BACKEND +TEST_CASE("RKNN accelerator metrics provider reports per-core busy-time load", "[system][metrics][rknn]") { + ScopedNpuLoadFixture fixture("NPU load: Core0: 9%, Core1: 42%,\n"); + auto provider = cosmo::service::detail::CreateAcceleratorMetricsProvider(); + REQUIRE(provider != nullptr); + + const auto metrics = provider->QueryUtilization(); + CHECK(metrics.gpuusageAvailable); + CHECK(metrics.gpuusage == Catch::Approx(0.42)); + CHECK(metrics.utilizationMetric == "busy-time-load"); + CHECK(metrics.memoryDomain == "shared-system"); + REQUIRE(metrics.coreUtilizations.size() == 2); + CHECK(metrics.coreUtilizations[0] == Catch::Approx(0.09)); + CHECK(metrics.coreUtilizations[1] == Catch::Approx(0.42)); + REQUIRE(metrics.gpudevusage.size() == 1); + CHECK(metrics.gpudevusage.front().gpuusage == Catch::Approx(0.42)); +} + +TEST_CASE("RKNN accelerator metrics provider rejects invalid load", "[system][metrics][rknn]") { + ScopedNpuLoadFixture fixture("NPU load: Core0: 105%, Core1: 0%,\n"); + auto provider = cosmo::service::detail::CreateAcceleratorMetricsProvider(); + REQUIRE(provider != nullptr); + + const auto metrics = provider->QueryUtilization(); + CHECK_FALSE(metrics.gpuusageAvailable); + CHECK(metrics.gpuusage == 0.0); + CHECK(metrics.coreUtilizations.empty()); +} +#endif diff --git a/test/test_ai_detector_fps.cc b/test/test_ai_detector_fps.cc index 872bbf113..765e443e2 100644 --- a/test/test_ai_detector_fps.cc +++ b/test/test_ai_detector_fps.cc @@ -95,6 +95,25 @@ TEST_CASE("AiDetectorFps DefaultReuseProfile follows tested fps gradient", "[AiD REQUIRE(EffectiveMaxReuseCount(24.0f, kBudget, kHardMax, profile) == 1); } +TEST_CASE("AiDetectorFps RKNN profile isolates channels by default", "[AiDetectorFps][rknn]") { + using ai_detector_fps::EffectiveMaxReuseCount; + const auto profile = ai_detector_fps::RknnDefaultReuseProfile(); + + REQUIRE(EffectiveMaxReuseCount(3.0f, 36.0f, 3, profile) == 1); + REQUIRE(EffectiveMaxReuseCount(7.0f, 36.0f, 3, profile) == 1); + REQUIRE(EffectiveMaxReuseCount(24.0f, 36.0f, 3, profile) == 1); +} + +TEST_CASE("AiDetectorFps drain batch never exceeds model capacity", "[AiDetectorFps][batch]") { + using ai_detector_fps::EffectiveDetectorDrainBatch; + + REQUIRE(EffectiveDetectorDrainBatch(4, 1) == 1); + REQUIRE(EffectiveDetectorDrainBatch(4, 2) == 2); + REQUIRE(EffectiveDetectorDrainBatch(4, 8) == 4); + REQUIRE(EffectiveDetectorDrainBatch(0, 4) == 1); + REQUIRE(EffectiveDetectorDrainBatch(4, 0) == 1); +} + TEST_CASE("AiDetectorFps ChannelAssignedFps takes max not sum", "[AiDetectorFps]") { using ai_detector_fps::ChannelAssignedFps; REQUIRE(ChannelAssignedFps(makeChannel("ch", {})) == Approx(0.0f)); @@ -189,7 +208,7 @@ TEST_CASE("AiDetectorFps CanAccept placement matrix", "[AiDetectorFps]") { } SECTION("default profile splits 12fps at two channels and 16fps at one channel") { - const auto profile = ai_detector_fps::DefaultReuseProfile(); + const auto profile = ai_detector_fps::DefaultReuseProfile(); std::vector<AiDetectorChannel> two = {makeChannel("ch1", {{"t1", 12.0f}}), makeChannel("ch2", {{"t2", 12.0f}})}; REQUIRE_FALSE(CanAccept(two, "ch3", 12.0f, kMaxReuse, kBudget, profile)); diff --git a/test/test_alg_data_queue.cc b/test/test_alg_data_queue.cc index a56843c2f..92de2b1db 100644 --- a/test/test_alg_data_queue.cc +++ b/test/test_alg_data_queue.cc @@ -129,6 +129,15 @@ TEST_CASE("AlgDataQueue RecordDiscard", "[AlgDataQueue]") { REQUIRE(info.status.discardCount == 1); } +TEST_CASE("AlgDataQueue reports immediate insert capacity", "[AlgDataQueue]") { + AlgDataQueue<int> queue("capacity_q", 1); + REQUIRE(queue.CanAccept()); + REQUIRE(queue.Insert(1)); + CHECK_FALSE(queue.CanAccept()); + CHECK(queue.Pop() == 1); + CHECK(queue.CanAccept()); +} + TEST_CASE("AlgDataQueue concurrent access", "[AlgDataQueue]") { AlgDataQueue<int> queue("concurrent_q", 100); const int N = 50; diff --git a/test/test_alg_distributor.cc b/test/test_alg_distributor.cc index baaff34be..ebe811f6f 100644 --- a/test/test_alg_distributor.cc +++ b/test/test_alg_distributor.cc @@ -3,6 +3,9 @@ * test_alg_distributor.cc - AlgDataQueueDistributor 单元测试 */ #include "flow/common/AlgDataQueueDistributor.h" +#include "mem/AllocatorCpu.h" +#include "mem/MemoryPoolMng.h" +#include "util/dto/ActionCodes.h" using namespace cosmo; @@ -82,3 +85,113 @@ TEST_CASE("AlgDataQueueDistributor sign changes", "[Distributor]") { int sign2 = dist.GetSign(); REQUIRE(sign2 > sign1); } + +TEST_CASE("AlgDataQueueDistributor plans before host frame materialization", "[Distributor]") { + AlgDataQueueDistributor dist("deferred_dist"); + auto task = makeTask("ch1", "deferred", "a1", -1.0f); + REQUIRE(dist.RegistProcQueue(task)); + + auto input = std::make_shared<AlgData>(); + input->firstTimePoint = std::chrono::steady_clock::now(); + auto ready_plan = dist.PrepareFrameDistribution(input); + REQUIRE_FALSE(ready_plan.Empty()); + REQUIRE(ready_plan.queues.size() == 1); + CHECK_FALSE(ready_plan.SupportsNativeInference()); + + for (size_t index = 0; index < task.que->GetMaxSize(); ++index) { + REQUIRE(task.que->Insert(std::make_shared<AlgData>())); + } + input->firstTimePoint = std::chrono::steady_clock::now() + std::chrono::seconds(1); + const auto saturated_plan = dist.PrepareFrameDistribution(input); + CHECK(saturated_plan.Empty()); + + AlgDataQueueInfo status; + REQUIRE(task.que->Status(status)); + CHECK(status.status.discardCount >= 1); +} + +TEST_CASE("Only regular detector queue plans advertise native inference", "[Distributor]") { + AlgDataQueueDistributor detector_dist("native_detector_dist"); + auto detector = makeTask("ch1", "detector", std::string(AADetect_Code), -1.0f); + REQUIRE(detector_dist.RegistProcQueue(detector)); + + auto input = std::make_shared<AlgData>(); + input->firstTimePoint = std::chrono::steady_clock::now(); + const auto detector_plan = detector_dist.PrepareFrameDistribution(input); + CHECK(detector_plan.SupportsNativeInference()); + + AlgDataQueueDistributor mixed_dist("native_mixed_dist"); + auto non_detector = makeTask("ch1", "classifier", std::string(AAClassify_Code), -1.0f); + REQUIRE(mixed_dist.RegistProcQueue(detector)); + REQUIRE(mixed_dist.RegistProcQueue(non_detector)); + input->firstTimePoint = std::chrono::steady_clock::now(); + const auto mixed_plan = mixed_dist.PrepareFrameDistribution(input); + CHECK_FALSE(mixed_plan.SupportsNativeInference()); +} + +TEST_CASE("Native inference descriptors are isolated across detector queues", "[Distributor]") { + AlgDataQueueDistributor dist("native_multi_detector_dist"); + auto detector_a = makeTask("ch1", "detector-a", std::string(AADetect_Code), -1.0f); + auto detector_b = makeTask("ch1", "detector-b", std::string(AADetect_Code), -1.0f); + REQUIRE(dist.RegistProcQueue(detector_a)); + REQUIRE(dist.RegistProcQueue(detector_b)); + + auto input = std::make_shared<AlgData>(); + input->firstTimePoint = std::chrono::steady_clock::now(); + const auto plan = dist.PrepareFrameDistribution(input); + REQUIRE(plan.SupportsNativeInference()); + REQUIRE(plan.queues.size() == 2); + + auto native = std::make_shared<media::NativeVideoBuffer>(); + native->fd = 7; + native->bytes = 24; + native->width = 4; + native->height = 4; + native->width_stride = 4; + native->height_stride = 4; + native->format = media::NativeVideoBufferFormat::NV12; + native->owner = std::make_shared<int>(1); + + constexpr int pool_size = 4 * 4 * 3 / 2; + mem::MemoryPoolMng memory_pool(std::make_unique<mem::AllocatorCpu>(), {pool_size}); + mem::SetMemoryPoolContext(&memory_pool); + struct PoolReset { + ~PoolReset() { + mem::SetMemoryPoolContext(nullptr); + } + } pool_reset; + auto frame = std::make_shared<media::VideoFrame>(4, 4, media::PixelFormat::PIXEL_I420); + + REQUIRE(dist.DistributorPreparedFrame(plan, input, frame, + [native](AlgDataPtr source, VideoFramePtr converted_frame) { + auto converted = AlgDataCopy(source); + converted->chanDataDec.frame = std::move(converted_frame); + converted->chanDataDec.native_buffer = native; + return converted; + }) == 2); + + auto queued_a = detector_a.que->Pop(); + auto queued_b = detector_b.que->Pop(); + REQUIRE(queued_a); + REQUIRE(queued_b); + CHECK(queued_a != queued_b); + REQUIRE(queued_a->chanDataDec.native_buffer); + REQUIRE(queued_b->chanDataDec.native_buffer); + queued_a->chanDataDec.native_buffer.reset(); + CHECK(queued_b->chanDataDec.native_buffer == native); +} + +TEST_CASE("Channel lifecycle queues do not force host frame materialization", "[Distributor]") { + AlgDataQueueDistributor dist("channel_metadata_dist"); + auto channel_task = makeTask("ch1", "ch1-ChannelTask", std::string(BAStreamChannel_Code), -1.0f); + REQUIRE(dist.RegistProcQueue(channel_task)); + + auto input = std::make_shared<AlgData>(); + input->dataType = AlgDataType::ChannelDataOrig; + input->firstTimePoint = std::chrono::steady_clock::now(); + const auto plan = dist.PrepareFrameDistribution(input); + + CHECK(plan.Empty()); + CHECK(channel_task.que->RestSize() == 1); + CHECK(channel_task.que->Pop() == input); +} diff --git a/test/test_algorithm_managed_paths.cc b/test/test_algorithm_managed_paths.cc index e4d620988..f94952e6c 100644 --- a/test/test_algorithm_managed_paths.cc +++ b/test/test_algorithm_managed_paths.cc @@ -184,6 +184,23 @@ TEST_CASE("Algorithm layout queries accept only the managed algorithm and templa REQUIRE(template_list.list.front().algorithmName == "Template"); } + SECTION("portable logical roots resolve under the configured app-data directory") { + cosmo::service::algorithm::LayoutDetailResult algorithm_detail; + REQUIRE(service.GetLayoutDetail("101", "", algorithm_detail) == cosmo::util::ErrorEnum::Success); + REQUIRE(algorithm_detail.algorithmName == "Managed"); + + cosmo::service::algorithm::LayoutDetailResult template_detail; + REQUIRE(service.GetLayoutDetail("202", "algorithm_template", template_detail) == + cosmo::util::ErrorEnum::Success); + REQUIRE(template_detail.algorithmName == "Template"); + + cosmo::service::algorithm::LayoutListResult template_list; + REQUIRE(service.GetLayoutList("", 1, "algorithm_template", template_list) == + cosmo::util::ErrorEnum::Success); + REQUIRE(template_list.list.size() == 1); + REQUIRE(template_list.list.front().algorithmName == "Template"); + } + SECTION("an external directory is rejected") { cosmo::service::algorithm::LayoutDetailResult detail; REQUIRE(service.GetLayoutDetail("303", fix.outside_root.string(), detail) == @@ -243,6 +260,15 @@ TEST_CASE("Algorithm layout save writes only to the managed algorithm root", REQUIRE(CountRegularFiles(fix.outside_root) == 0); } + SECTION("the portable default algorithm root is accepted") { + request.filePath.clear(); + REQUIRE_CALL(fix.mocks.algSvc, ReloadAlgorithmFromFile(trompeloeil::_)) + .RETURN(cosmo::util::ErrorEnum::Success); + REQUIRE(service.LayoutSave(request) == cosmo::util::ErrorEnum::Success); + REQUIRE(CountRegularFiles(fix.AlgorithmRoot()) == 1); + REQUIRE(CountRegularFiles(fix.outside_root) == 0); + } + SECTION("an external directory is rejected") { request.filePath = fix.outside_root.string(); REQUIRE(service.LayoutSave(request) == cosmo::util::ErrorEnum::InvalidParam); diff --git a/test/test_api_router.cc b/test/test_api_router.cc index c8819b587..75ac71105 100644 --- a/test/test_api_router.cc +++ b/test/test_api_router.cc @@ -6,6 +6,7 @@ #include "api/ApiRouterInternal.h" #include "catch_amalgamated.hpp" #include "mock/MockAuthService.h" +#include "mock/MockModelAuthorizationService.h" #include "mock/MockModelService.h" #include "mock/MockScheduleService.h" #include "mock/MockServiceRegistry.h" @@ -136,6 +137,38 @@ TEST_CASE("ApiRouter: Basic Routing and Dispatch", "[ApiRouter]") { fs::remove(export_path, cleanup_error); } + SECTION("HTTP model authorization requests stream the raw CMPR file") { + namespace fs = std::filesystem; + + const std::string valid_token = "model-authorization-request-token"; + ALLOW_CALL(mocks.authSvc, IsValidToken(valid_token)).RETURN(true); + + const auto suffix = std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()); + const fs::path request_path = fs::path(cosmo::path::GetTemporaryDirPath()) / + ("model-authorization-request-" + suffix + ".cmpr"); + std::ofstream(request_path, std::ios::binary) << std::string(48, '\x01'); + + REQUIRE_CALL(mocks.modelAuthorizationSvc, CreateDeviceRequest(trompeloeil::_, trompeloeil::_)) + .SIDE_EFFECT(_1 = request_path.string()) + .SIDE_EFFECT(_2 = "device-request.cmpr") + .RETURN(util::ErrorEnum::Success); + + RequestDispatchContext context; + context.uri = "/gtw/cwai/System/DownloadModelAuthorizationRequest"; + context.credential = valid_token; + context.transport = RequestTransport::kHttp; + RequestDispatchResponse response; + REQUIRE(router.DispatchRequestResponse(context, R"({"msgId":"1"})", response)); + CHECK(response.body.empty()); + CHECK(response.file_path == request_path.string()); + CHECK(response.file_name == "device-request.cmpr"); + CHECK(response.delete_file_after_send); + CHECK(fs::file_size(request_path) == 48); + + std::error_code cleanup_error; + fs::remove(request_path, cleanup_error); + } + SECTION("HTTP file exports reject unmanaged paths without leaking them") { namespace fs = std::filesystem; diff --git a/test/test_api_router_extended.cc b/test/test_api_router_extended.cc index da0017095..bbaa8df39 100644 --- a/test/test_api_router_extended.cc +++ b/test/test_api_router_extended.cc @@ -85,6 +85,7 @@ TEST_CASE("ApiRouter: Route registration completeness", "[ApiRouter][routes]") { REQUIRE(router.InterfaceSupport("/gtw/cwai/System/QueryDeviceInfo")); REQUIRE(router.InterfaceSupport("/gtw/cwai/System/QueryHardwareResource")); REQUIRE(router.InterfaceSupport("/gtw/cwai/System/Upgrade")); + REQUIRE(router.InterfaceSupport("/gtw/cwai/System/CheckUpgradeSpace")); REQUIRE(router.InterfaceSupport("/gtw/cwai/System/DebugQuit")); } diff --git a/test/test_audio_dto.cc b/test/test_audio_dto.cc new file mode 100644 index 000000000..e8d186b1f --- /dev/null +++ b/test/test_audio_dto.cc @@ -0,0 +1,51 @@ +// Audio API DTO regression tests. + +#include <catch_amalgamated.hpp> +#include <nlohmann/json.hpp> + +#include "service/media/dto/AudioDto.h" + +TEST_CASE("Audio device add request accepts a valid operation", "[audio][dto]") { + const auto request = nlohmann::json{ + {"devOperation", 1}, + {"audioDev", {{"name", "speaker"}, {"ip", "192.168.1.10"}, {"ethName", "eth0"}}}, + }; + + const auto dto = request.get<cosmo::Audio::MsgModifyAudioDeviceRecv>(); + + REQUIRE(static_cast<int>(dto.devOperation) == 1); + REQUIRE(dto.audioDev.name == "speaker"); + REQUIRE(dto.audioDev.ip == "192.168.1.10"); + REQUIRE(dto.audioDev.ethName == "eth0"); +} + +TEST_CASE("Audio device test request accepts valid playback operations", "[audio][dto]") { + auto request = nlohmann::json{ + {"operation", 1}, + {"devSn", "speaker-id"}, + {"data", "audio-id"}, + }; + + auto dto = request.get<cosmo::Audio::MsgTestAudioDeviceRecv>(); + REQUIRE(static_cast<int>(dto.operation) == 1); + + request["operation"] = 2; + request["data"] = "test announcement"; + dto = request.get<cosmo::Audio::MsgTestAudioDeviceRecv>(); + REQUIRE(static_cast<int>(dto.operation) == 2); +} + +TEST_CASE("Audio device requests reject invalid operations", "[audio][dto]") { + const auto modify_request = nlohmann::json{ + {"devOperation", 0}, + {"audioDev", {{"name", "speaker"}, {"ip", "192.168.1.10"}, {"ethName", "eth0"}}}, + }; + const auto test_request = nlohmann::json{ + {"operation", 3}, + {"devSn", "speaker-id"}, + {"data", "audio-id"}, + }; + + REQUIRE_THROWS(modify_request.get<cosmo::Audio::MsgModifyAudioDeviceRecv>()); + REQUIRE_THROWS(test_request.get<cosmo::Audio::MsgTestAudioDeviceRecv>()); +} diff --git a/test/test_audio_service_impl.cc b/test/test_audio_service_impl.cc index 7ba298f64..edace7a4a 100644 --- a/test/test_audio_service_impl.cc +++ b/test/test_audio_service_impl.cc @@ -30,8 +30,8 @@ struct AudioTestFixture { fs::create_directories(testDir + "/conf/audioMng"); // Create fake default audio file that AudioServiceImpl tries to copy - fs::create_directories(fs::path("./media/audio").parent_path()); - std::ofstream("./media/audio/beep.ogg"); + fs::create_directories(testDir + "/files/Audio"); + std::ofstream(testDir + "/files/Audio/beep.ogg"); } ~AudioTestFixture() { diff --git a/test/test_backend_contracts.cc b/test/test_backend_contracts.cc index a1c044924..d95a46840 100644 --- a/test/test_backend_contracts.cc +++ b/test/test_backend_contracts.cc @@ -11,6 +11,7 @@ TEST_CASE("backend capabilities identify host memory boundaries", "[nn][backend] CHECK(UsesHostMemory(DEVICE_NAIVE)); CHECK(UsesHostMemory(DEVICE_CPU)); + CHECK(UsesHostMemory(DEVICE_RKNN)); CHECK_FALSE(UsesHostMemory(DEVICE_SOPHON_TPU)); } diff --git a/test/test_camera_service_impl.cc b/test/test_camera_service_impl.cc index 92058df0d..558a4a6bd 100644 --- a/test/test_camera_service_impl.cc +++ b/test/test_camera_service_impl.cc @@ -107,6 +107,11 @@ TEST_CASE("CameraServiceImpl: operations on non-existent camera return proper er REQUIRE(frame == nullptr); } + SECTION("Preview lease for non-existent camera returns CameraNotExist") { + REQUIRE(svc.AcquirePreviewChannel("cam_not_exist") == cosmo::util::ErrorEnum::CameraNotExist); + REQUIRE_NOTHROW(svc.ReleasePreviewChannel("cam_not_exist")); + } + SECTION("GetChannelName for non-existent camera returns empty") { auto name = svc.GetChannelName("cam_not_exist"); REQUIRE(name.empty()); @@ -136,6 +141,47 @@ TEST_CASE("CameraServiceImpl: operations on non-existent camera return proper er } } +TEST_CASE("CameraServiceImpl: live preview leases keep the channel active", "[CameraService][preview]") { + const auto test_base = "/tmp/cosmo_camera_preview_lease_" + + std::to_string(std::chrono::system_clock::now().time_since_epoch().count()); + std::filesystem::create_directories(test_base); + cosmo::path::OverrideRootPathForTest(test_base, test_base); + + cosmo::test::MockServiceRegistry mocks; + CameraServiceImpl svc; + + MsgCameraInfo config; + config.videoChannelId = "preview-camera"; + config.channelName = "Preview Camera"; + config.url = "rtsp://127.0.0.1:1/test"; + config.channelType = MsgCameraType::MsgCameraTypeLive; + std::string id; + REQUIRE(svc.Add(config, id) == cosmo::util::ErrorEnum::Success); + + trompeloeil::sequence sequence; + REQUIRE_CALL(mocks.taskSvc, TaskIsStart("preview-camera-ChannelTask")) + .IN_SEQUENCE(sequence) + .RETURN(false); + REQUIRE_CALL(mocks.taskSvc, TaskStart("preview-camera", "preview-camera-ChannelTask")) + .IN_SEQUENCE(sequence) + .RETURN(true); + REQUIRE(svc.AcquirePreviewChannel("preview-camera") == cosmo::util::ErrorEnum::Success); + REQUIRE(svc.AcquirePreviewChannel("preview-camera") == cosmo::util::ErrorEnum::Success); + + // The first release retains the shared lease. The final release rechecks + // task demand and stops the otherwise idle channel. + svc.ReleasePreviewChannel("preview-camera"); + REQUIRE_CALL(mocks.taskSvc, TaskIsStart("preview-camera-ChannelTask")).IN_SEQUENCE(sequence).RETURN(true); + REQUIRE_CALL(mocks.taskSvc, TaskStop("preview-camera-ChannelTask")).IN_SEQUENCE(sequence).RETURN(true); + REQUIRE_CALL(mocks.taskSvc, GetChannelInst("preview-camera")).IN_SEQUENCE(sequence).RETURN(nullptr); + svc.ReleasePreviewChannel("preview-camera"); + REQUIRE_NOTHROW(svc.ReleasePreviewChannel("preview-camera")); + + REQUIRE_NOTHROW(svc.Stop()); + std::filesystem::remove_all(test_base); + cosmo::path::OverrideRootPathForTest("/tmp/cosmo_test", "/tmp/cosmo_test_app"); +} + // ============================================================ // Notify 通知空 ID 列表安全 // ============================================================ diff --git a/test/test_device_info_service_impl.cc b/test/test_device_info_service_impl.cc index 04eb0cd14..5cfe9bbe3 100644 --- a/test/test_device_info_service_impl.cc +++ b/test/test_device_info_service_impl.cc @@ -7,12 +7,15 @@ * aarch64 device. We tag device-dependent tests with [.device]. * Cross-platform tests focus on construction safety and basic getters. */ +#include <algorithm> #include <thread> #include "mock/MockServiceRegistry.h" +#include "mock/MockTaskService.h" #include "service/system/impl/DeviceInfoServiceImpl.h" using namespace cosmo::service; +using trompeloeil::_; TEST_CASE("DeviceInfoServiceImpl: construction and destruction", "[DeviceInfoService][.device]") { cosmo::test::MockServiceRegistry mocks; @@ -56,3 +59,28 @@ TEST_CASE("DeviceInfoServiceImpl: GetGpuNum returns at least 1", "[DeviceInfoSer REQUIRE(sut.GetGpuNum() >= 1); } + +#ifdef COSMO_NN_USE_RKNN_BACKEND +TEST_CASE("DeviceInfoServiceImpl: RKNN shared memory is exposed once", "[DeviceInfoService][.device][rknn]") { + cosmo::test::MockServiceRegistry mocks; + ALLOW_CALL(mocks.taskSvc, PacketStatus(_, _, _, _)).LR_SIDE_EFFECT(_1 = 0; _2 = 0; _3 = 0; _4 = 0); + DeviceInfoServiceImpl sut; + std::this_thread::sleep_for(std::chrono::seconds(1)); + + double custom_score = 0.0; + const auto items = sut.GetHardwareResource(custom_score); + const auto general = std::find_if( + items.begin(), items.end(), [](const auto& item) { return item.key == "generalMemoryUtilization"; }); + REQUIRE(general != items.end()); + CHECK(general->memoryDomain == "system"); + CHECK((general->usedSize.find("GiB") != std::string::npos || + general->usedSize.find("MiB") != std::string::npos)); + + const auto accelerator_memory_count = std::count_if(items.begin(), items.end(), [](const auto& item) { + return item.key == "specialMemoryUtilization" || item.key == "modelMemoryUtilization" || + item.key == "pictureMemoryUtilization" || item.key == "TPPMemoryUtilization"; + }); + CHECK(accelerator_memory_count == 0); + CHECK(sut.GetGpuUtilization().memoryDomain == "shared-system"); +} +#endif diff --git a/test/test_event_notifier.cc b/test/test_event_notifier.cc index df1987f77..1696f561e 100644 --- a/test/test_event_notifier.cc +++ b/test/test_event_notifier.cc @@ -1,5 +1,11 @@ +#include <arpa/inet.h> +#include <sys/socket.h> +#include <unistd.h> + #include <atomic> #include <chrono> +#include <cstring> +#include <string> #include <thread> #include "catch_amalgamated.hpp" @@ -7,6 +13,64 @@ using namespace cosmo::service; +namespace { + +int ReserveLoopbackPort() { + const int fd = socket(AF_INET, SOCK_STREAM, 0); + REQUIRE(fd >= 0); + + sockaddr_in address{}; + address.sin_family = AF_INET; + address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + address.sin_port = htons(0); + REQUIRE(bind(fd, reinterpret_cast<const sockaddr*>(&address), sizeof(address)) == 0); + + socklen_t address_size = sizeof(address); + REQUIRE(getsockname(fd, reinterpret_cast<sockaddr*>(&address), &address_size) == 0); + const int port = ntohs(address.sin_port); + close(fd); + return port; +} + +std::string GetOrdinaryHttpResponse(int port) { + for (int attempt = 0; attempt < 100; ++attempt) { + const int fd = socket(AF_INET, SOCK_STREAM, 0); + REQUIRE(fd >= 0); + + timeval timeout{}; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + REQUIRE(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == 0); + + sockaddr_in address{}; + address.sin_family = AF_INET; + address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + address.sin_port = htons(static_cast<uint16_t>(port)); + if (connect(fd, reinterpret_cast<const sockaddr*>(&address), sizeof(address)) == 0) { + constexpr char request[] = + "GET /health-probe HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n"; + const auto sent = send(fd, request, std::strlen(request), MSG_NOSIGNAL); + REQUIRE(sent == static_cast<ssize_t>(std::strlen(request))); + + std::string response; + char buffer[512]; + while (true) { + const auto count = recv(fd, buffer, sizeof(buffer), 0); + if (count <= 0) + break; + response.append(buffer, static_cast<size_t>(count)); + } + close(fd); + return response; + } + close(fd); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + return {}; +} + +} // namespace + TEST_CASE("EventNotifierImpl: construction and destruction", "[EventNotifier]") { REQUIRE_NOTHROW([]() { EventNotifierImpl notifier; }()); } @@ -81,3 +145,15 @@ TEST_CASE("EventNotifierImpl: WebSocket shutdown is deferred to server loop", "[ REQUIRE(notifier.InitializeWebSocket("127.0.0.1", 0)); REQUIRE_NOTHROW(notifier.ShutdownWebSocket()); } + +TEST_CASE("EventNotifierImpl: ordinary HTTP probe is rejected without aborting", "[EventNotifier]") { + EventNotifierImpl notifier; + const int port = ReserveLoopbackPort(); + + REQUIRE(notifier.InitializeWebSocket("127.0.0.1", port)); + const auto response = GetOrdinaryHttpResponse(port); + + REQUIRE(response.find("404 Not Found") != std::string::npos); + REQUIRE(response.find("Not Found") != std::string::npos); + REQUIRE_NOTHROW(notifier.ShutdownWebSocket()); +} diff --git a/test/test_inference_pipeline_metrics.cc b/test/test_inference_pipeline_metrics.cc new file mode 100644 index 000000000..fdf36be86 --- /dev/null +++ b/test/test_inference_pipeline_metrics.cc @@ -0,0 +1,148 @@ +#include "catch_amalgamated.hpp" +#include "nn/core/inference_pipeline_metrics.h" + +TEST_CASE("Inference pipeline metrics expose host, graph, and RKNN stage timings", "[nn][rknn][metrics]") { + cosmo::nn::InferencePipelineMetrics metrics; + + metrics.RecordColorConvert(2'000'000, 2); + metrics.RecordBlobConvert(3'000'000, 2); + metrics.RecordGraphForward(8'000'000, 2, true); + metrics.RecordGraphForward(1'000'000, 1, false); + metrics.RecordResultParse(4'000'000, 2, true); + metrics.RecordResultParse(500'000, 1, false); + constexpr auto detector = cosmo::nn::RknnModelScope::Detector; + metrics.RecordRknnPrepare(1'000'000, detector); + metrics.RecordRknnInputsSet(2'000'000, detector); + metrics.RecordRknnRun(3'000'000, detector); + metrics.RecordRknnOutputsGet(4'000'000, detector); + metrics.RecordRknnOutputsRelease(400'000, detector); + metrics.RecordRknnOutputTransform(5'000'000, detector); + metrics.RecordRknnForward(15'000'000, true, detector); + metrics.RecordRknnForward(7'000'000, false, detector); + metrics.RecordRknnMutexWait(600'000, detector); + metrics.RecordRknnPreprocessFastHit(); + metrics.RecordRknnRgaFill(700'000); + metrics.RecordRknnRgaResizeColor(800'000); + metrics.RecordRknnRgaFailure(); + metrics.RecordRknnCpuResizeFallback(900'000); + metrics.RecordRknnCpuNormalizeFallback(1'000'000); + metrics.RecordRknnNativeInputMap(1'100'000); + metrics.RecordRknnInputFormat(true); + metrics.RecordRknnInputFormat(false, true); + metrics.RecordRknnInputFormat(false, false, true); + metrics.RecordRknnBoundInputBind(true); + metrics.RecordRknnBoundInputBind(false); + metrics.RecordRknnBoundInputCopy(210'000, 1'228'800, true); + metrics.RecordRknnBoundInputCopy(10'000, 0, false); + metrics.RecordRknnBoundInputSync(220'000, true); + metrics.RecordRknnBoundInputSync(20'000, false); + metrics.RecordRknnBoundInputFrame(); + metrics.RecordRknnRgaBoundInputBind(true); + metrics.RecordRknnRgaBoundInputBind(false); + metrics.RecordRknnRgaBoundInputImport(30'000, true); + metrics.RecordRknnRgaBoundInputImport(40'000, false); + metrics.RecordRknnRgaBoundInputFrame(true); + metrics.RecordRknnRgaBoundInputRequantize(50'000, true); + metrics.RecordRknnRgaBoundInputRequantize(5'000, false); + metrics.RecordRknnRgaBoundInputFrame(false); + metrics.RecordRknnRgaBoundInputNormalizeBypass(); + metrics.RecordRknnMppDmaBufImport(60'000, true); + metrics.RecordRknnMppDmaBufImport(7'000, false); + metrics.RecordRknnMppDmaBufFrame(3'133'440); + metrics.RecordRknnMppDmaBufFallback(); + metrics.RecordRknnOutputFormat(true, 1'225'600); + metrics.RecordRknnOutputFormat(false, 4'902'400, true); + metrics.RecordRknnYolov8Transform(1'400'000, 1'500'000); + metrics.RecordRknnYolov8DirectCandidates(true, 8'400, 17, 2'822'400, 8'000); + metrics.RecordRknnYolov8DirectCandidates(false, 0, 0, 0); + metrics.RecordYolov8Postprocess(1'200'000); + metrics.RecordYolov8Nms(1'300'000); + + const auto snapshot = metrics.Snapshot(); + CHECK(snapshot.color_convert_frames == 2); + CHECK(snapshot.color_convert_nanoseconds == 2'000'000); + CHECK(snapshot.blob_convert_frames == 2); + CHECK(snapshot.graph_forward_frames == 3); + CHECK(snapshot.graph_forward_nanoseconds == 9'000'000); + CHECK(snapshot.graph_forward_failures == 1); + CHECK(snapshot.result_parse_frames == 3); + CHECK(snapshot.result_parse_failures == 1); + CHECK(snapshot.rknn_forwards == 2); + CHECK(snapshot.rknn_forward_nanoseconds == 22'000'000); + CHECK(snapshot.rknn_forward_failures == 1); + CHECK(snapshot.rknn_prepare_calls == 1); + CHECK(snapshot.rknn_inputs_set_calls == 1); + CHECK(snapshot.rknn_run_calls == 1); + CHECK(snapshot.rknn_outputs_get_calls == 1); + CHECK(snapshot.rknn_outputs_release_calls == 1); + CHECK(snapshot.rknn_outputs_release_nanoseconds == 400'000); + CHECK(snapshot.rknn_output_transform_calls == 1); + CHECK(snapshot.rknn_mutex_wait_calls == 1); + CHECK(snapshot.rknn_mutex_wait_nanoseconds == 600'000); + CHECK(snapshot.rknn_detector_forwards == 2); + CHECK(snapshot.rknn_detector_forward_nanoseconds == 22'000'000); + CHECK(snapshot.rknn_detector_forward_failures == 1); + CHECK(snapshot.rknn_detector_prepare_calls == 1); + CHECK(snapshot.rknn_detector_inputs_set_calls == 1); + CHECK(snapshot.rknn_detector_run_calls == 1); + CHECK(snapshot.rknn_detector_outputs_get_calls == 1); + CHECK(snapshot.rknn_detector_outputs_release_calls == 1); + CHECK(snapshot.rknn_detector_output_transform_calls == 1); + CHECK(snapshot.rknn_detector_mutex_wait_calls == 1); + CHECK(snapshot.rknn_preprocess_fast_hits == 1); + CHECK(snapshot.rknn_rga_fill_calls == 1); + CHECK(snapshot.rknn_rga_resize_color_calls == 1); + CHECK(snapshot.rknn_rga_failures == 1); + CHECK(snapshot.rknn_cpu_resize_fallback_calls == 1); + CHECK(snapshot.rknn_cpu_normalize_fallback_calls == 1); + CHECK(snapshot.rknn_native_input_map_calls == 1); + CHECK(snapshot.rknn_native_int8_inputs == 1); + CHECK(snapshot.rknn_float_inputs == 1); + CHECK(snapshot.rknn_uint8_contract_inputs == 1); + CHECK(snapshot.rknn_input_compatibility_fallbacks == 1); + CHECK(snapshot.rknn_bound_input_bind_attempts == 4); + CHECK(snapshot.rknn_bound_input_bind_failures == 2); + CHECK(snapshot.rknn_bound_input_copy_calls == 2); + CHECK(snapshot.rknn_bound_input_copy_nanoseconds == 220'000); + CHECK(snapshot.rknn_bound_input_copy_bytes == 1'228'800); + CHECK(snapshot.rknn_bound_input_copy_failures == 1); + CHECK(snapshot.rknn_bound_input_sync_calls == 2); + CHECK(snapshot.rknn_bound_input_sync_nanoseconds == 240'000); + CHECK(snapshot.rknn_bound_input_sync_failures == 1); + CHECK(snapshot.rknn_bound_input_frames == 3); + CHECK(snapshot.rknn_rga_bound_input_bind_attempts == 2); + CHECK(snapshot.rknn_rga_bound_input_bind_failures == 1); + CHECK(snapshot.rknn_rga_bound_input_import_calls == 2); + CHECK(snapshot.rknn_rga_bound_input_import_nanoseconds == 70'000); + CHECK(snapshot.rknn_rga_bound_input_import_failures == 1); + CHECK(snapshot.rknn_rga_bound_input_frames == 2); + CHECK(snapshot.rknn_rga_bound_uint8_frames == 1); + CHECK(snapshot.rknn_rga_bound_native_int8_frames == 1); + CHECK(snapshot.rknn_rga_bound_requantize_calls == 2); + CHECK(snapshot.rknn_rga_bound_requantize_nanoseconds == 55'000); + CHECK(snapshot.rknn_rga_bound_requantize_failures == 1); + CHECK(snapshot.rknn_rga_bound_input_normalize_bypasses == 1); + CHECK(snapshot.rknn_mpp_dmabuf_import_calls == 2); + CHECK(snapshot.rknn_mpp_dmabuf_import_nanoseconds == 67'000); + CHECK(snapshot.rknn_mpp_dmabuf_import_failures == 1); + CHECK(snapshot.rknn_mpp_dmabuf_frames == 1); + CHECK(snapshot.rknn_mpp_dmabuf_fallbacks == 1); + CHECK(snapshot.rknn_mpp_dmabuf_source_bytes == 3'133'440); + CHECK(snapshot.rknn_native_int8_outputs == 1); + CHECK(snapshot.rknn_float_outputs == 1); + CHECK(snapshot.rknn_output_compatibility_fallbacks == 1); + CHECK(snapshot.rknn_native_output_bytes == 1'225'600); + CHECK(snapshot.rknn_float_output_bytes == 4'902'400); + CHECK(snapshot.rknn_yolov8_dfl_calls == 1); + CHECK(snapshot.rknn_yolov8_dfl_nanoseconds == 1'400'000); + CHECK(snapshot.rknn_yolov8_class_calls == 1); + CHECK(snapshot.rknn_yolov8_class_nanoseconds == 1'500'000); + CHECK(snapshot.rknn_yolov8_direct_candidate_calls == 2); + CHECK(snapshot.rknn_yolov8_direct_candidate_failures == 1); + CHECK(snapshot.rknn_yolov8_direct_points_scanned == 8'400); + CHECK(snapshot.rknn_yolov8_direct_points_decoded == 17); + CHECK(snapshot.rknn_yolov8_score_sum_points_rejected == 8'000); + CHECK(snapshot.rknn_yolov8_logical_float_bytes_avoided == 2'822'400); + CHECK(snapshot.yolov8_postprocess_calls == 1); + CHECK(snapshot.yolov8_nms_calls == 1); +} diff --git a/test/test_json_serialization.cc b/test/test_json_serialization.cc index b83645e40..ecf404f76 100644 --- a/test/test_json_serialization.cc +++ b/test/test_json_serialization.cc @@ -147,6 +147,80 @@ TEST_CASE("device status exposes additive reboot identity", "[json][system][upgr CHECK(restored.resData.softwareVersion == original.resData.softwareVersion); } +TEST_CASE("accelerator telemetry exposes additive load semantics", "[json][system][metrics]") { + cosmo::MsgGpuInfo original; + original.gpuusage = 0.42; + original.gpuusageAvailable = true; + original.utilizationMetric = "busy-time-load"; + original.coreUtilizations = {0.09, 0.42}; + original.memoryDomain = "shared-system"; + original.rknnYolov8DirectCandidateCalls = 4; + original.rknnYolov8DirectCandidateFailures = 1; + original.rknnYolov8DirectPointsScanned = 33'600; + original.rknnYolov8DirectPointsDecoded = 68; + original.rknnYolov8ScoreSumPointsRejected = 32'000; + original.rknnYolov8LogicalFloatBytesAvoided = 11'289'600; + original.rknnBoundInputBindAttempts = 1; + original.rknnBoundInputCopyCalls = 4; + original.rknnBoundInputCopyMs = 1.5; + original.rknnBoundInputCopyBytes = 4'915'200; + original.rknnBoundInputSyncCalls = 4; + original.rknnBoundInputSyncMs = 0.5; + original.rknnBoundInputFrames = 4; + original.rknnRgaBoundInputFrames = 4; + original.rknnRgaBoundUint8Frames = 4; + original.rknnMppDmaBufImportCalls = 4; + original.rknnMppDmaBufImportMs = 1.25; + original.rknnMppDmaBufFrames = 4; + original.rknnMppDmaBufSourceBytes = 12'533'760; + + std::string json; + REQUIRE(cosmo::util::EncodeJson(original, json)); + const auto doc = ParseJson(json); + CHECK(doc["utilizationMetric"] == "busy-time-load"); + CHECK(doc["memoryDomain"] == "shared-system"); + REQUIRE(doc["coreUtilizations"].size() == 2); + CHECK(doc["coreUtilizations"][0].get<double>() == Catch::Approx(0.09)); + CHECK(doc["coreUtilizations"][1].get<double>() == Catch::Approx(0.42)); + CHECK(doc["rknnYolov8DirectCandidateCalls"] == 4); + CHECK(doc["rknnYolov8DirectPointsDecoded"] == 68); + CHECK(doc["rknnYolov8ScoreSumPointsRejected"] == 32'000); + CHECK(doc["rknnYolov8LogicalFloatBytesAvoided"] == 11'289'600); + CHECK(doc["rknnBoundInputBindAttempts"] == 1); + CHECK(doc["rknnBoundInputCopyBytes"] == 4'915'200); + CHECK(doc["rknnBoundInputFrames"] == 4); + CHECK(doc["rknnRgaBoundInputFrames"] == 4); + CHECK(doc["rknnRgaBoundUint8Frames"] == 4); + CHECK(doc["rknnMppDmaBufImportCalls"] == 4); + CHECK(doc["rknnMppDmaBufFrames"] == 4); + CHECK(doc["rknnMppDmaBufSourceBytes"] == 12'533'760); + + cosmo::MsgGpuInfo restored; + REQUIRE(cosmo::util::DecodeJson(json, restored)); + CHECK(restored.utilizationMetric == original.utilizationMetric); + CHECK(restored.coreUtilizations == original.coreUtilizations); + CHECK(restored.memoryDomain == original.memoryDomain); + CHECK(restored.rknnYolov8DirectCandidateCalls == original.rknnYolov8DirectCandidateCalls); + CHECK(restored.rknnYolov8DirectCandidateFailures == original.rknnYolov8DirectCandidateFailures); + CHECK(restored.rknnYolov8DirectPointsScanned == original.rknnYolov8DirectPointsScanned); + CHECK(restored.rknnYolov8DirectPointsDecoded == original.rknnYolov8DirectPointsDecoded); + CHECK(restored.rknnYolov8ScoreSumPointsRejected == original.rknnYolov8ScoreSumPointsRejected); + CHECK(restored.rknnYolov8LogicalFloatBytesAvoided == original.rknnYolov8LogicalFloatBytesAvoided); + CHECK(restored.rknnBoundInputBindAttempts == original.rknnBoundInputBindAttempts); + CHECK(restored.rknnBoundInputCopyCalls == original.rknnBoundInputCopyCalls); + CHECK(restored.rknnBoundInputCopyMs == original.rknnBoundInputCopyMs); + CHECK(restored.rknnBoundInputCopyBytes == original.rknnBoundInputCopyBytes); + CHECK(restored.rknnBoundInputSyncCalls == original.rknnBoundInputSyncCalls); + CHECK(restored.rknnBoundInputSyncMs == original.rknnBoundInputSyncMs); + CHECK(restored.rknnBoundInputFrames == original.rknnBoundInputFrames); + CHECK(restored.rknnRgaBoundInputFrames == original.rknnRgaBoundInputFrames); + CHECK(restored.rknnRgaBoundUint8Frames == original.rknnRgaBoundUint8Frames); + CHECK(restored.rknnMppDmaBufImportCalls == original.rknnMppDmaBufImportCalls); + CHECK(restored.rknnMppDmaBufImportMs == original.rknnMppDmaBufImportMs); + CHECK(restored.rknnMppDmaBufFrames == original.rknnMppDmaBufFrames); + CHECK(restored.rknnMppDmaBufSourceBytes == original.rknnMppDmaBufSourceBytes); +} + TEST_CASE("HTTP event targets serialize and round-trip", "[json][event][targets]") { cosmo::CMsgOnEventsReq event; event.messageId = "event-1"; diff --git a/test/test_legacy_migration_installer.sh b/test/test_legacy_migration_installer.sh new file mode 100644 index 000000000..9dd20c5bf --- /dev/null +++ b/test/test_legacy_migration_installer.sh @@ -0,0 +1,88 @@ +#!/bin/bash +set -euo pipefail + +repo="$(cd "$(dirname "$0")/.." && pwd -P)" +root="$(mktemp -d)" +trap 'rm -rf -- "$root"' EXIT + +payload="$root/payload" +active="$root/appfs/cosmo_wander/cwai_data" +mkdir -p "$payload/scripts" "$payload/bin" "$payload/files/Interface" \ + "$payload/web" "$active/resource/models" "$active/bin" +cp "$repo/scripts/legacy_migration_install.sh" "$payload/scripts/install.sh" +printf 'new\n' >"$payload/bin/cosmo-engine" +printf '#!/bin/sh\ntouch "$COSMO_MIGRATION_TEST_ROOT/stop.called"\n' >"$payload/scripts/stop.sh" +printf '#!/bin/sh\n' >"$payload/scripts/start.sh" +printf '#!/bin/sh\n' >"$payload/scripts/inte_run_start.sh" +chmod +x "$payload/scripts/"*.sh +printf 'http\n' >"$payload/files/Interface/ai-box-interface_v1.0.html" +printf 'mqtt\n' >"$payload/files/Interface/mqtt_v1.0.html" +printf 'old\n' >"$active/bin/cosmo-engine" +printf 'existing-model\n' >"$active/resource/models/model.nn" +printf 'preserved\n' >"$active/resource/device-local.conf" + +COSMO_MIGRATION_TEST_ROOT="$root" \ + sh "$payload/scripts/install.sh" "$root/install.log" + +grep -Fxq new "$active/bin/cosmo-engine" +grep -Fxq existing-model "$active/resource/models/model.nn" +grep -Fxq preserved "$active/resource/device-local.conf" +test ! -e "$root/appfs/cosmo_wander/.cosmo-migration-backup" +test -f "$root/stop.called" +test ! -e "$active/scripts/install.sh" +test -d "$active/bin/nginx_conf/logs" +test -L "$active/web/staticfile/httpInterface.html" +test -L "$active/web/staticfile/mqttInterface.html" +test -f "$root/data/cwaiuserdata/mqttUpgradeApp" +service="$root/etc/systemd/system/cosmo.service" +test -f "$service" +grep -Fxq 'ExecStart=/appfs/cosmo_wander/cwai_data/scripts/inte_run_start.sh' "$service" +grep -Fxq 'Restart=on-failure' "$service" +grep -Fxq 'RestartSec=10' "$service" +test -L "$root/etc/systemd/system/multi-user.target.wants/cosmo.service" + +# The same permanent MD5 lifecycle must remain valid after the first bridge +# from main; a later package uses the same installer contract. +printf 'newer\n' >"$payload/bin/cosmo-engine" +sed -i 's#/appfs/cosmo_wander/cwai_data#/appfs/minivision/mv_data#' "$service" +COSMO_MIGRATION_TEST_ROOT="$root" \ + sh "$payload/scripts/install.sh" "$root/install-again.log" +grep -Fxq newer "$active/bin/cosmo-engine" +grep -Fxq existing-model "$active/resource/models/model.nn" +grep -Fxq 'ExecStart=/appfs/cosmo_wander/cwai_data/scripts/inte_run_start.sh' "$service" + +rm -rf -- "$payload" "$active" +mkdir -p "$payload/scripts" "$payload/bin" "$payload/resource/models" "$active/resource/models" +cp "$repo/scripts/legacy_migration_install.sh" "$payload/scripts/install.sh" +printf 'new\n' >"$payload/bin/cosmo-engine" +printf '#!/bin/sh\n' >"$payload/scripts/stop.sh" +printf '#!/bin/sh\n' >"$payload/scripts/start.sh" +printf '#!/bin/sh\n' >"$payload/scripts/inte_run_start.sh" +chmod +x "$payload/scripts/"*.sh +printf 'packaged-model\n' >"$payload/resource/models/model.nn" +printf 'existing-model\n' >"$active/resource/models/model.nn" +printf 'preserved\n' >"$active/resource/device-local.conf" + +COSMO_MIGRATION_TEST_ROOT="$root" \ + sh "$payload/scripts/install.sh" "$root/install.log" + +grep -Fxq packaged-model "$active/resource/models/model.nn" +grep -Fxq preserved "$active/resource/device-local.conf" + +printf 'stale\n' >"$active/resource/stale.conf" +COSMO_MIGRATION_TEST_ROOT="$root" CLEAN_RESOURCE=1 \ + sh "$payload/scripts/install.sh" "$root/install-clean.log" +test ! -e "$active/resource/stale.conf" +grep -Fxq packaged-model "$active/resource/models/model.nn" + +# Preserved resources must be copied into staging before the package overlays +# them. Keeping the packaged resource tree in staging while copying the active +# tree creates an avoidable second model-sized allocation on /appfs. +installer="$repo/scripts/legacy_migration_install.sh" +preserved_copy_line="$(grep -nF 'cp -a -- "${active_root}/resource/." "${staging_root}/resource/"' "$installer" | cut -d: -f1)" +payload_copy_line="$(grep -nF 'cp -a -- "${payload_root}/." "$staging_root/"' "$installer" | cut -d: -f1)" +test -n "$preserved_copy_line" +test -n "$payload_copy_line" +test "$preserved_copy_line" -lt "$payload_copy_line" +! grep -Fq '.packaged-resource' "$installer" +echo "legacy migration installer tests passed" diff --git a/test/test_linkage_service_impl.cc b/test/test_linkage_service_impl.cc index e0e778291..70e095862 100644 --- a/test/test_linkage_service_impl.cc +++ b/test/test_linkage_service_impl.cc @@ -126,10 +126,24 @@ TEST_CASE("LinkageServiceImpl: CRUD and query operations", "[linkage-service]") REQUIRE(ret == ErrorEnum::Failed); } - SECTION("Add rejects an empty workflow") { + SECTION("Add creates a draft for an empty workflow") { std::string id; auto ret = sut.Add("test_strategy", "[]", id); - REQUIRE(ret == ErrorEnum::ParameterException); + REQUIRE(ret == ErrorEnum::Success); + REQUIRE_FALSE(id.empty()); + + size_t total = 0; + const auto results = sut.Query(1, 10, "test_strategy", total); + REQUIRE(total == 1); + REQUIRE(results.size() == 1); + REQUIRE(results.front().id == id); + REQUIRE(nlohmann::json::parse(results.front().workFlow).empty()); + } + + SECTION("Update still rejects an empty workflow") { + std::string id; + REQUIRE(sut.Add("configured", MakeValidWorkflow(), id) == ErrorEnum::Success); + REQUIRE(sut.Update("draft", id, "[]") == ErrorEnum::ParameterException); } SECTION("Add then Delete succeeds") { @@ -283,6 +297,26 @@ TEST_CASE("LinkageServiceImpl: CRUD and query operations", "[linkage-service]") } } +TEST_CASE("LinkageServiceImpl: empty workflow draft survives reload", "[linkage-service]") { + LinkageTestEnv env; + cosmo::test::MockServiceRegistry mocks; + env.SetupPaths(); + + std::string id; + { + LinkageServiceImpl writer; + REQUIRE(writer.Add("draft", "[]", id) == ErrorEnum::Success); + } + + LinkageServiceImpl reader; + size_t total = 0; + const auto results = reader.Query(1, 10, "draft", total); + REQUIRE(total == 1); + REQUIRE(results.size() == 1); + REQUIRE(results.front().id == id); + REQUIRE(nlohmann::json::parse(results.front().workFlow).empty()); +} + TEST_CASE("LinkageServiceImpl: persistence failure does not publish a ghost strategy", "[linkage-service][consistency]") { LinkageTestEnv env; diff --git a/test/test_live_stream_service_impl.cc b/test/test_live_stream_service_impl.cc index 149a8ba9f..c4aae4187 100644 --- a/test/test_live_stream_service_impl.cc +++ b/test/test_live_stream_service_impl.cc @@ -48,6 +48,22 @@ TEST_CASE("LiveStreamServiceImpl: 视频流管理核心逻辑", "[live-stream]") cosmo::util::ErrorEnum::TaskNotExist); } + SECTION("ViewerCreate 快速拒绝已停止的 OSD 任务") { + cosmo::ActionNode dummyAction; + auto mockChannel = + std::make_shared<cosmo::AlgChannel>("channel_1", "task_1", dummyAction, "rtsp://url"); + ALLOW_CALL(mocks.cameraSvc, GetChannelInst("channel_1")).RETURN(mockChannel); + cosmo::service::camera::CameraTaskDto task; + task.algorithmCode = "alg_code"; + task.enable = false; + ALLOW_CALL(mocks.cameraSvc, GetTasks("channel_1")) + .RETURN(std::vector<cosmo::service::camera::CameraTaskDto>{task}); + FORBID_CALL(mocks.cameraSvc, AcquirePreviewChannel(trompeloeil::_)); + + cosmo::LiveStream::LiveStreamInfo streamInfo; + REQUIRE(sut.ViewerCreate("channel_1", "alg_code", streamInfo) == cosmo::util::ErrorEnum::ActionStop); + } + SECTION("ViewerHeartBeat 返回 CameraNotExist 当 Channel 不存在") { ALLOW_CALL(mocks.cameraSvc, GetChannelInst(trompeloeil::_)).RETURN(nullptr); REQUIRE(sut.ViewerHeartBeat("non_exist_channel", "alg_code") == @@ -59,10 +75,13 @@ TEST_CASE("LiveStreamServiceImpl: 视频流管理核心逻辑", "[live-stream]") } SECTION("启动中的多客户端仅在最后一个客户端离开时取消") { - auto gate = std::make_shared<LiveStreamServiceImpl::ViewerStartGate>(); - gate->participants = 2; - const std::string key = "pending_channel\npending_alg"; - sut.starting_viewers_[key] = gate; + auto gate = std::make_shared<LiveStreamServiceImpl::ViewerStartGate>(); + gate->participants = 2; + gate->channel_id = "pending_channel"; + gate->channel_lease_acquired = true; + const std::string key = "pending_channel\npending_alg"; + sut.starting_viewers_[key] = gate; + REQUIRE_CALL(mocks.cameraSvc, ReleasePreviewChannel("pending_channel")); REQUIRE(sut.ViewerDelete("pending_channel", "pending_alg")); REQUIRE(gate->participants == 1); @@ -71,6 +90,7 @@ TEST_CASE("LiveStreamServiceImpl: 视频流管理核心逻辑", "[live-stream]") REQUIRE(sut.ViewerDelete("pending_channel", "pending_alg")); REQUIRE(gate->participants == 0); REQUIRE(gate->cancelled); + REQUIRE_FALSE(gate->channel_lease_acquired); } SECTION("SetViewCounts 不发生崩溃") { diff --git a/test/test_message_face_lib_handler.cc b/test/test_message_face_lib_handler.cc index ab47f00b2..efbafc344 100644 --- a/test/test_message_face_lib_handler.cc +++ b/test/test_message_face_lib_handler.cc @@ -12,6 +12,7 @@ #include "api/MessageFaceLibHandler.h" #include "flow/face/FaceLib.h" #include "flow/face/FaceManager.h" +#include "flow/face/Person.h" #include "mock/MockFaceLibService.h" #include "mock/MockPersonDaoService.h" #include "mock/MockServiceRegistry.h" @@ -226,6 +227,31 @@ TEST_CASE("FaceLibHandler: person update rejects partially resolved face librari REQUIRE_THROWS(handler.Handle(std::move(data), errc)); } +TEST_CASE("FaceLibHandler: staged person picture reaches image processing before database commit", + "[face-lib-handler][staged-upload]") { + MockServiceRegistry mocks; + auto person = std::make_shared<Person>("person-1"); + + REQUIRE_CALL(mocks.faceLibSvc, GetFaceLibs(_)).RETURN(std::vector<FaceLibPtr>{}); + REQUIRE_CALL(mocks.faceLibSvc, IsValidSerialNumber(_, _)).RETURN(true); + REQUIRE_CALL(mocks.faceLibSvc, CreatePerson()).RETURN(person); + REQUIRE_CALL(mocks.faceLibSvc, GetPersonId(person)).RETURN("person-1"); + REQUIRE_CALL(mocks.faceLibSvc, GetPersonPictures(person)).RETURN(std::vector<FacePicPtr>{}); + REQUIRE_CALL(mocks.videoCodecSvc, DecodeJpeg(_)).RETURN(nullptr); + FORBID_CALL(mocks.personDaoSvc, Begin()); + ALLOW_CALL(mocks.faceLibSvc, ReleaseFaceModels()); + + auto handler = MakeHandler(mocks); + Lib::MsgModifyFacePicLibRecv data{}; + data.personOperation = static_cast<int>(Operation::Add); + data.personName = "staged upload"; + data.pictureData.push_back({0xFF, 0xD8, 0xFF}); + + std::error_condition errc; + (void)handler.Handle(std::move(data), errc); + REQUIRE(errc == util::ErrorEnum::InternalError); +} + TEST_CASE("FaceManager: selected-person export does not require a prior query", "[face-lib-handler][export][consistency]") { MockServiceRegistry mocks; diff --git a/test/test_message_system_handler.cc b/test/test_message_system_handler.cc index 67c206a52..1e70803ba 100644 --- a/test/test_message_system_handler.cc +++ b/test/test_message_system_handler.cc @@ -14,6 +14,7 @@ #include "mock/MockServiceRegistry.h" #include "mock/MockSystemOperationService.h" #include "mock/MockTimeService.h" +#include "nn/core/inference_pipeline_metrics.h" #include "util/ErrorCode.h" using namespace cosmo; @@ -49,19 +50,88 @@ TEST_CASE("SystemHandler: QueryHardwareResource exposes accelerator preview tele MockServiceRegistry mocks; auto handler = MakeHandler(mocks); - REQUIRE_CALL(mocks.deviceInfoSvc, GetHardwareResource(_)).RETURN(std::vector<service::HwResourceItem>{}); + service::HwResourceItem system_memory{ + "generalMemoryUtilization", "系统内存使用率", 18, "1.37 GiB", "6.36 GiB", 1, "system"}; + REQUIRE_CALL(mocks.deviceInfoSvc, GetHardwareResource(_)) + .RETURN(std::vector<service::HwResourceItem>{system_memory}); MsgGpuInfo gpu; - gpu.gpuusage = 0.5; + gpu.gpuusage = 0.5; + gpu.gpuusageAvailable = false; REQUIRE_CALL(mocks.deviceInfoSvc, GetGpuUtilization()).RETURN(gpu); - const auto preview = media::GetPreviewPipelineMetrics().Snapshot(); + const auto preview = media::GetPreviewPipelineMetrics().Snapshot(); + const auto inference = nn::GetInferencePipelineMetrics().Snapshot(); System::MsgQueryHardwareResourceRecv data{}; std::error_condition errc; auto ret = handler.Handle(std::move(data), errc); CHECK(ret.resData.accelerator.gpuusage == 0.5); + CHECK_FALSE(ret.resData.accelerator.gpuusageAvailable); CHECK(ret.resData.accelerator.activePreviewStreams == preview.active_preview_streams); CHECK(ret.resData.accelerator.activeAlgorithmPreviewStreams == preview.active_algorithm_preview_streams); + CHECK_FALSE(ret.resData.accelerator.videoEncoderBackend.empty()); + CHECK_FALSE(ret.resData.accelerator.videoEncoderDetail.empty()); + CHECK_FALSE(ret.resData.accelerator.videoDecoderBackend.empty()); + CHECK_FALSE(ret.resData.accelerator.videoDecoderDetail.empty()); + CHECK(ret.resData.accelerator.rgaFrames == preview.rga_frames); + CHECK(ret.resData.accelerator.mppEncodedFrames == preview.mpp_encoded_frames); + CHECK(ret.resData.accelerator.mppDecodedFrames == preview.mpp_decoded_frames); + CHECK(ret.resData.accelerator.mppCopyOutFrames == preview.mpp_copy_out_frames); + CHECK(ret.resData.accelerator.mppEarlyDroppedFrames == preview.mpp_early_dropped_frames); + CHECK(ret.resData.accelerator.colorConvertFrames == inference.color_convert_frames); + CHECK(ret.resData.accelerator.rknnForwards == inference.rknn_forwards); + CHECK(ret.resData.accelerator.rknnDetectorForwards == inference.rknn_detector_forwards); + CHECK(ret.resData.accelerator.rknnPreprocessFastHits == inference.rknn_preprocess_fast_hits); + CHECK(ret.resData.accelerator.rknnOutputsReleaseCalls == inference.rknn_outputs_release_calls); + CHECK(ret.resData.accelerator.rknnNativeInt8Outputs == inference.rknn_native_int8_outputs); + CHECK(ret.resData.accelerator.rknnBoundInputBindAttempts == inference.rknn_bound_input_bind_attempts); + CHECK(ret.resData.accelerator.rknnBoundInputFrames == inference.rknn_bound_input_frames); + CHECK(ret.resData.accelerator.rknnRgaBoundInputBindAttempts == + inference.rknn_rga_bound_input_bind_attempts); + CHECK(ret.resData.accelerator.rknnRgaBoundInputImportCalls == + inference.rknn_rga_bound_input_import_calls); + CHECK(ret.resData.accelerator.rknnRgaBoundInputFrames == inference.rknn_rga_bound_input_frames); + CHECK(ret.resData.accelerator.rknnRgaBoundUint8Frames == inference.rknn_rga_bound_uint8_frames); + CHECK(ret.resData.accelerator.rknnRgaBoundRequantizeCalls == inference.rknn_rga_bound_requantize_calls); + CHECK(ret.resData.accelerator.rknnRgaBoundInputNormalizeBypasses == + inference.rknn_rga_bound_input_normalize_bypasses); + CHECK(ret.resData.accelerator.rknnMppDmaBufImportCalls == inference.rknn_mpp_dmabuf_import_calls); + CHECK(ret.resData.accelerator.rknnMppDmaBufFrames == inference.rknn_mpp_dmabuf_frames); + CHECK(ret.resData.accelerator.rknnMppDmaBufFallbacks == inference.rknn_mpp_dmabuf_fallbacks); + CHECK(ret.resData.accelerator.rknnOutputCompatibilityFallbacks == + inference.rknn_output_compatibility_fallbacks); + CHECK(ret.resData.accelerator.rknnYolov8DflCalls == inference.rknn_yolov8_dfl_calls); + CHECK(ret.resData.accelerator.rknnYolov8DirectCandidateCalls == + inference.rknn_yolov8_direct_candidate_calls); + CHECK(ret.resData.accelerator.rknnYolov8ScoreSumPointsRejected == + inference.rknn_yolov8_score_sum_points_rejected); + CHECK(ret.resData.accelerator.yolov8PostprocessCalls == inference.yolov8_postprocess_calls); + REQUIRE(ret.resData.itemList.size() == 1); + CHECK(ret.resData.itemList.front().memoryDomain == "system"); + CHECK(ret.resData.itemList.front().usedSize == "1.37 GiB"); +} + +TEST_CASE("SystemHandler: CheckUpgradeSpace exposes cleanup decision facts", "[system-handler][upgrade]") { + MockServiceRegistry mocks; + auto handler = MakeHandler(mocks); + + REQUIRE_CALL(mocks.systemOpSvc, CheckUpgradeSpace(2048, true, _)) + .SIDE_EFFECT(_3 = service::UpgradeSpaceStatus{false, 5120, 4096, 2048, 1024, 3}) + .RETURN(util::ErrorEnum::Success); + + System::MsgCheckUpgradeSpaceRecv data{}; + data.packageSizeBytes = 2048; + data.cleanupEventMedia = true; + std::error_condition errc; + const auto result = handler.Handle(std::move(data), errc); + + CHECK(!errc); + CHECK_FALSE(result.resData.sufficient); + CHECK(result.resData.requiredBytes == 5120); + CHECK(result.resData.availableBytes == 4096); + CHECK(result.resData.eventMediaBytes == 2048); + CHECK(result.resData.deletedMediaBytes == 1024); + CHECK(result.resData.deletedMediaFiles == 3); } TEST_CASE("SystemHandler: QueryPictureQuality", "[system-handler]") { diff --git a/test/test_mock_audio_pillar_server.py b/test/test_mock_audio_pillar_server.py new file mode 100644 index 000000000..5bf997320 --- /dev/null +++ b/test/test_mock_audio_pillar_server.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 +"""Contract tests for the network audio-pillar simulator.""" + +from __future__ import annotations + +import importlib.util +import json +import sys +import threading +import unittest +import urllib.error +import urllib.request +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +from pathlib import Path + + +sys.dont_write_bytecode = True +REPOSITORY = Path(__file__).resolve().parents[1] +SERVER_SOURCE = REPOSITORY / "tools" / "mock_audio_pillar_server.py" + + +def load_server_module(): + spec = importlib.util.spec_from_file_location("mock_audio_pillar_server", SERVER_SOURCE) + if spec is None or spec.loader is None: + raise RuntimeError(f"cannot load {SERVER_SOURCE}") + module = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = module + spec.loader.exec_module(module) + return module + + +def request_json(url: str, *, method: str = "GET", body=None): + data = None if body is None else json.dumps(body).encode("utf-8") + request = urllib.request.Request( + url, + data=data, + method=method, + headers={"Content-Type": "application/json"}, + ) + with urllib.request.urlopen(request, timeout=2) as response: + return response.status, json.loads(response.read().decode("utf-8")) + + +class AudioFileHandler(BaseHTTPRequestHandler): + def do_GET(self) -> None: # noqa: N802 - BaseHTTPRequestHandler API + body = b"synthetic-mp3-data" + self.send_response(206 if self.headers.get("Range") else 200) + self.send_header("Content-Type", "audio/mpeg") + self.send_header("Content-Length", str(len(body))) + self.end_headers() + self.wfile.write(body) + + def log_message(self, *_args) -> None: + return + + +class AudioPillarContractTest(unittest.TestCase): + @classmethod + def setUpClass(cls) -> None: + cls.server_module = load_server_module() + cls.server = cls.server_module.create_server("127.0.0.1", 0) + cls.thread = threading.Thread(target=cls.server.serve_forever, daemon=True) + cls.thread.start() + cls.base_url = f"http://127.0.0.1:{cls.server.server_port}" + + @classmethod + def tearDownClass(cls) -> None: + cls.server.shutdown() + cls.server.server_close() + cls.thread.join(timeout=2) + + def setUp(self) -> None: + request_json(f"{self.base_url}/__mock__/events", method="DELETE") + + def test_alive_matches_platform_contract(self) -> None: + status, response = request_json( + f"{self.base_url}/v1/check_alive", method="POST" + ) + self.assertEqual(status, 200) + self.assertEqual(response["code"], 200) + _, mock_status = request_json(f"{self.base_url}/__mock__/status") + self.assertEqual(mock_status["aliveChecks"], 1) + self.assertIsNotNone(mock_status["lastAliveAt"]) + + def test_text_speech_is_validated_and_recorded(self) -> None: + payload = { + "text": "发现人员闯入", + "vcn": "xiaoyan", + "speed": 45, + "volume": 70, + "rdn": "0", + "rcn": "0", + "reg": 0, + "sync": False, + "queue": False, + "prompt": False, + "loop": {"duration": 60, "times": 2, "gap": 3}, + } + _, response = request_json( + f"{self.base_url}/v1/speech", method="POST", body=payload + ) + self.assertEqual(response["code"], 200) + + _, events = request_json(f"{self.base_url}/__mock__/events") + self.assertEqual(events["count"], 1) + self.assertEqual(events["events"][0]["kind"], "text") + self.assertEqual(events["events"][0]["payload"], payload) + + def test_audio_url_speech_is_validated_and_recorded(self) -> None: + payload = { + "url": "http://192.168.0.72/audio/alarm.mp3", + "sync": False, + "queue": False, + "volume": 50, + "prompt": False, + "loop": {"duration": 30, "times": 1, "gap": 1}, + } + request_json(f"{self.base_url}/v1/speech", method="POST", body=payload) + + _, events = request_json(f"{self.base_url}/__mock__/events") + self.assertEqual(events["events"][0]["kind"], "audio_url") + self.assertEqual(events["events"][0]["payload"]["url"], payload["url"]) + + def test_audio_url_can_be_fetched_from_the_platform(self) -> None: + audio_server = ThreadingHTTPServer(("127.0.0.1", 0), AudioFileHandler) + audio_thread = threading.Thread(target=audio_server.serve_forever, daemon=True) + audio_thread.start() + pillar_server = self.server_module.create_server( + "127.0.0.1", 0, verify_audio_urls=True + ) + pillar_thread = threading.Thread(target=pillar_server.serve_forever, daemon=True) + pillar_thread.start() + try: + payload = { + "url": f"http://127.0.0.1:{audio_server.server_port}/alarm.mp3", + "volume": 50, + "loop": {"duration": 30, "times": 1, "gap": 1}, + } + _, response = request_json( + f"http://127.0.0.1:{pillar_server.server_port}/v1/speech", + method="POST", + body=payload, + ) + self.assertEqual(response["code"], 200) + _, events = request_json( + f"http://127.0.0.1:{pillar_server.server_port}/__mock__/events" + ) + self.assertTrue(events["events"][0]["audioFetch"]["ok"]) + self.assertEqual( + events["events"][0]["audioFetch"]["contentType"], "audio/mpeg" + ) + finally: + pillar_server.shutdown() + pillar_server.server_close() + pillar_thread.join(timeout=2) + audio_server.shutdown() + audio_server.server_close() + audio_thread.join(timeout=2) + + def test_invalid_speech_is_rejected_without_recording(self) -> None: + with self.assertRaises(urllib.error.HTTPError) as raised: + request_json( + f"{self.base_url}/v1/speech", + method="POST", + body={"volume": 101, "loop": {}}, + ) + self.assertEqual(raised.exception.code, 400) + + _, events = request_json(f"{self.base_url}/__mock__/events") + self.assertEqual(events["count"], 0) + + def test_next_command_can_simulate_device_failure(self) -> None: + request_json(f"{self.base_url}/__mock__/fail-next", method="POST", body={}) + status, response = request_json( + f"{self.base_url}/v1/speech", + method="POST", + body={"text": "test", "volume": 50, "speed": 50, "loop": {}}, + ) + self.assertEqual(status, 200) + self.assertEqual(response["code"], 500) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/test_model_authorization_service_impl.cc b/test/test_model_authorization_service_impl.cc new file mode 100644 index 000000000..e22d90510 --- /dev/null +++ b/test/test_model_authorization_service_impl.cc @@ -0,0 +1,20 @@ +#include "catch_amalgamated.hpp" +#include "service/modelguard/impl/ModelAuthorizationServiceImpl.h" + +TEST_CASE("ModelAuthorizationServiceImpl hides authorization when the controlled tool is absent", + "[service][model-authorization]") { + cosmo::service::ModelAuthorizationServiceImpl service("/definitely/not/cosmo-model-provision"); + + const auto status = service.Status(); + CHECK_FALSE(status.supported); + CHECK_FALSE(status.authorized); + CHECK(status.state == "unsupported"); + + std::string path; + std::string name; + CHECK(service.CreateDeviceRequest(path, name) == cosmo::util::ErrorEnum::OperationNotSupport); + CHECK(path.empty()); + CHECK(name.empty()); + CHECK(service.InstallCertificate("/definitely/not/a-certificate") == + cosmo::util::ErrorEnum::OperationNotSupport); +} diff --git a/test/test_model_import_exporter.cc b/test/test_model_import_exporter.cc index d6134d4fb..7afc65338 100644 --- a/test/test_model_import_exporter.cc +++ b/test/test_model_import_exporter.cc @@ -71,6 +71,10 @@ TEST_CASE("ModelImportExporter Tests", "[model]") { [&]() { return std::string("1234567"); }, [&](const nlohmann::json&) {}, [&](const std::string&, const std::string&) {}); +#ifndef COSMO_NN_USE_RKNN_BACKEND + // RKNN P0 intentionally admits only classify/yolov8_det and validates the + // device model with rknn_init, so a fake qwen3vl payload is not a portable + // success fixture for that backend. SECTION("2.1 AddAtomicModel:验证目录创建、config.json 生成、model.nn 创建") { std::string bmodelSrc = testUploadDir + "/source.bmodel"; std::ofstream out(bmodelSrc); @@ -142,6 +146,7 @@ TEST_CASE("ModelImportExporter Tests", "[model]") { fs::remove(bmodelSrc); fs::remove(invalidTable); } +#endif SECTION("OCR character table config binds the legacy 6624-entry table to 6625 CTC classes") { const std::string characterTable = testUploadDir + "/legacy_character_table.txt"; @@ -470,7 +475,8 @@ TEST_CASE("ModelImportExporter Tests", "[model]") { std::ofstream(outsideFile) << "must survive"; std::vector<cosmo::Model::BmodelFileInfo> files = {{"main", outsideFile}}; - auto result = importExporter.AddAtomicModel("", "OutsideModel", "DET", "", files, "", "", "", "", ""); + auto result = + importExporter.AddAtomicModel("", "OutsideModel", "classify", "", files, "", "", "", "", ""); REQUIRE(result == cosmo::util::ErrorEnum::FileNotExist); REQUIRE(fs::exists(outsideFile)); diff --git a/test/test_nginx_spa_cache_policy.sh b/test/test_nginx_spa_cache_policy.sh new file mode 100644 index 000000000..2bc30f58a --- /dev/null +++ b/test/test_nginx_spa_cache_policy.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -euo pipefail + +repo="$(cd "$(dirname "$0")/.." && pwd -P)" +config="$repo/nginx/conf/conf.d/default.conf" + +# Hashed frontend assets must never fall back to index.html. Returning HTML for +# a missing module makes browsers reject it with a strict MIME type error. +grep -Eq 'location[[:space:]]+\^~[[:space:]]+/assets/' "$config" +grep -Eq 'try_files[[:space:]]+\$uri[[:space:]]+=404;' "$config" +grep -Eq 'Cache-Control[[:space:]]+"public, max-age=31536000, immutable"' "$config" + +# The SPA entry point names hashed assets from one specific build. It must be +# re-fetched after an upgrade instead of being reused with a new asset set. +grep -Eq 'location[[:space:]]+=[[:space:]]+/index\.html' "$config" +grep -Eq 'Cache-Control[[:space:]]+"no-store, no-cache, must-revalidate"[[:space:]]+always;' "$config" + +echo "nginx SPA cache policy tests passed" diff --git a/test/test_package_profile.py b/test/test_package_profile.py new file mode 100644 index 000000000..3260dc32f --- /dev/null +++ b/test/test_package_profile.py @@ -0,0 +1,418 @@ +#!/usr/bin/python3 +"""Regression tests for Open/Protected permanent MD5 package policy.""" + +from __future__ import annotations + +import hashlib +import importlib.util +import io +import json +import os +import pathlib +import shutil +import subprocess +import tarfile +import tempfile +import unittest + + +REPOSITORY = pathlib.Path(__file__).resolve().parents[1] +spec = importlib.util.spec_from_file_location( + "package_verifier", REPOSITORY / "scripts/verify_package_contents.py" +) +assert spec and spec.loader +verifier = importlib.util.module_from_spec(spec) +spec.loader.exec_module(verifier) + + +class PackageProfileTests(unittest.TestCase): + @staticmethod + def find_bash() -> tuple[str | None, dict[str, str]]: + bash = shutil.which("bash") + environment = os.environ.copy() + if os.name == "nt": + git = shutil.which("git") + if git: + git_root = pathlib.Path(git).resolve().parents[1] + git_bash = git_root / "bin" / "bash.exe" + if git_bash.is_file(): + bash = str(git_bash) + environment["PATH"] = os.pathsep.join( + [ + str(git_root / "usr" / "bin"), + str(git_root / "mingw32" / "bin"), + environment.get("PATH", ""), + ] + ) + return bash, environment + + def make_package( + self, + profile: str, + model: bytes = b"plain-model", + model_type: str = "yolov8_det", + ) -> pathlib.Path: + root = "cosmo-V1.5.0" + directory = pathlib.Path(tempfile.mkdtemp()) + initial = directory / f"{root}.tar.gz" + executable_files = verifier.REQUIRED_EXECUTABLES + regular_files = verifier.REQUIRED_FILES + with tarfile.open(initial, "w:gz") as archive: + root_info = tarfile.TarInfo(root) + root_info.type = tarfile.DIRTYPE + root_info.mode = 0o755 + archive.addfile(root_info) + for name in sorted(verifier.REQUIRED_DIRS): + info = tarfile.TarInfo(f"{root}/{name}") + info.type = tarfile.DIRTYPE + info.mode = 0o755 + archive.addfile(info) + files = set(executable_files) | set(regular_files) + if profile == "production-release": + files.add("bin/cosmo-model-provision") + for name in sorted(files): + data = b"#!/bin/sh\n" if name in executable_files or name.endswith("provision") else b"V1.5.0\n" + info = tarfile.TarInfo(f"{root}/{name}") + info.size = len(data) + info.mode = 0o755 if name in executable_files or name.endswith("provision") else 0o644 + archive.addfile(info, io.BytesIO(data)) + model_path = f"{root}/resource/models/preset/model.nn" + info = tarfile.TarInfo(model_path) + info.size = len(model) + info.mode = 0o644 + archive.addfile(info, io.BytesIO(model)) + config = json.dumps({"model_type": model_type}).encode() + info = tarfile.TarInfo(f"{root}/resource/models/preset/config.json") + info.size = len(config) + info.mode = 0o644 + archive.addfile(info, io.BytesIO(config)) + digest = hashlib.md5(initial.read_bytes(), usedforsecurity=False).hexdigest() + final = directory / f"{root}-{digest}.tar.gz" + initial.rename(final) + return final + + def test_open_accepts_plain_model(self) -> None: + verifier.verify_package(self.make_package("public-runtime"), "public-runtime") + + def test_protected_accepts_encrypted_model(self) -> None: + verifier.verify_package( + self.make_package("production-release", b"CEMC" + b"encrypted"), + "production-release", + ) + + def test_protected_rejects_plain_vllm_model(self) -> None: + for model_type in ("qwen3vl", "qwen3_5"): + with self.subTest(model_type=model_type): + with self.assertRaises(verifier.PackageAuditError): + verifier.verify_package( + self.make_package("production-release", model_type=model_type), + "production-release", + ) + + def test_channels_reject_each_others_model_format(self) -> None: + with self.assertRaises(verifier.PackageAuditError): + verifier.verify_package( + self.make_package("public-runtime", b"CEMCencrypted"), "public-runtime" + ) + with self.assertRaises(verifier.PackageAuditError): + verifier.verify_package( + self.make_package("production-release", b"plain"), "production-release" + ) + + def test_build_has_no_signed_release_switches(self) -> None: + build_inputs = ( + (REPOSITORY / "CMakeLists.txt").read_text(encoding="utf-8") + + (REPOSITORY / "scripts/build.sh").read_text(encoding="utf-8") + + (REPOSITORY / "docker-compose.sophon.yml").read_text(encoding="utf-8") + ) + for obsolete in ( + "COSMO_RELEASE_PUBLIC_KEY_OBJECT", + "COSMO_REQUIRE_RELEASE_BOOTSTRAP", + "COSMO_LEGACY_MIGRATION_PACKAGE", + "cosmo-release-bootstrap", + ): + self.assertNotIn(obsolete, build_inputs) + + def test_sophon_compose_selects_resources_by_chip_model(self) -> None: + compose = (REPOSITORY / "docker-compose.sophon.yml").read_text( + encoding="utf-8" + ) + entrypoint = (REPOSITORY / "scripts/build_sophon_package.sh").read_text( + encoding="utf-8" + ) + + self.assertIn("scripts/build_sophon_package.sh", compose) + self.assertIn("command: []", compose) + self.assertNotIn("COSMO_SOPHON_RESOURCE_DIR", compose) + self.assertIn('bm1688|cv186x)', entrypoint) + self.assertIn("unsupported Sophon chip", entrypoint) + self.assertIn('./scripts/build.sh -T -c "${chip}"', entrypoint) + + build = (REPOSITORY / "scripts/build.sh").read_text(encoding="utf-8") + self.assertIn('CHIP_MODEL="${CHIP_MODEL:-bm1688}"', build) + self.assertIn('bm1688|cv186x)', build) + self.assertIn('aiboxresource_${CHIP_MODEL}', build) + self.assertIn('-DCOSMO_TARGET_CHIP="${CHIP_MODEL:-unspecified}"', build) + self.assertIn("-c and -m cannot be used together", build) + + def test_container_builds_bound_and_cache_npm_connections(self) -> None: + npmrc = (REPOSITORY / "src/web/.npmrc").read_text(encoding="utf-8") + self.assertIn("registry=https://registry.npmmirror.com/", npmrc) + self.assertIn("maxsockets=1", npmrc) + self.assertIn("prefer-offline=true", npmrc) + self.assertIn("update-notifier=false", npmrc) + + lock = json.loads( + (REPOSITORY / "src/web/package-lock.json").read_text(encoding="utf-8") + ) + locked_packages = [ + metadata + for path, metadata in lock["packages"].items() + if "node_modules/" in path and not metadata.get("link") + ] + self.assertTrue(locked_packages) + self.assertTrue(all(package.get("integrity") for package in locked_packages)) + self.assertTrue( + all( + package.get("resolved", "").startswith( + "https://cdn.npmmirror.com/packages/" + ) + for package in locked_packages + ) + ) + + npm_builder = ( + REPOSITORY / "scripts/build_npm_dependencies.sh" + ).read_text(encoding="utf-8") + self.assertIn("cache add", npm_builder) + self.assertIn("ci --offline", npm_builder) + self.assertIn("package-lock.json has incomplete entries", npm_builder) + + web_cmake = (REPOSITORY / "cmake/web_frontend.cmake").read_text( + encoding="utf-8" + ) + self.assertIn("build_npm_dependencies.sh", web_cmake) + + for compose_name in ("docker-compose.sophon.yml", "docker-compose.rk3576.yml"): + compose = (REPOSITORY / compose_name).read_text(encoding="utf-8") + self.assertIn('NPM_CONFIG_MAXSOCKETS: "${NPM_CONFIG_MAXSOCKETS:-1}"', compose) + self.assertIn("cosmo-npm-cache:/root/.npm", compose) + self.assertIn('NPM_CONFIG_PREFER_OFFLINE: "${NPM_CONFIG_PREFER_OFFLINE:-true}"', compose) + + def test_sophon_chip_selection_preserves_package_output_contract(self) -> None: + entrypoint = (REPOSITORY / "scripts/build_sophon_package.sh").read_text( + encoding="utf-8" + ) + cmake = (REPOSITORY / "CMakeLists.txt").read_text(encoding="utf-8") + + self.assertIn( + 'output_dir="/build_output/${COSMO_MODEL_GUARD_BUILD_PROFILE}/${chip}"', + entrypoint, + ) + self.assertIn("package_artifacts=(build/packages/*.tar.gz)", entrypoint) + self.assertIn( + 'printf \'%s\\n\' "${chip}" > "${output_dir}/TARGET_CHIP"', entrypoint + ) + self.assertIn('sha256sum -- "${package_name}" > SHA256SUMS', entrypoint) + self.assertIn('DESTINATION share/cosmo', cmake) + self.assertIn('"${COSMO_TARGET_CHIP_NORMALIZED}\\n"', cmake) + self.assertIn('set(CPACK_OUTPUT_FILE_PREFIX', cmake) + self.assertIn('scripts/package_md5_rename.sh', cmake) + + def test_sophon_package_entrypoint_behavior(self) -> None: + bash, test_environment = self.find_bash() + if not bash: + self.skipTest("bash is not available") + test_environment.pop("COSMO_MODEL_GUARD_BUILD_PROFILE", None) + + source = (REPOSITORY / "scripts/build_sophon_package.sh").read_text( + encoding="utf-8" + ) + source = source.replace( + 'output_dir="/build_output/${COSMO_MODEL_GUARD_BUILD_PROFILE}/${chip}"', + 'output_dir="$PWD/export/${COSMO_MODEL_GUARD_BUILD_PROFILE}/${chip}"', + ) + + with tempfile.TemporaryDirectory(dir=REPOSITORY) as temporary_directory: + workspace = pathlib.Path(temporary_directory) + scripts = workspace / "scripts" + scripts.mkdir() + (workspace / "build/packages").mkdir(parents=True) + entrypoint = scripts / "build_sophon_package.sh" + entrypoint.write_text(source, encoding="utf-8", newline="\n") + build_stub = scripts / "build.sh" + build_stub.write_text( + "#!/bin/bash\n" + "set -euo pipefail\n" + 'printf "%s\\n" "$*" > build-invocation.txt\n' + "printf package > " + "build/packages/cosmo-V1.1.0-deadbeef.tar.gz\n", + encoding="utf-8", + newline="\n", + ) + entrypoint.chmod(0o755) + build_stub.chmod(0o755) + + def run(*arguments: str) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [bash, "scripts/build_sophon_package.sh", *arguments], + cwd=workspace, + env=test_environment, + check=False, + capture_output=True, + text=True, + encoding="utf-8", + ) + + default_result = run() + self.assertEqual(default_result.returncode, 0, default_result.stderr) + self.assertEqual( + (workspace / "build-invocation.txt").read_text(encoding="utf-8"), + "-T -c bm1688\n", + ) + exported = ( + workspace + / "export/public-runtime/bm1688/cosmo-V1.1.0-deadbeef.tar.gz" + ) + self.assertEqual(exported.read_text(encoding="utf-8"), "package") + self.assertEqual( + (workspace / "export/public-runtime/bm1688/TARGET_CHIP").read_text( + encoding="utf-8" + ), + "bm1688\n", + ) + + explicit_bm1688_result = run("--chip", "bm1688") + self.assertEqual( + explicit_bm1688_result.returncode, 0, explicit_bm1688_result.stderr + ) + self.assertEqual( + (workspace / "build-invocation.txt").read_text(encoding="utf-8"), + "-T -c bm1688\n", + ) + + cv186x_result = run("--chip", "cv186x") + self.assertEqual(cv186x_result.returncode, 0, cv186x_result.stderr) + self.assertEqual( + (workspace / "build-invocation.txt").read_text(encoding="utf-8"), + "-T -c cv186x\n", + ) + cv186x_exported = ( + workspace + / "export/public-runtime/cv186x/cosmo-V1.1.0-deadbeef.tar.gz" + ) + self.assertEqual(cv186x_exported.read_text(encoding="utf-8"), "package") + self.assertEqual( + (workspace / "export/public-runtime/cv186x/TARGET_CHIP").read_text( + encoding="utf-8" + ), + "cv186x\n", + ) + + test_environment["COSMO_MODEL_GUARD_BUILD_PROFILE"] = ( + "production-release" + ) + production_result = run("--chip", "bm1688") + self.assertEqual( + production_result.returncode, 0, production_result.stderr + ) + production_exported = ( + workspace + / "export/production-release/bm1688/cosmo-V1.1.0-deadbeef.tar.gz" + ) + self.assertEqual( + production_exported.read_text(encoding="utf-8"), "package" + ) + + invalid_result = run("--chip", "unsupported-chip") + self.assertNotEqual(invalid_result.returncode, 0) + self.assertIn("unsupported Sophon chip", invalid_result.stderr) + + def test_sophon_build_resolves_chip_resource_directory(self) -> None: + bash, test_environment = self.find_bash() + if not bash: + self.skipTest("bash is not available") + + with tempfile.TemporaryDirectory(dir=REPOSITORY) as temporary_directory: + project_root = pathlib.Path(temporary_directory) + scripts = project_root / "scripts" + scripts.mkdir() + build_script = scripts / "build.sh" + build_script.write_text( + (REPOSITORY / "scripts/build.sh") + .read_text(encoding="utf-8") + .replace( + 'if [ -z "${PROJECT_ROOT_PATH:-}" ]; then', + 'PROJECT_ROOT_PATH="$(cd "$(dirname "$0")/.." && pwd -P)"\n' + 'if [ -z "${PROJECT_ROOT_PATH:-}" ]; then', + ), + encoding="utf-8", + newline="\n", + ) + build_script.chmod(0o755) + for chip in ("bm1688", "cv186x"): + (project_root / f"data/resource/aiboxresource_{chip}").mkdir( + parents=True + ) + + def run(*arguments: str) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [bash, "scripts/build.sh", *arguments], + cwd=project_root, + env=test_environment, + check=False, + capture_output=True, + text=True, + encoding="utf-8", + ) + + default_result = run() + self.assertIn( + "Sophon chip: bm1688", + default_result.stdout, + default_result.stderr, + ) + self.assertIn("aiboxresource_bm1688", default_result.stdout) + + cv186x_result = run("-c", "cv186x") + self.assertIn("Sophon chip: cv186x", cv186x_result.stdout) + self.assertIn("aiboxresource_cv186x", cv186x_result.stdout) + + invalid_result = run("-c", "unsupported-chip") + self.assertNotEqual(invalid_result.returncode, 0) + self.assertIn("unsupported Sophon chip", invalid_result.stderr) + + conflict_result = run("-c", "bm1688", "-m", "resource") + self.assertNotEqual(conflict_result.returncode, 0) + self.assertIn("-c and -m cannot be used together", conflict_result.stderr) + + def test_rk3576_release_builder_requires_pinned_rkllm(self) -> None: + compose = (REPOSITORY / "docker-compose.rk3576.yml").read_text( + encoding="utf-8" + ) + dockerfile = (REPOSITORY / "Dockerfile.rk3576").read_text(encoding="utf-8") + workflow = (REPOSITORY / ".github/workflows/ci-build-rk3576.yml").read_text( + encoding="utf-8" + ) + build = (REPOSITORY / "scripts/build_rknn.sh").read_text(encoding="utf-8") + cmake = (REPOSITORY / "cmake/rkllm.cmake").read_text(encoding="utf-8") + + self.assertIn( + "image: ghcr.io/cosmo-wander-ai/cosmo_edge-build-env_rk3576@sha256:" + "135d25d0baf14e7918726f7efb040a0627926aedd5825f52fab6c1cd208da348", + compose, + ) + self.assertNotIn("\n build:", compose) + self.assertIn("RKLLM_ROOT: /opt/rkllm", compose) + self.assertIn('COSMO_RKLLM_REQUIRED: "ON"', compose) + self.assertIn("docker compose -f docker-compose.rk3576.yml pull", workflow) + self.assertIn("878f9361fd3afa7e167b7079918918f78d2c1c2a", dockerfile) + self.assertIn("install_rkllm_sdk.py", dockerfile) + self.assertIn('lib/librkllmrt.so LICENSE', build) + self.assertIn("-DCOSMO_TARGET_CHIP=rk3576", build) + self.assertIn('-DCOSMO_RKLLM_REQUIRED="${RKLLM_REQUIRED}"', build) + self.assertIn('set(RKLLM_RUNTIME_LICENSE "${COSMO_RKLLM_ROOT}/LICENSE")', cmake) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/test_path_util.cc b/test/test_path_util.cc index efc9c57c2..67a786265 100644 --- a/test/test_path_util.cc +++ b/test/test_path_util.cc @@ -140,6 +140,11 @@ TEST_CASE("PathUtil: GetBaseDir returns test override path", "[path-util]") { REQUIRE(base.find(fix.test_dir) != std::string::npos); } +TEST_CASE("PathUtil: runtime root overrides require absolute paths", "[path-util][deployment]") { + REQUIRE_THROWS_AS(OverrideRootPaths("relative/data", "/tmp/cosmo-app"), std::invalid_argument); + REQUIRE_THROWS_AS(OverrideRootPaths("/tmp/cosmo-data", "relative/app"), std::invalid_argument); +} + TEST_CASE("PathUtil: GetBackupCfgPath returns non-empty", "[path-util]") { TestPathFixture fix; auto backup = GetBackupCfgPath(); diff --git a/test/test_preview_pipeline_metrics.cc b/test/test_preview_pipeline_metrics.cc index e2e45d618..dc4d8cafe 100644 --- a/test/test_preview_pipeline_metrics.cc +++ b/test/test_preview_pipeline_metrics.cc @@ -9,6 +9,16 @@ TEST_CASE("Preview pipeline metrics expose lifecycle and stage timings", "[media metrics.PreviewStarted(true, 25'000'000); metrics.RecordOsdFrame(2'000'000); metrics.RecordPublishedFrame(3'000'000); + metrics.RecordRgaOperation(true, 4'000'000); + metrics.RecordRgaOperation(false, 5'000'000); + metrics.RecordMppEncode(true, 6'000'000); + metrics.RecordMppEncode(false, 7'000'000); + metrics.RecordMppDecode(true, 8'000'000); + metrics.RecordMppDecode(false, 9'000'000); + metrics.RecordMppDecodeFallback(); + metrics.RecordMppCopyOut(true, 11'000'000); + metrics.RecordMppCopyOut(false, 12'000'000); + metrics.RecordMppEarlyDrop(); metrics.PreviewFailed(); auto during = metrics.Snapshot(); @@ -25,6 +35,20 @@ TEST_CASE("Preview pipeline metrics expose lifecycle and stage timings", "[media CHECK(during.first_frames == 2); CHECK(during.first_frame_nanoseconds == 35'000'000); CHECK(during.first_frame_max_nanoseconds == 25'000'000); + CHECK(during.rga_frames == 1); + CHECK(during.rga_nanoseconds == 4'000'000); + CHECK(during.rga_failures == 1); + CHECK(during.mpp_encoded_frames == 1); + CHECK(during.mpp_encode_nanoseconds == 6'000'000); + CHECK(during.mpp_encode_failures == 1); + CHECK(during.mpp_decoded_frames == 1); + CHECK(during.mpp_decode_nanoseconds == 8'000'000); + CHECK(during.mpp_decode_failures == 1); + CHECK(during.mpp_decode_fallbacks == 1); + CHECK(during.mpp_copy_out_frames == 1); + CHECK(during.mpp_copy_out_nanoseconds == 11'000'000); + CHECK(during.mpp_copy_out_failures == 1); + CHECK(during.mpp_early_dropped_frames == 1); metrics.PreviewStopped(false); metrics.PreviewStopped(true); diff --git a/test/test_rknn_fast_preprocess.cc b/test/test_rknn_fast_preprocess.cc new file mode 100644 index 000000000..1ac4d22a6 --- /dev/null +++ b/test/test_rknn_fast_preprocess.cc @@ -0,0 +1,607 @@ +#include "catch_amalgamated.hpp" + +#if defined(COSMO_NN_USE_RKNN_BACKEND) && defined(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + +#include <algorithm> +#include <array> +#include <cstdlib> +#include <optional> +#include <string> +#include <vector> + +#include "nn/core/inference_pipeline_metrics.h" +#include "nn/core/shared_resource.h" +#include "nn/device/rknn/rknn_net_node.h" +#include "nn/device/rknn/rknn_preprocess_node.h" +#include "nn/utils/op.h" + +namespace { + +class ScopedEnvironment { +public: + ScopedEnvironment(const char* name, const char* value) : name_(name) { + if (const char* current = std::getenv(name)) + previous_ = current; + setenv(name, value, 1); + } + ~ScopedEnvironment() { + if (previous_) + setenv(name_.c_str(), previous_->c_str(), 1); + else + unsetenv(name_.c_str()); + } + +private: + std::string name_; + std::optional<std::string> previous_; +}; + +class StubBoundInputProvider final : public cosmo::nn::RknnBoundInputProvider { +public: + bool EnsureRgaBoundInput(int /*height*/, int /*width*/, std::string& reason) override { + reason.clear(); + return true; + } +}; + +cosmo::nn::BlobDesc PackedImageDesc(int height, int width, cosmo::nn::ImageFormat format, + cosmo::nn::DataType type = cosmo::nn::DATA_TYPE_UINT8) { + cosmo::nn::BlobDesc desc; + desc.device_type = cosmo::nn::DEVICE_NAIVE; + desc.data_type = type; + desc.data_format = cosmo::nn::DATA_FORMAT_NHWC; + desc.image_format = format; + desc.dims = {1, height, width, 3}; + return desc; +} + +} // namespace + +TEST_CASE("RKNN detector fast preprocessing contracts are exact", "[nn][rknn][fast-preprocess]") { + using namespace cosmo::nn; + CHECK(IsRknnDetectorResizeContract(640, 640, 1, {114, 114, 114})); + CHECK_FALSE(IsRknnDetectorResizeContract(640, 640, 0, {114, 114, 114})); + CHECK_FALSE(IsRknnDetectorResizeContract(224, 224, 1, {114, 114, 114})); + CHECK(IsRknnNativeNormalizeContract({0.0f, 0.0f, 0.0f}, {}, 0.00392157f, {1, 640, 640, 3})); + CHECK_FALSE(IsRknnNativeNormalizeContract({1.0f, 0.0f, 0.0f}, {}, 0.00392157f, {1, 640, 640, 3})); + CHECK_FALSE(IsRknnNativeNormalizeContract({0.0f, 0.0f, 0.0f}, {}, 0.00392157f, {1, 224, 224, 3})); + + const std::array<uint8_t, 6> rgb{0, 127, 255, 255, 1, 128}; + std::array<int8_t, 6> native{}; + MapPackedU8ToNativeInt8(rgb.data(), native.data(), 2, false); + CHECK((native == std::array<int8_t, 6>{-128, -1, 127, 127, -127, 0})); + MapPackedU8ToNativeInt8(rgb.data(), native.data(), 2, true); + CHECK((native == std::array<int8_t, 6>{127, -1, -128, 0, -127, 127})); +} + +TEST_CASE("RKNN native input contract requires the model quantization identity", + "[nn][rknn][fast-preprocess]") { + using namespace cosmo::nn; + rknn_tensor_attr attr{}; + attr.n_dims = 4; + attr.dims[0] = 1; + attr.dims[1] = 640; + attr.dims[2] = 640; + attr.dims[3] = 3; + attr.fmt = RKNN_TENSOR_NHWC; + attr.type = RKNN_TENSOR_INT8; + attr.qnt_type = RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC; + attr.zp = -128; + attr.scale = 0.00392157f; + const auto desc = PackedImageDesc(640, 640, IMAGE_RGB, DATA_TYPE_INT8); + CHECK(IsRknnNativeInt8InputCompatible(attr, desc)); + attr.zp = 0; + CHECK_FALSE(IsRknnNativeInt8InputCompatible(attr, desc)); +} + +TEST_CASE("RKNN bound input validates native stride and copies packed rows", "[nn][rknn][bound-input]") { + using namespace cosmo::nn; + rknn_tensor_attr attr{}; + attr.n_dims = 4; + attr.dims[0] = 1; + attr.dims[1] = 2; + attr.dims[2] = 2; + attr.dims[3] = 3; + attr.fmt = RKNN_TENSOR_NHWC; + attr.type = RKNN_TENSOR_INT8; + attr.qnt_type = RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC; + attr.zp = -128; + attr.scale = 0.00392157f; + attr.w_stride = 4; + attr.size = 12; + attr.size_with_stride = 24; + const auto desc = PackedImageDesc(2, 2, IMAGE_RGB, DATA_TYPE_INT8); + std::string reason; + CHECK(IsRknnBoundInt8InputCompatible(attr, desc, &reason)); + CHECK(reason.empty()); + + const std::array<int8_t, 12> source{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + std::array<int8_t, 24> destination{}; + destination.fill(-1); + REQUIRE(CopyRknnPackedInt8Input(source.data(), source.size(), destination.data(), destination.size(), 2, + 2, 3, 4, &reason)); + CHECK(std::equal(source.begin(), source.begin() + 6, destination.begin())); + CHECK(std::equal(source.begin() + 6, source.end(), destination.begin() + 12)); + CHECK(std::all_of(destination.begin() + 6, destination.begin() + 12, + [](int8_t value) { return value == -1; })); + + std::array<int8_t, 12> compact{}; + REQUIRE(CopyRknnPackedInt8Input(source.data(), source.size(), compact.data(), compact.size(), 2, 2, 3, 0, + &reason)); + CHECK(compact == source); + + attr.w_stride = 1; + CHECK_FALSE(IsRknnBoundInt8InputCompatible(attr, desc, &reason)); + CHECK(reason.find("stride") != std::string::npos); + CHECK_FALSE( + CopyRknnPackedInt8Input(source.data(), source.size(), destination.data(), 8, 2, 2, 3, 2, &reason)); + CHECK(reason.find("smaller") != std::string::npos); +} + +TEST_CASE("RKNN RGA bound input validates the native tensor and DMA-BUF target stride", + "[nn][rknn][bound-input][rga]") { + using namespace cosmo::nn; + CHECK(IsRknnRgbUint8InputContract(kRknnRgbUint8InputContract)); + CHECK_FALSE(IsRknnRgbUint8InputContract("host-normalized-int8")); + + rknn_tensor_attr attr{}; + attr.n_dims = 4; + attr.dims[0] = 1; + attr.dims[1] = 2; + attr.dims[2] = 2; + attr.dims[3] = 3; + attr.fmt = RKNN_TENSOR_NHWC; + attr.type = RKNN_TENSOR_INT8; + attr.qnt_type = RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC; + attr.zp = -128; + attr.scale = 0.00392157f; + attr.w_stride = 4; + attr.size = 12; + attr.size_with_stride = 24; + std::string reason; + CHECK(IsRknnRgaBoundInputCompatible(attr, 2, 2, &reason)); + + rknn_tensor_attr uint8_attr{}; + REQUIRE(ConfigureRknnRgaUint8InputAttr(attr, 2, 2, uint8_attr, &reason)); + CHECK(uint8_attr.type == RKNN_TENSOR_UINT8); + CHECK(uint8_attr.fmt == RKNN_TENSOR_NHWC); + CHECK(uint8_attr.pass_through == 0); + CHECK(uint8_attr.qnt_type == attr.qnt_type); + CHECK(uint8_attr.zp == attr.zp); + CHECK(uint8_attr.scale == attr.scale); + CHECK(uint8_attr.size_with_stride == attr.size_with_stride); + CHECK(reason.empty()); + + auto incompatible = attr; + incompatible.zp = 0; + CHECK_FALSE(ConfigureRknnRgaUint8InputAttr(incompatible, 2, 2, uint8_attr, &reason)); + CHECK(reason.find("quantization") != std::string::npos); + + StubBoundInputProvider provider; + uint8_t storage[24]{}; + RknnBoundInputTarget target; + target.owner = &provider; + target.virtual_address = storage; + target.fd = 3; + target.bytes = sizeof(storage); + target.height = 2; + target.width = 2; + target.channels = 3; + target.width_stride = 4; + CHECK(target.Matches(2, 2)); + target.bytes = 23; + CHECK_FALSE(target.Matches(2, 2)); +} + +TEST_CASE("RKNN RGA bound input requantizes UINT8 pixels in place without touching stride padding", + "[nn][rknn][bound-input][rga]") { + using namespace cosmo::nn; + std::array<uint8_t, 24> pixels{}; + pixels.fill(99); + const std::array<uint8_t, 12> packed{0, 1, 127, 128, 254, 255, 255, 128, 127, 126, 1, 0}; + std::copy(packed.begin(), packed.begin() + 6, pixels.begin()); + std::copy(packed.begin() + 6, packed.end(), pixels.begin() + 12); + std::string reason; + REQUIRE(RequantizeRknnPackedUint8ToInt8InPlace(pixels.data(), pixels.size(), 2, 2, 3, 4, &reason)); + CHECK((std::array<uint8_t, 6>{pixels[0], pixels[1], pixels[2], pixels[3], pixels[4], pixels[5]}) == + std::array<uint8_t, 6>{128, 129, 255, 0, 126, 127}); + CHECK((std::array<uint8_t, 6>{pixels[12], pixels[13], pixels[14], pixels[15], pixels[16], pixels[17]}) == + std::array<uint8_t, 6>{127, 0, 255, 254, 129, 128}); + CHECK(std::all_of(pixels.begin() + 6, pixels.begin() + 12, [](uint8_t value) { return value == 99; })); + CHECK(std::all_of(pixels.begin() + 18, pixels.end(), [](uint8_t value) { return value == 99; })); + CHECK(reason.empty()); + + CHECK_FALSE(RequantizeRknnPackedUint8ToInt8InPlace(pixels.data(), 8, 2, 2, 3, 2, &reason)); + CHECK(reason.find("smaller") != std::string::npos); +} + +TEST_CASE("RKNN UINT8 model contract restores raw pixels for FP16 runtime input", + "[nn][rknn][input-contract]") { + using namespace cosmo::nn; + const std::array<int8_t, 12> native{-128, -127, -1, 0, 126, 127, 127, 0, -1, -2, -127, -128}; + std::array<uint8_t, 24> restored{}; + restored.fill(99); + std::string reason; + REQUIRE(CopyRknnPackedNativeInt8ToUint8(native.data(), native.size(), restored.data(), restored.size(), 2, + 2, 3, 4, &reason)); + CHECK((std::array<uint8_t, 6>{restored[0], restored[1], restored[2], restored[3], restored[4], + restored[5]}) == std::array<uint8_t, 6>{0, 1, 127, 128, 254, 255}); + CHECK((std::array<uint8_t, 6>{restored[12], restored[13], restored[14], restored[15], restored[16], + restored[17]}) == std::array<uint8_t, 6>{255, 128, 127, 126, 1, 0}); + CHECK( + std::all_of(restored.begin() + 6, restored.begin() + 12, [](uint8_t value) { return value == 99; })); + CHECK(std::all_of(restored.begin() + 18, restored.end(), [](uint8_t value) { return value == 99; })); + CHECK(reason.empty()); + + const std::array<float, 6> normalized{0.0f, 1.0f / 255.0f, 0.5f, 1.0f, -0.1f, 1.1f}; + std::array<uint8_t, 6> pixels{}; + REQUIRE(ConvertRknnNormalizedFloatToUint8(normalized.data(), normalized.size(), pixels.data(), + pixels.size(), &reason)); + CHECK((pixels == std::array<uint8_t, 6>{0, 1, 128, 255, 0, 255})); + CHECK(reason.empty()); +} + +TEST_CASE("RKNN bound input switch defaults on and supports explicit rollback", "[nn][rknn][bound-input]") { + using namespace cosmo::nn; + { + ScopedEnvironment enabled("COSMO_RKNN_BOUND_INPUT", "1"); + CHECK(RknnBoundInputEnabled()); + } + { + ScopedEnvironment disabled("COSMO_RKNN_BOUND_INPUT", "0"); + CHECK_FALSE(RknnBoundInputEnabled()); + } +} + +TEST_CASE("RKNN core scheduling maps explicit and split modes deterministically", + "[nn][rknn][core-scheduling]") { + using namespace cosmo::nn; + bool valid = false; + CHECK(ParseRknnCoreMode(" auto ", &valid) == RknnCoreMode::Auto); + CHECK(valid); + CHECK(ParseRknnCoreMode("CORE0", &valid) == RknnCoreMode::Core0); + CHECK(valid); + CHECK(ParseRknnCoreMode("core_1", &valid) == RknnCoreMode::Core1); + CHECK(valid); + CHECK(ParseRknnCoreMode("dual", &valid) == RknnCoreMode::Core01); + CHECK(valid); + CHECK(ParseRknnCoreMode("split", &valid) == RknnCoreMode::Split); + CHECK(valid); + CHECK(ParseRknnCoreMode("unsupported", &valid) == RknnCoreMode::Auto); + CHECK_FALSE(valid); + + CHECK(ResolveRknnCoreMask(RknnCoreMode::Auto, 7) == RKNN_NPU_CORE_AUTO); + CHECK(ResolveRknnCoreMask(RknnCoreMode::Core0, 7) == RKNN_NPU_CORE_0); + CHECK(ResolveRknnCoreMask(RknnCoreMode::Core1, 7) == RKNN_NPU_CORE_1); + CHECK(ResolveRknnCoreMask(RknnCoreMode::Core01, 7) == RKNN_NPU_CORE_0_1); + CHECK(ResolveRknnCoreMask(RknnCoreMode::Split, 0) == RKNN_NPU_CORE_0); + CHECK(ResolveRknnCoreMask(RknnCoreMode::Split, 1) == RKNN_NPU_CORE_1); + CHECK(ResolveRknnCoreMask(RknnCoreMode::Split, 2) == RKNN_NPU_CORE_0); + CHECK(std::string(RknnCoreModeName(RknnCoreMode::Core01)) == "core0_1"); +} + +TEST_CASE("RKNN MPP DMA-BUF switch defaults on and supports explicit rollback", "[nn][rknn][mpp-dmabuf]") { + using namespace cosmo::nn; + { + ScopedEnvironment enabled("COSMO_RKNN_MPP_DMABUF", "1"); + CHECK(RknnMppDmaBufEnabled()); + } + { + ScopedEnvironment disabled("COSMO_RKNN_MPP_DMABUF", "0"); + CHECK_FALSE(RknnMppDmaBufEnabled()); + } + { + ScopedEnvironment forced("COSMO_RKNN_MPP_DMABUF_FORCE_FAIL", "1"); + CHECK(RknnForceMppDmaBufFailure()); + } + + BlobHandle handle; + handle.native_image.fd = 7; + handle.native_image.bytes = 1920 * 1088 * 3 / 2; + handle.native_image.width = 1920; + handle.native_image.height = 1080; + handle.native_image.width_stride = 1920; + handle.native_image.height_stride = 1088; + handle.native_image.format = IMAGE_NV12; + CHECK(handle.native_image.Valid()); + handle.native_image.width_stride = 1919; + CHECK_FALSE(handle.native_image.Valid()); +} + +TEST_CASE("RKNN native output capability excludes FP16 and malformed YOLOv8 heads", + "[nn][rknn][fast-output][fp16]") { + using namespace cosmo::nn; + const std::array<std::array<uint32_t, 4>, 6> shapes{{ + {{1, 64, 80, 80}}, + {{1, 80, 80, 80}}, + {{1, 64, 40, 40}}, + {{1, 80, 40, 40}}, + {{1, 64, 20, 20}}, + {{1, 80, 20, 20}}, + }}; + std::vector<rknn_tensor_attr> attrs(shapes.size()); + for (size_t index = 0; index < attrs.size(); ++index) { + auto& attr = attrs[index]; + attr.index = static_cast<uint32_t>(index); + attr.n_dims = 4; + attr.fmt = RKNN_TENSOR_NCHW; + attr.type = RKNN_TENSOR_INT8; + attr.qnt_type = RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC; + attr.zp = index % 2 == 0 ? -61 : 114; + attr.scale = index % 2 == 0 ? 0.11488f : 0.113557f; + size_t count = 1; + for (size_t dim = 0; dim < shapes[index].size(); ++dim) { + attr.dims[dim] = shapes[index][dim]; + count *= shapes[index][dim]; + } + attr.n_elems = static_cast<uint32_t>(count); + attr.size = static_cast<uint32_t>(count); + } + + std::string reason; + CHECK(IsRknnNativeYolov8OutputCompatible(attrs, &reason)); + CHECK(reason.empty()); + + auto fp16 = attrs; + fp16[0].type = RKNN_TENSOR_FLOAT16; + fp16[0].size *= 2; + CHECK_FALSE(IsRknnNativeYolov8OutputCompatible(fp16, &reason)); + CHECK(reason.find("FP16") != std::string::npos); + + auto wrong_format = attrs; + wrong_format[0].fmt = RKNN_TENSOR_NHWC; + CHECK_FALSE(IsRknnNativeYolov8OutputCompatible(wrong_format)); + auto wrong_size = attrs; + wrong_size[0].size += 1; + CHECK_FALSE(IsRknnNativeYolov8OutputCompatible(wrong_size)); + auto wrong_quantization = attrs; + wrong_quantization[0].scale = 0.0f; + CHECK_FALSE(IsRknnNativeYolov8OutputCompatible(wrong_quantization)); + + const std::array<std::array<uint32_t, 4>, 9> score_sum_shapes{{ + {{1, 64, 80, 80}}, + {{1, 80, 80, 80}}, + {{1, 1, 80, 80}}, + {{1, 64, 40, 40}}, + {{1, 80, 40, 40}}, + {{1, 1, 40, 40}}, + {{1, 64, 20, 20}}, + {{1, 80, 20, 20}}, + {{1, 1, 20, 20}}, + }}; + std::vector<rknn_tensor_attr> score_sum_attrs(score_sum_shapes.size()); + for (size_t index = 0; index < score_sum_attrs.size(); ++index) { + auto& attr = score_sum_attrs[index]; + attr.index = static_cast<uint32_t>(index); + attr.n_dims = 4; + attr.fmt = RKNN_TENSOR_NCHW; + attr.type = RKNN_TENSOR_INT8; + attr.qnt_type = RKNN_TENSOR_QNT_AFFINE_ASYMMETRIC; + attr.zp = 0; + attr.scale = index % 3 == 0 ? 0.1f : 0.01f; + size_t count = 1; + for (size_t dim = 0; dim < score_sum_shapes[index].size(); ++dim) { + attr.dims[dim] = score_sum_shapes[index][dim]; + count *= score_sum_shapes[index][dim]; + } + attr.n_elems = static_cast<uint32_t>(count); + attr.size = static_cast<uint32_t>(count); + } + CHECK(IsRknnNativeYolov8OutputCompatible(score_sum_attrs, &reason)); + auto score_sum_fp16 = score_sum_attrs; + score_sum_fp16[4].type = RKNN_TENSOR_FLOAT16; + score_sum_fp16[4].size *= 2; + CHECK_FALSE(IsRknnNativeYolov8OutputCompatible(score_sum_fp16, &reason)); + CHECK(reason.find("FP16") != std::string::npos); +} + +TEST_CASE("RKNN native output switch defaults on and supports explicit rollback", "[nn][rknn][fast-output]") { + using namespace cosmo::nn; + { + ScopedEnvironment enabled("COSMO_RKNN_FAST_OUTPUT", "1"); + CHECK(RknnFastOutputEnabled()); + } + { + ScopedEnvironment disabled("COSMO_RKNN_FAST_OUTPUT", "0"); + CHECK_FALSE(RknnFastOutputEnabled()); + } + { + ScopedEnvironment enabled("COSMO_RKNN_DIRECT_CANDIDATES", "1"); + CHECK(RknnDirectCandidatesEnabled()); + } + { + ScopedEnvironment disabled("COSMO_RKNN_DIRECT_CANDIDATES", "0"); + CHECK_FALSE(RknnDirectCandidatesEnabled()); + } +} + +TEST_CASE("RKNN classifier-sized normalization keeps the legacy float layout", + "[nn][rknn][fast-preprocess]") { + using namespace cosmo::nn; + Normalize normalize; + normalize.mean = {0.0f, 0.0f, 0.0f}; + normalize.scale = 0.00392157f; + normalize.is_bgr = false; + SharedResource resource; + RknnNormalizeNode node; + node.SetSharedResource(&resource); + node.LoadParam(&normalize); + REQUIRE(bool(node.InferTopShapesWithBottoms({{1, 224, 224, 3}}, {DATA_TYPE_UINT8}))); + CHECK(node.GetTopBlobDataTypes().front() == DATA_TYPE_FLOAT); + CHECK((node.GetTopBlobShapes().front() == DimsVector{1, 3, 224, 224})); + + auto bottom_desc = PackedImageDesc(224, 224, IMAGE_BGR); + bottom_desc.data_format = DATA_FORMAT_NCHW; // Legacy crop/resize nodes leave this metadata unset. + auto bottom = std::make_shared<Blob>(bottom_desc, true); + BlobDesc top_desc; + top_desc.device_type = DEVICE_NAIVE; + top_desc.data_type = DATA_TYPE_FLOAT; + top_desc.dims = {1, 3, 224, 224}; + auto top = std::make_shared<Blob>(top_desc, true); + auto* input = static_cast<uint8_t*>(bottom->GetHandle().base); + for (size_t pixel = 0; pixel < static_cast<size_t>(224) * 224; ++pixel) { + input[pixel * 3] = 10; + input[pixel * 3 + 1] = 20; + input[pixel * 3 + 2] = 30; + } + std::vector<std::shared_ptr<Blob>> bottoms{bottom}; + std::vector<std::shared_ptr<Blob>> tops{top}; + REQUIRE(bool(node.Forward(bottoms, tops))); + const auto* output = static_cast<const float*>(top->GetHandle().base); + CHECK(output[0] == Catch::Approx(30.0f * 0.00392157f)); + CHECK(output[224 * 224] == Catch::Approx(20.0f * 0.00392157f)); + CHECK(output[2 * 224 * 224] == Catch::Approx(10.0f * 0.00392157f)); +} + +TEST_CASE("RKNN normalize bypasses host mapping for an RGA-bound frame", "[nn][rknn][bound-input][rga]") { + using namespace cosmo::nn; + Normalize normalize; + normalize.mean = {0.0f, 0.0f, 0.0f}; + normalize.scale = 0.00392157f; + normalize.is_bgr = false; + SharedResource resource; + StubBoundInputProvider provider; + resource.rknn_bound_input_provider = &provider; + RknnNormalizeNode node; + node.SetSharedResource(&resource); + node.LoadParam(&normalize); + REQUIRE(bool(node.InferTopShapesWithBottoms({{1, 640, 640, 3}}, {DATA_TYPE_UINT8}))); + + auto bottom = std::make_shared<Blob>(PackedImageDesc(640, 640, IMAGE_RGB), true); + BlobDesc top_desc; + top_desc.device_type = DEVICE_NAIVE; + top_desc.data_type = node.GetTopBlobDataTypes().front(); + top_desc.data_format = DATA_FORMAT_NHWC; + top_desc.dims = node.GetTopBlobShapes().front(); + auto top = std::make_shared<Blob>(top_desc, true); + auto* output = static_cast<int8_t*>(top->GetHandle().base); + const size_t bytes = static_cast<size_t>(640) * 640 * 3; + std::fill(output, output + bytes, static_cast<int8_t>(42)); + + auto& target = resource.rknn_bound_input_target; + target.owner = &provider; + target.virtual_address = bottom->GetHandle().base; + target.fd = 3; + target.bytes = bytes; + target.height = 640; + target.width = 640; + target.channels = 3; + target.width_stride = 640; + target.generation = 1; + target.frame_ready = true; + + const auto before = GetInferencePipelineMetrics().Snapshot(); + std::vector<std::shared_ptr<Blob>> bottoms{bottom}; + std::vector<std::shared_ptr<Blob>> tops{top}; + REQUIRE(bool(node.Forward(bottoms, tops))); + const auto after = GetInferencePipelineMetrics().Snapshot(); + CHECK(after.rknn_rga_bound_input_normalize_bypasses == + before.rknn_rga_bound_input_normalize_bypasses + 1); + CHECK(after.rknn_native_input_map_calls == before.rknn_native_input_map_calls); + CHECK(target.frame_ready); + CHECK(output[0] == 42); + CHECK(output[bytes - 1] == 42); +} + +TEST_CASE("RKNN RGA preprocessing performs centered RGB letterbox on host buffers", + "[nn][rknn][rga][fast-preprocess]") { + using namespace cosmo::nn; + ScopedEnvironment enable("COSMO_RKNN_FAST_PREPROCESS", "1"); + ScopedEnvironment no_force_fail("COSMO_RKNN_RGA_FORCE_FAIL", "0"); + + Resize resize; + resize.dsize = {640, 640}; + resize.gravity = 1; + resize.color = {114, 114, 114}; + SharedResource resource; + RknnResizeNode node; + node.SetSharedResource(&resource); + node.LoadParam(&resize); + REQUIRE(bool(node.InferTopShapes())); + + auto bottom = std::make_shared<Blob>(PackedImageDesc(720, 1280, IMAGE_BGR), true); + BlobDesc top_desc; + top_desc.device_type = DEVICE_NAIVE; + top_desc.data_type = node.GetTopBlobDataTypes().front(); + top_desc.dims = node.GetTopBlobShapes().front(); + auto top = std::make_shared<Blob>(top_desc, true); + auto* source = static_cast<uint8_t*>(bottom->GetHandle().base); + for (size_t pixel = 0; pixel < static_cast<size_t>(720) * 1280; ++pixel) { + source[pixel * 3] = 10; + source[pixel * 3 + 1] = 20; + source[pixel * 3 + 2] = 30; + } + + const auto before = GetInferencePipelineMetrics().Snapshot(); + std::vector<std::shared_ptr<Blob>> bottoms{bottom}; + std::vector<std::shared_ptr<Blob>> tops{top}; + REQUIRE(bool(node.Forward(bottoms, tops))); + const auto after = GetInferencePipelineMetrics().Snapshot(); + CHECK(after.rknn_rga_fill_calls == before.rknn_rga_fill_calls + 1); + CHECK(after.rknn_rga_resize_color_calls == before.rknn_rga_resize_color_calls + 1); + CHECK(after.rknn_rga_failures == before.rknn_rga_failures); + CHECK(after.rknn_cpu_resize_fallback_calls == before.rknn_cpu_resize_fallback_calls); + CHECK(top->GetBlobDesc().image_format == IMAGE_RGB); + CHECK(top->GetBlobDesc().data_format == DATA_FORMAT_NHWC); + const auto* output = static_cast<const uint8_t*>(top->GetHandle().base); + CHECK(output[(10 * 640 + 320) * 3] == 114); + const size_t center = (static_cast<size_t>(320) * 640 + 320) * 3; + CHECK(output[center] == 30); + CHECK(output[center + 1] == 20); + CHECK(output[center + 2] == 10); +} + +TEST_CASE("RKNN RGA failure falls back once to CPU while preserving native input mapping", + "[nn][rknn][rga][fast-preprocess]") { + using namespace cosmo::nn; + ScopedEnvironment force_fail("COSMO_RKNN_RGA_FORCE_FAIL", "1"); + Resize resize; + resize.dsize = {640, 640}; + resize.gravity = 1; + resize.color = {114, 114, 114}; + SharedResource resource; + RknnResizeNode resize_node; + resize_node.SetSharedResource(&resource); + resize_node.LoadParam(&resize); + REQUIRE(bool(resize_node.InferTopShapes())); + + auto bottom = std::make_shared<Blob>(PackedImageDesc(320, 640, IMAGE_BGR), true); + BlobDesc resized_desc; + resized_desc.device_type = DEVICE_NAIVE; + resized_desc.data_type = resize_node.GetTopBlobDataTypes().front(); + resized_desc.dims = resize_node.GetTopBlobShapes().front(); + auto resized = std::make_shared<Blob>(resized_desc, true); + auto* source = static_cast<uint8_t*>(bottom->GetHandle().base); + std::fill(source, source + static_cast<size_t>(320) * 640 * 3, 128); + + const auto before = GetInferencePipelineMetrics().Snapshot(); + std::vector<std::shared_ptr<Blob>> resize_bottoms{bottom}; + std::vector<std::shared_ptr<Blob>> resize_tops{resized}; + REQUIRE(bool(resize_node.Forward(resize_bottoms, resize_tops))); + const auto resized_metrics = GetInferencePipelineMetrics().Snapshot(); + CHECK(resized_metrics.rknn_rga_failures == before.rknn_rga_failures + 1); + CHECK(resized_metrics.rknn_cpu_resize_fallback_calls == before.rknn_cpu_resize_fallback_calls + 1); + + Normalize normalize; + normalize.mean = {0.0f, 0.0f, 0.0f}; + normalize.scale = 0.00392157f; + normalize.is_bgr = false; + RknnNormalizeNode normalize_node; + normalize_node.SetSharedResource(&resource); + normalize_node.LoadParam(&normalize); + REQUIRE(bool(normalize_node.InferTopShapesWithBottoms({resized->GetBlobDesc().dims}, + {resized->GetBlobDesc().data_type}))); + BlobDesc native_desc; + native_desc.device_type = DEVICE_NAIVE; + native_desc.data_type = normalize_node.GetTopBlobDataTypes().front(); + native_desc.dims = normalize_node.GetTopBlobShapes().front(); + auto native = std::make_shared<Blob>(native_desc, true); + std::vector<std::shared_ptr<Blob>> normalize_bottoms{resized}; + std::vector<std::shared_ptr<Blob>> normalize_tops{native}; + REQUIRE(bool(normalize_node.Forward(normalize_bottoms, normalize_tops))); + CHECK(native->GetBlobDesc().data_type == DATA_TYPE_INT8); + CHECK(native->GetBlobDesc().data_format == DATA_FORMAT_NHWC); + CHECK(static_cast<const int8_t*>(native->GetHandle().base)[(320 * 640 + 320) * 3] == 0); +} + +#endif diff --git a/test/test_rknn_yolov8_adapter.cc b/test/test_rknn_yolov8_adapter.cc new file mode 100644 index 000000000..13ce1ed40 --- /dev/null +++ b/test/test_rknn_yolov8_adapter.cc @@ -0,0 +1,384 @@ +#include "catch_amalgamated.hpp" + +#ifdef COSMO_NN_USE_RKNN_BACKEND + +#include <algorithm> +#include <cstdint> +#include <cstring> +#include <memory> +#include <string> +#include <vector> + +#include "nn/core/blob.h" +#include "nn/core/shared_resource.h" +#include "nn/device/rknn/rknn_yolov8_adapter.h" +#include "nn/node/yolov8_decode_node.h" +#include "nn/utils/op.h" + +TEST_CASE("RKNN YOLOv8 adapter reconstructs the logical tensor", "[nn][rknn][yolov8]") { + using namespace cosmo::nn; + + const std::vector<std::vector<int>> shapes{ + {1, 64, 4, 4}, {1, 3, 4, 4}, {1, 64, 2, 2}, {1, 3, 2, 2}, {1, 64, 1, 1}, {1, 3, 1, 1}, + }; + RknnYolov8Layout layout; + std::string error; + REQUIRE(DetectRknnYolov8Layout(shapes, layout, error)); + REQUIRE(layout.logical_shape == std::vector<int>{1, 7, 21}); + + std::vector<std::vector<float>> values; + std::vector<RknnYolov8Head> heads; + for (const auto& shape : shapes) { + const size_t count = static_cast<size_t>(shape[1] * shape[2] * shape[3]); + values.emplace_back(count, 0.0f); + heads.push_back({values.back().data(), values.back().size(), shape}); + } + + std::vector<float> output(static_cast<size_t>(7 * 21)); + REQUIRE(ReconstructRknnYolov8(heads, 32, 32, output.data(), output.size(), error)); + CHECK(output[0] == Catch::Approx(4.0f)); + CHECK(output[21] == Catch::Approx(4.0f)); + CHECK(output[42] == Catch::Approx(120.0f)); + CHECK(output[63] == Catch::Approx(120.0f)); + CHECK(output[84] == Catch::Approx(0.5f)); + CHECK(output[105] == Catch::Approx(0.5f)); + CHECK(output[126] == Catch::Approx(0.5f)); + CHECK(output[16] == Catch::Approx(8.0f)); + CHECK(output[20] == Catch::Approx(16.0f)); +} + +TEST_CASE("RKNN YOLOv8 adapter rejects malformed head order", "[nn][rknn][yolov8]") { + using namespace cosmo::nn; + const std::vector<std::vector<int>> shapes{ + {1, 64, 4, 4}, {1, 3, 4, 4}, {1, 64, 4, 4}, {1, 3, 4, 4}, {1, 64, 1, 1}, {1, 3, 1, 1}, + }; + RknnYolov8Layout layout; + std::string error; + CHECK_FALSE(DetectRknnYolov8Layout(shapes, layout, error)); + CHECK_FALSE(error.empty()); + + RknnOutputAdapterContract fallback; + REQUIRE(ResolveRknnOutputAdapter(shapes, fallback, error)); + CHECK(fallback.kind == RknnOutputAdapterKind::GenericTensorV1); + CHECK(fallback.logical_shape.empty()); +} + +TEST_CASE("RKNN output adapter registry separates implemented tensor contracts", + "[nn][rknn][output-adapter]") { + using namespace cosmo::nn; + + const auto& registry = RknnOutputAdapterRegistry(); + REQUIRE(registry.size() == 7); + CHECK(std::string(RknnOutputAdapterName(RknnOutputAdapterKind::GenericTensorV1)) == "generic_tensor_v1"); + CHECK(std::string(RknnOutputAdapterName(RknnOutputAdapterKind::YoloDfl6HeadV1)) == "yolo_dfl_6head_v1"); + CHECK(std::string(RknnOutputAdapterName(RknnOutputAdapterKind::YoloDfl9HeadScoreSumV1)) == + "yolo_dfl_9head_score_sum_v1"); + + const auto pose = + std::find_if(registry.begin(), registry.end(), [](const RknnOutputAdapterRegistryEntry& entry) { + return entry.kind == RknnOutputAdapterKind::YoloPoseV1; + }); + REQUIRE(pose != registry.end()); + CHECK_FALSE(pose->implemented); + CHECK_FALSE(pose->auto_detect); + + const std::vector<std::vector<int>> generic_shapes{{1, 2}, {1, 3}}; + RknnOutputAdapterContract contract; + std::string error; + REQUIRE(ResolveRknnOutputAdapter(generic_shapes, contract, error)); + CHECK(contract.kind == RknnOutputAdapterKind::GenericTensorV1); +} + +TEST_CASE("RKNN YOLOv8 nine-head contract preserves probability scores for FP16 fallback", + "[nn][rknn][yolov8][score-sum][fp16]") { + using namespace cosmo::nn; + + const std::vector<std::vector<int>> shapes{ + {1, 64, 4, 4}, {1, 3, 4, 4}, {1, 1, 4, 4}, {1, 64, 2, 2}, {1, 3, 2, 2}, + {1, 1, 2, 2}, {1, 64, 1, 1}, {1, 3, 1, 1}, {1, 1, 1, 1}, + }; + RknnYolov8Layout layout; + std::string error; + REQUIRE(DetectRknnYolov8Layout(shapes, layout, error)); + CHECK(layout.kind == RknnOutputAdapterKind::YoloDfl9HeadScoreSumV1); + CHECK(layout.class_scores_are_probabilities); + CHECK(layout.branches[0].box_index == 0); + CHECK(layout.branches[0].class_index == 1); + CHECK(layout.branches[0].score_sum_index == 2); + CHECK(layout.logical_shape == std::vector<int>{1, 7, 21}); + + std::vector<std::vector<float>> values; + std::vector<RknnYolov8Head> heads; + values.reserve(shapes.size()); + heads.reserve(shapes.size()); + for (size_t index = 0; index < shapes.size(); ++index) { + const auto& shape = shapes[index]; + const size_t count = static_cast<size_t>(shape[1] * shape[2] * shape[3]); + const bool class_head = index % 3 == 1; + values.emplace_back(count, class_head ? 0.2f : 0.0f); + heads.push_back({values.back().data(), values.back().size(), shape}); + } + + std::vector<float> output(static_cast<size_t>(7 * 21)); + REQUIRE(ReconstructRknnYolov8(heads, 32, 32, output.data(), output.size(), error)); + CHECK(output[4 * 21] == Catch::Approx(0.2f)); + CHECK(output[5 * 21] == Catch::Approx(0.2f)); + CHECK(output[6 * 21] == Catch::Approx(0.2f)); + + auto malformed = shapes; + malformed[2] = {1, 2, 4, 4}; + CHECK_FALSE(DetectRknnYolov8Layout(malformed, layout, error)); + CHECK(error.find("score-sum") != std::string::npos); +} + +TEST_CASE("RKNN YOLOv8 nine-head direct path uses score-sum without double sigmoid", + "[nn][rknn][yolov8][score-sum][direct-candidates]") { + using namespace cosmo::nn; + + const std::vector<std::vector<int>> shapes{ + {1, 64, 4, 4}, {1, 3, 4, 4}, {1, 1, 4, 4}, {1, 64, 2, 2}, {1, 3, 2, 2}, + {1, 1, 2, 2}, {1, 64, 1, 1}, {1, 3, 1, 1}, {1, 1, 1, 1}, + }; + std::vector<std::vector<int8_t>> values; + std::vector<RknnYolov8QuantizedHead> heads; + values.reserve(shapes.size()); + heads.reserve(shapes.size()); + for (size_t index = 0; index < shapes.size(); ++index) { + const auto& shape = shapes[index]; + const size_t count = static_cast<size_t>(shape[1] * shape[2] * shape[3]); + const bool class_head = index % 3 == 1; + const bool sum_head = index % 3 == 2; + values.emplace_back(count, class_head + ? static_cast<int8_t>(5) + : (sum_head ? static_cast<int8_t>(10) : static_cast<int8_t>(0))); + heads.push_back({values.back().data(), count, shape, 0, class_head || sum_head ? 0.01f : 0.1f}); + } + values[1][0] = 80; + values[2][0] = 90; + + RknnYolov8CandidateScratch scratch; + RknnYolov8CandidateTiming timing; + std::vector<Yolov8Candidate> candidates; + std::string error; + REQUIRE(DecodeRknnYolov8QuantizedCandidates(heads, 32, 32, 0.25f, scratch, candidates, error, &timing)); + REQUIRE(candidates.size() == 1); + CHECK(candidates.front().confidence == Catch::Approx(0.8f)); + CHECK(candidates.front().class_id == 0); + CHECK(timing.points_scanned == 21); + CHECK(timing.points_decoded == 1); + CHECK(timing.score_sum_points_rejected == 20); + + std::vector<float> reconstructed(static_cast<size_t>(7 * 21)); + RknnYolov8TransformTiming transform_timing; + REQUIRE(ReconstructRknnYolov8Quantized(heads, 32, 32, reconstructed.data(), reconstructed.size(), error, + &transform_timing)); + CHECK(reconstructed[4 * 21] == Catch::Approx(0.8f)); +} + +TEST_CASE("RKNN YOLOv8 quantized adapter matches dequantized float heads", + "[nn][rknn][yolov8][fast-output]") { + using namespace cosmo::nn; + + const std::vector<std::vector<int>> shapes{ + {1, 64, 4, 4}, {1, 3, 4, 4}, {1, 64, 2, 2}, {1, 3, 2, 2}, {1, 64, 1, 1}, {1, 3, 1, 1}, + }; + std::vector<std::vector<int8_t>> quantized_values; + std::vector<std::vector<float>> float_values; + std::vector<RknnYolov8QuantizedHead> quantized_heads; + std::vector<RknnYolov8Head> float_heads; + for (size_t head = 0; head < shapes.size(); ++head) { + const size_t count = static_cast<size_t>(shapes[head][1] * shapes[head][2] * shapes[head][3]); + const int32_t zero_point = head % 2 == 0 ? -61 : 114; + const float scale = head % 2 == 0 ? 0.11488f : 0.113557f; + quantized_values.emplace_back(count); + float_values.emplace_back(count); + for (size_t index = 0; index < count; ++index) { + const auto value = static_cast<int8_t>(static_cast<int>(index % 97) - 48); + quantized_values.back()[index] = value; + float_values.back()[index] = (static_cast<float>(value) - static_cast<float>(zero_point)) * scale; + } + quantized_heads.push_back({quantized_values.back().data(), count, shapes[head], zero_point, scale}); + float_heads.push_back({float_values.back().data(), count, shapes[head]}); + } + + std::vector<float> expected(static_cast<size_t>(7 * 21)); + std::vector<float> actual(expected.size()); + std::string error; + REQUIRE(ReconstructRknnYolov8(float_heads, 32, 32, expected.data(), expected.size(), error)); + RknnYolov8TransformTiming timing; + REQUIRE(ReconstructRknnYolov8Quantized(quantized_heads, 32, 32, actual.data(), actual.size(), error, + &timing)); + for (size_t index = 0; index < expected.size(); ++index) + CHECK(actual[index] == Catch::Approx(expected[index]).margin(1e-4f)); +} + +TEST_CASE("RKNN YOLOv8 quantized adapter rejects invalid quantization", "[nn][rknn][yolov8][fast-output]") { + using namespace cosmo::nn; + const std::vector<std::vector<int>> shapes{ + {1, 64, 4, 4}, {1, 3, 4, 4}, {1, 64, 2, 2}, {1, 3, 2, 2}, {1, 64, 1, 1}, {1, 3, 1, 1}, + }; + std::vector<std::vector<int8_t>> values; + std::vector<RknnYolov8QuantizedHead> heads; + for (const auto& shape : shapes) { + const size_t count = static_cast<size_t>(shape[1] * shape[2] * shape[3]); + values.emplace_back(count, 0); + heads.push_back({values.back().data(), count, shape, 0, 0.1f}); + } + heads[1].scale = 0.0f; + std::vector<float> output(static_cast<size_t>(7 * 21)); + std::string error; + CHECK_FALSE(ReconstructRknnYolov8Quantized(heads, 32, 32, output.data(), output.size(), error)); + CHECK_FALSE(error.empty()); + + RknnYolov8CandidateScratch scratch; + std::vector<Yolov8Candidate> candidates; + error.clear(); + CHECK_FALSE(DecodeRknnYolov8QuantizedCandidates(heads, 32, 32, 0.25f, scratch, candidates, error)); + CHECK_FALSE(error.empty()); +} + +TEST_CASE("RKNN YOLOv8 direct candidates match the logical tensor decoder", + "[nn][rknn][yolov8][direct-candidates]") { + using namespace cosmo::nn; + + const std::vector<std::vector<int>> shapes{ + {1, 64, 4, 4}, {1, 3, 4, 4}, {1, 64, 2, 2}, {1, 3, 2, 2}, {1, 64, 1, 1}, {1, 3, 1, 1}, + }; + std::vector<std::vector<int8_t>> quantized_values; + std::vector<std::vector<float>> float_values; + std::vector<RknnYolov8QuantizedHead> quantized_heads; + std::vector<RknnYolov8Head> float_heads; + for (size_t head = 0; head < shapes.size(); ++head) { + const size_t count = static_cast<size_t>(shapes[head][1] * shapes[head][2] * shapes[head][3]); + const bool class_head = head % 2 == 1; + const int8_t initial = class_head ? static_cast<int8_t>(-30) : static_cast<int8_t>(0); + quantized_values.emplace_back(count, initial); + float_values.emplace_back(count, static_cast<float>(initial) * 0.1f); + quantized_heads.push_back({quantized_values.back().data(), count, shapes[head], 0, 0.1f}); + float_heads.push_back({float_values.back().data(), count, shapes[head]}); + } + + const auto set_score = [&](size_t head, int class_id, int spatial_index, int8_t value) { + const int spatial_count = shapes[head][2] * shapes[head][3]; + const size_t index = static_cast<size_t>(class_id * spatial_count + spatial_index); + quantized_values[head][index] = value; + float_values[head][index] = static_cast<float>(value) * 0.1f; + }; + set_score(1, 0, 0, 20); + set_score(1, 1, 15, 18); + set_score(3, 2, 0, 22); + + std::vector<float> logical_output(static_cast<size_t>(7 * 21)); + std::string error; + REQUIRE(ReconstructRknnYolov8(float_heads, 32, 32, logical_output.data(), logical_output.size(), error)); + + SharedResource resource; + YoloV8DecodeNode node; + node.SetSharedResource(&resource); + node.SetMaxBatch(1); + YoloPost post; + post.nms_threshold = 0.7f; + post.nms_detection_conf = 0.25f; + post.top_k = 8; + post.input_width = 32; + post.input_height = 32; + node.LoadParam(&post); + REQUIRE(bool(node.InferTopShapes())); + + BlobDesc input_desc; + input_desc.device_type = DEVICE_NAIVE; + input_desc.data_type = DATA_TYPE_FLOAT; + input_desc.data_format = DATA_FORMAT_NCHW; + input_desc.dims = {1, 7, 21}; + auto input = std::make_shared<Blob>(input_desc, true); + std::memcpy(input->GetHandle().base, logical_output.data(), logical_output.size() * sizeof(float)); + + BlobDesc output_desc; + output_desc.device_type = DEVICE_NAIVE; + output_desc.data_type = DATA_TYPE_FLOAT; + output_desc.data_format = DATA_FORMAT_NCHW; + output_desc.dims = node.GetTopBlobShapes().front(); + auto legacy_output = std::make_shared<Blob>(output_desc, true); + auto direct_output = std::make_shared<Blob>(output_desc, true); + std::vector<std::shared_ptr<Blob>> bottoms{input}; + std::vector<std::shared_ptr<Blob>> legacy_tops{legacy_output}; + REQUIRE(bool(node.Forward(bottoms, legacy_tops))); + + RknnYolov8CandidateScratch scratch; + RknnYolov8CandidateTiming timing; + REQUIRE(DecodeRknnYolov8QuantizedCandidates(quantized_heads, 32, 32, 0.25f, scratch, + resource.yolov8_candidate_batch.candidates, error, &timing)); + CHECK(timing.points_scanned == 21); + CHECK(timing.points_decoded == 3); + CHECK(resource.yolov8_candidate_batch.candidates.size() == 3); + resource.yolov8_candidate_batch.ready = true; + + std::vector<std::shared_ptr<Blob>> direct_tops{direct_output}; + REQUIRE(bool(node.Forward(bottoms, direct_tops))); + CHECK_FALSE(resource.yolov8_candidate_batch.ready); + const auto count = static_cast<size_t>(post.top_k) * 6; + const auto* expected = static_cast<const float*>(legacy_output->GetHandle().base); + const auto* actual = static_cast<const float*>(direct_output->GetHandle().base); + for (size_t index = 0; index < count; ++index) + CHECK(actual[index] == Catch::Approx(expected[index]).margin(1e-5f)); +} + +TEST_CASE("RKNN YOLOv8 class-major capability preserves decode results", "[nn][rknn][yolov8][fast-output]") { + using namespace cosmo::nn; + + SharedResource resource; + YoloV8DecodeNode node; + node.SetSharedResource(&resource); + node.SetMaxBatch(1); + YoloPost post; + post.nms_threshold = 0.7f; + post.nms_detection_conf = 0.25f; + post.top_k = 8; + post.input_width = 640; + post.input_height = 640; + node.LoadParam(&post); + REQUIRE(bool(node.InferTopShapes())); + + BlobDesc input_desc; + input_desc.device_type = DEVICE_NAIVE; + input_desc.data_type = DATA_TYPE_FLOAT; + input_desc.data_format = DATA_FORMAT_NCHW; + input_desc.dims = {1, 7, 5}; + auto input = std::make_shared<Blob>(input_desc, true); + auto* values = static_cast<float*>(input->GetHandle().base); + std::fill(values, values + 35, 0.0f); + for (int box = 0; box < 5; ++box) { + values[box] = 50.0f + box * 100.0f; + values[5 + box] = 50.0f + box * 100.0f; + values[10 + box] = 20.0f; + values[15 + box] = 20.0f; + } + values[20] = 0.9f; + values[26] = 0.8f; + values[32] = 0.7f; + values[23] = 0.6f; + values[28] = 0.6f; // Tie: lower class index must continue to win. + + BlobDesc output_desc; + output_desc.device_type = DEVICE_NAIVE; + output_desc.data_type = DATA_TYPE_FLOAT; + output_desc.data_format = DATA_FORMAT_NCHW; + output_desc.dims = node.GetTopBlobShapes().front(); + auto legacy_output = std::make_shared<Blob>(output_desc, true); + auto fast_output = std::make_shared<Blob>(output_desc, true); + std::vector<std::shared_ptr<Blob>> bottoms{input}; + + resource.prefer_yolov8_class_major_scan = false; + std::vector<std::shared_ptr<Blob>> legacy_tops{legacy_output}; + REQUIRE(bool(node.Forward(bottoms, legacy_tops))); + resource.prefer_yolov8_class_major_scan = true; + std::vector<std::shared_ptr<Blob>> fast_tops{fast_output}; + REQUIRE(bool(node.Forward(bottoms, fast_tops))); + + CHECK(legacy_output->GetBlobDesc().dims == fast_output->GetBlobDesc().dims); + const auto count = static_cast<size_t>(post.top_k) * 6; + CHECK(std::memcmp(legacy_output->GetHandle().base, fast_output->GetHandle().base, + count * sizeof(float)) == 0); +} + +#endif // COSMO_NN_USE_RKNN_BACKEND diff --git a/test/test_rockchip_media_backend.cc b/test/test_rockchip_media_backend.cc new file mode 100644 index 000000000..5b189900e --- /dev/null +++ b/test/test_rockchip_media_backend.cc @@ -0,0 +1,385 @@ +#include "catch_amalgamated.hpp" + +#ifdef COSMO_MEDIA_USE_ROCKCHIP_BACKEND + +#include <algorithm> +#include <cmath> +#include <cstdlib> +#include <filesystem> +#include <fstream> +#include <memory> +#include <optional> +#include <string> +#include <vector> + +#include "media/IOsdTextRenderer.h" +#include "media/PixelFormat.h" +#include "media/PreviewPipelineMetrics.h" +#include "media/VideoDecoder.h" +#include "media/VideoEncoder.h" +#include "media/VideoFrame.h" +#include "media/VideoFrameProcRockchip.h" +#include "mem/AllocatorCpu.h" +#include "mem/MemoryPoolMng.h" +#if defined(COSMO_NN_USE_RKNN_BACKEND) +#include "nn/core/blob.h" +#include "nn/core/inference_pipeline_metrics.h" +#include "nn/core/shared_resource.h" +#include "nn/device/rknn/rknn_preprocess_node.h" +#include "nn/utils/op.h" +#endif + +namespace { + +class StubOsdTextRenderer final : public cosmo::media::IOsdTextRenderer { +public: + bool Init(const std::string&) override { + return true; + } + bool IsReady() const override { + return false; + } + TextBitmap RenderString(const std::string&, float) const override { + return {}; + } + OutlinedTextBitmap RenderStringWithOutline(const std::string&, float) const override { + return {}; + } +}; + +bool HasAnnexBStartCode(const std::vector<uint8_t>& data) { + return data.size() >= 4 && data[0] == 0 && data[1] == 0 && + ((data[2] == 1) || (data[2] == 0 && data[3] == 1)); +} + +size_t CountSelfDmaBufFds() { + std::error_code error; + size_t count = 0; + for (const auto& entry : std::filesystem::directory_iterator("/proc/self/fdinfo", error)) { + if (error) + break; + std::ifstream input(entry.path()); + std::string line; + while (std::getline(input, line)) { + if (line.rfind("exp_name:", 0) == 0) { + ++count; + break; + } + } + } + return count; +} + +#if defined(COSMO_NN_USE_RKNN_BACKEND) +class ScopedEnvValue { +public: + ScopedEnvValue(const char* name, const char* value) : name_(name) { + if (const char* current = std::getenv(name)) + previous_ = current; + setenv(name, value, 1); + } + ~ScopedEnvValue() { + if (previous_) + setenv(name_.c_str(), previous_->c_str(), 1); + else + unsetenv(name_.c_str()); + } + +private: + std::string name_; + std::optional<std::string> previous_; +}; +#endif + +} // namespace + +TEST_CASE("Rockchip MPP encodes compact I420 as Annex-B H264", "[media][rockchip][encoder][.device]") { + constexpr int width = 640; + constexpr int height = 360; + std::vector<uint8_t> i420(static_cast<size_t>(width) * height * 3 / 2, 128); + std::fill_n(i420.begin(), static_cast<size_t>(width) * height, 32); + + auto encoder = cosmo::media::VideoEncoder::Create(nullptr); + REQUIRE(encoder); + encoder->Set(cosmo::media::VideoCodecType::kH264, width, height); + REQUIRE(encoder->Open()); + + auto packet = encoder->SendYUVFrame(i420.data()); + REQUIRE(packet); + CHECK(packet->GetSize() > 0); + CHECK(packet->IsIFrame()); + CHECK(HasAnnexBStartCode(packet->data)); +} + +TEST_CASE("Rockchip RGA performs admitted host-buffer conversions and resize", + "[media][rockchip][rga][.device]") { + constexpr int width = 64; + constexpr int height = 64; + constexpr int pool_size = width * height * 3; + cosmo::mem::MemoryPoolMng memory_pool(std::make_unique<cosmo::mem::AllocatorCpu>(), {pool_size}); + cosmo::mem::SetMemoryPoolContext(&memory_pool); + struct PoolReset { + ~PoolReset() { + cosmo::mem::SetMemoryPoolContext(nullptr); + } + } pool_reset; + + const auto before = cosmo::media::GetPreviewPipelineMetrics().Snapshot(); + { + StubOsdTextRenderer osd; + cosmo::media::VideoFrameProcRockchip processor(osd); + auto bgr = + std::make_shared<cosmo::media::VideoFrame>(width, height, cosmo::media::PixelFormat::PIXEL_BGR8); + REQUIRE(VideoFrameValid(bgr, true)); + std::fill_n(bgr->GetData(), bgr->GetSize(), 96); + + auto i420 = processor.BGR2I420(bgr); + REQUIRE(VideoFrameValid(i420, true)); + CHECK(i420->GetPixelFormat() == cosmo::media::PixelFormat::PIXEL_I420); + + auto resized = processor.Resize(i420, height / 2, width / 2); + REQUIRE(VideoFrameValid(resized, true)); + CHECK(resized->GetWidth() == width / 2); + CHECK(resized->GetHeight() == height / 2); + + auto rgb = processor.I4202RGB(i420); + REQUIRE(VideoFrameValid(rgb, true)); + CHECK(rgb->GetPixelFormat() == cosmo::media::PixelFormat::PIXEL_RGB8); + } + + const auto after = cosmo::media::GetPreviewPipelineMetrics().Snapshot(); + CHECK(after.rga_frames - before.rga_frames == 3); + CHECK(after.rga_failures - before.rga_failures == 0); +} + +TEST_CASE("Rockchip MPP decodes its H264 output through the Copy-out boundary", + "[media][rockchip][decoder][.device]") { + constexpr int width = 640; + constexpr int height = 360; + constexpr int pool_size = width * height * 3 / 2; + constexpr int bgr_size = width * height * 3; + cosmo::mem::MemoryPoolMng memory_pool(std::make_unique<cosmo::mem::AllocatorCpu>(), + {pool_size, bgr_size}); + cosmo::mem::SetMemoryPoolContext(&memory_pool); + struct PoolReset { + ~PoolReset() { + cosmo::mem::SetMemoryPoolContext(nullptr); + } + } pool_reset; + + std::vector<uint8_t> i420(static_cast<size_t>(pool_size), 128); + std::fill_n(i420.begin(), static_cast<size_t>(width) * height, 48); + + auto encoder = cosmo::media::VideoEncoder::Create(nullptr); + REQUIRE(encoder); + encoder->Set(cosmo::media::VideoCodecType::kH264, width, height); + REQUIRE(encoder->Open()); + + std::vector<cosmo::media::VideoPacketPtr> packets; + for (int index = 0; index < 16; ++index) { + auto packet = encoder->SendYUVFrame(i420.data()); + REQUIRE(packet); + packets.push_back(std::move(packet)); + } + + auto decoder = cosmo::media::VideoDecoder::Create(0, nullptr); + REQUIRE(decoder); + decoder->SetCodecType(cosmo::media::VideoCodecType::kH264, width, height); + REQUIRE(decoder->Open()); + + const auto before = cosmo::media::GetPreviewPipelineMetrics().Snapshot(); + cosmo::media::VideoFramePtr decoded; + cosmo::media::NativeVideoBufferPtr native_buffer; + bool discarded_deferred_output = false; + for (size_t index = 0; index < packets.size(); ++index) { + bool accepted = false; + auto output = decoder->DecodeFrame(packets[index]->data.data(), packets[index]->data.size(), + static_cast<int64_t>(index + 1), accepted); + CHECK(accepted); + if (output.IsDeferred() && !discarded_deferred_output) { + output.Discard(); + discarded_deferred_output = true; + continue; + } + if (output.HasFrame()) { + native_buffer = output.ExportNativeBuffer(); + decoded = output.Materialize(); + } + if (decoded) { + break; + } + } + for (int attempt = 0; !decoded && attempt < 8; ++attempt) { + decoded = decoder->GetFrame(); + } + + REQUIRE(decoded); + CHECK(decoded->GetWidth() == width); + CHECK(decoded->GetHeight() == height); + CHECK(decoded->GetPixelFormat() == cosmo::media::PixelFormat::PIXEL_I420); + CHECK(decoded->Active()); + REQUIRE(native_buffer); + CHECK(native_buffer->Valid()); + CHECK(native_buffer->format == cosmo::media::NativeVideoBufferFormat::NV12); + CHECK(native_buffer->width == width); + CHECK(native_buffer->height == height); + CHECK(native_buffer->width_stride >= width); + CHECK(native_buffer->height_stride >= height); + +#if defined(COSMO_NN_USE_RKNN_BACKEND) + StubOsdTextRenderer osd; + cosmo::media::VideoFrameProcRockchip processor(osd); + auto bgr = processor.I4202BGR(decoded); + REQUIRE(VideoFrameValid(bgr, true)); + + cosmo::nn::BlobDesc source_desc; + source_desc.device_type = cosmo::nn::DEVICE_NAIVE; + source_desc.data_type = cosmo::nn::DATA_TYPE_UINT8; + source_desc.data_format = cosmo::nn::DATA_FORMAT_NHWC; + source_desc.image_format = cosmo::nn::IMAGE_BGR; + source_desc.dims = {1, height, width, 3}; + cosmo::nn::BlobHandle source_handle; + source_handle.base = bgr->GetData(); + source_handle.native_image.fd = native_buffer->fd; + source_handle.native_image.bytes = native_buffer->bytes; + source_handle.native_image.width = native_buffer->width; + source_handle.native_image.height = native_buffer->height; + source_handle.native_image.width_stride = native_buffer->width_stride; + source_handle.native_image.height_stride = native_buffer->height_stride; + source_handle.native_image.format = cosmo::nn::IMAGE_NV12; + auto source_blob = std::make_shared<cosmo::nn::Blob>(source_desc, source_handle); + + cosmo::nn::Resize resize; + resize.dsize = {640, 640}; + resize.gravity = 1; + resize.color = {114, 114, 114}; + cosmo::nn::SharedResource resource; + cosmo::nn::RknnResizeNode resize_node; + resize_node.SetSharedResource(&resource); + resize_node.LoadParam(&resize); + REQUIRE(bool(resize_node.InferTopShapes())); + cosmo::nn::BlobDesc target_desc; + target_desc.device_type = cosmo::nn::DEVICE_NAIVE; + target_desc.data_type = cosmo::nn::DATA_TYPE_UINT8; + target_desc.data_format = cosmo::nn::DATA_FORMAT_NHWC; + target_desc.image_format = cosmo::nn::IMAGE_RGB; + target_desc.dims = {1, 640, 640, 3}; + auto target = std::make_shared<cosmo::nn::Blob>(target_desc, true); + REQUIRE(target->GetHandle().base); + std::vector<std::shared_ptr<cosmo::nn::Blob>> bottoms{source_blob}; + std::vector<std::shared_ptr<cosmo::nn::Blob>> tops{target}; + + std::vector<uint8_t> host_result(640 * 640 * 3); + { + ScopedEnvValue disabled("COSMO_RKNN_MPP_DMABUF", "0"); + REQUIRE(bool(resize_node.Forward(bottoms, tops))); + std::copy_n(static_cast<const uint8_t*>(target->GetHandle().base), host_result.size(), + host_result.begin()); + } + const auto inference_before = cosmo::nn::GetInferencePipelineMetrics().Snapshot(); + { + ScopedEnvValue enabled("COSMO_RKNN_MPP_DMABUF", "1"); + REQUIRE(bool(resize_node.Forward(bottoms, tops))); + } + const auto inference_after = cosmo::nn::GetInferencePipelineMetrics().Snapshot(); + const auto* native_result = static_cast<const uint8_t*>(target->GetHandle().base); + uint64_t absolute_error_sum = 0; + int max_absolute_error = 0; + for (size_t index = 0; index < host_result.size(); ++index) { + const int error = std::abs(static_cast<int>(host_result[index]) - native_result[index]); + absolute_error_sum += static_cast<uint64_t>(error); + max_absolute_error = std::max(max_absolute_error, error); + } + const double mean_absolute_error = + static_cast<double>(absolute_error_sum) / static_cast<double>(host_result.size()); + CHECK(mean_absolute_error <= 2.0); + CHECK(max_absolute_error <= 12); + CHECK(inference_after.rknn_mpp_dmabuf_frames == inference_before.rknn_mpp_dmabuf_frames + 1); + CHECK(inference_after.rknn_mpp_dmabuf_import_failures == + inference_before.rknn_mpp_dmabuf_import_failures); + + const auto fallback_before = cosmo::nn::GetInferencePipelineMetrics().Snapshot(); + { + ScopedEnvValue enabled("COSMO_RKNN_MPP_DMABUF", "1"); + ScopedEnvValue forced("COSMO_RKNN_MPP_DMABUF_FORCE_FAIL", "1"); + REQUIRE(bool(resize_node.Forward(bottoms, tops))); + } + const auto fallback_after = cosmo::nn::GetInferencePipelineMetrics().Snapshot(); + CHECK(std::equal(host_result.begin(), host_result.end(), + static_cast<const uint8_t*>(target->GetHandle().base))); + CHECK(fallback_after.rknn_mpp_dmabuf_fallbacks == fallback_before.rknn_mpp_dmabuf_fallbacks + 1); +#endif + + const auto after = cosmo::media::GetPreviewPipelineMetrics().Snapshot(); + CHECK(discarded_deferred_output); + CHECK(after.mpp_decoded_frames > before.mpp_decoded_frames); + CHECK(after.mpp_decode_failures == before.mpp_decode_failures); + CHECK(after.mpp_decode_fallbacks == before.mpp_decode_fallbacks); + CHECK(after.mpp_copy_out_frames > before.mpp_copy_out_frames); + CHECK(after.mpp_copy_out_failures == before.mpp_copy_out_failures); + CHECK(after.mpp_early_dropped_frames == before.mpp_early_dropped_frames + 1); + native_buffer.reset(); + decoded.reset(); + CHECK(decoder->Close()); + + // Local loop playback changes streamIndex for every pass. Keep a compatible + // RK3576 MPP context alive while exporting its DMA-BUF through RGA, then + // require the warmed frame-group FD count to remain bounded. + REQUIRE(decoder->Open()); + CHECK_FALSE(decoder->ReuseForStreamRestart(cosmo::media::VideoCodecType::kH264, width + 2, height)); + CHECK_FALSE(decoder->ReuseForStreamRestart(cosmo::media::VideoCodecType::kH265, width, height)); + size_t dmabuf_fds_after_warmup = 0; + size_t reused_stream_frames = 0; + for (int cycle = 0; cycle < 17; ++cycle) { + if (cycle > 0) { + REQUIRE(decoder->ReuseForStreamRestart(cosmo::media::VideoCodecType::kH264, width, height)); + } + bool got_frame = false; + for (size_t packet_index = 0; packet_index < packets.size() && !got_frame; ++packet_index) { + bool accepted = false; + auto output = + decoder->DecodeFrame(packets[packet_index]->data.data(), packets[packet_index]->data.size(), + 1000 + cycle * 100 + packet_index, accepted); + REQUIRE(accepted); + if (!output.HasFrame()) + continue; + auto replay_native = output.ExportNativeBuffer(); + auto replay_frame = output.Materialize(); + REQUIRE(replay_native); + REQUIRE(replay_frame); +#if defined(COSMO_NN_USE_RKNN_BACKEND) + auto replay_bgr = processor.I4202BGR(replay_frame); + REQUIRE(VideoFrameValid(replay_bgr, true)); + auto replay_handle = source_blob->GetHandle(); + replay_handle.base = replay_bgr->GetData(); + replay_handle.native_image.fd = replay_native->fd; + replay_handle.native_image.bytes = replay_native->bytes; + replay_handle.native_image.width = replay_native->width; + replay_handle.native_image.height = replay_native->height; + replay_handle.native_image.width_stride = replay_native->width_stride; + replay_handle.native_image.height_stride = replay_native->height_stride; + replay_handle.native_image.format = cosmo::nn::IMAGE_NV12; + source_blob->SetHandle(replay_handle); + { + ScopedEnvValue enabled("COSMO_RKNN_MPP_DMABUF", "1"); + REQUIRE(bool(resize_node.Forward(bottoms, tops))); + } +#endif + ++reused_stream_frames; + got_frame = true; + } + REQUIRE(got_frame); + if (cycle == 0) { + dmabuf_fds_after_warmup = CountSelfDmaBufFds(); + REQUIRE(dmabuf_fds_after_warmup > 0); + } + } + REQUIRE(reused_stream_frames == 17); + const auto dmabuf_fds_after_reuse = CountSelfDmaBufFds(); + INFO("DMA-BUF FDs after warmup=" << dmabuf_fds_after_warmup + << " after stream reuse=" << dmabuf_fds_after_reuse); + CHECK(dmabuf_fds_after_reuse <= dmabuf_fds_after_warmup + 4); + CHECK(decoder->Close()); +} + +#endif diff --git a/test/test_sophon_bmrt_ownership.cc b/test/test_sophon_bmrt_ownership.cc new file mode 100644 index 000000000..23a2db9d9 --- /dev/null +++ b/test/test_sophon_bmrt_ownership.cc @@ -0,0 +1,27 @@ +#include "catch_amalgamated.hpp" + +#ifdef COSMO_NN_USE_SOPHON_BACKEND + +#include <type_traits> +#include <utility> + +#include "nn/device/sophon/sophon_net_node.h" + +namespace cosmo::nn { +namespace { + + static_assert(std::is_nothrow_move_constructible_v<OwnedBmrt>); + static_assert(!std::is_copy_constructible_v<OwnedBmrt>); + + TEST_CASE("Sophon BMRuntime ownership rejects an empty handle", "[nn][sophon][ownership]") { + SophonNetNode node; + OwnedBmrt runtime; + + auto status = node.AttachOwnedBmrt(std::move(runtime)); + REQUIRE(static_cast<int>(status) == static_cast<int>(COSMO_NN_ERR_LOAD_MODEL)); + } + +} // namespace +} // namespace cosmo::nn + +#endif diff --git a/test/test_system_operation_service_impl.cc b/test/test_system_operation_service_impl.cc index 352b080b8..07c7f11d3 100644 --- a/test/test_system_operation_service_impl.cc +++ b/test/test_system_operation_service_impl.cc @@ -1,15 +1,17 @@ #include <array> #include <filesystem> #include <fstream> +#include <limits> #include <sstream> #include <string> -#include <string_view> #include "catch_amalgamated.hpp" #include "mock/MockServiceRegistry.h" +#include "platform/SystemReboot.h" #include "service/detail/ServiceRegistry.h" #include "service/system/impl/PacketUpgrade.h" #include "service/system/impl/SystemOperationServiceImpl.h" +#include "service/system/impl/UpgradeStorage.h" #include "util/Exec.h" #include "util/PathUtil.h" #include "util/ResourceBudget.h" @@ -45,6 +47,24 @@ fs::path AddUpgradeChecksumToName(const fs::path& archive, const fs::path& desti } // namespace +TEST_CASE("Factory reset preserves model authorization data", "[system][reset]") { + const auto root = fs::temp_directory_path() / "cosmo_factory_reset_test"; + const auto certificate = root / "model-guard" / "device-certificate.bin"; + std::error_code ec; + fs::remove_all(root, ec); + fs::create_directories(certificate.parent_path()); + fs::create_directories(root / "conf"); + std::ofstream(certificate) << "certificate"; + std::ofstream(root / "conf" / "config.json") << "{}"; + std::ofstream(root / "temporary-file") << "temporary"; + + CHECK_FALSE(cosmo::platform::ClearFactoryResetData(root.string())); + CHECK(fs::is_regular_file(certificate)); + CHECK_FALSE(fs::exists(root / "conf")); + CHECK_FALSE(fs::exists(root / "temporary-file")); + fs::remove_all(root, ec); +} + TEST_CASE("SystemOperationServiceImpl: System operations", "[system][service]") { cosmo::test::MockServiceRegistry mocks; cosmo::service::SystemOperationServiceImpl sysOpSvc; @@ -117,6 +137,72 @@ TEST_CASE("PacketUpgrade rejects missing md5", "[system][upgrade]") { REQUIRE(result != cosmo::util::ErrorEnum::Success); } +TEST_CASE("Upgrade storage requires two and a half package sizes", "[system][upgrade][storage]") { + CHECK(cosmo::service::RequiredUpgradeSpaceBytes(0) == 0); + CHECK(cosmo::service::RequiredUpgradeSpaceBytes(4) == 10); + CHECK(cosmo::service::RequiredUpgradeSpaceBytes(5) == 13); + CHECK(cosmo::service::RequiredUpgradeSpaceBytes(std::numeric_limits<std::uint64_t>::max()) == + std::numeric_limits<std::uint64_t>::max()); +} + +TEST_CASE("Upgrade storage cleanup removes only event images and videos", "[system][upgrade][storage]") { + const auto root = fs::temp_directory_path() / "cosmo_upgrade_storage_cleanup_test"; + const auto event_root = root / "event"; + const auto outside = root / "outside.jpg"; + std::error_code ec; + fs::remove_all(root, ec); + fs::create_directories(event_root / "2026/08/17"); + std::ofstream(event_root / "2026/08/17/alarm.jpg") << "image"; + std::ofstream(event_root / "2026/08/17/alarm.MP4") << "video"; + std::ofstream(event_root / "2026/08/17/alarm.json") << "metadata"; + std::ofstream(event_root / "2026/08/17/engine.log") << "log"; + std::ofstream(outside) << "outside"; + fs::create_symlink(outside, event_root / "2026/08/17/outside.jpg", ec); + REQUIRE(!ec); + + const auto result = cosmo::service::DeleteEventMediaFiles(event_root); + + CHECK(result.error == cosmo::util::ErrorEnum::Success); + CHECK(result.deleted_files == 2); + CHECK(result.deleted_bytes == 10); + CHECK_FALSE(fs::exists(event_root / "2026/08/17/alarm.jpg")); + CHECK_FALSE(fs::exists(event_root / "2026/08/17/alarm.MP4")); + CHECK(fs::is_regular_file(event_root / "2026/08/17/alarm.json")); + CHECK(fs::is_regular_file(event_root / "2026/08/17/engine.log")); + CHECK(fs::is_symlink(event_root / "2026/08/17/outside.jpg")); + CHECK(fs::is_regular_file(outside)); + fs::remove_all(root, ec); +} + +TEST_CASE("Upgrade storage rechecks available space after confirmed cleanup", "[system][upgrade][storage]") { + const auto root = fs::temp_directory_path() / "cosmo_upgrade_storage_recheck_test"; + const auto event_root = root / "event"; + std::error_code ec; + fs::remove_all(root, ec); + fs::create_directories(event_root); + std::ofstream(event_root / "alarm.jpg") << "image"; + std::ofstream(event_root / "alarm.json") << "metadata"; + + cosmo::service::UpgradeSpaceStatus status; + const auto inspect_result = cosmo::service::CheckUpgradeStorage( + root, event_root, std::numeric_limits<std::uint64_t>::max(), false, status); + REQUIRE(inspect_result == cosmo::util::ErrorEnum::Success); + CHECK_FALSE(status.sufficient); + CHECK(status.required_bytes == std::numeric_limits<std::uint64_t>::max()); + CHECK(status.event_media_bytes == 5); + CHECK(fs::is_regular_file(event_root / "alarm.jpg")); + + const auto cleanup_result = cosmo::service::CheckUpgradeStorage( + root, event_root, std::numeric_limits<std::uint64_t>::max(), true, status); + REQUIRE(cleanup_result == cosmo::util::ErrorEnum::Success); + CHECK_FALSE(status.sufficient); + CHECK(status.deleted_media_files == 1); + CHECK(status.deleted_media_bytes == 5); + CHECK_FALSE(fs::exists(event_root / "alarm.jpg")); + CHECK(fs::is_regular_file(event_root / "alarm.json")); + fs::remove_all(root, ec); +} + TEST_CASE("PacketUpgrade validates archive boundaries before extraction", "[system][upgrade][archive]") { const auto root = fs::temp_directory_path() / "cosmo_packet_upgrade_validation_test"; const auto data_root = root / "data"; diff --git a/test/test_upload_staging_service.cc b/test/test_upload_staging_service.cc index b038434e2..75892d412 100644 --- a/test/test_upload_staging_service.cc +++ b/test/test_upload_staging_service.cc @@ -79,6 +79,10 @@ TEST_CASE("Upload staging binds opaque sessions to owner and consumes once", "[u REQUIRE(ParseUploadPurpose("image", parsed_purpose)); CHECK(parsed_purpose == UploadPurpose::kImage); CHECK(UploadPurposeName(UploadPurpose::kImage) == "image"); + CHECK(ParseUploadPurpose("model-authorization-certificate", parsed_purpose)); + CHECK(parsed_purpose == UploadPurpose::kModelAuthorizationCertificate); + CHECK(UploadPurposeName(UploadPurpose::kModelAuthorizationCertificate) == + "model-authorization-certificate"); CHECK_FALSE(ParseUploadPurpose("unknown", parsed_purpose)); TempDirectory temp; diff --git a/test/test_verify_model_guard_v2_sdk.py b/test/test_verify_model_guard_v2_sdk.py new file mode 100644 index 000000000..22e819fd3 --- /dev/null +++ b/test/test_verify_model_guard_v2_sdk.py @@ -0,0 +1,174 @@ +#!/usr/bin/python3 +"""Focused tests for the minimal Model Guard SDK check.""" + +from __future__ import annotations + +import contextlib +import importlib.machinery +import importlib.util +import io +import os +import sys +import tempfile +import unittest +from pathlib import Path +from unittest import mock + + +sys.dont_write_bytecode = True +REPOSITORY = Path(__file__).resolve().parents[1] +VERIFIER_SOURCE = REPOSITORY / "scripts/verify_model_guard_v2_sdk.py" +loader = importlib.machinery.SourceFileLoader( + "verify_model_guard_v2_sdk_under_test", str(VERIFIER_SOURCE) +) +spec = importlib.util.spec_from_loader(loader.name, loader) +if spec is None: + raise RuntimeError("cannot load Model Guard SDK verifier") +verifier = importlib.util.module_from_spec(spec) +sys.modules[loader.name] = verifier +loader.exec_module(verifier) + + +HEADER = ( + b"#define CMG_V2_ABI_MAJOR UINT32_C(2)\n" + b"#define CMG_V2_ARTIFACT_INFO_SIZE UINT32_C(72)\n" + b"#define CMG_V2_SOPHON_LOAD_OPTIONS_SIZE UINT32_C(16)\n" + b"int CmgV2OpenArtifact(void);\n" + b"int CmgV2GetArtifactInfo(void);\n" + b"int CmgV2LoadSophonSegment(void);\n" + b"void CmgV2CloseArtifact(void);\n" +) +LIBRARY = b"synthetic-guard\n" +PROVISION = b"synthetic-provisioner\n" + + +class ModelGuardHeaderTest(unittest.TestCase): + def test_required_interface_is_accepted(self) -> None: + verifier.verify_header(HEADER) + + def test_missing_function_is_rejected(self) -> None: + with self.assertRaisesRegex(RuntimeError, "CmgV2CloseArtifact"): + verifier.verify_header( + HEADER.replace(b"void CmgV2CloseArtifact(void);\n", b"") + ) + + +class ModelGuardSdkVerifierTest(unittest.TestCase): + def setUp(self) -> None: + self.temporary = tempfile.TemporaryDirectory( + prefix="cosmo-model-guard-sdk-test-" + ) + self.root = Path(self.temporary.name) + + def tearDown(self) -> None: + self.temporary.cleanup() + + def sdk( + self, + name: str, + *, + provision: bool = False, + marked: bool = False, + ) -> Path: + root = self.root / f"sdk-{name}" + for relative in ("include", "lib", "share/cosmo-model-guard"): + (root / relative).mkdir(parents=True) + (root / "include/cosmo_model_guard_v2.h").write_bytes(HEADER) + (root / "lib/libcosmo_model_guard.so.2.0.0").write_bytes(LIBRARY) + os.symlink( + "libcosmo_model_guard.so.2.0.0", + root / "lib/libcosmo_model_guard.so.2", + ) + os.symlink( + "libcosmo_model_guard.so.2", + root / "lib/libcosmo_model_guard.so", + ) + if provision: + (root / "bin").mkdir() + tool = root / "bin/cosmo-model-provision" + tool.write_bytes(PROVISION) + tool.chmod(0o755) + if marked: + ( + root + / f"share/cosmo-model-guard/{verifier.TEST_FIXTURE_MARKER_NAME}" + ).write_bytes(verifier.TEST_FIXTURE_MARKER_CONTENT) + return root + + def verify(self, sdk: Path, profile: str) -> tuple[str, mock.Mock]: + arguments = [ + str(VERIFIER_SOURCE), + "--admission-profile", + profile, + "--sdk-root", + str(sdk), + "--readelf", + "/usr/bin/true", + "--nm", + "/usr/bin/true", + ] + output = io.StringIO() + with ( + mock.patch.object(sys, "argv", arguments), + mock.patch.object(verifier, "verify_elf"), + mock.patch.object(verifier, "verify_provision_tool") as provision_check, + contextlib.redirect_stdout(output), + ): + self.assertEqual(verifier.main(), 0) + return output.getvalue(), provision_check + + def test_public_runtime_accepts_header_and_library(self) -> None: + output, provision_check = self.verify( + self.sdk("public"), verifier.ADMISSION_PUBLIC_RUNTIME + ) + + self.assertIn("sdk_profile=public-runtime", output) + self.assertIn("library_sha256=", output) + provision_check.assert_not_called() + + def test_production_profile_adds_provisioning_tool(self) -> None: + output, provision_check = self.verify( + self.sdk("production", provision=True), + verifier.ADMISSION_PRODUCTION_RELEASE, + ) + + self.assertIn("sdk_profile=production", output) + provision_check.assert_called_once() + + def test_production_profile_requires_provisioning_tool(self) -> None: + with self.assertRaisesRegex(RuntimeError, "cannot read SDK file"): + self.verify( + self.sdk("missing-provision"), + verifier.ADMISSION_PRODUCTION_RELEASE, + ) + + def test_fixture_requires_marker(self) -> None: + sdk = self.sdk("fixture", provision=True, marked=True) + + output, _ = self.verify(sdk, verifier.ADMISSION_TEST_FIXTURE) + self.assertIn("sdk_profile=TEST-FIXTURE-DO-NOT-DEPLOY", output) + + ( + sdk + / f"share/cosmo-model-guard/{verifier.TEST_FIXTURE_MARKER_NAME}" + ).unlink() + with self.assertRaisesRegex(RuntimeError, "requires the exact"): + self.verify(sdk, verifier.ADMISSION_TEST_FIXTURE) + + def test_file_permissions_and_header_symlink_are_not_inputs(self) -> None: + sdk = self.sdk("permissive") + header = sdk / "include/cosmo_model_guard_v2.h" + target = header.with_name("header-target.h") + header.rename(target) + os.symlink(target.name, header) + for path in (sdk, sdk / "include", sdk / "lib"): + path.chmod(0o777) + target.chmod(0o666) + (sdk / "lib/libcosmo_model_guard.so.2.0.0").chmod(0o777) + + output, _ = self.verify(sdk, verifier.ADMISSION_PUBLIC_RUNTIME) + self.assertIn("sdk_profile=public-runtime", output) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/test_video_decoder_capability.cc b/test/test_video_decoder_capability.cc new file mode 100644 index 000000000..ce8cc686e --- /dev/null +++ b/test/test_video_decoder_capability.cc @@ -0,0 +1,29 @@ +#include "catch_amalgamated.hpp" +#include "media/VideoDecoder.h" + +TEST_CASE("Video decoder capability uses a deterministic backend", "[media][decoder][capability]") { + const auto h264 = cosmo::media::VideoDecoder::Probe(cosmo::media::VideoCodecType::kH264); + const auto h265 = cosmo::media::VideoDecoder::Probe(cosmo::media::VideoCodecType::kH265); + + CHECK(h264.available); + CHECK_FALSE(h264.backend.empty()); + CHECK_FALSE(h264.implementation.empty()); + CHECK_FALSE(h264.detail.empty()); + CHECK(h265.available); + CHECK_FALSE(h265.backend.empty()); + CHECK_FALSE(h265.implementation.empty()); + CHECK_FALSE(h265.detail.empty()); + +#ifdef COSMO_MEDIA_USE_ROCKCHIP_BACKEND + CHECK(h264.backend == "rockchip-copy-out"); + CHECK(h264.implementation == "rockchip-mpp-vpu"); + CHECK(h265.backend == "rockchip-copy-out"); + CHECK(h265.implementation == "rockchip-mpp-vpu"); +#elif defined(COSMO_MEDIA_USE_SOPHON_BACKEND) + CHECK(h264.backend == "sophon-vpu"); + CHECK(h265.backend == "sophon-vpu"); +#else + CHECK(h264.backend == "ffmpeg-software"); + CHECK(h265.backend == "ffmpeg-software"); +#endif +} diff --git a/test/test_video_encoder_capability.cc b/test/test_video_encoder_capability.cc new file mode 100644 index 000000000..cadff3fa1 --- /dev/null +++ b/test/test_video_encoder_capability.cc @@ -0,0 +1,33 @@ +#include "catch_amalgamated.hpp" +#include "media/VideoEncoder.h" + +#ifdef COSMO_MEDIA_USE_CPU_BACKEND +#include "media/VideoEncoderCpu.h" +#endif + +TEST_CASE("Video encoder capability uses a deterministic backend", "[media][encoder][capability]") { + const auto capability = cosmo::media::VideoEncoder::Probe(cosmo::media::VideoCodecType::kH264); + + CHECK_FALSE(capability.backend.empty()); + CHECK_FALSE(capability.detail.empty()); + +#ifdef COSMO_MEDIA_USE_CPU_BACKEND + CHECK(capability.backend == "ffmpeg-software"); + CHECK(capability.implementation == "libopenh264"); + CHECK(cosmo::media::VideoEncoderCpu::IsAllowedEncoderName(cosmo::media::VideoCodecType::kH264, + "libopenh264")); + CHECK_FALSE(cosmo::media::VideoEncoderCpu::IsAllowedEncoderName(cosmo::media::VideoCodecType::kH264, + "h264_v4l2m2m")); + CHECK_FALSE(cosmo::media::VideoEncoderCpu::IsAllowedEncoderName(cosmo::media::VideoCodecType::kH264, + "h264_nvenc")); +#elif defined(COSMO_MEDIA_USE_ROCKCHIP_BACKEND) + CHECK(capability.available); + CHECK(capability.backend == "rockchip-copy-first"); + CHECK(capability.implementation == "rockchip-mpp"); + const auto h265 = cosmo::media::VideoEncoder::Probe(cosmo::media::VideoCodecType::kH265); + CHECK(h265.implementation != "rockchip-mpp"); + CHECK(h265.detail.find("H264-only") != std::string::npos); +#else + CHECK(capability.available); +#endif +} diff --git a/test/test_video_eof_policy.cc b/test/test_video_eof_policy.cc new file mode 100644 index 000000000..897ac1854 --- /dev/null +++ b/test/test_video_eof_policy.cc @@ -0,0 +1,33 @@ +#include "catch_amalgamated.hpp" +#include "flow/channel/VideoEofPolicy.h" + +using cosmo::flow::DecideVideoEof; +using cosmo::flow::IsTerminalOfflineReadEnd; +using cosmo::flow::VideoEofDisposition; + +TEST_CASE("Infinite local video EOF always reopens", "[video-eof][repeat]") { + for (int read_count = 1; read_count <= 1000; ++read_count) { + CHECK(DecideVideoEof(false, read_count, 0) == VideoEofDisposition::Reopen); + } +} + +TEST_CASE("Finite local video EOF completes only after the configured playback count", + "[video-eof][repeat]") { + CHECK(DecideVideoEof(false, 1, 1) == VideoEofDisposition::Complete); + + CHECK(DecideVideoEof(false, 1, 3) == VideoEofDisposition::Reopen); + CHECK(DecideVideoEof(false, 2, 3) == VideoEofDisposition::Reopen); + CHECK(DecideVideoEof(false, 3, 3) == VideoEofDisposition::Complete); +} + +TEST_CASE("Live stream EOF remains a reopen condition", "[video-eof][live]") { + CHECK(DecideVideoEof(true, 1, 1) == VideoEofDisposition::Reopen); + CHECK(DecideVideoEof(true, 1000, 3) == VideoEofDisposition::Reopen); +} + +TEST_CASE("Camera monitor rejects terminal interpretation while reopen is pending", "[video-eof][monitor]") { + CHECK_FALSE(IsTerminalOfflineReadEnd(false, false)); + CHECK_FALSE(IsTerminalOfflineReadEnd(false, true)); + CHECK_FALSE(IsTerminalOfflineReadEnd(true, true)); + CHECK(IsTerminalOfflineReadEnd(true, false)); +} diff --git a/test/test_video_frame_safety.cc b/test/test_video_frame_safety.cc index 6d62c2515..2c1de8949 100644 --- a/test/test_video_frame_safety.cc +++ b/test/test_video_frame_safety.cc @@ -69,6 +69,41 @@ TEST_CASE("Decoder failure logging handles empty and short packets", "[video-fra REQUIRE_FALSE(result); } +TEST_CASE("Deferred decoded frames materialize or discard exactly once", "[video-frame-safety][decoder]") { + int materialize_count = 0; + int discard_count = 0; + DecodedVideoFrame discarded( + 41, 1920, 1080, PixelFormat::PIXEL_I420, + [&]() { + materialize_count++; + return VideoFramePtr{}; + }, + [&]() { discard_count++; }); + + REQUIRE(discarded.HasFrame()); + REQUIRE(discarded.IsDeferred()); + CHECK(discarded.GetFrameIndex() == 41); + CHECK(discarded.GetWidth() == 1920); + CHECK(discarded.GetHeight() == 1080); + discarded.Discard(); + discarded.Discard(); + CHECK(materialize_count == 0); + CHECK(discard_count == 1); + CHECK_FALSE(discarded.HasFrame()); + + DecodedVideoFrame materialized( + 42, 1280, 720, PixelFormat::PIXEL_I420, + [&]() { + materialize_count++; + return VideoFramePtr{}; + }, + [&]() { discard_count++; }); + CHECK(materialized.Materialize() == nullptr); + materialized.Discard(); + CHECK(materialize_count == 1); + CHECK(discard_count == 1); +} + TEST_CASE("Frame size calculation rejects unsafe dimensions", "[video-frame-safety]") { REQUIRE_FALSE(PixelFormatUtils::CalculateFrameSize(-1, 1080, PixelFormat::PIXEL_I420)); REQUIRE_FALSE(PixelFormatUtils::CalculateFrameSize(1920, 0, PixelFormat::PIXEL_I420)); diff --git a/tools/mock_audio_pillar_server.md b/tools/mock_audio_pillar_server.md new file mode 100644 index 000000000..e1c3a2124 --- /dev/null +++ b/tools/mock_audio_pillar_server.md @@ -0,0 +1,71 @@ +# 网络音柱模拟服务 + +此工具模拟 CosmoEdge 当前接入的网络音柱 HTTP 协议,用于没有真实音柱时验证软件链路: + +- 平台对音柱的在线检测; +- 音频文件播放命令及音频 URL 可访问性; +- 文字转语音命令及音量、语速、音色、循环参数; +- 联动策略触发后是否真正向音柱下发命令; +- 音柱返回失败时平台的错误处理。 + +它验证到“音柱收到并接受正确命令”为止,不模拟功放,也不能代替真实设备的出声、音量和音质验收。 + +## 启动 + +模拟服务必须运行在平台设备可访问的测试机上。平台当前只允许填写 IPv4 地址且请求默认使用 80 端口,所以监听端口必须是 80: + +```bash +cd /path/to/cosmo-edge +python3 tools/mock_audio_pillar_server.py \ + --host 0.0.0.0 \ + --port 80 \ + --verify-audio-url \ + --log-file /tmp/mock-audio-pillar.jsonl +``` + +Linux 普通用户若无权监听 80 端口,应由测试机管理员授予该端口的运行权限或使用已有的端口转发;工具本身不要求安装第三方 Python 包。不要把该无认证服务暴露到公网。 + +先在平台设备所在网络验证可达性,下面的 `TEST_HOST_IP` 替换成运行模拟器的 IPv4 地址: + +```bash +curl -sS -X POST http://TEST_HOST_IP/v1/check_alive +curl -sS http://TEST_HOST_IP/__mock__/status +``` + +第一条应返回 `{"code": 200, ...}`,第二条的 `aliveChecks` 应大于 0。 + +## 平台端到端验收 + +1. 在“外设管理 → 网络音柱”新增设备,IP 填模拟器所在测试机的 IPv4 地址,网卡选择能到达该测试机的接口。 +2. 刷新音柱列表,确认设备在线。访问 `http://TEST_HOST_IP/__mock__/status`,确认 `aliveChecks` 增加。 +3. 打开音柱测试,先测试文字播放。确认平台提示成功,状态中的 `speechCommands` 增加,`lastSpeech.kind` 为 `text`,参数与页面填写值一致。 +4. 测试音频文件播放。启动参数带有 `--verify-audio-url` 时,模拟器会像真实音柱一样,从平台下发的 URL 拉取一个字节;URL 不可达时返回失败。确认 `lastSpeech.kind` 为 `audio_url` 且 `lastSpeech.audioFetch.ok` 为 `true`。 +5. 在联动策略中选择这个模拟音柱,配置算法告警数据和网络音柱联动,保存并触发一次匹配的算法告警。确认 `speechCommands` 再次增加,且 `lastSpeech.payload` 是联动中配置的内容。 + +查看全部播放命令: + +```bash +curl -sS http://TEST_HOST_IP/__mock__/events +``` + +清空本轮记录后重新测试: + +```bash +curl -sS -X DELETE http://TEST_HOST_IP/__mock__/events +``` + +让下一条播放命令模拟设备内部失败(HTTP 成功但设备业务码为失败): + +```bash +curl -sS -X POST http://TEST_HOST_IP/__mock__/fail-next +``` + +## 自动化契约测试 + +在仓库根目录执行: + +```bash +python3 test/test_mock_audio_pillar_server.py -v +``` + +测试会使用随机本地端口,不需要管理员权限,也不会访问真实设备。 diff --git a/tools/mock_audio_pillar_server.py b/tools/mock_audio_pillar_server.py new file mode 100644 index 000000000..4bb018a0e --- /dev/null +++ b/tools/mock_audio_pillar_server.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python3 +"""A dependency-free simulator for the HTTP network audio pillar used by CosmoEdge. + +The production platform posts health checks to ``/v1/check_alive`` and both +text-to-speech and audio URL commands to ``/v1/speech``. This server implements +that device-side contract and exposes received commands under ``/__mock__/`` so +an operator or an automated test can verify the complete request path. +""" + +from __future__ import annotations + +import argparse +import json +import logging +import threading +import time +import urllib.error +import urllib.parse +import urllib.request +from dataclasses import dataclass, field +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +from pathlib import Path +from typing import Any + + +LOGGER = logging.getLogger("mock-audio-pillar") +MAX_REQUEST_BYTES = 1024 * 1024 + + +@dataclass +class SimulatorState: + verify_audio_urls: bool = True + log_file: Path | None = None + events: list[dict[str, Any]] = field(default_factory=list) + alive_checks: int = 0 + last_alive_at: str | None = None + fail_next: bool = False + lock: threading.Lock = field(default_factory=threading.Lock) + + def clear(self) -> None: + with self.lock: + self.events.clear() + self.fail_next = False + self.alive_checks = 0 + self.last_alive_at = None + + def record_alive(self) -> None: + with self.lock: + self.alive_checks += 1 + self.last_alive_at = timestamp() + + def consume_failure(self) -> bool: + with self.lock: + fail = self.fail_next + self.fail_next = False + return fail + + def set_failure(self) -> None: + with self.lock: + self.fail_next = True + + def append(self, event: dict[str, Any]) -> dict[str, Any]: + with self.lock: + event = {"sequence": len(self.events) + 1, **event} + self.events.append(event) + if self.log_file is not None: + self.log_file.parent.mkdir(parents=True, exist_ok=True) + with self.log_file.open("a", encoding="utf-8") as stream: + stream.write(json.dumps(event, ensure_ascii=False) + "\n") + return event + + def snapshot(self) -> list[dict[str, Any]]: + with self.lock: + return list(self.events) + + def status(self) -> dict[str, Any]: + with self.lock: + return { + "status": "ok", + "aliveChecks": self.alive_checks, + "lastAliveAt": self.last_alive_at, + "speechCommands": len(self.events), + "lastSpeech": self.events[-1] if self.events else None, + "failNext": self.fail_next, + } + + +class AudioPillarServer(ThreadingHTTPServer): + daemon_threads = True + + def __init__(self, address, handler, state: SimulatorState): + super().__init__(address, handler) + self.state = state + + +class AudioPillarHandler(BaseHTTPRequestHandler): + server: AudioPillarServer + protocol_version = "HTTP/1.1" + + def log_message(self, message: str, *args: Any) -> None: + LOGGER.info("%s - %s", self.client_address[0], message % args) + + def _json(self, status: int, body: dict[str, Any]) -> None: + encoded = json.dumps(body, ensure_ascii=False).encode("utf-8") + self.send_response(status) + self.send_header("Content-Type", "application/json; charset=utf-8") + self.send_header("Content-Length", str(len(encoded))) + self.send_header("Cache-Control", "no-store") + self.end_headers() + self.wfile.write(encoded) + + def _read_json(self, *, allow_empty: bool = False) -> dict[str, Any]: + try: + length = int(self.headers.get("Content-Length", "0")) + except ValueError as error: + raise ValueError("invalid Content-Length") from error + if length > MAX_REQUEST_BYTES: + raise ValueError("request body is too large") + raw = self.rfile.read(length) + if not raw and allow_empty: + return {} + try: + value = json.loads(raw.decode("utf-8")) + except (UnicodeDecodeError, json.JSONDecodeError) as error: + raise ValueError("request body must be a UTF-8 JSON object") from error + if not isinstance(value, dict): + raise ValueError("request body must be a JSON object") + return value + + def do_GET(self) -> None: # noqa: N802 - BaseHTTPRequestHandler API + path = urllib.parse.urlsplit(self.path).path + if path == "/__mock__/events": + events = self.server.state.snapshot() + self._json(200, {"count": len(events), "events": events}) + return + if path == "/__mock__/health": + self._json(200, {"status": "ok", "service": "mock-audio-pillar"}) + return + if path == "/__mock__/status": + self._json(200, self.server.state.status()) + return + self._json(404, {"code": 404, "message": "not found"}) + + def do_DELETE(self) -> None: # noqa: N802 - BaseHTTPRequestHandler API + if urllib.parse.urlsplit(self.path).path != "/__mock__/events": + self._json(404, {"code": 404, "message": "not found"}) + return + self.server.state.clear() + self._json(200, {"code": 200, "message": "events cleared"}) + + def do_POST(self) -> None: # noqa: N802 - BaseHTTPRequestHandler API + path = urllib.parse.urlsplit(self.path).path + try: + if path == "/v1/check_alive": + self._read_json(allow_empty=True) + self.server.state.record_alive() + self._json(200, {"code": 200, "message": "alive"}) + return + if path == "/__mock__/fail-next": + self._read_json(allow_empty=True) + self.server.state.set_failure() + self._json(200, {"code": 200, "message": "next speech will fail"}) + return + if path != "/v1/speech": + self._json(404, {"code": 404, "message": "not found"}) + return + + payload = self._read_json() + kind = validate_speech(payload) + event = { + "receivedAt": timestamp(), + "client": self.client_address[0], + "kind": kind, + "payload": payload, + } + if kind == "audio_url" and self.server.state.verify_audio_urls: + event["audioFetch"] = fetch_audio_url(payload["url"]) + if not event["audioFetch"]["ok"]: + self.server.state.append(event) + self._json(200, {"code": 502, "message": "audio URL is not reachable"}) + return + + self.server.state.append(event) + LOGGER.info("accepted %s command: %s", kind, json.dumps(payload, ensure_ascii=False)) + if self.server.state.consume_failure(): + self._json(200, {"code": 500, "message": "simulated device failure"}) + return + self._json(200, {"code": 200, "message": "accepted"}) + except ValueError as error: + self._json(400, {"code": 400, "message": str(error)}) + + +def require_integer(payload: dict[str, Any], name: str, minimum: int, maximum: int) -> None: + value = payload.get(name) + if isinstance(value, bool) or not isinstance(value, int) or not minimum <= value <= maximum: + raise ValueError(f"{name} must be an integer from {minimum} to {maximum}") + + +def timestamp() -> str: + return time.strftime("%Y-%m-%dT%H:%M:%S%z") + + +def validate_speech(payload: dict[str, Any]) -> str: + has_text = "text" in payload + has_url = "url" in payload + if has_text == has_url: + raise ValueError("speech command must contain exactly one of text or url") + + require_integer(payload, "volume", 0, 100) + loop = payload.get("loop") + if not isinstance(loop, dict): + raise ValueError("loop must be a JSON object") + for name in ("duration", "times", "gap"): + value = loop.get(name, 0) + if isinstance(value, bool) or not isinstance(value, int) or value < 0: + raise ValueError(f"loop.{name} must be a non-negative integer") + + if has_text: + if not isinstance(payload["text"], str) or not payload["text"].strip(): + raise ValueError("text must be a non-empty string") + require_integer(payload, "speed", 0, 100) + return "text" + + if not isinstance(payload["url"], str): + raise ValueError("url must be a string") + parsed = urllib.parse.urlsplit(payload["url"]) + if parsed.scheme not in ("http", "https") or not parsed.netloc: + raise ValueError("url must be an absolute HTTP or HTTPS URL") + return "audio_url" + + +def fetch_audio_url(url: str) -> dict[str, Any]: + request = urllib.request.Request(url, headers={"Range": "bytes=0-0"}) + try: + with urllib.request.urlopen(request, timeout=5) as response: + response.read(1) + return { + "ok": 200 <= response.status < 400, + "status": response.status, + "contentType": response.headers.get("Content-Type", ""), + } + except (urllib.error.URLError, TimeoutError, OSError) as error: + return {"ok": False, "error": str(error)} + + +def create_server( + host: str, + port: int, + *, + verify_audio_urls: bool = False, + log_file: Path | None = None, +) -> AudioPillarServer: + state = SimulatorState(verify_audio_urls=verify_audio_urls, log_file=log_file) + return AudioPillarServer((host, port), AudioPillarHandler, state) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Simulate a CosmoEdge-compatible network audio pillar") + parser.add_argument("--host", default="0.0.0.0", help="listen address (default: 0.0.0.0)") + parser.add_argument( + "--port", + default=80, + type=int, + help="listen port (default: 80; CosmoEdge stores an IPv4 address without a port)", + ) + parser.add_argument("--log-file", type=Path, help="append accepted commands as JSON Lines") + parser.add_argument( + "--verify-audio-url", + action="store_true", + help="fetch audio URLs before accepting them, like a real network speaker", + ) + return parser.parse_args() + + +def main() -> int: + arguments = parse_args() + logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") + server = create_server( + arguments.host, + arguments.port, + verify_audio_urls=arguments.verify_audio_url, + log_file=arguments.log_file, + ) + LOGGER.info( + "mock audio pillar listening on http://%s:%d (audio URL verification: %s)", + arguments.host, + server.server_port, + arguments.verify_audio_url, + ) + try: + server.serve_forever() + except KeyboardInterrupt: + LOGGER.info("stopping") + finally: + server.server_close() + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/compare_outputs.py b/tools/rknn/compare_outputs.py new file mode 100755 index 000000000..db7dd6d90 --- /dev/null +++ b/tools/rknn/compare_outputs.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +"""Compare board RKNN float outputs with an ONNX Runtime reference.""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path + +import numpy as np + + +def load_values(path: Path, shape: list[int]) -> np.ndarray: + if path.suffix == ".npy": + values = np.load(path) + else: + values = np.fromfile(path, dtype=np.float32) + expected = int(np.prod(shape)) + if values.size != expected: + raise ValueError(f"{path} has {values.size} values; expected {expected} for shape {shape}") + return values.astype(np.float32, copy=False).reshape(shape) + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--spec", required=True, type=Path) + parser.add_argument("--precision", required=True, choices=("fp16", "int8")) + parser.add_argument("--reference", required=True, type=Path) + parser.add_argument("--actual", required=True, type=Path) + parser.add_argument("--output-index", type=int, default=0) + parser.add_argument("--report", type=Path) + args = parser.parse_args() + + spec = json.loads(args.spec.read_text(encoding="utf-8")) + shape = spec["outputs"][args.output_index]["shape"] + reference = load_values(args.reference, shape) + actual = load_values(args.actual, shape) + difference = actual - reference + ref_flat = reference.ravel().astype(np.float64) + actual_flat = actual.ravel().astype(np.float64) + denominator = np.linalg.norm(ref_flat) * np.linalg.norm(actual_flat) + cosine = float(np.dot(ref_flat, actual_flat) / denominator) if denominator else float(np.array_equal(reference, actual)) + maximum_absolute_error = float(np.max(np.abs(difference))) + metrics = { + "maximum_absolute_error": maximum_absolute_error, + "mean_absolute_error": float(np.mean(np.abs(difference))), + "root_mean_square_error": float(np.sqrt(np.mean(np.square(difference)))), + "cosine_similarity": cosine, + } + if spec["model_type"] == "classify": + metrics["reference_argmax"] = int(np.argmax(reference)) + metrics["actual_argmax"] = int(np.argmax(actual)) + metrics["argmax_match"] = metrics["reference_argmax"] == metrics["actual_argmax"] + limits = spec["validation"][args.precision] + passed = cosine >= limits["minimum_cosine_similarity"] and maximum_absolute_error <= limits["maximum_absolute_error"] + if spec["model_type"] == "classify": + passed = passed and metrics["argmax_match"] + result = {"passed": passed, "precision": args.precision, "metrics": metrics, "limits": limits} + serialized = json.dumps(result, indent=2, sort_keys=True) + "\n" + if args.report: + args.report.parent.mkdir(parents=True, exist_ok=True) + args.report.write_text(serialized, encoding="utf-8") + print(serialized, end="") + return 0 if passed else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/compare_yolov8_detections.py b/tools/rknn/compare_yolov8_detections.py new file mode 100755 index 000000000..d6ab2a4dc --- /dev/null +++ b/tools/rknn/compare_yolov8_detections.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 +"""Compare decoded YOLOv8 detections rather than irrelevant low-score raw boxes.""" + +from __future__ import annotations + +import argparse +import json +from pathlib import Path + +import numpy as np + + +def load_values(path: Path, shape: list[int]) -> np.ndarray: + values = np.load(path) if path.suffix == ".npy" else np.fromfile(path, dtype=np.float32) + if values.size != int(np.prod(shape)): + raise ValueError(f"unexpected value count in {path}") + return values.astype(np.float32, copy=False).reshape(shape) + + +def box_iou(box: np.ndarray, boxes: np.ndarray) -> np.ndarray: + x1 = np.maximum(box[0], boxes[:, 0]) + y1 = np.maximum(box[1], boxes[:, 1]) + x2 = np.minimum(box[2], boxes[:, 2]) + y2 = np.minimum(box[3], boxes[:, 3]) + intersection = np.maximum(0.0, x2 - x1) * np.maximum(0.0, y2 - y1) + area = max(0.0, box[2] - box[0]) * max(0.0, box[3] - box[1]) + other_area = np.maximum(0.0, boxes[:, 2] - boxes[:, 0]) * np.maximum(0.0, boxes[:, 3] - boxes[:, 1]) + return intersection / np.maximum(area + other_area - intersection, 1e-9) + + +def decode( + output: np.ndarray, + confidence: float, + nms_threshold: float, + top_k: int, + class_filter: set[int] | None, +) -> list[dict]: + values = output[0] + class_ids = np.argmax(values[4:], axis=0) + scores = values[4 + class_ids, np.arange(values.shape[1])] + selected = np.flatnonzero(scores >= confidence) + if class_filter is not None: + class_mask = np.fromiter( + (int(class_ids[index]) in class_filter for index in selected), + dtype=np.bool_, + count=selected.size, + ) + selected = selected[class_mask] + if selected.size == 0: + return [] + centers = values[:4, selected].T + boxes = np.empty_like(centers) + boxes[:, 0] = centers[:, 0] - centers[:, 2] / 2 + boxes[:, 1] = centers[:, 1] - centers[:, 3] / 2 + boxes[:, 2] = centers[:, 0] + centers[:, 2] / 2 + boxes[:, 3] = centers[:, 1] + centers[:, 3] / 2 + selected_scores = scores[selected] + selected_classes = class_ids[selected] + keep = [] + for class_id in np.unique(selected_classes): + candidates = np.flatnonzero(selected_classes == class_id) + order = candidates[np.argsort(selected_scores[candidates])[::-1]] + while order.size: + current = int(order[0]) + keep.append(current) + if order.size == 1: + break + remaining = order[1:] + order = remaining[box_iou(boxes[current], boxes[remaining]) <= nms_threshold] + keep = sorted(keep, key=lambda index: float(selected_scores[index]), reverse=True)[:top_k] + return [ + { + "class_id": int(selected_classes[index]), + "score": float(selected_scores[index]), + "box": [float(value) for value in boxes[index]], + } + for index in keep + ] + + +def match(reference: list[dict], actual: list[dict], minimum_iou: float) -> dict: + unmatched_actual = set(range(len(actual))) + matches = [] + for reference_index, expected in enumerate(reference): + candidates = [index for index in unmatched_actual if actual[index]["class_id"] == expected["class_id"]] + if not candidates: + continue + expected_box = np.asarray(expected["box"], dtype=np.float32) + candidate_boxes = np.asarray([actual[index]["box"] for index in candidates], dtype=np.float32) + overlaps = box_iou(expected_box, candidate_boxes) + best_offset = int(np.argmax(overlaps)) + if overlaps[best_offset] < minimum_iou: + continue + actual_index = candidates[best_offset] + unmatched_actual.remove(actual_index) + matches.append( + { + "reference_index": reference_index, + "actual_index": actual_index, + "class_id": expected["class_id"], + "iou": float(overlaps[best_offset]), + "score_error": abs(expected["score"] - actual[actual_index]["score"]), + } + ) + precision = len(matches) / len(actual) if actual else float(not reference) + recall = len(matches) / len(reference) if reference else float(not actual) + f1 = 2 * precision * recall / (precision + recall) if precision + recall else 0.0 + return { + "reference_count": len(reference), + "actual_count": len(actual), + "matched_count": len(matches), + "precision": precision, + "recall": recall, + "f1": f1, + "mean_matched_iou": float(np.mean([item["iou"] for item in matches])) if matches else float(not reference and not actual), + "maximum_matched_score_error": max((item["score_error"] for item in matches), default=0.0), + "matches": matches, + } + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--spec", required=True, type=Path) + parser.add_argument("--precision", required=True, choices=("fp16", "int8")) + parser.add_argument("--reference", required=True, type=Path) + parser.add_argument("--actual", required=True, type=Path) + parser.add_argument("--confidence", type=float, default=0.25) + parser.add_argument("--nms", type=float, default=0.7) + parser.add_argument("--match-iou", type=float, default=0.5) + parser.add_argument("--top-k", type=int, default=1000) + parser.add_argument("--report", type=Path) + args = parser.parse_args() + + spec = json.loads(args.spec.read_text(encoding="utf-8")) + shape = spec["outputs"][0]["shape"] + class_ids = spec["validation"].get("class_ids") + class_filter = set(int(value) for value in class_ids) if class_ids is not None else None + expected = decode(load_values(args.reference, shape), args.confidence, args.nms, args.top_k, class_filter) + observed = decode(load_values(args.actual, shape), args.confidence, args.nms, args.top_k, class_filter) + metrics = match(expected, observed, args.match_iou) + limits = spec["validation"][args.precision] + passed = ( + metrics["f1"] >= limits["minimum_detection_f1"] + and metrics["mean_matched_iou"] >= limits["minimum_matched_iou"] + and metrics["maximum_matched_score_error"] <= limits["maximum_matched_score_error"] + ) + result = { + "passed": passed, + "precision": args.precision, + "thresholds": {"confidence": args.confidence, "nms": args.nms, "match_iou": args.match_iou}, + "class_ids": sorted(class_filter) if class_filter is not None else None, + "limits": { + key: limits[key] + for key in ("minimum_detection_f1", "minimum_matched_iou", "maximum_matched_score_error") + }, + "metrics": metrics, + "reference_detections": expected, + "actual_detections": observed, + } + serialized = json.dumps(result, indent=2, sort_keys=True) + "\n" + if args.report: + args.report.parent.mkdir(parents=True, exist_ok=True) + args.report.write_text(serialized, encoding="utf-8") + print(serialized, end="") + return 0 if passed else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/convert_model.py b/tools/rknn/convert_model.py new file mode 100755 index 000000000..f121ae96c --- /dev/null +++ b/tools/rknn/convert_model.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +"""Build a reproducible RKNN artifact from an ONNX model specification.""" + +from __future__ import annotations + +import argparse +import hashlib +import importlib.metadata +import json +from datetime import datetime, timezone +from pathlib import Path + +import onnx +from rknn.api import RKNN + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def require_success(code: int, action: str) -> None: + if code != 0: + raise RuntimeError(f"{action} failed with RKNN code {code}") + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--spec", required=True, type=Path) + parser.add_argument("--model", required=True, type=Path) + parser.add_argument("--output", required=True, type=Path) + parser.add_argument("--dataset", type=Path, help="RKNN calibration dataset list") + parser.add_argument("--report", type=Path) + parser.add_argument("--quantize", action="store_true") + parser.add_argument("--verbose", action="store_true") + parser.add_argument("--force", action="store_true") + args = parser.parse_args() + + spec_path = args.spec.resolve() + model_path = args.model.resolve() + output_path = args.output.resolve() + report_path = (args.report or output_path.with_suffix(output_path.suffix + ".build.json")).resolve() + if not spec_path.is_file() or not model_path.is_file(): + parser.error("--spec and --model must be existing files") + if args.quantize and (args.dataset is None or not args.dataset.is_file()): + parser.error("--quantize requires an existing --dataset list") + if not args.quantize and args.dataset is not None: + parser.error("--dataset is only valid with --quantize") + for candidate in (output_path, report_path): + if candidate.exists() and not args.force: + parser.error(f"refusing to overwrite {candidate}; pass --force") + + spec = json.loads(spec_path.read_text(encoding="utf-8")) + expected_hash = spec["conversion"].get("input_sha256", spec.get("source_sha256")) + actual_hash = sha256(model_path) + if expected_hash and actual_hash != expected_hash: + raise RuntimeError( + f"source SHA-256 mismatch: expected {expected_hash}, got {actual_hash}; " + "use a spec that identifies this exact model" + ) + + model = onnx.load(model_path) + onnx.checker.check_model(model) + runtime_outputs = spec.get("runtime_outputs") + if runtime_outputs: + actual_outputs = [item.name for item in model.graph.output] + expected_outputs = [item["name"] for item in runtime_outputs] + if actual_outputs != expected_outputs: + raise RuntimeError( + f"runtime output contract mismatch: expected {expected_outputs}, got {actual_outputs}" + ) + opsets = {item.domain: item.version for item in model.opset_import} + default_opset = opsets.get("", 0) + maximum_opset = int(spec["conversion"]["maximum_onnx_opset"]) + if default_opset > maximum_opset: + raise RuntimeError(f"ONNX opset {default_opset} exceeds locked RKNN maximum {maximum_opset}") + maximum_ir = spec["conversion"].get("maximum_onnx_ir_version") + if maximum_ir is not None and model.ir_version > int(maximum_ir): + raise RuntimeError(f"ONNX IR {model.ir_version} exceeds locked maximum {maximum_ir}") + if spec["conversion"].get("preprocessing_owner") != "host": + raise RuntimeError("P0-P4 contract requires preprocessing_owner=host") + + conversion = spec["conversion"] + output_path.parent.mkdir(parents=True, exist_ok=True) + rknn = RKNN(verbose=args.verbose) + try: + # Mean/std are intentionally omitted: CosmoEdge already supplies normalized + # NCHW float tensors and must remain the single preprocessing owner. + require_success( + rknn.config( + target_platform=conversion["target_platform"], + optimization_level=int(conversion["optimization_level"]), + ), + "rknn.config", + ) + require_success(rknn.load_onnx(model=str(model_path)), "rknn.load_onnx") + dataset = str(args.dataset.resolve()) if args.dataset else None + require_success( + rknn.build(do_quantization=args.quantize, dataset=dataset), + "rknn.build", + ) + require_success(rknn.export_rknn(str(output_path)), "rknn.export_rknn") + finally: + rknn.release() + + report = { + "schema_version": 1, + "created_at": datetime.now(timezone.utc).isoformat(), + "rknn_toolkit2_version": importlib.metadata.version("rknn-toolkit2"), + "spec": {"path": str(spec_path), "sha256": sha256(spec_path)}, + "source": { + "path": str(model_path), + "sha256": actual_hash, + "ir_version": model.ir_version, + "opsets": opsets, + "outputs": [item.name for item in model.graph.output], + }, + "build": { + "target_platform": conversion["target_platform"], + "optimization_level": conversion["optimization_level"], + "quantized": args.quantize, + "dataset": str(args.dataset.resolve()) if args.dataset else None, + "dataset_sha256": sha256(args.dataset.resolve()) if args.dataset else None, + "preprocessing_owner": "host", + }, + "artifact": { + "path": str(output_path), + "sha256": sha256(output_path), + "bytes": output_path.stat().st_size, + }, + } + report_path.parent.mkdir(parents=True, exist_ok=True) + report_path.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(json.dumps(report, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/convert_onnx_opset.py b/tools/rknn/convert_onnx_opset.py new file mode 100755 index 000000000..2776d66a9 --- /dev/null +++ b/tools/rknn/convert_onnx_opset.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Convert an ONNX model to the RKNN Toolkit2 supported opset and record provenance.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path + +import onnx + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--input", required=True, type=Path) + parser.add_argument("--output", required=True, type=Path) + parser.add_argument("--opset", required=True, type=int) + parser.add_argument("--ir-version", type=int) + parser.add_argument("--report", type=Path) + parser.add_argument("--force", action="store_true") + args = parser.parse_args() + + source = args.input.resolve() + output = args.output.resolve() + report = (args.report or output.with_suffix(output.suffix + ".provenance.json")).resolve() + if not source.is_file(): + parser.error(f"input does not exist: {source}") + for candidate in (output, report): + if candidate.exists() and not args.force: + parser.error(f"refusing to overwrite {candidate}; pass --force") + + model = onnx.load(source) + source_opsets = {item.domain: item.version for item in model.opset_import} + source_ir = model.ir_version + converted = onnx.version_converter.convert_version(model, args.opset) + if args.ir_version is not None: + converted.ir_version = args.ir_version + onnx.checker.check_model(converted) + + output.parent.mkdir(parents=True, exist_ok=True) + onnx.save(converted, output) + converted_check = onnx.load(output) + onnx.checker.check_model(converted_check) + converted_opsets = {item.domain: item.version for item in converted_check.opset_import} + + provenance = { + "schema_version": 1, + "tool": "onnx.version_converter", + "onnx_version": onnx.__version__, + "source": { + "path": str(source), + "sha256": sha256(source), + "ir_version": source_ir, + "opsets": source_opsets, + }, + "converted": { + "path": str(output), + "sha256": sha256(output), + "ir_version": converted_check.ir_version, + "opsets": converted_opsets, + }, + } + report.parent.mkdir(parents=True, exist_ok=True) + report.write_text(json.dumps(provenance, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(json.dumps(provenance, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/cosmo_rknn_backend_smoke.cc b/tools/rknn/cosmo_rknn_backend_smoke.cc new file mode 100644 index 000000000..d6aa13eaa --- /dev/null +++ b/tools/rknn/cosmo_rknn_backend_smoke.cc @@ -0,0 +1,174 @@ +#include <algorithm> +#include <chrono> +#include <cstdint> +#include <filesystem> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <limits> +#include <numeric> +#include <stdexcept> +#include <string> +#include <vector> + +#include "infer/BmodelTool.h" +#include "nn/core/blob.h" +#include "nn/device/rknn/rknn_net_node.h" +#include "util/Log.h" + +namespace { + +template <typename T> +std::vector<T> ReadFile(const std::filesystem::path& path) { + std::ifstream stream(path, std::ios::binary | std::ios::ate); + if (!stream) + throw std::runtime_error("cannot open " + path.string()); + const auto bytes = stream.tellg(); + if (bytes <= 0 || bytes % static_cast<std::streamoff>(sizeof(T)) != 0) + throw std::runtime_error("invalid byte count for " + path.string()); + std::vector<T> result(static_cast<size_t>(bytes) / sizeof(T)); + stream.seekg(0); + if (!stream.read(reinterpret_cast<char*>(result.data()), bytes)) + throw std::runtime_error("short read from " + path.string()); + return result; +} + +void WriteFile(const std::filesystem::path& path, const void* data, size_t size) { + std::ofstream stream(path, std::ios::binary); + if (!stream || !stream.write(static_cast<const char*>(data), static_cast<std::streamsize>(size))) + throw std::runtime_error("cannot write " + path.string()); +} + +size_t ElementCount(const cosmo::nn::DimsVector& shape) { + size_t count = 1; + for (int dim : shape) { + if (dim <= 0 || count > std::numeric_limits<size_t>::max() / static_cast<size_t>(dim)) + throw std::runtime_error("invalid tensor shape"); + count *= static_cast<size_t>(dim); + } + return count; +} + +std::string ShapeString(const std::vector<int>& shape) { + std::string result; + for (size_t index = 0; index < shape.size(); ++index) { + if (index != 0) + result += "x"; + result += std::to_string(shape[index]); + } + return result; +} + +class LogGuard { +public: + LogGuard() { + cosmo::log::LogInit("cosmo-rknn-backend-smoke", "/tmp", "p3"); + } + ~LogGuard() { + cosmo::log::LogShutDown(); + } +}; + +} // namespace + +int main(int argc, char** argv) { + if (argc < 7 || argc > 8) { + std::cerr << "Usage: " << argv[0] + << " <model.rknn> <input-f32-nchw.bin> <height> <width> <output.bin> <iterations> " + "[warmup=1]\n"; + return 2; + } + + try { + const auto model = ReadFile<unsigned char>(argv[1]); + const auto input = ReadFile<float>(argv[2]); + const int height = std::stoi(argv[3]); + const int width = std::stoi(argv[4]); + const int iterations = std::stoi(argv[6]); + const int warmup = argc == 8 ? std::stoi(argv[7]) : 1; + if (height <= 0 || width <= 0 || iterations <= 0 || warmup < 0 || + input.size() != static_cast<size_t>(3) * height * width) { + throw std::runtime_error("invalid dimensions, iteration count, or input size"); + } + + LogGuard log_guard; + const auto model_info = cosmo::BmodelTool::GetBmodelInfo(argv[1]); + if (!model_info.valid || model_info.networks.size() != 1) + throw std::runtime_error("RKNN model metadata query failed: " + model_info.error_msg); + const auto& network = model_info.networks[0]; + const std::vector<int> expected_input{1, 3, height, width}; + if (network.inputs.size() != 1 || network.inputs[0].shape != expected_input || + network.outputs.size() != 1) { + throw std::runtime_error("RKNN model metadata does not match the smoke contract"); + } + + cosmo::nn::RknnNetNode node; + node.SetNetworkInputNames({"images"}); + node.SetNetworkOutputNames({"output0"}); + auto status = node.LoadWeight(reinterpret_cast<const char*>(model.data()), model.size()); + if (!bool(status)) + throw std::runtime_error(status.description()); + status = node.InferTopShapes(); + if (!bool(status)) + throw std::runtime_error(status.description()); + + const auto top_shapes = node.GetTopBlobShapes(); + if (top_shapes.size() != 1 || network.outputs[0].shape != top_shapes[0]) + throw std::runtime_error("smoke runner requires one logical output"); + + cosmo::nn::BlobDesc bottom_desc; + bottom_desc.device_type = cosmo::nn::DEVICE_NAIVE; + bottom_desc.data_type = cosmo::nn::DATA_TYPE_FLOAT; + bottom_desc.data_format = cosmo::nn::DATA_FORMAT_NCHW; + bottom_desc.dims = {1, 3, height, width}; + cosmo::nn::BlobHandle bottom_handle; + bottom_handle.base = const_cast<float*>(input.data()); + auto bottom = std::make_shared<cosmo::nn::Blob>(bottom_desc, bottom_handle); + + cosmo::nn::BlobDesc top_desc; + top_desc.device_type = cosmo::nn::DEVICE_NAIVE; + top_desc.data_type = cosmo::nn::DATA_TYPE_FLOAT; + top_desc.data_format = cosmo::nn::DATA_FORMAT_NCHW; + top_desc.dims = top_shapes[0]; + auto top = std::make_shared<cosmo::nn::Blob>(top_desc, true); + if (!top->GetHandle().base) + throw std::runtime_error("failed to allocate logical output"); + + std::vector<std::shared_ptr<cosmo::nn::Blob>> bottoms{bottom}; + std::vector<std::shared_ptr<cosmo::nn::Blob>> tops{top}; + for (int index = 0; index < warmup; ++index) { + status = node.Forward(bottoms, tops); + if (!bool(status)) + throw std::runtime_error(status.description()); + } + + std::vector<double> elapsed_ms; + elapsed_ms.reserve(iterations); + for (int index = 0; index < iterations; ++index) { + const auto start = std::chrono::steady_clock::now(); + status = node.Forward(bottoms, tops); + const auto stop = std::chrono::steady_clock::now(); + if (!bool(status)) + throw std::runtime_error(status.description()); + elapsed_ms.push_back(std::chrono::duration<double, std::milli>(stop - start).count()); + } + + const size_t output_count = ElementCount(top_shapes[0]); + WriteFile(argv[5], top->GetHandle().base, output_count * sizeof(float)); + const double sum = std::accumulate(elapsed_ms.begin(), elapsed_ms.end(), 0.0); + const auto minmax = std::minmax_element(elapsed_ms.begin(), elapsed_ms.end()); + std::cout << std::fixed << std::setprecision(4) << "metadata_status=PASS\n" + << "metadata_input_shape=" << ShapeString(network.inputs[0].shape) << "\n" + << "metadata_output_shape=" << ShapeString(network.outputs[0].shape) << "\n" + << "logical_shape="; + for (size_t index = 0; index < top_shapes[0].size(); ++index) + std::cout << (index == 0 ? "" : "x") << top_shapes[0][index]; + std::cout << "\niterations=" << iterations << "\nlatency_mean_ms=" << sum / elapsed_ms.size() + << "\nlatency_min_ms=" << *minmax.first << "\nlatency_max_ms=" << *minmax.second + << "\nbackend_smoke_status=PASS\n"; + return 0; + } catch (const std::exception& error) { + std::cerr << "backend_smoke_status=FAIL error=" << error.what() << '\n'; + return 1; + } +} diff --git a/tools/rknn/cosmo_rknn_fastpath_qualify.cc b/tools/rknn/cosmo_rknn_fastpath_qualify.cc new file mode 100644 index 000000000..ce58ba58d --- /dev/null +++ b/tools/rknn/cosmo_rknn_fastpath_qualify.cc @@ -0,0 +1,620 @@ +// librga 1.10.1 headers use NULL without including a definition. +// clang-format off +#include <cstddef> +// clang-format on + +#include <chrono> +#include <cstdint> +#include <cstdlib> +#include <filesystem> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <limits> +#include <memory> +#include <numeric> +#include <sstream> +#include <stdexcept> +#include <string> +#include <vector> + +// clang-format off +#include <rga/im2d.h> +// clang-format on + +#include "nn/core/blob.h" +#include "nn/core/inference_pipeline_metrics.h" +#include "nn/core/shared_resource.h" +#include "nn/device/cpu/cpu_normalize_node.h" +#include "nn/device/cpu/cpu_resize_node.h" +#include "nn/device/rknn/rknn_net_node.h" +#include "nn/device/rknn/rknn_preprocess_node.h" +#include "nn/node/yolov8_decode_node.h" +#include "nn/utils/op.h" +#include "stb/stb_image.h" +#include "util/Log.h" + +namespace { + +using Clock = std::chrono::steady_clock; +using cosmo::nn::Blob; +using cosmo::nn::BlobDesc; +using cosmo::nn::BlobHandle; +using cosmo::nn::DataFormat; +using cosmo::nn::DataType; +using cosmo::nn::DimsVector; +using cosmo::nn::ImageFormat; +using cosmo::nn::Node; + +template <typename T> +std::vector<T> ReadFile(const std::filesystem::path& path) { + std::ifstream stream(path, std::ios::binary | std::ios::ate); + if (!stream) + throw std::runtime_error("cannot open " + path.string()); + const auto bytes = stream.tellg(); + if (bytes <= 0 || bytes % static_cast<std::streamoff>(sizeof(T)) != 0) + throw std::runtime_error("invalid byte count for " + path.string()); + std::vector<T> result(static_cast<size_t>(bytes) / sizeof(T)); + stream.seekg(0); + if (!stream.read(reinterpret_cast<char*>(result.data()), bytes)) + throw std::runtime_error("short read from " + path.string()); + return result; +} + +void WriteFile(const std::filesystem::path& path, const void* data, size_t size) { + std::filesystem::create_directories(path.parent_path()); + std::ofstream stream(path, std::ios::binary); + if (!stream || !stream.write(static_cast<const char*>(data), static_cast<std::streamsize>(size))) + throw std::runtime_error("cannot write " + path.string()); +} + +std::vector<std::filesystem::path> ReadInputList(const std::filesystem::path& path) { + std::ifstream stream(path); + if (!stream) + throw std::runtime_error("cannot open input list " + path.string()); + std::vector<std::filesystem::path> result; + std::string line; + while (std::getline(stream, line)) { + if (!line.empty() && line.back() == '\r') + line.pop_back(); + if (!line.empty()) + result.emplace_back(line); + } + if (result.empty()) + throw std::runtime_error("input list is empty"); + return result; +} + +std::vector<uint8_t> ReadBgrFrame(const std::filesystem::path& path, int expected_height, + int expected_width) { + if (path.extension() == ".bin") + return ReadFile<uint8_t>(path); + const auto encoded = ReadFile<uint8_t>(path); + int width = 0, height = 0, channels = 0; + std::unique_ptr<unsigned char, decltype(&stbi_image_free)> rgb( + stbi_load_from_memory(encoded.data(), static_cast<int>(encoded.size()), &width, &height, &channels, + 3), + stbi_image_free); + if (!rgb) + throw std::runtime_error("cannot decode image " + path.string()); + if (height != expected_height || width != expected_width) + throw std::runtime_error("decoded image dimensions do not match the qualification contract"); + const size_t bytes = static_cast<size_t>(width) * static_cast<size_t>(height) * 3; + std::vector<uint8_t> bgr(bytes); + for (size_t offset = 0; offset < bytes; offset += 3) { + bgr[offset] = rgb.get()[offset + 2]; + bgr[offset + 1] = rgb.get()[offset + 1]; + bgr[offset + 2] = rgb.get()[offset]; + } + return bgr; +} + +size_t ElementCount(const DimsVector& shape) { + size_t count = 1; + for (int dim : shape) { + if (dim <= 0 || count > std::numeric_limits<size_t>::max() / static_cast<size_t>(dim)) + throw std::runtime_error("invalid tensor shape"); + count *= static_cast<size_t>(dim); + } + return count; +} + +BlobDesc MakeDesc(DataType type, DataFormat format, ImageFormat image_format, DimsVector dims) { + BlobDesc desc; + desc.device_type = cosmo::nn::DEVICE_NAIVE; + desc.data_type = type; + desc.data_format = format; + desc.image_format = image_format; + desc.dims = std::move(dims); + return desc; +} + +std::shared_ptr<Blob> AllocateBlob(const BlobDesc& desc) { + auto blob = std::make_shared<Blob>(desc, true); + if (!blob->GetHandle().base) + throw std::runtime_error("failed to allocate blob"); + return blob; +} + +void CheckStatus(cosmo::nn::Status status, const char* operation) { + if (!status) + throw std::runtime_error(std::string(operation) + ": " + status.description()); +} + +double ElapsedMilliseconds(Clock::time_point started_at) { + return std::chrono::duration<double, std::milli>(Clock::now() - started_at).count(); +} + +struct StageTimes { + double resize_ms{0}; + double normalize_ms{0}; + double network_ms{0}; + double total_ms{0}; +}; + +struct DirectOutputStageTimes { + double network_ms{0}; + double postprocess_ms{0}; + double total_ms{0}; +}; + +class ScopedEnvironmentFlag { +public: + ScopedEnvironmentFlag(const char* name, const char* value) : name_(name) { + if (const char* current = std::getenv(name_)) { + had_value_ = true; + value_ = current; + } + if (setenv(name_, value, 1) != 0) + throw std::runtime_error(std::string("cannot set environment flag ") + name_); + } + + ~ScopedEnvironmentFlag() { + if (had_value_) + setenv(name_, value_.c_str(), 1); + else + unsetenv(name_); + } + +private: + const char* name_; + bool had_value_{false}; + std::string value_; +}; + +struct PathBuffers { + std::unique_ptr<Node> resize; + std::unique_ptr<Node> normalize; + std::shared_ptr<Blob> resized; + std::shared_ptr<Blob> normalized; +}; + +class QualificationRunner { +public: + QualificationRunner(const std::vector<unsigned char>& model, int source_height, int source_width, + bool qualify_rga_bound_input, bool qualify_rga_uint8_input, bool uint8_input_contract) + : source_height_(source_height), + source_width_(source_width), + qualify_rga_bound_input_(qualify_rga_bound_input) { + ConfigurePreprocessing(); + if (uint8_input_contract) + network_.SetInputContract(cosmo::nn::kRknnRgbUint8InputContract); + ConfigureNetwork(network_, model, nullptr, output_); + if (qualify_rga_bound_input_) { + bound_network_ = std::make_unique<cosmo::nn::RknnNetNode>(); + if (qualify_rga_uint8_input) + bound_network_->SetInputContract(cosmo::nn::kRknnRgbUint8InputContract); + ConfigureNetwork(*bound_network_, model, &fast_resource_, bound_output_); + } + } + + StageTimes RunLegacy(const std::vector<uint8_t>& source, const std::filesystem::path& output_path) { + return Run(source, legacy_, network_, output_, output_path); + } + + StageTimes RunFast(const std::vector<uint8_t>& source, const std::filesystem::path& output_path) { + if (bound_network_) + return Run(source, fast_, *bound_network_, bound_output_, output_path); + return Run(source, fast_, network_, output_, output_path); + } + + void DumpLastResizedInputs(const std::filesystem::path& output_dir) const { + constexpr size_t kPackedBytes = static_cast<size_t>(640) * 640 * 3; + WriteFile(output_dir / "legacy-resized.bgr.u8.bin", legacy_.resized->GetHandle().base, kPackedBytes); + WriteFile(output_dir / "fast-resized.rgb.u8.bin", fast_.resized->GetHandle().base, kPackedBytes); + const auto& target = fast_resource_.rknn_bound_input_target; + if (target.Matches(640, 640)) { + WriteFile(output_dir / "rga-bound-input.rgb.u8.bin", target.virtual_address, target.bytes); + } + } + + const std::shared_ptr<Blob>& FastNormalized() const { + return fast_.normalized; + } + + [[nodiscard]] bool UsesRgaBoundInput() const { + return qualify_rga_bound_input_; + } + +private: + void ConfigureNetwork(cosmo::nn::RknnNetNode& network, const std::vector<unsigned char>& model, + cosmo::nn::SharedResource* resource, std::shared_ptr<Blob>& output) { + if (resource) + network.SetSharedResource(resource); + network.SetNetworkInputNames({"images"}); + network.SetNetworkOutputNames({"output0"}); + CheckStatus(network.LoadWeight(reinterpret_cast<const char*>(model.data()), model.size()), + "load RKNN model"); + CheckStatus(network.InferTopShapes(), "infer RKNN output shapes"); + const auto output_shapes = network.GetTopBlobShapes(); + const auto output_types = network.GetTopBlobDataTypes(); + if (output_shapes.size() != 1 || output_types.size() != 1 || + output_types.front() != cosmo::nn::DATA_TYPE_FLOAT) { + throw std::runtime_error("qualification runner requires one logical float output"); + } + output = AllocateBlob(MakeDesc(output_types.front(), cosmo::nn::DATA_FORMAT_NCHW, + cosmo::nn::IMAGE_UNKNOWN, output_shapes.front())); + output_bytes_ = ElementCount(output_shapes.front()) * sizeof(float); + } + + void ConfigurePreprocessing() { + cosmo::nn::Resize resize; + resize.dsize = {640, 640}; + resize.gravity = 1; + resize.color = {114, 114, 114}; + cosmo::nn::Normalize normalize; + normalize.mean = {0.0f, 0.0f, 0.0f}; + normalize.scale = 0.00392157f; + normalize.is_bgr = false; + + legacy_.resize = std::make_unique<cosmo::nn::CpuResizeNode>(); + legacy_.normalize = std::make_unique<cosmo::nn::CpuNormalizeNode>(); + ConfigurePath(legacy_, legacy_resource_, resize, normalize); + + fast_.resize = std::make_unique<cosmo::nn::RknnResizeNode>(); + fast_.normalize = std::make_unique<cosmo::nn::RknnNormalizeNode>(); + ConfigurePath(fast_, fast_resource_, resize, normalize); + } + + static void ConfigurePath(PathBuffers& path, cosmo::nn::SharedResource& resource, + cosmo::nn::Resize& resize, cosmo::nn::Normalize& normalize) { + path.resize->SetSharedResource(&resource); + path.resize->LoadParam(&resize); + CheckStatus(path.resize->InferTopShapes(), "infer resize output shape"); + path.resized = + AllocateBlob(MakeDesc(path.resize->GetTopBlobDataTypes().front(), cosmo::nn::DATA_FORMAT_NHWC, + cosmo::nn::IMAGE_UNKNOWN, path.resize->GetTopBlobShapes().front())); + + path.normalize->SetSharedResource(&resource); + path.normalize->LoadParam(&normalize); + CheckStatus(path.normalize->InferTopShapesWithBottoms({path.resized->GetBlobDesc().dims}, + {path.resized->GetBlobDesc().data_type}), + "infer normalize output shape"); + const auto normalized_type = path.normalize->GetTopBlobDataTypes().front(); + const auto normalized_format = normalized_type == cosmo::nn::DATA_TYPE_INT8 + ? cosmo::nn::DATA_FORMAT_NHWC + : cosmo::nn::DATA_FORMAT_NCHW; + path.normalized = AllocateBlob(MakeDesc(normalized_type, normalized_format, cosmo::nn::IMAGE_RGB, + path.normalize->GetTopBlobShapes().front())); + } + + StageTimes Run(const std::vector<uint8_t>& source, PathBuffers& path, cosmo::nn::RknnNetNode& network, + const std::shared_ptr<Blob>& output, const std::filesystem::path& output_path) { + const size_t expected_bytes = + static_cast<size_t>(source_height_) * static_cast<size_t>(source_width_) * 3; + if (source.size() != expected_bytes) + throw std::runtime_error("source frame byte count does not match dimensions"); + + BlobHandle source_handle; + source_handle.base = const_cast<uint8_t*>(source.data()); + auto source_blob = + std::make_shared<Blob>(MakeDesc(cosmo::nn::DATA_TYPE_UINT8, cosmo::nn::DATA_FORMAT_NHWC, + cosmo::nn::IMAGE_BGR, {1, source_height_, source_width_, 3}), + source_handle); + + StageTimes times; + const auto total_started = Clock::now(); + std::vector<std::shared_ptr<Blob>> resize_bottoms{source_blob}; + std::vector<std::shared_ptr<Blob>> resize_tops{path.resized}; + auto stage_started = Clock::now(); + CheckStatus(path.resize->Forward(resize_bottoms, resize_tops), "resize frame"); + times.resize_ms = ElapsedMilliseconds(stage_started); + + std::vector<std::shared_ptr<Blob>> normalize_bottoms{path.resized}; + std::vector<std::shared_ptr<Blob>> normalize_tops{path.normalized}; + stage_started = Clock::now(); + CheckStatus(path.normalize->Forward(normalize_bottoms, normalize_tops), "normalize frame"); + times.normalize_ms = ElapsedMilliseconds(stage_started); + + std::vector<std::shared_ptr<Blob>> network_bottoms{path.normalized}; + std::vector<std::shared_ptr<Blob>> network_tops{output}; + stage_started = Clock::now(); + CheckStatus(network.Forward(network_bottoms, network_tops), "run RKNN detector"); + times.network_ms = ElapsedMilliseconds(stage_started); + times.total_ms = ElapsedMilliseconds(total_started); + WriteFile(output_path, output->GetHandle().base, output_bytes_); + return times; + } + + int source_height_; + int source_width_; + size_t output_bytes_{0}; + bool qualify_rga_bound_input_{false}; + cosmo::nn::SharedResource legacy_resource_; + cosmo::nn::SharedResource fast_resource_; + std::unique_ptr<cosmo::nn::RknnNetNode> bound_network_; + PathBuffers legacy_; + PathBuffers fast_; + cosmo::nn::RknnNetNode network_; + std::shared_ptr<Blob> output_; + std::shared_ptr<Blob> bound_output_; +}; + +class DirectOutputQualificationRunner { +public: + DirectOutputQualificationRunner(const std::vector<unsigned char>& model, bool uint8_input_contract) { + if (uint8_input_contract) + network_.SetInputContract(cosmo::nn::kRknnRgbUint8InputContract); + network_.SetSharedResource(&resource_); + network_.SetNetworkInputNames({"images"}); + network_.SetNetworkOutputNames({"output0"}); + CheckStatus(network_.LoadWeight(reinterpret_cast<const char*>(model.data()), model.size()), + "load direct-output RKNN model"); + CheckStatus(network_.InferTopShapes(), "infer direct-output RKNN shapes"); + const auto network_shapes = network_.GetTopBlobShapes(); + const auto network_types = network_.GetTopBlobDataTypes(); + if (network_shapes.size() != 1 || network_types.size() != 1 || + network_types.front() != cosmo::nn::DATA_TYPE_FLOAT) { + throw std::runtime_error("direct-output qualification requires one logical float output"); + } + logical_output_ = AllocateBlob(MakeDesc(network_types.front(), cosmo::nn::DATA_FORMAT_NCHW, + cosmo::nn::IMAGE_UNKNOWN, network_shapes.front())); + + cosmo::nn::YoloPost post; + post.nms_threshold = 0.7f; + post.nms_detection_conf = 0.25f; + post.top_k = 1000; + post.input_width = 640; + post.input_height = 640; + decode_.SetSharedResource(&resource_); + decode_.SetMaxBatch(1); + decode_.LoadParam(&post); + CheckStatus(decode_.InferTopShapes(), "infer direct-output YOLOv8 decode shape"); + detection_output_ = + AllocateBlob(MakeDesc(decode_.GetTopBlobDataTypes().front(), cosmo::nn::DATA_FORMAT_NCHW, + cosmo::nn::IMAGE_UNKNOWN, decode_.GetTopBlobShapes().front())); + detection_bytes_ = ElementCount(decode_.GetTopBlobShapes().front()) * sizeof(float); + } + + DirectOutputStageTimes Run(const std::shared_ptr<Blob>& normalized, bool direct, + const std::filesystem::path& output_path) { + ScopedEnvironmentFlag direct_flag("COSMO_RKNN_DIRECT_CANDIDATES", direct ? "1" : "0"); + DirectOutputStageTimes times; + const auto total_started = Clock::now(); + std::vector<std::shared_ptr<Blob>> network_bottoms{normalized}; + std::vector<std::shared_ptr<Blob>> network_tops{logical_output_}; + auto stage_started = Clock::now(); + CheckStatus(network_.Forward(network_bottoms, network_tops), "run direct-output RKNN detector"); + times.network_ms = ElapsedMilliseconds(stage_started); + + std::vector<std::shared_ptr<Blob>> decode_bottoms{logical_output_}; + std::vector<std::shared_ptr<Blob>> decode_tops{detection_output_}; + stage_started = Clock::now(); + CheckStatus(decode_.Forward(decode_bottoms, decode_tops), "decode direct-output detections"); + times.postprocess_ms = ElapsedMilliseconds(stage_started); + times.total_ms = ElapsedMilliseconds(total_started); + WriteFile(output_path, detection_output_->GetHandle().base, detection_bytes_); + return times; + } + +private: + cosmo::nn::SharedResource resource_; + cosmo::nn::RknnNetNode network_; + cosmo::nn::YoloV8DecodeNode decode_; + std::shared_ptr<Blob> logical_output_; + std::shared_ptr<Blob> detection_output_; + size_t detection_bytes_{0}; +}; + +class LogGuard { +public: + LogGuard() { + cosmo::log::LogInit("cosmo-rknn-fastpath-qualify", "/tmp", "qualify"); + } + ~LogGuard() { + cosmo::log::LogShutDown(); + } +}; + +} // namespace + +int main(int argc, char** argv) { + if (argc != 6 && argc != 7) { + std::cerr << "Usage: " << argv[0] + << " <model.rknn> <bgr-input-list.txt> <height> <width> <output-dir> " + "[--direct-output-parity|--direct-output-parity-uint8-contract|" + "--rga-bound-input-parity|--rga-bound-uint8-parity]\n"; + return 2; + } + + try { + const auto model = ReadFile<unsigned char>(argv[1]); + const auto input_paths = ReadInputList(argv[2]); + const int height = std::stoi(argv[3]); + const int width = std::stoi(argv[4]); + const std::filesystem::path output_dir(argv[5]); + const std::string qualification_option = argc == 7 ? argv[6] : ""; + const bool qualify_direct_output = qualification_option == "--direct-output-parity" || + qualification_option == "--direct-output-parity-uint8-contract"; + const bool qualify_direct_output_uint8 = + qualification_option == "--direct-output-parity-uint8-contract"; + const bool qualify_rga_bound_input = argc == 7 && std::string(argv[6]) == "--rga-bound-input-parity"; + const bool qualify_rga_uint8_input = argc == 7 && std::string(argv[6]) == "--rga-bound-uint8-parity"; + if (argc == 7 && !qualify_direct_output && !qualify_rga_bound_input && !qualify_rga_uint8_input) + throw std::runtime_error("unknown qualification option"); + if (height <= 0 || width <= 0) + throw std::runtime_error("source dimensions must be positive"); + std::filesystem::create_directories(output_dir / "legacy"); + std::filesystem::create_directories(output_dir / "fast"); + if (qualify_direct_output) { + std::filesystem::create_directories(output_dir / "output-legacy"); + std::filesystem::create_directories(output_dir / "output-direct"); + } + + LogGuard log_guard; + const auto metrics_before = cosmo::nn::GetInferencePipelineMetrics().Snapshot(); + QualificationRunner runner(model, height, width, qualify_rga_bound_input || qualify_rga_uint8_input, + qualify_rga_uint8_input, qualify_direct_output_uint8); + std::unique_ptr<DirectOutputQualificationRunner> direct_output_runner; + if (qualify_direct_output) + direct_output_runner = + std::make_unique<DirectOutputQualificationRunner>(model, qualify_direct_output_uint8); + std::ofstream timings(output_dir / "timings.tsv"); + if (!timings) + throw std::runtime_error("cannot write timing report"); + timings << "sample\tmode\tresize_ms\tnormalize_ms\tnetwork_ms\ttotal_ms\n"; + timings << std::fixed << std::setprecision(4); + std::ofstream direct_output_timings; + if (qualify_direct_output) { + direct_output_timings.open(output_dir / "direct-output-timings.tsv"); + if (!direct_output_timings) + throw std::runtime_error("cannot write direct-output timing report"); + direct_output_timings << "sample\tmode\tnetwork_ms\tpostprocess_ms\ttotal_ms\n"; + direct_output_timings << std::fixed << std::setprecision(4); + } + + for (size_t index = 0; index < input_paths.size(); ++index) { + const auto source = ReadBgrFrame(input_paths[index], height, width); + const auto sample = "sample-" + [&] { + std::ostringstream stream; + stream << std::setw(4) << std::setfill('0') << index; + return stream.str(); + }(); + const auto legacy = runner.RunLegacy(source, output_dir / "legacy" / (sample + ".f32.bin")); + const auto fast = runner.RunFast(source, output_dir / "fast" / (sample + ".f32.bin")); + const auto write_times = [&](const char* mode, const StageTimes& value) { + timings << sample << '\t' << mode << '\t' << value.resize_ms << '\t' << value.normalize_ms + << '\t' << value.network_ms << '\t' << value.total_ms << '\n'; + }; + write_times("legacy", legacy); + write_times("fast", fast); + if (direct_output_runner) { + const auto legacy_output = direct_output_runner->Run( + runner.FastNormalized(), false, output_dir / "output-legacy" / (sample + ".f32.bin")); + const auto direct_output = direct_output_runner->Run( + runner.FastNormalized(), true, output_dir / "output-direct" / (sample + ".f32.bin")); + const auto write_direct_times = [&](const char* mode, const DirectOutputStageTimes& value) { + direct_output_timings << sample << '\t' << mode << '\t' << value.network_ms << '\t' + << value.postprocess_ms << '\t' << value.total_ms << '\n'; + }; + write_direct_times("legacy-output", legacy_output); + write_direct_times("direct-output", direct_output); + } + if (index == 0) + runner.DumpLastResizedInputs(output_dir / "preprocessed-sample-0000"); + std::cout << "qualified=" << (index + 1) << '/' << input_paths.size() << '\n'; + } + if (qualify_direct_output) { + const auto metrics_after = cosmo::nn::GetInferencePipelineMetrics().Snapshot(); + std::cout << "direct_candidate_calls=" + << metrics_after.rknn_yolov8_direct_candidate_calls - + metrics_before.rknn_yolov8_direct_candidate_calls + << '\n'; + std::cout << "direct_points_scanned=" + << metrics_after.rknn_yolov8_direct_points_scanned - + metrics_before.rknn_yolov8_direct_points_scanned + << '\n'; + std::cout << "direct_points_decoded=" + << metrics_after.rknn_yolov8_direct_points_decoded - + metrics_before.rknn_yolov8_direct_points_decoded + << '\n'; + std::cout << "score_sum_points_rejected=" + << metrics_after.rknn_yolov8_score_sum_points_rejected - + metrics_before.rknn_yolov8_score_sum_points_rejected + << '\n'; + } + if (qualify_direct_output || qualify_rga_bound_input || qualify_rga_uint8_input) { + const auto metrics_after = cosmo::nn::GetInferencePipelineMetrics().Snapshot(); + std::cout << "bound_input_bind_attempts=" + << metrics_after.rknn_bound_input_bind_attempts - + metrics_before.rknn_bound_input_bind_attempts + << '\n'; + std::cout << "bound_input_bind_failures=" + << metrics_after.rknn_bound_input_bind_failures - + metrics_before.rknn_bound_input_bind_failures + << '\n'; + std::cout << "bound_input_frames=" + << metrics_after.rknn_bound_input_frames - metrics_before.rknn_bound_input_frames + << '\n'; + std::cout << "bound_input_copy_bytes=" + << metrics_after.rknn_bound_input_copy_bytes - + metrics_before.rknn_bound_input_copy_bytes + << '\n'; + std::cout << "bound_input_copy_ms=" + << (metrics_after.rknn_bound_input_copy_nanoseconds - + metrics_before.rknn_bound_input_copy_nanoseconds) / + 1000000.0 + << '\n'; + std::cout << "bound_input_sync_ms=" + << (metrics_after.rknn_bound_input_sync_nanoseconds - + metrics_before.rknn_bound_input_sync_nanoseconds) / + 1000000.0 + << '\n'; + std::cout << "rga_bound_input_bind_attempts=" + << metrics_after.rknn_rga_bound_input_bind_attempts - + metrics_before.rknn_rga_bound_input_bind_attempts + << '\n'; + std::cout << "rga_bound_input_bind_failures=" + << metrics_after.rknn_rga_bound_input_bind_failures - + metrics_before.rknn_rga_bound_input_bind_failures + << '\n'; + std::cout << "rga_bound_input_import_calls=" + << metrics_after.rknn_rga_bound_input_import_calls - + metrics_before.rknn_rga_bound_input_import_calls + << '\n'; + std::cout << "rga_bound_input_import_failures=" + << metrics_after.rknn_rga_bound_input_import_failures - + metrics_before.rknn_rga_bound_input_import_failures + << '\n'; + std::cout << "rga_bound_input_frames=" + << metrics_after.rknn_rga_bound_input_frames - + metrics_before.rknn_rga_bound_input_frames + << '\n'; + std::cout << "rga_bound_uint8_frames=" + << metrics_after.rknn_rga_bound_uint8_frames - + metrics_before.rknn_rga_bound_uint8_frames + << '\n'; + std::cout << "rga_bound_native_int8_frames=" + << metrics_after.rknn_rga_bound_native_int8_frames - + metrics_before.rknn_rga_bound_native_int8_frames + << '\n'; + std::cout << "rga_bound_requantize_calls=" + << metrics_after.rknn_rga_bound_requantize_calls - + metrics_before.rknn_rga_bound_requantize_calls + << '\n'; + std::cout << "rga_bound_requantize_ms=" + << (metrics_after.rknn_rga_bound_requantize_nanoseconds - + metrics_before.rknn_rga_bound_requantize_nanoseconds) / + 1000000.0 + << '\n'; + std::cout << "rga_bound_requantize_failures=" + << metrics_after.rknn_rga_bound_requantize_failures - + metrics_before.rknn_rga_bound_requantize_failures + << '\n'; + std::cout << "rga_bound_input_normalize_bypasses=" + << metrics_after.rknn_rga_bound_input_normalize_bypasses - + metrics_before.rknn_rga_bound_input_normalize_bypasses + << '\n'; + std::cout << "rknn_inputs_set_calls=" + << metrics_after.rknn_inputs_set_calls - metrics_before.rknn_inputs_set_calls << '\n'; + std::cout << "uint8_contract_inputs=" + << metrics_after.rknn_uint8_contract_inputs - metrics_before.rknn_uint8_contract_inputs + << '\n'; + } + std::cout << "fastpath_qualification_status=PASS samples=" << input_paths.size() << '\n'; + return 0; + } catch (const std::exception& error) { + std::cerr << "fastpath_qualification_status=FAIL error=" << error.what() << '\n'; + return 1; + } +} diff --git a/tools/rknn/extract_yolov8_heads.py b/tools/rknn/extract_yolov8_heads.py new file mode 100755 index 000000000..e62a5d72b --- /dev/null +++ b/tools/rknn/extract_yolov8_heads.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Extract YOLOv8 box/class heads so DFL and sigmoid stay on the host.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path + +import onnx + + +OUTPUT_NAMES = [ + f"/model.22/{kind}.{branch}/{kind}.{branch}.2/Conv_output_0" + for branch in range(3) + for kind in ("cv2", "cv3") +] + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--input", required=True, type=Path) + parser.add_argument("--output", required=True, type=Path) + parser.add_argument("--report", type=Path) + parser.add_argument("--force", action="store_true") + args = parser.parse_args() + source = args.input.resolve() + output = args.output.resolve() + report = (args.report or output.with_suffix(output.suffix + ".provenance.json")).resolve() + if not source.is_file(): + parser.error(f"input does not exist: {source}") + for candidate in (output, report): + if candidate.exists() and not args.force: + parser.error(f"refusing to overwrite {candidate}; pass --force") + + inferred = onnx.shape_inference.infer_shapes(onnx.load(source)) + known_values = { + item.name: item for item in list(inferred.graph.value_info) + list(inferred.graph.output) + } + missing = [name for name in OUTPUT_NAMES if name not in known_values] + if missing: + raise RuntimeError(f"source is not the expected YOLOv8 graph; missing outputs: {missing}") + extractor = onnx.utils.Extractor(inferred) + extracted = extractor.extract_model(["images"], OUTPUT_NAMES) + onnx.checker.check_model(extracted) + output.parent.mkdir(parents=True, exist_ok=True) + onnx.save(extracted, output) + checked = onnx.load(output) + onnx.checker.check_model(checked) + output_shapes = [ + [dimension.dim_value for dimension in item.type.tensor_type.shape.dim] + for item in checked.graph.output + ] + provenance = { + "schema_version": 1, + "tool": "onnx.utils.Extractor", + "onnx_version": onnx.__version__, + "source": {"path": str(source), "sha256": sha256(source)}, + "extracted": { + "path": str(output), + "sha256": sha256(output), + "outputs": [ + {"name": name, "shape": shape} for name, shape in zip(OUTPUT_NAMES, output_shapes) + ], + }, + "host_output_adapter": "yolo_dfl_6head_v1", + } + report.parent.mkdir(parents=True, exist_ok=True) + report.write_text(json.dumps(provenance, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(json.dumps(provenance, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/prepare_validation_data.py b/tools/rknn/prepare_validation_data.py new file mode 100755 index 000000000..d45746eff --- /dev/null +++ b/tools/rknn/prepare_validation_data.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python3 +"""Create deterministic RKNN calibration and numerical-validation inputs.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path + +import cv2 +import numpy as np +import onnxruntime as ort + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def resize_image(image: np.ndarray, config: dict) -> tuple[np.ndarray, dict]: + _, _, target_h, target_w = config["shape"] + if config["resize"] == "stretch": + resized = cv2.resize(image, (target_w, target_h), interpolation=cv2.INTER_LINEAR) + return resized, {"scale": [target_w / image.shape[1], target_h / image.shape[0]], "pad": [0, 0]} + if config["resize"] != "letterbox_center": + raise ValueError(f"unsupported resize mode: {config['resize']}") + scale = min(target_w / image.shape[1], target_h / image.shape[0]) + new_w = int(image.shape[1] * scale) + new_h = int(image.shape[0] * scale) + resized = cv2.resize(image, (new_w, new_h), interpolation=cv2.INTER_LINEAR) + canvas = np.full((target_h, target_w, 3), config["padding_color"], dtype=np.uint8) + pad_x = (target_w - new_w) // 2 + pad_y = (target_h - new_h) // 2 + canvas[pad_y : pad_y + new_h, pad_x : pad_x + new_w] = resized + return canvas, {"scale": [scale, scale], "pad": [pad_x, pad_y]} + + +def preprocess(image: np.ndarray, config: dict) -> tuple[np.ndarray, dict]: + resized, transform = resize_image(image, config) + if config["color"] == "RGB": + resized = cv2.cvtColor(resized, cv2.COLOR_BGR2RGB) + elif config["color"] != "BGR": + raise ValueError(f"unsupported color format: {config['color']}") + values = resized.astype(np.float32) + mean = np.asarray(config["mean"], dtype=np.float32).reshape(1, 1, 3) + values = (values - mean) * np.float32(config["scale"]) + if config["layout"] == "NCHW": + values = np.transpose(values, (2, 0, 1))[None] + else: + raise ValueError(f"unsupported layout: {config['layout']}") + return np.ascontiguousarray(values), transform + + +def iou_one_to_many(box: np.ndarray, boxes: np.ndarray) -> np.ndarray: + x1 = np.maximum(box[0], boxes[:, 0]) + y1 = np.maximum(box[1], boxes[:, 1]) + x2 = np.minimum(box[2], boxes[:, 2]) + y2 = np.minimum(box[3], boxes[:, 3]) + intersection = np.maximum(0.0, x2 - x1) * np.maximum(0.0, y2 - y1) + box_area = max(0.0, box[2] - box[0]) * max(0.0, box[3] - box[1]) + areas = np.maximum(0.0, boxes[:, 2] - boxes[:, 0]) * np.maximum(0.0, boxes[:, 3] - boxes[:, 1]) + return intersection / np.maximum(box_area + areas - intersection, 1e-9) + + +def nms(boxes: np.ndarray, scores: np.ndarray, threshold: float) -> list[int]: + order = np.argsort(scores)[::-1] + keep: list[int] = [] + while order.size: + current = int(order[0]) + keep.append(current) + if order.size == 1: + break + remaining = order[1:] + order = remaining[iou_one_to_many(boxes[current], boxes[remaining]) <= threshold] + return keep + + +class PersonDetector: + def __init__(self, model_path: Path, confidence: float = 0.25, nms_threshold: float = 0.45): + self.session = ort.InferenceSession(str(model_path), providers=["CPUExecutionProvider"]) + self.input_name = self.session.get_inputs()[0].name + self.confidence = confidence + self.nms_threshold = nms_threshold + self.config = { + "shape": [1, 3, 640, 640], + "resize": "letterbox_center", + "padding_color": [114, 114, 114], + "color": "RGB", + "mean": [0.0, 0.0, 0.0], + "scale": 1.0 / 255.0, + "layout": "NCHW", + } + + def detect(self, image: np.ndarray) -> list[dict]: + tensor, transform = preprocess(image, self.config) + output = self.session.run(None, {self.input_name: tensor})[0][0] + scores = output[4] + selected = np.flatnonzero(scores >= self.confidence) + if selected.size == 0: + return [] + center_boxes = output[:4, selected].T + boxes = np.empty_like(center_boxes) + boxes[:, 0] = center_boxes[:, 0] - center_boxes[:, 2] / 2 + boxes[:, 1] = center_boxes[:, 1] - center_boxes[:, 3] / 2 + boxes[:, 2] = center_boxes[:, 0] + center_boxes[:, 2] / 2 + boxes[:, 3] = center_boxes[:, 1] + center_boxes[:, 3] / 2 + chosen_scores = scores[selected] + scale = transform["scale"][0] + pad_x, pad_y = transform["pad"] + boxes[:, [0, 2]] = (boxes[:, [0, 2]] - pad_x) / scale + boxes[:, [1, 3]] = (boxes[:, [1, 3]] - pad_y) / scale + boxes[:, [0, 2]] = np.clip(boxes[:, [0, 2]], 0, image.shape[1]) + boxes[:, [1, 3]] = np.clip(boxes[:, [1, 3]], 0, image.shape[0]) + results = [] + for index in nms(boxes, chosen_scores, self.nms_threshold): + x1, y1, x2, y2 = boxes[index] + if x2 - x1 >= 8 and y2 - y1 >= 8: + results.append({"box": [float(x1), float(y1), float(x2), float(y2)], "score": float(chosen_scores[index])}) + return results + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--spec", required=True, type=Path) + parser.add_argument("--video", required=True, type=Path) + parser.add_argument("--output-dir", required=True, type=Path) + parser.add_argument("--samples", type=int, default=32) + parser.add_argument("--frame-offset", type=int, default=0) + parser.add_argument("--person-detector", type=Path) + parser.add_argument("--max-crops-per-frame", type=int, default=3) + args = parser.parse_args() + if args.samples <= 0: + parser.error("--samples must be positive") + + spec_path = args.spec.resolve() + video_path = args.video.resolve() + output_dir = args.output_dir.resolve() + spec = json.loads(spec_path.read_text(encoding="utf-8")) + if not video_path.is_file(): + parser.error(f"video does not exist: {video_path}") + if spec["model_type"] == "classify" and args.person_detector is None: + parser.error("classifier calibration requires --person-detector for representative person crops") + detector = PersonDetector(args.person_detector.resolve()) if args.person_detector else None + + inputs_dir = output_dir / "inputs" + sources_dir = output_dir / "sources" + inputs_dir.mkdir(parents=True, exist_ok=True) + sources_dir.mkdir(parents=True, exist_ok=True) + capture = cv2.VideoCapture(str(video_path)) + if not capture.isOpened(): + raise RuntimeError(f"cannot decode video: {video_path}") + frame_count = int(capture.get(cv2.CAP_PROP_FRAME_COUNT)) + # Oversample candidate frames because classifier preparation can yield + # several or zero person crops per frame. + candidate_count = min(frame_count, max(args.samples * 3, args.samples + args.frame_offset)) + frame_indices = np.linspace(args.frame_offset, frame_count - 1, candidate_count, dtype=int) + + records = [] + for frame_index in frame_indices: + if len(records) >= args.samples: + break + capture.set(cv2.CAP_PROP_POS_FRAMES, int(frame_index)) + ok, frame = capture.read() + if not ok: + continue + selections = [{"image": frame, "detection": None}] + if detector: + selections = [] + for detection in detector.detect(frame)[: args.max_crops_per_frame]: + x1, y1, x2, y2 = [int(round(value)) for value in detection["box"]] + crop = frame[max(0, y1) : min(frame.shape[0], y2), max(0, x1) : min(frame.shape[1], x2)] + if crop.size: + selections.append({"image": crop, "detection": detection}) + for selection in selections: + if len(records) >= args.samples: + break + sample_id = f"sample-{len(records):04d}" + tensor, transform = preprocess(selection["image"], spec["input"]) + npy_path = inputs_dir / f"{sample_id}.npy" + bin_path = inputs_dir / f"{sample_id}.f32.bin" + image_path = sources_dir / f"{sample_id}.jpg" + np.save(npy_path, tensor) + tensor.tofile(bin_path) + cv2.imwrite(str(image_path), selection["image"]) + records.append( + { + "id": sample_id, + "frame_index": int(frame_index), + "detection": selection["detection"], + "transform": transform, + "tensor": { + "shape": list(tensor.shape), + "dtype": str(tensor.dtype), + "npy": str(npy_path), + "npy_sha256": sha256(npy_path), + "bin": str(bin_path), + "bin_sha256": sha256(bin_path), + }, + "source_image": str(image_path), + } + ) + capture.release() + if len(records) < args.samples: + raise RuntimeError(f"only prepared {len(records)} of {args.samples} requested samples") + + dataset_path = output_dir / "dataset.txt" + dataset_path.write_text("".join(record["tensor"]["npy"] + "\n" for record in records), encoding="utf-8") + manifest = { + "schema_version": 1, + "spec": {"path": str(spec_path), "sha256": sha256(spec_path)}, + "video": {"path": str(video_path), "sha256": sha256(video_path), "frame_count": frame_count}, + "person_detector": ( + {"path": str(args.person_detector.resolve()), "sha256": sha256(args.person_detector.resolve())} + if args.person_detector + else None + ), + "labeled": False, + "purpose": "representative calibration and numerical parity; not an accuracy benchmark", + "samples": records, + "dataset": {"path": str(dataset_path), "sha256": sha256(dataset_path)}, + } + manifest_path = output_dir / "manifest.json" + manifest_path.write_text(json.dumps(manifest, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(f"prepared_samples={len(records)}") + print(f"dataset={dataset_path}") + print(f"manifest={manifest_path}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/qualify_yolov8_fastpath.py b/tools/rknn/qualify_yolov8_fastpath.py new file mode 100644 index 000000000..e719befc3 --- /dev/null +++ b/tools/rknn/qualify_yolov8_fastpath.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python3 +"""Qualify fixed-frame YOLOv8 detection parity between legacy and fast paths.""" + +from __future__ import annotations + +import argparse +import json +import math +from collections import Counter +from pathlib import Path + +import numpy as np + +from compare_yolov8_detections import decode, load_values, match + + +def parse_shape(raw: str) -> list[int]: + try: + shape = [int(value) for value in raw.lower().split("x")] + except ValueError as error: + raise argparse.ArgumentTypeError("shape must contain integer dimensions") from error + if not shape or any(value <= 0 for value in shape): + raise argparse.ArgumentTypeError("shape dimensions must be positive") + return shape + + +def invalid_box_counts(detections: list[dict], input_size: int) -> tuple[int, int]: + invalid = 0 + out_of_bounds = 0 + for detection in detections: + box = detection["box"] + values = [*box, detection["score"]] + if not all(math.isfinite(value) for value in values) or box[2] <= box[0] or box[3] <= box[1]: + invalid += 1 + if box[0] < 0 or box[1] < 0 or box[2] > input_size or box[3] > input_size: + out_of_bounds += 1 + return invalid, out_of_bounds + + +def output_files(directory: Path) -> list[Path]: + return sorted(directory.glob("*.f32.bin")) + + +def decode_candidate_output( + output: np.ndarray, + confidence: float, + top_k: int, + class_filter: set[int] | None, +) -> list[dict]: + rows = output.reshape(-1, 6) + detections = [] + for row in rows: + score = float(row[4]) + class_id = int(row[5]) + if not math.isfinite(score) or score < confidence: + continue + if class_filter is not None and class_id not in class_filter: + continue + center_x, center_y, width, height = (float(value) for value in row[:4]) + detections.append( + { + "class_id": class_id, + "score": score, + "box": [ + center_x - width / 2, + center_y - height / 2, + center_x + width / 2, + center_y + height / 2, + ], + } + ) + if len(detections) >= top_k: + break + return detections + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--reference-dir", required=True, type=Path) + parser.add_argument("--actual-dir", required=True, type=Path) + parser.add_argument("--report", required=True, type=Path) + parser.add_argument("--shape", type=parse_shape, default=parse_shape("1x84x8400")) + parser.add_argument("--input-size", type=int, default=640) + parser.add_argument("--confidence", type=float, default=0.25) + parser.add_argument("--nms", type=float, default=0.7) + parser.add_argument("--match-iou", type=float, default=0.5) + parser.add_argument("--top-k", type=int, default=1000) + parser.add_argument("--class-id", type=int, action="append") + parser.add_argument( + "--candidate-output", + action="store_true", + help="inputs are post-NMS [batch, top_k, 6] candidate tensors", + ) + parser.add_argument("--minimum-precision", type=float, default=0.99) + parser.add_argument("--minimum-recall", type=float, default=0.99) + parser.add_argument("--minimum-median-iou", type=float, default=0.99) + parser.add_argument("--minimum-p5-iou", type=float, default=0.95) + parser.add_argument("--maximum-confidence-difference", type=float, default=0.03) + parser.add_argument("--maximum-class-count-delta-ratio", type=float, default=0.01) + args = parser.parse_args() + + reference_paths = output_files(args.reference_dir) + actual_paths = output_files(args.actual_dir) + if not reference_paths: + parser.error("reference directory contains no *.f32.bin files") + if [path.name for path in reference_paths] != [path.name for path in actual_paths]: + parser.error("reference and actual file sets differ") + class_filter = set(args.class_id) if args.class_id else None + + ious: list[float] = [] + score_errors: list[float] = [] + reference_total = 0 + actual_total = 0 + matched_total = 0 + reference_classes: Counter[int] = Counter() + actual_classes: Counter[int] = Counter() + empty_regressions = 0 + nonfinite_frames = 0 + reference_invalid = 0 + actual_invalid = 0 + reference_out_of_bounds = 0 + actual_out_of_bounds = 0 + frames = [] + + for reference_path, actual_path in zip(reference_paths, actual_paths): + reference_values = load_values(reference_path, args.shape) + actual_values = load_values(actual_path, args.shape) + if not np.isfinite(reference_values).all() or not np.isfinite(actual_values).all(): + nonfinite_frames += 1 + if args.candidate_output: + reference = decode_candidate_output( + reference_values, args.confidence, args.top_k, class_filter + ) + actual = decode_candidate_output( + actual_values, args.confidence, args.top_k, class_filter + ) + else: + reference = decode( + reference_values, args.confidence, args.nms, args.top_k, class_filter + ) + actual = decode( + actual_values, args.confidence, args.nms, args.top_k, class_filter + ) + matching = match(reference, actual, args.match_iou) + frame_ious = [item["iou"] for item in matching["matches"]] + frame_score_errors = [item["score_error"] for item in matching["matches"]] + ious.extend(frame_ious) + score_errors.extend(frame_score_errors) + reference_total += len(reference) + actual_total += len(actual) + matched_total += len(frame_ious) + reference_classes.update(item["class_id"] for item in reference) + actual_classes.update(item["class_id"] for item in actual) + empty_regressions += int(bool(reference) and not actual) + ref_invalid, ref_oob = invalid_box_counts(reference, args.input_size) + act_invalid, act_oob = invalid_box_counts(actual, args.input_size) + reference_invalid += ref_invalid + actual_invalid += act_invalid + reference_out_of_bounds += ref_oob + actual_out_of_bounds += act_oob + frames.append( + { + "sample": reference_path.name.removesuffix(".f32.bin"), + "reference_detections": len(reference), + "actual_detections": len(actual), + "matched_detections": len(frame_ious), + "median_iou": float(np.median(frame_ious)) if frame_ious else None, + "maximum_confidence_difference": max(frame_score_errors, default=0.0), + } + ) + + precision = matched_total / actual_total if actual_total else float(reference_total == 0) + recall = matched_total / reference_total if reference_total else float(actual_total == 0) + all_class_ids = sorted(reference_classes.keys() | actual_classes.keys()) + class_count_deltas = { + str(class_id): actual_classes[class_id] - reference_classes[class_id] + for class_id in all_class_ids + } + maximum_class_delta = max((abs(value) for value in class_count_deltas.values()), default=0) + allowed_class_delta = max( + 1, math.ceil(reference_total * args.maximum_class_count_delta_ratio) + ) + metrics = { + "frames": len(reference_paths), + "reference_detections": reference_total, + "actual_detections": actual_total, + "matched_detections": matched_total, + "precision": precision, + "recall": recall, + "median_iou": float(np.median(ious)) if ious else 0.0, + "p5_iou": float(np.percentile(ious, 5)) if ious else 0.0, + "maximum_confidence_difference": max(score_errors, default=0.0), + "median_confidence_difference": float(np.median(score_errors)) if score_errors else 0.0, + "reference_class_histogram": dict(sorted(reference_classes.items())), + "actual_class_histogram": dict(sorted(actual_classes.items())), + "class_count_deltas": class_count_deltas, + "maximum_class_count_delta": maximum_class_delta, + "allowed_class_count_delta": allowed_class_delta, + "empty_regressions": empty_regressions, + "nonfinite_frames": nonfinite_frames, + "reference_invalid_boxes": reference_invalid, + "actual_invalid_boxes": actual_invalid, + "reference_out_of_bounds_boxes": reference_out_of_bounds, + "actual_out_of_bounds_boxes": actual_out_of_bounds, + } + gates = { + "precision": precision >= args.minimum_precision, + "recall": recall >= args.minimum_recall, + "median_iou": metrics["median_iou"] >= args.minimum_median_iou, + "p5_iou": metrics["p5_iou"] >= args.minimum_p5_iou, + "confidence_difference": metrics["maximum_confidence_difference"] + <= args.maximum_confidence_difference, + "no_systematic_class_change": maximum_class_delta <= allowed_class_delta, + "no_new_empty_results": empty_regressions == 0, + "no_nonfinite_results": nonfinite_frames == 0, + "no_new_invalid_boxes": actual_invalid <= reference_invalid, + "no_new_out_of_bounds_boxes": actual_out_of_bounds <= reference_out_of_bounds, + } + report = { + "passed": all(gates.values()), + "inputs": { + "reference_dir": str(args.reference_dir.resolve()), + "actual_dir": str(args.actual_dir.resolve()), + "shape": args.shape, + "candidate_output": args.candidate_output, + "class_filter": sorted(class_filter) if class_filter else None, + "confidence": args.confidence, + "nms": args.nms, + "match_iou": args.match_iou, + }, + "limits": { + "minimum_precision": args.minimum_precision, + "minimum_recall": args.minimum_recall, + "minimum_median_iou": args.minimum_median_iou, + "minimum_p5_iou": args.minimum_p5_iou, + "maximum_confidence_difference": args.maximum_confidence_difference, + "maximum_class_count_delta_ratio": args.maximum_class_count_delta_ratio, + }, + "gates": gates, + "metrics": metrics, + "frame_results": frames, + } + serialized = json.dumps(report, indent=2, sort_keys=True) + "\n" + args.report.parent.mkdir(parents=True, exist_ok=True) + args.report.write_text(serialized, encoding="utf-8") + print(serialized, end="") + return 0 if report["passed"] else 1 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/reconstruct_yolov8_output.py b/tools/rknn/reconstruct_yolov8_output.py new file mode 100755 index 000000000..07b3ae1b4 --- /dev/null +++ b/tools/rknn/reconstruct_yolov8_output.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +"""Reconstruct the standard [1,84,8400] YOLOv8 tensor from six RKNN heads.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +from pathlib import Path + +import numpy as np + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def load_head(path: Path, shape: list[int]) -> np.ndarray: + values = np.load(path) if path.suffix == ".npy" else np.fromfile(path, dtype=np.float32) + if values.size != int(np.prod(shape)): + raise ValueError(f"{path} has {values.size} values, expected {int(np.prod(shape))}") + return values.astype(np.float32, copy=False).reshape(shape) + + +def sigmoid(values: np.ndarray) -> np.ndarray: + positive = values >= 0 + result = np.empty_like(values, dtype=np.float32) + result[positive] = 1.0 / (1.0 + np.exp(-values[positive])) + exponential = np.exp(values[~positive]) + result[~positive] = exponential / (1.0 + exponential) + return result + + +def reconstruct(heads: list[np.ndarray], input_size: int) -> np.ndarray: + if len(heads) != 6: + raise ValueError("yolo_dfl_6head_v1 requires three box/class head pairs") + branches = [] + weights = np.arange(16, dtype=np.float32).reshape(1, 1, 16, 1, 1) + for branch in range(3): + box_logits = heads[branch * 2] + class_logits = heads[branch * 2 + 1] + batch, channels, height, width = box_logits.shape + if channels != 64 or class_logits.shape != (batch, 80, height, width): + raise ValueError("unexpected YOLOv8 head shape") + distributions = box_logits.reshape(batch, 4, 16, height, width) + distributions = distributions - np.max(distributions, axis=2, keepdims=True) + distributions = np.exp(distributions) + distributions /= np.sum(distributions, axis=2, keepdims=True) + distances = np.sum(distributions * weights, axis=2) + rows, columns = np.meshgrid(np.arange(height), np.arange(width), indexing="ij") + grid = np.stack([columns, rows], axis=0).reshape(1, 2, height, width) + 0.5 + upper_left = grid - distances[:, :2] + lower_right = grid + distances[:, 2:] + xy = (upper_left + lower_right) / 2.0 + wh = lower_right - upper_left + coordinates = np.concatenate([xy, wh], axis=1) * (input_size // height) + probabilities = sigmoid(class_logits) + branches.append( + np.concatenate( + [coordinates.reshape(batch, 4, -1), probabilities.reshape(batch, 80, -1)], + axis=1, + ) + ) + return np.ascontiguousarray(np.concatenate(branches, axis=2), dtype=np.float32) + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--spec", required=True, type=Path) + parser.add_argument("--input-dir", required=True, type=Path) + parser.add_argument("--output", required=True, type=Path) + parser.add_argument("--report", type=Path) + args = parser.parse_args() + + spec = json.loads(args.spec.read_text(encoding="utf-8")) + if spec["conversion"].get("output_adapter") != "yolo_dfl_6head_v1": + raise ValueError("spec does not select yolo_dfl_6head_v1") + runtime_outputs = spec["runtime_outputs"] + input_paths = [args.input_dir / f"output-{index}.f32.bin" for index in range(len(runtime_outputs))] + heads = [load_head(path, item["shape"]) for path, item in zip(input_paths, runtime_outputs)] + logical = reconstruct(heads, int(spec["input"]["shape"][2])) + expected_shape = spec["outputs"][0]["shape"] + if list(logical.shape) != expected_shape: + raise ValueError(f"logical output shape {list(logical.shape)} does not match {expected_shape}") + + output_path = args.output.resolve() + if output_path.suffix != ".npy": + parser.error("--output must end in .npy") + output_path.parent.mkdir(parents=True, exist_ok=True) + np.save(output_path, logical) + binary_path = output_path.with_suffix(".f32.bin") + logical.tofile(binary_path) + report = { + "schema_version": 1, + "adapter": "yolo_dfl_6head_v1", + "inputs": [ + {"path": str(path.resolve()), "sha256": sha256(path.resolve()), "shape": item["shape"]} + for path, item in zip(input_paths, runtime_outputs) + ], + "output": { + "path": str(output_path), + "sha256": sha256(output_path), + "binary_path": str(binary_path), + "binary_sha256": sha256(binary_path), + "shape": list(logical.shape), + }, + } + report_path = (args.report or output_path.with_suffix(".reconstruction.json")).resolve() + report_path.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(json.dumps(report, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/rknn/rknn_model_runner.cc b/tools/rknn/rknn_model_runner.cc new file mode 100644 index 000000000..0a414bc65 --- /dev/null +++ b/tools/rknn/rknn_model_runner.cc @@ -0,0 +1,330 @@ +#include <algorithm> +#include <chrono> +#include <cstdint> +#include <filesystem> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <limits> +#include <numeric> +#include <string> +#include <vector> + +#include "rknn_api.h" + +namespace { + +class ContextGuard { +public: + ~ContextGuard() { + if (context_ != 0) { + rknn_destroy(context_); + } + } + rknn_context* Out() { + return &context_; + } + rknn_context Get() const { + return context_; + } + +private: + rknn_context context_{0}; +}; + +template <typename T> +std::vector<T> ReadFile(const std::filesystem::path& path) { + std::ifstream stream(path, std::ios::binary | std::ios::ate); + if (!stream) { + throw std::runtime_error("cannot open: " + path.string()); + } + const auto bytes = stream.tellg(); + if (bytes <= 0 || bytes % static_cast<std::streamoff>(sizeof(T)) != 0) { + throw std::runtime_error("invalid byte count: " + path.string()); + } + std::vector<T> data(static_cast<std::size_t>(bytes) / sizeof(T)); + stream.seekg(0); + stream.read(reinterpret_cast<char*>(data.data()), bytes); + if (!stream) { + throw std::runtime_error("short read: " + path.string()); + } + return data; +} + +void WriteFile(const std::filesystem::path& path, const void* data, std::size_t bytes) { + std::ofstream stream(path, std::ios::binary); + if (!stream) { + throw std::runtime_error("cannot create: " + path.string()); + } + stream.write(static_cast<const char*>(data), static_cast<std::streamsize>(bytes)); + if (!stream) { + throw std::runtime_error("short write: " + path.string()); + } +} + +void Check(int result, const std::string& action) { + if (result != RKNN_SUCC) { + throw std::runtime_error(action + " failed with RKNN code " + std::to_string(result)); + } +} + +rknn_core_mask ParseCoreMask(const std::string& value) { + if (value == "auto") + return RKNN_NPU_CORE_AUTO; + if (value == "0") + return RKNN_NPU_CORE_0; + if (value == "1") + return RKNN_NPU_CORE_1; + if (value == "01") + return RKNN_NPU_CORE_0_1; + throw std::runtime_error("core mask must be one of: auto, 0, 1, 01"); +} + +std::size_t ElementCount(const rknn_tensor_attr& attr) { + if (attr.n_elems != 0) { + return attr.n_elems; + } + return std::accumulate(attr.dims, attr.dims + attr.n_dims, std::size_t{1}, + [](std::size_t product, std::uint32_t value) { return product * value; }); +} + +std::string Shape(const rknn_tensor_attr& attr) { + std::string result; + for (std::uint32_t index = 0; index < attr.n_dims; ++index) { + if (!result.empty()) { + result += 'x'; + } + result += std::to_string(attr.dims[index]); + } + return result; +} + +void PrintTiming(const char* name, const std::vector<double>& values) { + const auto sum = std::accumulate(values.begin(), values.end(), 0.0); + const auto minmax = std::minmax_element(values.begin(), values.end()); + std::cout << name << "_mean_ms=" << sum / values.size() << '\n'; + std::cout << name << "_min_ms=" << *minmax.first << '\n'; + std::cout << name << "_max_ms=" << *minmax.second << '\n'; +} + +std::vector<float> NchwToNhwc(const std::vector<float>& source, const rknn_tensor_attr& attr) { + if (attr.n_dims != 4) { + throw std::runtime_error("validation runner requires a four-dimensional image input"); + } + std::size_t batch = attr.dims[0]; + std::size_t channels = 0; + std::size_t height = 0; + std::size_t width = 0; + if (attr.fmt == RKNN_TENSOR_NCHW) { + channels = attr.dims[1]; + height = attr.dims[2]; + width = attr.dims[3]; + } else if (attr.fmt == RKNN_TENSOR_NHWC) { + height = attr.dims[1]; + width = attr.dims[2]; + channels = attr.dims[3]; + } else { + throw std::runtime_error("validation runner supports only NCHW/NHWC native inputs"); + } + std::vector<float> result(source.size()); + for (std::size_t n = 0; n < batch; ++n) { + for (std::size_t c = 0; c < channels; ++c) { + for (std::size_t h = 0; h < height; ++h) { + for (std::size_t w = 0; w < width; ++w) { + const auto source_index = ((n * channels + c) * height + h) * width + w; + const auto target_index = ((n * height + h) * width + w) * channels + c; + result[target_index] = source[source_index]; + } + } + } + } + return result; +} + +} // namespace + +int main(int argc, char** argv) { + if (argc < 4 || argc > 9) { + std::cerr << "Usage: " << argv[0] + << " <model.rknn> <input.bin> <output-dir> [iterations=1] [warmup=1]" + " [auto|0|1|01] [float32|uint8|int8] [float32|native]\n"; + return 2; + } + + try { + const auto model = ReadFile<std::uint8_t>(argv[1]); + const std::filesystem::path output_dir(argv[3]); + const int iterations = argc >= 5 ? std::stoi(argv[4]) : 1; + const int warmup = argc >= 6 ? std::stoi(argv[5]) : 1; + const auto core_mask = ParseCoreMask(argc >= 7 ? argv[6] : "auto"); + const std::string source_type = argc >= 8 ? argv[7] : "float32"; + const std::string output_type = argc >= 9 ? argv[8] : "float32"; + if (source_type != "float32" && source_type != "uint8" && source_type != "int8") { + throw std::runtime_error("input source type must be float32, uint8, or int8"); + } + if (output_type != "float32" && output_type != "native") { + throw std::runtime_error("output type must be float32 or native"); + } + const auto input_f32 = source_type == "float32" ? ReadFile<float>(argv[2]) : std::vector<float>{}; + const auto input_u8 = + source_type == "uint8" ? ReadFile<std::uint8_t>(argv[2]) : std::vector<std::uint8_t>{}; + const auto input_i8 = + source_type == "int8" ? ReadFile<std::int8_t>(argv[2]) : std::vector<std::int8_t>{}; + if (iterations <= 0 || warmup < 0) { + throw std::runtime_error("iterations must be positive and warmup must be non-negative"); + } + std::filesystem::create_directories(output_dir); + + ContextGuard context; + if (model.size() > std::numeric_limits<std::uint32_t>::max()) { + throw std::runtime_error("model exceeds RKNN API size limit"); + } + Check(rknn_init(context.Out(), const_cast<std::uint8_t*>(model.data()), + static_cast<std::uint32_t>(model.size()), 0, nullptr), + "rknn_init"); + Check(rknn_set_core_mask(context.Get(), core_mask), "rknn_set_core_mask"); + + rknn_sdk_version version{}; + Check(rknn_query(context.Get(), RKNN_QUERY_SDK_VERSION, &version, sizeof(version)), + "RKNN_QUERY_SDK_VERSION"); + rknn_input_output_num counts{}; + Check(rknn_query(context.Get(), RKNN_QUERY_IN_OUT_NUM, &counts, sizeof(counts)), + "RKNN_QUERY_IN_OUT_NUM"); + if (counts.n_input != 1) { + throw std::runtime_error("validation runner currently requires exactly one input"); + } + rknn_tensor_attr input_attr{}; + input_attr.index = 0; + Check(rknn_query(context.Get(), RKNN_QUERY_INPUT_ATTR, &input_attr, sizeof(input_attr)), + "RKNN_QUERY_INPUT_ATTR"); + std::vector<rknn_tensor_attr> output_attrs(counts.n_output); + for (std::uint32_t index = 0; index < counts.n_output; ++index) { + output_attrs[index].index = index; + Check(rknn_query(context.Get(), RKNN_QUERY_OUTPUT_ATTR, &output_attrs[index], + sizeof(output_attrs[index])), + "RKNN_QUERY_OUTPUT_ATTR[" + std::to_string(index) + ']'); + } + const auto element_count = ElementCount(input_attr); + std::vector<float> input_nhwc; + if (source_type == "float32") { + if (input_f32.size() != element_count) { + throw std::runtime_error("input float count " + std::to_string(input_f32.size()) + + " does not match model element count " + + std::to_string(element_count)); + } + input_nhwc = NchwToNhwc(input_f32, input_attr); + } else { + const auto input_count = source_type == "uint8" ? input_u8.size() : input_i8.size(); + if (input_count != element_count) { + throw std::runtime_error("input " + source_type + " count " + std::to_string(input_count) + + " does not match model element count " + + std::to_string(element_count)); + } + } + + rknn_input input{}; + input.index = 0; + input.buf = + source_type == "float32" + ? static_cast<void*>(input_nhwc.data()) + : (source_type == "uint8" ? static_cast<void*>(const_cast<std::uint8_t*>(input_u8.data())) + : static_cast<void*>(const_cast<std::int8_t*>(input_i8.data()))); + input.size = static_cast<std::uint32_t>(source_type == "float32" ? input_nhwc.size() * sizeof(float) + : element_count); + input.pass_through = source_type == "int8" ? 1 : 0; + input.type = source_type == "float32" + ? RKNN_TENSOR_FLOAT32 + : (source_type == "uint8" ? RKNN_TENSOR_UINT8 : RKNN_TENSOR_INT8); + // RKNN Runtime 2.3.2 only accepts NHWC source layout on its input + // conversion path. CosmoEdge supplies NCHW, so make the boundary copy + // explicit rather than relying on a silently rejected NCHW request. + input.fmt = RKNN_TENSOR_NHWC; + Check(rknn_inputs_set(context.Get(), 1, &input), "rknn_inputs_set"); + + const auto collect_outputs = [&](bool write_outputs, double* get_ms, double* release_ms) { + std::vector<rknn_output> outputs(counts.n_output); + for (std::uint32_t index = 0; index < counts.n_output; ++index) { + outputs[index].index = index; + outputs[index].want_float = output_type == "float32" ? 1 : 0; + outputs[index].is_prealloc = 0; + } + const auto get_started = std::chrono::steady_clock::now(); + Check(rknn_outputs_get(context.Get(), counts.n_output, outputs.data(), nullptr), + "rknn_outputs_get"); + const auto get_finished = std::chrono::steady_clock::now(); + if (get_ms) { + *get_ms = std::chrono::duration<double, std::milli>(get_finished - get_started).count(); + } + if (write_outputs) { + const auto suffix = output_type == "float32" ? ".f32.bin" : ".native.bin"; + for (std::uint32_t index = 0; index < counts.n_output; ++index) { + const auto path = output_dir / ("output-" + std::to_string(index) + suffix); + WriteFile(path, outputs[index].buf, outputs[index].size); + std::cout << "output_" << index << "_path=" << path << '\n'; + std::cout << "output_" << index << "_bytes=" << outputs[index].size << '\n'; + } + } + const auto release_started = std::chrono::steady_clock::now(); + Check(rknn_outputs_release(context.Get(), counts.n_output, outputs.data()), + "rknn_outputs_release"); + const auto release_finished = std::chrono::steady_clock::now(); + if (release_ms) { + *release_ms = + std::chrono::duration<double, std::milli>(release_finished - release_started).count(); + } + }; + + for (int index = 0; index < warmup; ++index) { + Check(rknn_run(context.Get(), nullptr), "rknn_run warmup"); + collect_outputs(false, nullptr, nullptr); + } + + std::vector<double> run_ms; + std::vector<double> outputs_get_ms; + std::vector<double> outputs_release_ms; + run_ms.reserve(iterations); + outputs_get_ms.reserve(iterations); + outputs_release_ms.reserve(iterations); + for (int index = 0; index < iterations; ++index) { + const auto run_started = std::chrono::steady_clock::now(); + Check(rknn_run(context.Get(), nullptr), "rknn_run"); + const auto run_finished = std::chrono::steady_clock::now(); + run_ms.push_back(std::chrono::duration<double, std::milli>(run_finished - run_started).count()); + double get_ms = 0.0; + double release_ms = 0.0; + collect_outputs(index + 1 == iterations, &get_ms, &release_ms); + outputs_get_ms.push_back(get_ms); + outputs_release_ms.push_back(release_ms); + } + + std::cout << std::fixed << std::setprecision(4); + std::cout << "api_version=" << version.api_version << '\n'; + std::cout << "driver_version=" << version.drv_version << '\n'; + std::cout << "input_native_type=" << get_type_string(input_attr.type) << '\n'; + std::cout << "input_native_format=" << get_format_string(input_attr.fmt) << '\n'; + std::cout << "input_source_type=" << source_type << '\n'; + std::cout << "input_source_format=NHWC\n"; + std::cout << "output_source_type=" << output_type << '\n'; + for (std::uint32_t index = 0; index < output_attrs.size(); ++index) { + const auto& attr = output_attrs[index]; + std::cout << "output_" << index << "_shape=" << Shape(attr) << '\n'; + std::cout << "output_" << index << "_native_type=" << get_type_string(attr.type) << '\n'; + std::cout << "output_" << index << "_native_format=" << get_format_string(attr.fmt) << '\n'; + std::cout << "output_" << index << "_quant=" << get_qnt_type_string(attr.qnt_type) << '\n'; + std::cout << "output_" << index << "_zero_point=" << attr.zp << '\n'; + std::cout << "output_" << index << "_scale=" << std::setprecision(9) << attr.scale + << std::setprecision(4) << '\n'; + std::cout << "output_" << index << "_native_bytes=" << attr.size << '\n'; + std::cout << "output_" << index << "_stride_bytes=" << attr.size_with_stride << '\n'; + } + std::cout << "iterations=" << iterations << '\n'; + PrintTiming("run", run_ms); + PrintTiming("outputs_get", outputs_get_ms); + PrintTiming("outputs_release", outputs_release_ms); + std::cout << "runner_status=PASS\n"; + return 0; + } catch (const std::exception& error) { + std::cerr << "runner_status=FAIL error=" << error.what() << '\n'; + return 1; + } +} diff --git a/tools/rknn/rknn_runtime_probe.cc b/tools/rknn/rknn_runtime_probe.cc new file mode 100644 index 000000000..1d648d9c9 --- /dev/null +++ b/tools/rknn/rknn_runtime_probe.cc @@ -0,0 +1,185 @@ +#include <algorithm> +#include <cstdint> +#include <cstring> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <limits> +#include <string> +#include <vector> + +#include "rknn_api.h" + +namespace { + +class ContextGuard { +public: + ~ContextGuard() { + if (context_ != 0) { + rknn_destroy(context_); + } + } + + rknn_context* Out() { + return &context_; + } + rknn_context Get() const { + return context_; + } + +private: + rknn_context context_{0}; +}; + +std::vector<std::uint8_t> ReadFile(const std::string& path) { + std::ifstream stream(path, std::ios::binary | std::ios::ate); + if (!stream) { + throw std::runtime_error("cannot open model: " + path); + } + const auto size = stream.tellg(); + if (size <= 0 || static_cast<std::uint64_t>(size) > std::numeric_limits<std::uint32_t>::max()) { + throw std::runtime_error("invalid model size: " + path); + } + std::vector<std::uint8_t> data(static_cast<std::size_t>(size)); + stream.seekg(0); + stream.read(reinterpret_cast<char*>(data.data()), size); + if (!stream) { + throw std::runtime_error("cannot read complete model: " + path); + } + return data; +} + +void Check(int result, const std::string& action) { + if (result != RKNN_SUCC) { + throw std::runtime_error(action + " failed with RKNN code " + std::to_string(result)); + } +} + +rknn_core_mask ParseCoreMask(const std::string& value) { + if (value == "auto") + return RKNN_NPU_CORE_AUTO; + if (value == "0") + return RKNN_NPU_CORE_0; + if (value == "1") + return RKNN_NPU_CORE_1; + if (value == "01") + return RKNN_NPU_CORE_0_1; + throw std::runtime_error("core mask must be one of: auto, 0, 1, 01"); +} + +std::string Shape(const rknn_tensor_attr& attr) { + std::string result; + for (std::uint32_t index = 0; index < attr.n_dims; ++index) { + if (!result.empty()) + result += 'x'; + result += std::to_string(attr.dims[index]); + } + return result; +} + +void PrintTensor(const char* direction, const rknn_tensor_attr& attr) { + std::cout << direction << '[' << attr.index << "] name=" << attr.name << " shape=" << Shape(attr) + << " type=" << get_type_string(attr.type) << " format=" << get_format_string(attr.fmt) + << " quant=" << get_qnt_type_string(attr.qnt_type) << " bytes=" << attr.size + << " stride_bytes=" << attr.size_with_stride << " zp=" << attr.zp << " scale=" << attr.scale + << '\n'; +} + +} // namespace + +int main(int argc, char** argv) { + if (argc < 2 || argc > 3) { + std::cerr << "Usage: " << argv[0] << " <model.rknn> [auto|0|1|01]\n"; + return 2; + } + + try { + const auto model = ReadFile(argv[1]); + const auto core_mask = ParseCoreMask(argc == 3 ? argv[2] : "auto"); + + ContextGuard context; + Check(rknn_init(context.Out(), const_cast<std::uint8_t*>(model.data()), + static_cast<std::uint32_t>(model.size()), 0, nullptr), + "rknn_init"); + Check(rknn_set_core_mask(context.Get(), core_mask), "rknn_set_core_mask"); + + rknn_sdk_version version{}; + Check(rknn_query(context.Get(), RKNN_QUERY_SDK_VERSION, &version, sizeof(version)), + "RKNN_QUERY_SDK_VERSION"); + std::cout << "api_version=" << version.api_version << '\n'; + std::cout << "driver_version=" << version.drv_version << '\n'; + + rknn_input_output_num counts{}; + Check(rknn_query(context.Get(), RKNN_QUERY_IN_OUT_NUM, &counts, sizeof(counts)), + "RKNN_QUERY_IN_OUT_NUM"); + std::cout << "inputs=" << counts.n_input << " outputs=" << counts.n_output << '\n'; + + std::vector<rknn_tensor_attr> input_attrs(counts.n_input); + std::vector<rknn_input> inputs(counts.n_input); + std::vector<std::vector<std::uint8_t>> input_buffers(counts.n_input); + for (std::uint32_t index = 0; index < counts.n_input; ++index) { + auto& attr = input_attrs[index]; + attr.index = index; + Check(rknn_query(context.Get(), RKNN_QUERY_INPUT_ATTR, &attr, sizeof(attr)), + "RKNN_QUERY_INPUT_ATTR[" + std::to_string(index) + ']'); + PrintTensor("input", attr); + + input_buffers[index].resize(attr.size, 0); + inputs[index].index = index; + inputs[index].buf = input_buffers[index].data(); + inputs[index].size = attr.size; + inputs[index].pass_through = 0; + inputs[index].type = attr.type; + inputs[index].fmt = attr.fmt; + } + + std::vector<rknn_tensor_attr> output_attrs(counts.n_output); + for (std::uint32_t index = 0; index < counts.n_output; ++index) { + auto& attr = output_attrs[index]; + attr.index = index; + Check(rknn_query(context.Get(), RKNN_QUERY_OUTPUT_ATTR, &attr, sizeof(attr)), + "RKNN_QUERY_OUTPUT_ATTR[" + std::to_string(index) + ']'); + PrintTensor("output", attr); + } + + Check(rknn_inputs_set(context.Get(), counts.n_input, inputs.data()), "rknn_inputs_set"); + Check(rknn_run(context.Get(), nullptr), "rknn_run"); + + std::vector<rknn_output> outputs(counts.n_output); + for (std::uint32_t index = 0; index < counts.n_output; ++index) { + outputs[index].index = index; + outputs[index].want_float = 1; + outputs[index].is_prealloc = 0; + } + Check(rknn_outputs_get(context.Get(), counts.n_output, outputs.data(), nullptr), "rknn_outputs_get"); + + for (std::uint32_t index = 0; index < counts.n_output; ++index) { + const auto count = outputs[index].size / sizeof(float); + const auto* values = static_cast<const float*>(outputs[index].buf); + std::cout << "output[" << index << "] float_count=" << count; + if (count > 0) { + std::cout << " first=" << std::setprecision(8) << values[0]; + } + std::cout << '\n'; + } + Check(rknn_outputs_release(context.Get(), counts.n_output, outputs.data()), "rknn_outputs_release"); + + rknn_perf_run perf{}; + if (rknn_query(context.Get(), RKNN_QUERY_PERF_RUN, &perf, sizeof(perf)) == RKNN_SUCC) { + std::cout << "npu_run_us=" << perf.run_duration << '\n'; + } + + rknn_mem_size memory{}; + if (rknn_query(context.Get(), RKNN_QUERY_MEM_SIZE, &memory, sizeof(memory)) == RKNN_SUCC) { + std::cout << "weight_bytes=" << memory.total_weight_size + << " internal_bytes=" << memory.total_internal_size + << " dma_bytes=" << memory.total_dma_allocated_size << '\n'; + } + + std::cout << "probe_status=PASS\n"; + return 0; + } catch (const std::exception& error) { + std::cerr << "probe_status=FAIL error=" << error.what() << '\n'; + return 1; + } +} diff --git a/tools/rknn/run_onnx_reference.py b/tools/rknn/run_onnx_reference.py new file mode 100755 index 000000000..6c2a1fda0 --- /dev/null +++ b/tools/rknn/run_onnx_reference.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +"""Run one ONNX reference input and persist outputs plus runtime provenance.""" + +from __future__ import annotations + +import argparse +import hashlib +import json +import time +from pathlib import Path + +import numpy as np +import onnxruntime as ort + + +def sha256(path: Path) -> str: + digest = hashlib.sha256() + with path.open("rb") as stream: + for chunk in iter(lambda: stream.read(1024 * 1024), b""): + digest.update(chunk) + return digest.hexdigest() + + +def main() -> int: + parser = argparse.ArgumentParser() + parser.add_argument("--model", required=True, type=Path) + parser.add_argument("--input", required=True, type=Path) + parser.add_argument("--output-dir", required=True, type=Path) + parser.add_argument("--iterations", type=int, default=5) + parser.add_argument("--warmup", type=int, default=1) + args = parser.parse_args() + if args.iterations <= 0 or args.warmup < 0: + parser.error("--iterations must be positive and --warmup non-negative") + + model_path = args.model.resolve() + input_path = args.input.resolve() + output_dir = args.output_dir.resolve() + values = np.load(input_path).astype(np.float32, copy=False) + session = ort.InferenceSession(str(model_path), providers=["CPUExecutionProvider"]) + model_input = session.get_inputs()[0] + feeds = {model_input.name: values} + for _ in range(args.warmup): + session.run(None, feeds) + timings = [] + outputs = None + for _ in range(args.iterations): + start = time.perf_counter() + outputs = session.run(None, feeds) + timings.append((time.perf_counter() - start) * 1000.0) + assert outputs is not None + + output_dir.mkdir(parents=True, exist_ok=True) + output_records = [] + for index, output in enumerate(outputs): + array = np.asarray(output, dtype=np.float32) + npy_path = output_dir / f"output-{index}.npy" + bin_path = output_dir / f"output-{index}.f32.bin" + np.save(npy_path, array) + array.tofile(bin_path) + output_records.append( + { + "index": index, + "name": session.get_outputs()[index].name, + "shape": list(array.shape), + "npy": str(npy_path), + "npy_sha256": sha256(npy_path), + "bin": str(bin_path), + "bin_sha256": sha256(bin_path), + } + ) + report = { + "schema_version": 1, + "onnxruntime_version": ort.__version__, + "providers": session.get_providers(), + "model": {"path": str(model_path), "sha256": sha256(model_path)}, + "input": { + "path": str(input_path), + "sha256": sha256(input_path), + "name": model_input.name, + "shape": list(values.shape), + "dtype": str(values.dtype), + }, + "outputs": output_records, + "timing_ms": { + "iterations": args.iterations, + "warmup": args.warmup, + "mean": float(np.mean(timings)), + "minimum": float(np.min(timings)), + "maximum": float(np.max(timings)), + }, + } + report_path = output_dir / "report.json" + report_path.write_text(json.dumps(report, indent=2, sort_keys=True) + "\n", encoding="utf-8") + print(json.dumps(report, indent=2, sort_keys=True)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/scenario-bench/README.md b/tools/scenario-bench/README.md index 107dbd1c8..35cf4ec31 100644 --- a/tools/scenario-bench/README.md +++ b/tools/scenario-bench/README.md @@ -65,6 +65,23 @@ node src/cli.js run \ | `metrics.json` | 完整采样数据,包含每个 tick 的通道指标和硬件资源 | | `metrics.partial.json` | 运行过程中每 30 秒更新的临时采样文件,用于异常中断兜底且不让证据写盘干扰采样周期 | +长稳任务运行期间可对临时采样做只读检查点审计。检查点不会停止任务,也不会把“尚未跑满时长”误判为通过: + +```bash +node src/cli.js checkpoint \ + --input reports/rk3576-12h/metrics.partial.json \ + --identity reports/rk3576-12h/identity.txt \ + --output reports/rk3576-12h/checkpoint-12h.json \ + --gate-hours 12 \ + --max-gap-sec 120 \ + --min-fps-ratio 0.9 \ + --expected-preview-streams 4 \ + --expected-decoder-backend rockchip-copy-out \ + --expected-encoder-backend rockchip-copy-first +``` + +输出结论只有三种:`IN_PROGRESS` 表示时长尚未达到且其余门禁正常(命令退出码 3),`FAIL` 表示连续性、负载、资源或原生媒体链路存在失败(退出码 1),`PASS` 仅在时长达到且全部必需检查通过时产生(退出码 0)。审计覆盖采样间断/新鲜度、固定路数、逐通道 FPS 与丢帧、CPU/内存/磁盘、内存池增长、MPP/RGA/RKNN 失败及计数器回退、延迟 Copy-out 记账、OSD/编码/发布帧流和 SRS 发布流;输入和候选身份文件的 SHA-256 会写入结果。 + ## 创建场景包 场景包依赖一个预先导出的算法编排模板。该模板不是工具自动生成的,需要先在 CosmoEdge Web 页面上完成一次场景任务编排,然后从平台导出。 @@ -251,6 +268,10 @@ node src/cli.js run --device <url> --user <u> --password <p> --scenario <dir> -- | `--media-base <url>` | HTTP-FLV 服务基址;启用预览时必填 | | `--srs-api <url>` | SRS API 基址,用于采集发布流和客户端数 | +启用真实预览客户端时,工具会在设备登录、编排导入和通道创建之前执行 +`ffmpeg -version` 预检;专项 `preview` 命令还会同时预检 `ffprobe`。缺失或 +不可执行时会直接失败,避免测试环境问题在设备产生临时配置后才暴露。 + ### 预览负载矩阵 正式验收应至少覆盖以下四种负载,它们分别隔离算法基线、单路媒体开销、随路数增长的媒体开销和同流多客户端分发开销: diff --git a/tools/scenario-bench/scenarios/rk3576-detector-fastpath-1-2-4-8/scenario.yml b/tools/scenario-bench/scenarios/rk3576-detector-fastpath-1-2-4-8/scenario.yml new file mode 100644 index 000000000..227e87583 --- /dev/null +++ b/tools/scenario-bench/scenarios/rk3576-detector-fastpath-1-2-4-8/scenario.yml @@ -0,0 +1,49 @@ +name: rk3576-detector-fastpath-1-2-4-8 +displayName: RK3576 Detect 快路径 1/2/4/8 路(5 FPS) +sampleIntervalSec: 3 + +channels: + mode: local + repeatCount: 0 + sources: + - name: safety-helmet + file: ../../../../data/test-video/Safety Helmet.mp4 + +tasks: + - id: no-helmet + displayName: 未戴安全帽检测 + type: cv + algorithmId: "7463" + scheduleId: "e89c6c6385e5454b35cde0d1653vg" + template: ../../../../data/resource/aiboxresource_x86/algorithm/7463_No Safety Helmet_20260629094147.json + targetFps: 5 + taskConfig: + params: + - key: param.targetAlarmInterval + value: "36000" + - key: param.targetAlarmCount + value: "1" + - key: param.restrainSwitch + value: "1" + - key: param.sensitivity + value: "1" + - key: param.detectionDuration + value: "3600" + +loadProfile: + - channels: 1 + holdSec: 90 + - channels: 2 + holdSec: 90 + - channels: 4 + holdSec: 90 + - channels: 8 + holdSec: 90 + +thresholds: + pass: + maxCriticalPathLatencyMs: 500 + maxDetectorLatencyMs: 400 + avgDiscardRate: 0.1 + maxPacketDiscardRate: 0.01 + maxDiskUsedPercent: 90 diff --git a/tools/scenario-bench/scenarios/rk3576-no-helmet-customer-journey/README.md b/tools/scenario-bench/scenarios/rk3576-no-helmet-customer-journey/README.md new file mode 100644 index 000000000..7afd5438b --- /dev/null +++ b/tools/scenario-bench/scenarios/rk3576-no-helmet-customer-journey/README.md @@ -0,0 +1,13 @@ +# RK3576 customer journey + +This one-channel, 5 FPS workload provides a bounded window for the customer +journey: web login, video-channel visibility, task binding, real raw and +algorithm HTTP-FLV playback, event visibility, task stop/start recovery and +final cleanup. + +Run it with `--profile configured` and execute the dedicated `preview` command +against the prepared channel while the 180-second hold is active. The preview +gate must use a real media client and validate H.264 decode, timestamps, OSD +pixel delta, concurrent consumers, reconnect, invalid requests and lifecycle +cleanup. Event correctness is customer-journey evidence, not a labeled model +accuracy result. diff --git a/tools/scenario-bench/scenarios/rk3576-no-helmet-customer-journey/scenario.yml b/tools/scenario-bench/scenarios/rk3576-no-helmet-customer-journey/scenario.yml new file mode 100644 index 000000000..2d4a88c0b --- /dev/null +++ b/tools/scenario-bench/scenarios/rk3576-no-helmet-customer-journey/scenario.yml @@ -0,0 +1,31 @@ +name: rk3576-no-helmet-customer-journey +displayName: RK3576 客户旅程(单路 5 FPS) +sampleIntervalSec: 3 + +channels: + mode: local + repeatCount: 0 + sources: + - name: safety-helmet + file: ../../../../data/test-video/Safety Helmet.mp4 + +tasks: + - id: no-helmet + displayName: 未戴安全帽检测 + type: cv + algorithmId: "7463" + scheduleId: "e89c6c6385e5454b35cde0d1653vg" + template: ../../../../data/resource/aiboxresource_x86/algorithm/7463_No Safety Helmet_20260629094147.json + targetFps: 5 + +loadProfile: + - channels: 1 + holdSec: 180 + +thresholds: + pass: + maxCriticalPathLatencyMs: 300 + maxDetectorLatencyMs: 200 + avgDiscardRate: 0.05 + maxPacketDiscardRate: 0.01 + maxDiskUsedPercent: 90 diff --git a/tools/scenario-bench/scenarios/rk3576-no-helmet-longrun-4x5fps/README.md b/tools/scenario-bench/scenarios/rk3576-no-helmet-longrun-4x5fps/README.md new file mode 100644 index 000000000..4f99e1e92 --- /dev/null +++ b/tools/scenario-bench/scenarios/rk3576-no-helmet-longrun-4x5fps/README.md @@ -0,0 +1,17 @@ +# RK3576 12-hour 4x5 FPS soak + +This board-bound soak keeps four 5 FPS inference tasks and four algorithm +preview publishers active for 12 hours. It samples task throughput, CPU, +memory, RKNN/MPP/RGA counters and the host frame memory pool once per minute. + +The validation clip repeatedly contains positive targets. The scenario keeps +the complete CV, OSD, MPP encode and RTMP publish paths active, but extends the +alarm decision window and alarm interval so repeated fixture loops do not fill +the device disk with event images. Business-event correctness is validated in +the separate customer journey; this soak is a bounded-resource stability gate. +The runner also stops the workload if device disk usage reaches 90%. + +Use `--preview algorithm --preview-streams all --preview-clients 1` and run the +CLI on an always-on host. `--password-stdin` keeps the account password out of +the process arguments and the client discards it after login. Audit the final +checkpoint with `--gate-hours 12`. diff --git a/tools/scenario-bench/scenarios/rk3576-no-helmet-longrun-4x5fps/scenario.yml b/tools/scenario-bench/scenarios/rk3576-no-helmet-longrun-4x5fps/scenario.yml new file mode 100644 index 000000000..39485bf46 --- /dev/null +++ b/tools/scenario-bench/scenarios/rk3576-no-helmet-longrun-4x5fps/scenario.yml @@ -0,0 +1,45 @@ +name: rk3576-no-helmet-longrun-4x5fps +displayName: RK3576 延迟 Copy-out 12 小时长稳(4 路 5 FPS) +sampleIntervalSec: 60 + +channels: + mode: local + repeatCount: 0 + sources: + - name: safety-helmet + file: ../../../../data/test-video/Safety Helmet.mp4 + +tasks: + - id: no-helmet + displayName: 未戴安全帽检测 + type: cv + algorithmId: "7463" + scheduleId: "e89c6c6385e5454b35cde0d1653vg" + template: ../../../../data/resource/aiboxresource_x86/algorithm/7463_No Safety Helmet_20260629094147.json + targetFps: 5 + taskConfig: + params: + # Keep the complete detector/classifier/OSD pipeline active without + # filling the device disk with repeated validation-fixture alarms. + - key: param.targetAlarmInterval + value: "36000" + - key: param.targetAlarmCount + value: "1" + - key: param.restrainSwitch + value: "1" + - key: param.sensitivity + value: "1" + - key: param.detectionDuration + value: "3600" + +loadProfile: + - channels: 4 + holdSec: 43200 + +thresholds: + pass: + maxCriticalPathLatencyMs: 300 + maxDetectorLatencyMs: 200 + avgDiscardRate: 0.05 + maxPacketDiscardRate: 0.01 + maxDiskUsedPercent: 90 diff --git a/tools/scenario-bench/src/cli.js b/tools/scenario-bench/src/cli.js index 3ef9a3a17..7923fc9ef 100644 --- a/tools/scenario-bench/src/cli.js +++ b/tools/scenario-bench/src/cli.js @@ -19,6 +19,12 @@ import { summarizeStep, runtimeStepDecision } from './step-evaluator.js'; import { strategyForTaskType } from './task-strategies.js'; import { PreviewLoad } from './preview-load.js'; import { runPreviewValidation } from './preview-validator.js'; +import { auditLongRunFile, writeLongRunAudit } from './longrun-auditor.js'; +import { + installShutdownSignalHandlers, + sleepWithSignal, + throwIfAborted, +} from './shutdown-signal.js'; function parseArgs(argv) { const args = {}; @@ -28,12 +34,12 @@ function parseArgs(argv) { args.command = 'help'; } else if (a.startsWith('--')) { const key = a.slice(2); - if (['verbose', 'no-reuse', 'cleanup', 'skip-import'].includes(key)) { + if (['verbose', 'no-reuse', 'cleanup', 'skip-import', 'password-stdin'].includes(key)) { args[key] = true; } else { args[key] = argv[++i]; } - } else if (!args.command && ['run', 'doctor', 'preview', 'init-scenario'].includes(a)) { + } else if (!args.command && ['run', 'doctor', 'preview', 'init-scenario', 'checkpoint'].includes(a)) { args.command = a; } } @@ -48,11 +54,13 @@ Usage: scenario-bench preview --device <url> (--user <u> --password <p> | --token-env <name>) --channel <id> --output <dir> [options] scenario-bench doctor --scenario <dir> [--device <url> --user <u> --password <p>] [--output <dir>] scenario-bench init-scenario --name <name> --template <algorithm-template.json> --video <file> [options] + scenario-bench checkpoint --input <metrics.partial.json> --output <checkpoint.json> --gate-hours <hours> [options] run required: --device <url> Device base URL, e.g. http://192.168.1.10:8080 --user <account> Login account (use together with --password) --password <plain> Login password + --password-stdin Read the login password from stdin instead of process arguments --token-env <name> Read an existing device token from this environment variable --scenario <dir> Scenario package directory --output <dir> Report output directory @@ -65,6 +73,7 @@ run options: --skip-import Skip algorithm/layout/save when the template already exists --no-reuse Always create new bench channels --profile <mode> capacity (default) expands to every channel count; configured keeps scenario.yml steps + --only-channels <n> Run only one exact channel-count step from the effective profile --ramp-batch-size <n> --ramp-batch-delay-sec <n> --preview <mode> none (default) | raw | algorithm @@ -96,6 +105,22 @@ init-scenario options: --algorithm-id <id> Defaults to algorithmCode/algorithmId from the template --schedule-id <id> Defaults to default-schedule --target-fps <n> Writes tasks[].targetFps when the template cannot expose it + +checkpoint options: + --input <file> Running metrics.partial.json or completed metrics.json + --output <file> Atomic JSON checkpoint output path + --gate-hours <n> Required continuous runtime, e.g. 12 + --identity <file> Optional immutable candidate identity key=value file + --source-label <s> Canonical remote/source path recorded in evidence + --identity-label <s> Canonical identity path recorded in evidence + --max-gap-sec <n> Maximum sampling gap, default 120 + --max-freshness-sec <n> Maximum age of last running sample, default 120 + --min-fps-ratio <n> Per-binding minimum FPS / target FPS, default 0.9 + --pool-growth-warmup-sec <n> Ignore only memory-pool growth before this hold-phase warm-up + --expected-preview-streams <n> Required preview publishing stream count + --expected-decoder-backend <s> Required decoder backend identifier + --expected-encoder-backend <s> Required encoder backend identifier + --min-rga-bound-uint8-frames <n> Required fused RGA-to-RKNN UINT8 frames `); } @@ -124,13 +149,16 @@ function ensureWritableDir(dir) { function deviceAuth(args) { const tokenEnv = args['token-env']; const token = tokenEnv ? process.env[tokenEnv] : null; + const stdinPassword = args['password-stdin'] + ? fs.readFileSync(0, 'utf8').split(/\r?\n/, 1)[0] + : null; if (tokenEnv && !token) { throw new Error(`environment variable ${tokenEnv} is empty or unset`); } - if (!token && (!args.user || !args.password)) { - throw new Error('provide --user and --password together, or use --token-env'); + if (!token && (!args.user || !(args.password || stdinPassword))) { + throw new Error('provide --user with --password/--password-stdin, or use --token-env'); } - return { user: args.user, password: args.password, token }; + return { user: args.user, password: args.password || stdinPassword, token }; } async function runDoctor(args) { @@ -341,6 +369,7 @@ async function runBenchmark(args) { const startedAt = new Date().toISOString(); let pkg = null; let deviceInfo = {}; + let client = null; let channelMgr = null; let previewLoad = null; const samples = []; @@ -355,6 +384,14 @@ async function runBenchmark(args) { let currentStepIndex = -1; const writer = new ReportWriter(args.output); let effectiveLoadProfile = []; + const abortController = new AbortController(); + const signal = abortController.signal; + const disposeSignalHandlers = installShutdownSignalHandlers(abortController, { + onSignal: (error) => { + process.exitCode = error.exitCode; + log.warn(`${error.message}; active tasks and preview clients will be cleaned up.`); + }, + }); const buildResult = (status = runError ? 'aborted' : 'completed') => ({ scenarioName: pkg?.scenario?.displayName ?? pkg?.scenario?.name, @@ -367,6 +404,7 @@ async function runBenchmark(args) { scheduleId: task.scheduleId, targetFps: task.targetFps, templateFile: task.templateFile, + taskConfig: task.taskConfig, })) ?? [], bindings: pkg?.bindings ?? [], algorithmId: pkg?.algorithmId, @@ -414,20 +452,45 @@ async function runBenchmark(args) { }; try { + throwIfAborted(signal); log.info(`Loading scenario package: ${args.scenario}`); pkg = new ScenarioPackage(args.scenario).load(); log.info(`Scenario "${pkg.scenario.name}" | tasks=${pkg.tasks.map((t) => `${t.id}:${t.algorithmId}`).join(', ')} | mode=${pkg.videoMode}`); effectiveLoadProfile = buildEffectiveLoadProfile(pkg.loadProfile, args.profile ?? 'capacity'); + if (args['only-channels'] != null) { + const onlyChannels = Number(args['only-channels']); + if (!Number.isInteger(onlyChannels) || onlyChannels <= 0) { + throw new Error('--only-channels must be a positive integer'); + } + const exactStep = effectiveLoadProfile.find((step) => step.channels === onlyChannels); + if (!exactStep) { + throw new Error(`--only-channels ${onlyChannels} is not present in the effective load profile`); + } + effectiveLoadProfile = [exactStep]; + } const maxChannels = Math.max(...effectiveLoadProfile.map((s) => s.channels)); log.info(`Profile mode: ${args.profile ?? 'capacity'} | configured=${pkg.loadProfile.map((s) => s.channels).join(',')} | effective=${effectiveLoadProfile.map((s) => s.channels).join(',')}`); - log.info(`Connecting to device ${args.device}...`); - const client = new CosmoClient({ + client = new CosmoClient({ base: args.device, ...auth, lang: args.lang ?? 'zh-CN', + signal, }); + previewLoad = new PreviewLoad(client, { + mode: args.preview ?? 'none', + streamLimit: args['preview-streams'] ?? 'all', + clientsPerStream: Number(args['preview-clients'] ?? 1), + mediaBase: args['media-base'], + srsApiBase: args['srs-api'], + ffmpeg: args.ffmpeg ?? 'ffmpeg', + logger: log, + }); + await previewLoad.preflight(); + throwIfAborted(signal); + log.info(`Connecting to device ${args.device}...`); await client.login(); + throwIfAborted(signal); log.info('Login OK.'); const deviceInfoRaw = await client.queryDeviceInfo().catch((e) => { @@ -437,6 +500,7 @@ async function runBenchmark(args) { for (const it of deviceInfoRaw?.devInfoList ?? []) { if (it?.key) deviceInfo[it.key] = it.value; } + throwIfAborted(signal); if (args['skip-import']) { log.info('Skipping layout save (--skip-import).'); @@ -444,6 +508,7 @@ async function runBenchmark(args) { for (const item of pkg.layoutSavePayloads) { log.info(`Saving orchestration template for task "${item.taskId}" via /algorithm/layout/save...`); await client.layoutSave(item.payload); + throwIfAborted(signal); } log.info(`Layout saved for ${pkg.layoutSavePayloads.length} task(s).`); } @@ -456,6 +521,7 @@ async function runBenchmark(args) { }); log.info(`Ensuring ${maxChannels} channels (mode=${pkg.videoMode})...`); const videoChannelIds = await channelMgr.ensureChannels(pkg.videos, maxChannels); + throwIfAborted(signal); log.info(`Channels ready: ${videoChannelIds.join(', ')}`); const runner = new TaskRunner(client, { @@ -463,25 +529,17 @@ async function runBenchmark(args) { bindings: pkg.bindings, rampBatchSize: Number(args['ramp-batch-size'] ?? 1), rampBatchDelaySec: Number(args['ramp-batch-delay-sec'] ?? 15), + signal, }, log); runner.setChannels(videoChannelIds); - previewLoad = new PreviewLoad(client, { - mode: args.preview ?? 'none', - streamLimit: args['preview-streams'] ?? 'all', - clientsPerStream: Number(args['preview-clients'] ?? 1), - mediaBase: args['media-base'], - srsApiBase: args['srs-api'], - ffmpeg: args.ffmpeg ?? 'ffmpeg', - logger: log, - }); - const sampler = new MetricsSampler(client, log); const activeEntries = () => runner.expectedTaskEntries(runner.allChannelIds.slice(0, currentChannels)); const FPS_HALVE_RATIO = 0.5; const DISCARD_BOTTLENECK = 0.05; const captureSample = async (phase = 'hold', targetChannels = currentChannels) => { + throwIfAborted(signal); previewLoad.assertHealthy(); const sample = await sampler.sample(activeEntries()); sample.preview = await previewLoad.snapshot(); @@ -490,6 +548,7 @@ async function runBenchmark(args) { sample.targetChannels = targetChannels; samples.push(sample); await writePartial(); + throwIfAborted(signal); const ch0 = sample.channels[0]; log.debug(`sample step=${currentStepIndex} ch=${sample.activeChannels} bindings=${sample.activeTaskBindings ?? sample.channels.length} first=${ch0?.taskKey ?? '-'} fps=${ch0?.measuredFps ?? '-'} discard=${ch0?.discardRate ?? '-'} cpu=${sample.hardware?.cpuUtilization?.usedPercent ?? '-'}%`); return sample; @@ -531,11 +590,16 @@ async function runBenchmark(args) { const cpu98Count = lastConsecutive((s) => s.hardware?.cpuUtilization?.usedPercent, (v) => v >= 98); const npu98Count = lastConsecutive((s) => s.hardware?.npuUtilization?.usedPercent, (v) => v >= 98); const discardCount = lastConsecutive(meanChannelDiscard, (v) => v > DISCARD_BOTTLENECK); + const diskUsed = sample.hardware?.eMMCUtilization?.usedPercent; + const diskLimit = Number(pkg?.thresholds?.pass?.maxDiskUsedPercent ?? 90); if (mem98Count >= 3) reasons.push(`memory >= 98% for ${mem98Count} consecutive samples`); if (memAvg60s != null && memAvg60s >= 95) reasons.push(`memory 60s average ${memAvg60s.toFixed(1)}% >= 95%`); if (cpu98Count >= 3) reasons.push(`CPU >= 98% for ${cpu98Count} consecutive samples`); // if (npu98Count >= 3) reasons.push(`NPU >= 98% for ${npu98Count} consecutive samples`); if (discardCount >= 2) reasons.push(`discardRate > ${DISCARD_BOTTLENECK} for ${discardCount} consecutive samples`); + if (Number.isFinite(diskUsed) && Number.isFinite(diskLimit) && diskUsed >= diskLimit) { + reasons.push(`disk ${diskUsed}% >= ${diskLimit}%`); + } return reasons.length ? { stop: true, reason: reasons.join('; ') } : { stop: false }; }; @@ -552,12 +616,13 @@ async function runBenchmark(args) { const hasVLM = activeEntries().some((e) => e.taskType === 'vlm'); if (hasVLM && step.index === 0) { log.info(`[warmup] VLM detected in first step, waiting 30 seconds for model loading before sampling...`); - await new Promise((resolve) => setTimeout(resolve, 30000)); + await sleepWithSignal(30_000, signal); } await previewLoad.sync(entries); + throwIfAborted(signal); }, onSample: async () => { - await captureSample('hold', currentChannels); + return quickFuse(await captureSample('hold', currentChannels)); }, onStepEnd: async (step) => { const summary = summarizeStep(step, samples, pkg.thresholds, pkg.videoMode); @@ -597,6 +662,9 @@ async function runBenchmark(args) { runError = err; log.error(`Benchmark aborted; a partial report will be written: ${err.message}`); } finally { + // The run signal cancels long in-flight work. Cleanup requests use their + // own bounded timeouts so an already-aborted signal cannot suppress them. + client?.beginCleanup(); if (previewLoad) { try { await previewLoad.stop(); @@ -611,12 +679,17 @@ async function runBenchmark(args) { log.warn(`Channel cleanup failed: ${e.message}`); } } + if (!runError && signal.aborted) { + runError = signal.reason instanceof Error ? signal.reason : new Error('benchmark aborted'); + } + disposeSignalHandlers(); } if (!pkg) { console.error(`\nBenchmark failed: ${runError?.message ?? 'unknown error'}`); if (runError?.stack && process.env.BENCH_DEBUG) console.error(runError.stack); - process.exit(1); + process.exitCode = runError?.exitCode ?? 1; + return; } const result = buildResult(); @@ -625,7 +698,8 @@ async function runBenchmark(args) { log.warn(`Partial report written:\n ${jsonPath}\n ${htmlPath}`); console.error(`\nBenchmark aborted: ${runError.message}`); if (runError.stack && process.env.BENCH_DEBUG) console.error(runError.stack); - process.exit(1); + process.exitCode = runError.exitCode ?? 1; + return; } log.info(`Report written:\n ${jsonPath}\n ${htmlPath}`); } @@ -658,6 +732,40 @@ async function runPreviewCommand(args) { log.info(`Preview validation ${report.status}: ${path.join(path.resolve(args.output), 'preview-validation.json')}`); } +function optionalNumber(args, key) { + if (args[key] == null) return undefined; + const value = Number(args[key]); + if (!Number.isFinite(value)) throw new Error(`--${key} must be a number`); + return value; +} + +async function runCheckpoint(args) { + requireArgs(args, ['input', 'output', 'gate-hours']); + const result = auditLongRunFile(args.input, { + gateHours: optionalNumber(args, 'gate-hours'), + maxGapSec: optionalNumber(args, 'max-gap-sec'), + maxFreshnessSec: optionalNumber(args, 'max-freshness-sec'), + minFpsRatio: optionalNumber(args, 'min-fps-ratio'), + maxCpuPercent: optionalNumber(args, 'max-cpu-percent'), + maxMemoryPercent: optionalNumber(args, 'max-memory-percent'), + maxPoolGrowthBytes: optionalNumber(args, 'max-pool-growth-bytes'), + poolGrowthWarmupSec: optionalNumber(args, 'pool-growth-warmup-sec'), + minRgaBoundUint8Frames: optionalNumber(args, 'min-rga-bound-uint8-frames'), + expectedPreviewStreams: optionalNumber(args, 'expected-preview-streams'), + expectedDecoderBackend: args['expected-decoder-backend'], + expectedEncoderBackend: args['expected-encoder-backend'], + identityPath: args.identity, + sourceLabel: args['source-label'], + identityLabel: args['identity-label'], + }); + const output = writeLongRunAudit(args.output, result); + console.log(`Long-run ${args['gate-hours']}h checkpoint: ${result.verdict}`); + console.log(` ${output}`); + if (result.failures.length) console.log(` failed: ${result.failures.join(', ')}`); + if (result.pending.length) console.log(` pending: ${result.pending.join(', ')}`); + process.exitCode = result.verdict === 'PASS' ? 0 : (result.verdict === 'IN_PROGRESS' ? 3 : 1); +} + async function main() { const args = parseArgs(process.argv.slice(2)); if (!args.command || args.command === 'help') { @@ -676,11 +784,15 @@ async function main() { await runPreviewCommand(args); return; } + if (args.command === 'checkpoint') { + await runCheckpoint(args); + return; + } await runBenchmark(args); } main().catch((err) => { console.error(`\nscenario-bench failed: ${err.message}`); if (err.stack && process.env.BENCH_DEBUG) console.error(err.stack); - process.exit(1); + process.exitCode = err.exitCode ?? 1; }); diff --git a/tools/scenario-bench/src/cosmo-client.js b/tools/scenario-bench/src/cosmo-client.js index d2e4f7d92..b4220355a 100644 --- a/tools/scenario-bench/src/cosmo-client.js +++ b/tools/scenario-bench/src/cosmo-client.js @@ -16,8 +16,47 @@ const LONG_TIMEOUT_ROUTES = new Set([ '/Camera/AddVideo', '/algorithm/layout/save', '/atomic/model/uploadTemp', + '/aihost/PTaskCreate', + '/aihost/PTaskDetectPic', ]); +const DEFAULT_UPLOAD_CONCURRENCY = 2; +const DEFAULT_UPLOAD_ATTEMPTS = 4; +const DEFAULT_UPLOAD_BACKOFF_MS = 250; + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +function throwIfSignalAborted(signal) { + if (!signal?.aborted) return; + if (signal.reason instanceof Error) throw signal.reason; + throw new Error('request aborted'); +} + +function requestAbortContext(timeout, externalSignal) { + const controller = new AbortController(); + let timedOut = false; + const onExternalAbort = () => controller.abort(externalSignal.reason); + if (externalSignal?.aborted) { + onExternalAbort(); + } else { + externalSignal?.addEventListener('abort', onExternalAbort, { once: true }); + } + const timer = setTimeout(() => { + timedOut = true; + controller.abort(); + }, timeout); + return { + signal: controller.signal, + timedOut: () => timedOut, + cleanup: () => { + clearTimeout(timer); + externalSignal?.removeEventListener('abort', onExternalAbort); + }, + }; +} + /** MD5-hashed + uppercased password, matching the backend's ToUpper(passwdMd5) comparison. */ export function hashPassword(plain) { return crypto.createHash('md5').update(String(plain), 'utf8').digest('hex').toUpperCase(); @@ -31,13 +70,73 @@ export class CosmoClient { * @param {string} [opts.password] Plain-text password (hashed internally). * @param {string} [opts.token] Existing short-lived device token. * @param {string} [opts.lang] Accept-Language header value, default zh-CN. + * @param {AbortSignal} [opts.signal] Cancels in-flight benchmark requests. */ - constructor({ base, user, password, token = null, lang = 'zh-CN' }) { + constructor({ + base, + user, + password, + token = null, + lang = 'zh-CN', + uploadConcurrency = DEFAULT_UPLOAD_CONCURRENCY, + uploadAttempts = DEFAULT_UPLOAD_ATTEMPTS, + uploadBackoffMs = DEFAULT_UPLOAD_BACKOFF_MS, + fetchImpl = globalThis.fetch, + sleepImpl = sleep, + signal = null, + }) { + if (!Number.isInteger(uploadConcurrency) || uploadConcurrency < 1) { + throw new Error('uploadConcurrency must be a positive integer'); + } + if (!Number.isInteger(uploadAttempts) || uploadAttempts < 1) { + throw new Error('uploadAttempts must be a positive integer'); + } + if (!Number.isFinite(uploadBackoffMs) || uploadBackoffMs < 0) { + throw new Error('uploadBackoffMs must be a non-negative number'); + } + if (typeof fetchImpl !== 'function' || typeof sleepImpl !== 'function') { + throw new Error('fetchImpl and sleepImpl must be functions'); + } this.base = base.replace(/\/+$/, ''); this.user = user; this.password = password; this.lang = lang; this.mtk = token; + this.uploadConcurrency = uploadConcurrency; + this.uploadAttempts = uploadAttempts; + this.uploadBackoffMs = uploadBackoffMs; + this.fetchImpl = fetchImpl; + this.sleepImpl = sleepImpl; + this.signal = signal; + this.uploadActive = 0; + this.uploadWaiters = []; + this.uploadStats = { + attempts: 0, + retries: 0, + busyResponses: 0, + maxActive: 0, + cleanupAttempts: 0, + cleanupFailures: 0, + }; + } + + uploadTelemetry() { + return { + ...this.uploadStats, + active: this.uploadActive, + queued: this.uploadWaiters.length, + concurrencyLimit: this.uploadConcurrency, + attemptLimit: this.uploadAttempts, + }; + } + + /** + * Detach subsequent bounded cleanup requests from the benchmark shutdown + * signal. Requests that are already in flight keep their own linked abort + * controller; task/preview/channel cleanup can then run with normal timeouts. + */ + beginCleanup() { + this.signal = null; } /** Log in and store the mtk token. Returns the login response resData. */ @@ -52,6 +151,7 @@ export class CosmoClient { if (!this.mtk) { throw new Error('Login succeeded but no mtk returned'); } + this.password = null; return res.resData; } @@ -63,6 +163,13 @@ export class CosmoClient { return (await this._post('/System/QueryHardwareResource', {})).resData; } + async queryDeviceMemoryPool() { + const response = await this._post('/v1/cwai/aihost/QueryDeviceMemStatus', {}); + // Legacy /v1 core routes serialize their payload at the response root, + // while /gtw/cwai routes place it under resData. + return response.resData ?? response; + } + /** Save or update an algorithm orchestration layout. payload = parsed export JSON. */ async layoutSave(payload) { return this._post('/algorithm/layout/save', payload); @@ -109,6 +216,20 @@ export class CosmoClient { return this._post('/atomic/model/cancelUpload', { uploadId }); } + async cancelUploadBestEffort(uploadId) { + if (!uploadId) return false; + this.uploadStats.cleanupAttempts += 1; + try { + await this.cancelUpload(uploadId); + return true; + } catch { + // A detect request may already have consumed the one-shot upload. That + // makes cancel return "missing" even though no staged payload remains. + this.uploadStats.cleanupFailures += 1; + return false; + } + } + /** Add an RTSP camera channel. */ async cameraAdd(payload) { return this._post('/Camera/Add', payload); @@ -174,6 +295,21 @@ export class CosmoClient { return (await this._post('/event/page', payload)).resData; } + /** Create or reuse one picture-analysis task. */ + async pictureTaskCreate(payload) { + return this._post('/aihost/PTaskCreate', payload); + } + + /** Run one authenticated, staged-image picture inference request. */ + async pictureDetect(payload) { + return this._post('/aihost/PTaskDetectPic', payload); + } + + /** Cancel one picture-analysis task and release its model/action instances. */ + async pictureTaskCancel(payload) { + return this._post('/aihost/PTaskCancle', payload); + } + /** Start or join a live preview and wait until its first frame reaches SRS. */ async requestLiveStream({ channelId, algorithmId = '' }) { return (await this._post('/LiveStream/RequestLiveStream', { channelId, algorithmId })).resData?.stream; @@ -225,49 +361,103 @@ export class CosmoClient { headers.mtk = this.mtk; headers.token = this.mtk; } - const timeout = LONG_TIMEOUT_ROUTES.has(path) ? LONG_TIMEOUT_MS : DEFAULT_TIMEOUT_MS; - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), timeout); - let resp; - try { - resp = await fetch(url, { method: 'POST', headers, body, signal: controller.signal, duplex: 'half' }); - } catch (err) { - if (err.name === 'AbortError') { - throw new Error(`Request timed out after ${timeout}ms: POST ${path}`); - } - throw new Error(`Network error on POST ${path}: ${err.message}`); - } finally { - clearTimeout(timer); - } - if (!resp.ok) { - throw new Error(`HTTP ${resp.status} on POST ${path}`); + return this._withUploadSlot(() => this._sendMultipartWithRetry(path, url, headers, body)); + } + + async _withUploadSlot(operation) { + if (this.uploadActive >= this.uploadConcurrency) { + await new Promise((resolve) => this.uploadWaiters.push(resolve)); } - let data; + this.uploadActive += 1; + this.uploadStats.maxActive = Math.max(this.uploadStats.maxActive, this.uploadActive); try { - data = await resp.json(); - } catch { - throw new Error(`Non-JSON response on POST ${path}`); + return await operation(); + } finally { + this.uploadActive -= 1; + this.uploadWaiters.shift()?.(); } - if (data.resCode !== 1) { - const firstMsg = Array.isArray(data.resMsg) ? data.resMsg[0] : null; - const text = firstMsg?.msgText || firstMsg?.msgKey || data.msg || 'unknown error'; - const code = firstMsg?.msgCode || ''; - const err = new Error(`API error on POST ${path}: ${text}${code ? ` (code ${code})` : ''}`); - err.resCode = data.resCode; - err.msgCode = code; - throw err; + } + + async _sendMultipartWithRetry(path, url, headers, body) { + const timeout = LONG_TIMEOUT_ROUTES.has(path) ? LONG_TIMEOUT_MS : DEFAULT_TIMEOUT_MS; + for (let attempt = 1; attempt <= this.uploadAttempts; attempt += 1) { + throwIfSignalAborted(this.signal); + this.uploadStats.attempts += 1; + const abortContext = requestAbortContext(timeout, this.signal); + let resp; + try { + resp = await this.fetchImpl(url, { + method: 'POST', headers, body, signal: abortContext.signal, duplex: 'half', + }); + } catch (err) { + throwIfSignalAborted(this.signal); + if (abortContext.timedOut()) { + throw new Error(`Request timed out after ${timeout}ms: POST ${path}`); + } + throw new Error(`Network error on POST ${path}: ${err.message}`); + } finally { + abortContext.cleanup(); + } + + let responseText; + let data; + try { + responseText = await resp.text(); + data = JSON.parse(responseText); + } catch (error) { + throwIfSignalAborted(this.signal); + data = null; + } + + if (resp.status === 503) { + this.uploadStats.busyResponses += 1; + const firstMsg = Array.isArray(data?.resMsg) ? data.resMsg[0] : null; + if (attempt < this.uploadAttempts) { + this.uploadStats.retries += 1; + const serverDelayMs = Number(firstMsg?.retryAfterSeconds ?? 0) * 1000; + const exponentialMs = this.uploadBackoffMs * (2 ** (attempt - 1)); + await this.sleepImpl(Math.max(serverDelayMs, exponentialMs)); + continue; + } + const error = new Error(`HTTP 503 on POST ${path} after ${attempt} attempts`); + error.httpStatus = 503; + error.retryable = firstMsg?.retryable ?? true; + error.msgCode = firstMsg?.msgCode ?? 'HTTP_SERVICE_BUSY'; + throw error; + } + if (!resp.ok) { + const error = new Error(`HTTP ${resp.status} on POST ${path}`); + error.httpStatus = resp.status; + throw error; + } + if (!data) { + throw new Error(`Non-JSON response on POST ${path}`); + } + if (data.resCode !== 1) { + const firstMsg = Array.isArray(data.resMsg) ? data.resMsg[0] : null; + const text = firstMsg?.msgText || firstMsg?.msgKey || data.msg || 'unknown error'; + const code = firstMsg?.msgCode || ''; + const error = new Error(`API error on POST ${path}: ${text}${code ? ` (code ${code})` : ''}`); + error.resCode = data.resCode; + error.msgCode = code; + throw error; + } + return data; } - return data; + throw new Error(`Multipart retry loop exhausted on POST ${path}`); } /** - * Core POST. Prepends the /gtw/cwai prefix, injects auth headers, normalizes errors. - * @param {string} path route path after /gtw/cwai, e.g. /System/QueryHardwareResource + * Core POST. Prepends /gtw/cwai unless the caller supplies an absolute API + * path such as /v1/cwai/aihost/QueryDeviceMemStatus. + * @param {string} path route path after /gtw/cwai, or an absolute /v1 path * @param {object} body JSON body * @returns {Promise<object>} full wire response (with resCode/resData/resMsg) */ async _post(path, body) { - const url = `${this.base}${API_PREFIX}${path}`; + const url = path.startsWith('/v1/') + ? `${this.base}${path}` + : `${this.base}${API_PREFIX}${path}`; const headers = { 'Content-Type': 'application/json', 'Accept-Language': this.lang, @@ -279,23 +469,24 @@ export class CosmoClient { } } const timeout = LONG_TIMEOUT_ROUTES.has(path) ? LONG_TIMEOUT_MS : DEFAULT_TIMEOUT_MS; - const controller = new AbortController(); - const timer = setTimeout(() => controller.abort(), timeout); + throwIfSignalAborted(this.signal); + const abortContext = requestAbortContext(timeout, this.signal); let resp; try { - resp = await fetch(url, { + resp = await this.fetchImpl(url, { method: 'POST', headers, body: JSON.stringify(body ?? {}), - signal: controller.signal, + signal: abortContext.signal, }); } catch (err) { - if (err.name === 'AbortError') { + throwIfSignalAborted(this.signal); + if (abortContext.timedOut()) { throw new Error(`Request timed out after ${timeout}ms: POST ${path}`); } throw new Error(`Network error on POST ${path}: ${err.message}`); } finally { - clearTimeout(timer); + abortContext.cleanup(); } if (!resp.ok) { @@ -304,7 +495,8 @@ export class CosmoClient { let data; try { data = await resp.json(); - } catch { + } catch (error) { + throwIfSignalAborted(this.signal); throw new Error(`Non-JSON response on POST ${path}`); } // Wire contract: resCode === 1 means success. diff --git a/tools/scenario-bench/src/longrun-auditor.js b/tools/scenario-bench/src/longrun-auditor.js new file mode 100644 index 000000000..a25913399 --- /dev/null +++ b/tools/scenario-bench/src/longrun-auditor.js @@ -0,0 +1,710 @@ +import crypto from 'node:crypto'; +import fs from 'node:fs'; +import path from 'node:path'; + +const MIB = 1024 * 1024; + +const REQUIRED_FAILURE_COUNTERS = [ + 'graphForwardFailures', + 'mppCopyOutFailures', + 'mppDecodeFailures', + 'mppDecodeFallbacks', + 'mppEncodeFailures', + 'previewStreamFailures', + 'resultParseFailures', + 'rgaFailures', + 'rknnForwardFailures', + 'rknnRgaFailures', + 'rknnRgaBoundInputImportFailures', + 'rknnRgaBoundRequantizeFailures', +]; + +const MONOTONIC_COUNTERS = [ + 'blobConvertFrames', + 'colorConvertFrames', + 'graphForwardFrames', + 'mppCopyOutFrames', + 'mppDecodedFrames', + 'mppEarlyDroppedFrames', + 'mppEncodedFrames', + 'osdFrames', + 'publishedFrames', + 'resultParseFrames', + 'rgaFrames', + 'rknnForwards', + 'rknnRgaBoundInputFrames', + 'rknnRgaBoundUint8Frames', +]; + +const IDENTITY_ALLOWLIST = new Set([ + 'engineSourceCommit', + 'harnessCommit', + 'sourceCommit', + 'sourceTree', + 'engineSha256', + 'modelSha256', + 'scenarioSha256', + 'videoSha256', + 'templateSha256', + 'startedAt', + 'runnerPid', + 'watcherPid', + 'liveMonitorPid', + 'scenario', + 'previewClients', + 'rknnRuntime', + 'rknnDriver', + 'kernel', + 'rga', + 'mpp', +]); + +function round(value, digits = 3) { + if (!Number.isFinite(value)) return null; + const factor = 10 ** digits; + return Math.round(value * factor) / factor; +} + +function mean(values) { + return values.length ? values.reduce((sum, value) => sum + value, 0) / values.length : null; +} + +function percentile(values, fraction) { + if (!values.length) return null; + const sorted = [...values].sort((a, b) => a - b); + return sorted[Math.min(sorted.length - 1, Math.max(0, Math.ceil(sorted.length * fraction) - 1))]; +} + +function numeric(values) { + return values.filter((value) => typeof value === 'number' && Number.isFinite(value)); +} + +function counterSeries(samples, key) { + return numeric(samples.map((sample) => sample.hardware?.accelerator?.[key])); +} + +function counterSummary(samples, key) { + const values = counterSeries(samples, key); + return { + samples: values.length, + first: values[0] ?? null, + last: values.at(-1) ?? null, + delta: values.length ? values.at(-1) - values[0] : null, + decreases: values.slice(1).reduce( + (count, value, index) => count + (value < values[index] ? 1 : 0), + 0, + ), + }; +} + +function resourceSummary(samples, key) { + const values = numeric(samples.map((sample) => sample.hardware?.[key]?.usedPercent)); + return { + samples: values.length, + min: values.length ? Math.min(...values) : null, + avg: round(mean(values), 2), + p95: percentile(values, 0.95), + max: values.length ? Math.max(...values) : null, + }; +} + +function parseIdentity(raw) { + const properties = {}; + for (const line of raw.split(/\r?\n/)) { + const separator = line.indexOf('='); + if (separator <= 0) continue; + const key = line.slice(0, separator).trim(); + if (!IDENTITY_ALLOWLIST.has(key)) continue; + properties[key] = line.slice(separator + 1).trim(); + } + return properties; +} + +function sha256(buffer) { + return crypto.createHash('sha256').update(buffer).digest('hex'); +} + +function check(id, status, actual, expected, detail = null) { + return { id, status, actual, expected, detail }; +} + +/** + * Audit a running or completed ScenarioBench long-run result without mutating it. + * A PASS is intentionally impossible until the requested wall-clock gate has + * elapsed and every continuity, workload, resource, and native-media check passes. + */ +export function auditLongRun(runResult, options = {}) { + if (!runResult || typeof runResult !== 'object' || Array.isArray(runResult)) { + throw new Error('long-run input must be a JSON object'); + } + + const gateHours = Number(options.gateHours ?? 24); + const maxGapSec = Number(options.maxGapSec ?? 120); + const maxFreshnessSec = Number(options.maxFreshnessSec ?? maxGapSec); + const minFpsRatio = Number(options.minFpsRatio ?? 0.9); + const maxCpuPercent = Number(options.maxCpuPercent ?? 98); + const maxMemoryPercent = Number(options.maxMemoryPercent ?? 98); + const maxPoolGrowthBytes = Number(options.maxPoolGrowthBytes ?? 64 * MIB); + const poolGrowthWarmupSec = Number(options.poolGrowthWarmupSec ?? 0); + const minRgaBoundUint8Frames = options.minRgaBoundUint8Frames == null + ? null + : Number(options.minRgaBoundUint8Frames); + const nowMs = Number(options.nowMs ?? Date.now()); + const expectedPreviewStreams = options.expectedPreviewStreams == null + ? null + : Number(options.expectedPreviewStreams); + + for (const [name, value] of Object.entries({ + gateHours, + maxGapSec, + maxFreshnessSec, + minFpsRatio, + maxCpuPercent, + maxMemoryPercent, + maxPoolGrowthBytes, + poolGrowthWarmupSec, + nowMs, + })) { + if (!Number.isFinite(value) || value < 0) throw new Error(`${name} must be a non-negative number`); + } + if (gateHours <= 0) throw new Error('gateHours must be greater than zero'); + if (minFpsRatio <= 0) throw new Error('minFpsRatio must be greater than zero'); + if (expectedPreviewStreams != null + && (!Number.isInteger(expectedPreviewStreams) || expectedPreviewStreams < 0)) { + throw new Error('expectedPreviewStreams must be a non-negative integer'); + } + if (minRgaBoundUint8Frames != null + && (!Number.isInteger(minRgaBoundUint8Frames) || minRgaBoundUint8Frames < 0)) { + throw new Error('minRgaBoundUint8Frames must be a non-negative integer'); + } + + const checks = []; + const add = (...args) => checks.push(check(...args)); + const samples = Array.isArray(runResult.samples) ? runResult.samples : []; + const holdSamples = samples.filter((sample) => sample?.phase !== 'ramp'); + const timestamps = holdSamples.map((sample) => Number(sample?.ts)); + const validTimestamps = timestamps.filter(Number.isFinite); + const startedMs = Date.parse(runResult.startedAt); + const reportedEndedMs = Date.parse(runResult.endedAt); + const firstTs = validTimestamps[0] ?? null; + const lastTs = validTimestamps.at(-1) ?? null; + const gapsSec = validTimestamps.slice(1).map((value, index) => (value - validTimestamps[index]) / 1000); + const nonIncreasingTimestamps = gapsSec.filter((gap) => gap <= 0).length; + const maxObservedGapSec = gapsSec.length ? Math.max(...gapsSec) : null; + const effectiveEndMs = runResult.status === 'completed' && Number.isFinite(reportedEndedMs) + ? reportedEndedMs + : lastTs; + const runAgeSec = Number.isFinite(startedMs) && effectiveEndMs != null + ? (effectiveEndMs - startedMs) / 1000 + : null; + const sampleSpanSec = firstTs != null && lastTs != null ? (lastTs - firstTs) / 1000 : null; + const firstSampleDelaySec = Number.isFinite(startedMs) && firstTs != null ? (firstTs - startedMs) / 1000 : null; + const finalSampleDelaySec = runResult.status === 'completed' + && Number.isFinite(reportedEndedMs) + && lastTs != null + ? (reportedEndedMs - lastTs) / 1000 + : null; + const freshnessSec = lastTs == null ? null : (nowMs - lastTs) / 1000; + const requiredDurationSec = gateHours * 3600; + + add( + 'run.status', + ['running', 'completed'].includes(runResult.status) ? 'PASS' : 'FAIL', + runResult.status ?? null, + 'running or completed', + runResult.error?.message ?? null, + ); + add( + 'samples.present', + holdSamples.length > 1 ? 'PASS' : 'FAIL', + holdSamples.length, + '> 1 hold sample', + ); + add( + 'samples.timestamps', + validTimestamps.length === holdSamples.length && nonIncreasingTimestamps === 0 ? 'PASS' : 'FAIL', + { valid: validTimestamps.length, hold: holdSamples.length, nonIncreasing: nonIncreasingTimestamps }, + 'all hold timestamps valid and strictly increasing', + ); + add( + 'samples.initialDelay', + firstSampleDelaySec != null && firstSampleDelaySec >= 0 && firstSampleDelaySec <= maxGapSec ? 'PASS' : 'FAIL', + round(firstSampleDelaySec), + `0..${maxGapSec}s`, + ); + add( + 'samples.maxGap', + maxObservedGapSec != null && maxObservedGapSec <= maxGapSec ? 'PASS' : 'FAIL', + round(maxObservedGapSec), + `<= ${maxGapSec}s`, + ); + + if (runResult.status === 'running') { + add( + 'samples.freshness', + freshnessSec != null && freshnessSec >= 0 && freshnessSec <= maxFreshnessSec ? 'PASS' : 'FAIL', + round(freshnessSec), + `0..${maxFreshnessSec}s while running`, + ); + } else { + add('samples.freshness', 'N/A', round(freshnessSec), 'not required after completion'); + add( + 'samples.finalDelay', + finalSampleDelaySec != null && finalSampleDelaySec >= 0 && finalSampleDelaySec <= maxGapSec ? 'PASS' : 'FAIL', + round(finalSampleDelaySec), + `0..${maxGapSec}s from final sample to completedAt`, + ); + } + + const durationReached = runAgeSec != null && runAgeSec >= requiredDurationSec; + add( + 'gate.duration', + durationReached ? 'PASS' : (runResult.status === 'running' ? 'IN_PROGRESS' : 'FAIL'), + round(runAgeSec), + `>= ${requiredDurationSec}s (${gateHours}h)`, + ); + + const stepIndexes = [...new Set(holdSamples.map((sample) => sample.stepIndex))]; + const observedTargets = numeric(holdSamples.map((sample) => Number(sample.targetChannels))); + const step = (runResult.steps ?? []).find((item) => item.index === stepIndexes[0]); + const expectedChannels = Number(step?.channels ?? observedTargets[0]); + const shapeFailures = holdSamples.reduce((count, sample) => { + const uniqueChannels = new Set((sample.channels ?? []).map((channel) => channel.channelId)); + return count + ( + sample.activeChannels !== expectedChannels + || sample.targetChannels !== expectedChannels + || uniqueChannels.size !== expectedChannels + ? 1 + : 0 + ); + }, 0); + add( + 'workload.singleStep', + stepIndexes.length === 1 ? 'PASS' : 'FAIL', + stepIndexes, + 'exactly one hold step', + ); + add( + 'workload.channelShape', + Number.isInteger(expectedChannels) && expectedChannels > 0 && shapeFailures === 0 ? 'PASS' : 'FAIL', + { expectedChannels: Number.isFinite(expectedChannels) ? expectedChannels : null, failedSamples: shapeFailures }, + 'active, target, and unique observed channels stay at the configured count', + ); + + const bindings = new Map(); + let missingBindings = 0; + for (const sample of holdSamples) { + for (const channel of sample.channels ?? []) { + const key = `${channel.taskKey ?? 'default'}::${channel.channelId ?? 'unknown'}`; + if (!bindings.has(key)) { + bindings.set(key, { + taskKey: channel.taskKey ?? 'default', + channelId: channel.channelId ?? null, + targetFps: null, + fps: [], + discard: [], + observations: 0, + missing: 0, + }); + } + const binding = bindings.get(key); + binding.observations++; + if (channel.missing || channel.telemetryMissing) { + binding.missing++; + missingBindings++; + } + if (Number.isFinite(Number(channel.targetFps)) && Number(channel.targetFps) > 0) { + binding.targetFps = Number(channel.targetFps); + } + if (typeof channel.measuredFps === 'number' && Number.isFinite(channel.measuredFps)) { + binding.fps.push(channel.measuredFps); + } + if (typeof channel.discardRate === 'number' && Number.isFinite(channel.discardRate)) { + binding.discard.push(channel.discardRate); + } + } + } + + const bindingStats = [...bindings.values()].map((binding) => { + const ratios = binding.targetFps + ? binding.fps.map((fps) => fps / binding.targetFps) + : []; + return { + taskKey: binding.taskKey, + channelId: binding.channelId, + observations: binding.observations, + missing: binding.missing, + targetFps: binding.targetFps, + fpsMin: binding.fps.length ? round(Math.min(...binding.fps), 3) : null, + fpsAvg: round(mean(binding.fps), 3), + fpsP01: round(percentile(binding.fps, 0.01), 3), + minFpsRatio: ratios.length ? round(Math.min(...ratios), 4) : null, + discardAvg: round(mean(binding.discard), 6), + discardMax: binding.discard.length ? round(Math.max(...binding.discard), 6) : null, + }; + }); + const missingFpsTargets = bindingStats.filter((binding) => binding.minFpsRatio == null).length; + const worstFpsRatio = bindingStats.length && !missingFpsTargets + ? Math.min(...bindingStats.map((binding) => binding.minFpsRatio)) + : null; + const maxMissingRate = bindingStats.length + ? Math.max(...bindingStats.map((binding) => ( + binding.observations ? binding.missing / binding.observations : 1 + ))) + : null; + const worstAverageDiscard = bindingStats.length + ? Math.max(...bindingStats.map((binding) => binding.discardAvg ?? Number.POSITIVE_INFINITY)) + : null; + const discardLimit = Number( + runResult.thresholds?.pass?.avgDiscardRate + ?? runResult.thresholds?.pass?.maxDiscardRate + ?? 0.05, + ); + + add( + 'workload.telemetry', + bindingStats.length > 0 && missingBindings === 0 ? 'PASS' : 'FAIL', + { bindings: bindingStats.length, missingObservations: missingBindings, maxMissingRate: round(maxMissingRate, 6) }, + 'no missing task/channel telemetry', + ); + add( + 'workload.fps', + worstFpsRatio != null && worstFpsRatio >= minFpsRatio ? 'PASS' : 'FAIL', + { worstRatio: worstFpsRatio, missingTargets: missingFpsTargets }, + `every task/channel minimum FPS ratio >= ${minFpsRatio}`, + ); + add( + 'workload.discard', + Number.isFinite(worstAverageDiscard) && worstAverageDiscard <= discardLimit ? 'PASS' : 'FAIL', + worstAverageDiscard, + `worst task/channel average discard <= ${discardLimit}`, + ); + + const resources = { + cpu: resourceSummary(holdSamples, 'cpuUtilization'), + memory: resourceSummary(holdSamples, 'generalMemoryUtilization'), + disk: resourceSummary(holdSamples, 'eMMCUtilization'), + }; + const diskLimit = Number(runResult.thresholds?.pass?.maxDiskUsedPercent ?? 90); + add('resource.cpu', resources.cpu.max != null && resources.cpu.max < maxCpuPercent ? 'PASS' : 'FAIL', resources.cpu.max, `< ${maxCpuPercent}%`); + add('resource.memory', resources.memory.max != null && resources.memory.max < maxMemoryPercent ? 'PASS' : 'FAIL', resources.memory.max, `< ${maxMemoryPercent}%`); + add('resource.disk', resources.disk.max != null && resources.disk.max <= diskLimit ? 'PASS' : 'FAIL', resources.disk.max, `<= ${diskLimit}%`); + + const poolMeasurementStartMs = firstTs == null + ? null + : firstTs + poolGrowthWarmupSec * 1000; + const poolSamples = poolMeasurementStartMs == null + ? [] + : holdSamples.filter((sample) => Number(sample?.ts) >= poolMeasurementStartMs); + const coldPoolAllocated = numeric(holdSamples.map( + (sample) => sample.hardware?.memoryPool?.totalAllocatedBytes, + )); + const poolAllocated = numeric(poolSamples.map( + (sample) => sample.hardware?.memoryPool?.totalAllocatedBytes, + )); + const poolInUse = numeric(poolSamples.map( + (sample) => sample.hardware?.memoryPool?.totalInUseBytes, + )); + const poolUtilization = numeric(poolSamples.map( + (sample) => sample.hardware?.memoryPool?.utilizationPercent, + )); + const pool = { + growthWarmupSec: poolGrowthWarmupSec, + growthSamples: poolAllocated.length, + growthBaselineAt: poolSamples[0]?.iso ?? null, + coldStartAllocatedFirstBytes: coldPoolAllocated[0] ?? null, + coldStartAllocatedLastBytes: coldPoolAllocated.at(-1) ?? null, + coldStartAllocatedMaxBytes: coldPoolAllocated.length ? Math.max(...coldPoolAllocated) : null, + coldStartAllocatedNetGrowthBytes: coldPoolAllocated.length + ? coldPoolAllocated.at(-1) - coldPoolAllocated[0] + : null, + coldStartAllocatedPeakGrowthBytes: coldPoolAllocated.length + ? Math.max(...coldPoolAllocated) - coldPoolAllocated[0] + : null, + allocatedFirstBytes: poolAllocated[0] ?? null, + allocatedLastBytes: poolAllocated.at(-1) ?? null, + allocatedMaxBytes: poolAllocated.length ? Math.max(...poolAllocated) : null, + allocatedNetGrowthBytes: poolAllocated.length ? poolAllocated.at(-1) - poolAllocated[0] : null, + allocatedPeakGrowthBytes: poolAllocated.length ? Math.max(...poolAllocated) - poolAllocated[0] : null, + inUseMaxBytes: poolInUse.length ? Math.max(...poolInUse) : null, + inUseLastBytes: poolInUse.at(-1) ?? null, + utilizationMaxPercent: poolUtilization.length ? Math.max(...poolUtilization) : null, + }; + add( + 'resource.poolGrowth', + poolAllocated.length > 1 + && pool.allocatedNetGrowthBytes != null + && pool.allocatedPeakGrowthBytes != null + && pool.allocatedNetGrowthBytes <= maxPoolGrowthBytes + && pool.allocatedPeakGrowthBytes <= maxPoolGrowthBytes + ? 'PASS' + : 'FAIL', + { + samples: poolAllocated.length, + warmupSec: poolGrowthWarmupSec, + netBytes: pool.allocatedNetGrowthBytes, + peakBytes: pool.allocatedPeakGrowthBytes, + }, + `after ${poolGrowthWarmupSec}s warm-up, net and peak allocated growth <= ${maxPoolGrowthBytes} bytes`, + ); + + const accelerators = holdSamples.map((sample) => sample.hardware?.accelerator ?? null); + const acceleratorMissing = accelerators.filter((value) => !value).length; + add( + 'native.telemetry', + accelerators.length > 0 && acceleratorMissing === 0 ? 'PASS' : 'FAIL', + { samples: accelerators.length, missing: acceleratorMissing }, + 'accelerator telemetry present in every hold sample', + ); + + const counterKeys = [...new Set([...MONOTONIC_COUNTERS, ...REQUIRED_FAILURE_COUNTERS])]; + const counters = Object.fromEntries( + counterKeys.map((key) => [key, counterSummary(holdSamples, key)]), + ); + const missingCounters = counterKeys.filter((key) => counters[key].samples !== holdSamples.length); + const resetCounters = MONOTONIC_COUNTERS.filter((key) => counters[key].decreases > 0); + const failureDeltas = Object.fromEntries( + REQUIRED_FAILURE_COUNTERS.map((key) => [key, counters[key].delta]), + ); + const nonZeroFailures = Object.entries(failureDeltas).filter(([, delta]) => delta !== 0); + add( + 'native.countersPresent', + missingCounters.length === 0 ? 'PASS' : 'FAIL', + missingCounters, + 'all required native-media counters present in every hold sample', + ); + add( + 'native.counterContinuity', + resetCounters.length === 0 ? 'PASS' : 'FAIL', + resetCounters, + 'no monotonic counter decrease (engine/process restart signal)', + ); + add( + 'native.failures', + nonZeroFailures.length === 0 ? 'PASS' : 'FAIL', + Object.fromEntries(nonZeroFailures), + 'all failure/fallback counter deltas equal zero', + ); + if (minRgaBoundUint8Frames != null) { + const fusedFrames = counters.rknnRgaBoundUint8Frames?.delta; + add( + 'native.rgaBoundUint8', + Number.isFinite(fusedFrames) && fusedFrames >= minRgaBoundUint8Frames ? 'PASS' : 'FAIL', + fusedFrames ?? null, + `>= ${minRgaBoundUint8Frames} fused UINT8 bound-input frames`, + ); + } + + const backendValues = (key) => [...new Set( + accelerators.map((value) => value?.[key]).filter(Boolean), + )]; + const decoderBackends = backendValues('videoDecoderBackend'); + const encoderBackends = backendValues('videoEncoderBackend'); + if (options.expectedDecoderBackend) { + add( + 'native.decoderBackend', + decoderBackends.length === 1 && decoderBackends[0] === options.expectedDecoderBackend ? 'PASS' : 'FAIL', + decoderBackends, + options.expectedDecoderBackend, + ); + } else { + add('native.decoderBackend', 'N/A', decoderBackends, 'no expected backend supplied'); + } + if (options.expectedEncoderBackend) { + add( + 'native.encoderBackend', + encoderBackends.length === 1 && encoderBackends[0] === options.expectedEncoderBackend ? 'PASS' : 'FAIL', + encoderBackends, + options.expectedEncoderBackend, + ); + } else { + add('native.encoderBackend', 'N/A', encoderBackends, 'no expected backend supplied'); + } + + const decoded = counters.mppDecodedFrames?.delta; + const copied = counters.mppCopyOutFrames?.delta; + const earlyDropped = counters.mppEarlyDroppedFrames?.delta; + const copyAccountingError = [decoded, copied, earlyDropped].every(Number.isFinite) + ? Math.abs(decoded - copied - earlyDropped) + : null; + const copyAccountingTolerance = Number.isFinite(decoded) + ? Math.max(16, Math.ceil(decoded * 0.001)) + : null; + add( + 'native.copyOutAccounting', + copyAccountingError != null && copyAccountingError <= copyAccountingTolerance ? 'PASS' : 'FAIL', + { decoded, copied, earlyDropped, error: copyAccountingError }, + `decoded ~= copied + earlyDropped (tolerance ${copyAccountingTolerance})`, + ); + if (options.expectedDecoderBackend === 'rockchip-copy-out') { + add( + 'native.earlyDropActive', + earlyDropped > 0 ? 'PASS' : 'FAIL', + earlyDropped, + '> 0 frames avoided copy-out', + ); + } + + const encoded = counters.mppEncodedFrames?.delta; + const osd = counters.osdFrames?.delta; + const published = counters.publishedFrames?.delta; + const publishRatio = Number.isFinite(encoded) && encoded > 0 && Number.isFinite(published) + ? published / encoded + : null; + const osdRatio = Number.isFinite(encoded) && encoded > 0 && Number.isFinite(osd) + ? osd / encoded + : null; + add( + 'native.previewFrameFlow', + encoded > 0 && publishRatio >= 0.99 && publishRatio <= 1.01 + && osdRatio >= 0.99 && osdRatio <= 1.01 + ? 'PASS' + : 'FAIL', + { encoded, osd, published, osdRatio: round(osdRatio, 6), publishRatio: round(publishRatio, 6) }, + 'OSD and published frame deltas stay within 1% of encoded frames', + ); + + const previews = holdSamples.map((sample) => sample.preview ?? {}); + const previewErrors = previews.filter((preview) => ( + Array.isArray(preview.errors) && preview.errors.length > 0 + )).length; + const requestedStreams = numeric(previews.map((preview) => preview.requestedStreams)); + const publishingStreams = numeric(previews.map((preview) => preview.srsPublishingStreams)); + const srsStreams = numeric(previews.map((preview) => preview.srsStreams)); + const inferredPreviewStreams = expectedPreviewStreams + ?? (requestedStreams.length ? Math.max(...requestedStreams) : 0); + const previewMode = runResult.previewProfile?.mode ?? previews.find((preview) => preview.mode)?.mode ?? 'none'; + if (previewMode === 'none' && inferredPreviewStreams === 0) { + add('preview.health', 'N/A', { mode: previewMode }, 'preview disabled'); + } else { + const badRequested = requestedStreams.filter((value) => value !== inferredPreviewStreams).length; + const badPublishing = publishingStreams.filter((value) => value < inferredPreviewStreams).length; + const badSrs = srsStreams.filter((value) => value < inferredPreviewStreams).length; + add( + 'preview.health', + previews.length === holdSamples.length + && previewErrors === 0 + && requestedStreams.length === holdSamples.length + && publishingStreams.length === holdSamples.length + && srsStreams.length === holdSamples.length + && badRequested === 0 + && badPublishing === 0 + && badSrs === 0 + ? 'PASS' + : 'FAIL', + { + mode: previewMode, + expectedStreams: inferredPreviewStreams, + errorSamples: previewErrors, + badRequestedSamples: badRequested, + badPublishingSamples: badPublishing, + badSrsSamples: badSrs, + }, + 'requested and SRS publishing streams remain healthy for every hold sample', + ); + } + + const failedChecks = checks.filter((item) => item.status === 'FAIL'); + const pendingChecks = checks.filter((item) => item.status === 'IN_PROGRESS'); + const verdict = failedChecks.length ? 'FAIL' : (pendingChecks.length ? 'IN_PROGRESS' : 'PASS'); + + return { + schemaVersion: 1, + kind: 'scenario-bench-longrun-checkpoint', + auditedAt: new Date(nowMs).toISOString(), + verdict, + gate: { + gateHours, + requiredDurationSec, + reached: durationReached, + runAgeSec: round(runAgeSec), + sampleSpanSec: round(sampleSpanSec), + firstSampleDelaySec: round(firstSampleDelaySec), + finalSampleDelaySec: round(finalSampleDelaySec), + freshnessSec: round(freshnessSec), + }, + run: { + scenarioName: runResult.scenarioName ?? null, + status: runResult.status ?? null, + startedAt: runResult.startedAt ?? null, + reportedEndedAt: runResult.endedAt ?? null, + allSamples: samples.length, + holdSamples: holdSamples.length, + expectedChannels: Number.isFinite(expectedChannels) ? expectedChannels : null, + stepIndexes, + firstHoldAt: holdSamples[0]?.iso ?? (firstTs == null ? null : new Date(firstTs).toISOString()), + lastHoldAt: holdSamples.at(-1)?.iso ?? (lastTs == null ? null : new Date(lastTs).toISOString()), + }, + continuity: { + medianGapSec: round(percentile(gapsSec, 0.5)), + p95GapSec: round(percentile(gapsSec, 0.95)), + maxGapSec: round(maxObservedGapSec), + gapsOverLimit: gapsSec.filter((gap) => gap > maxGapSec).length, + nonIncreasingTimestamps, + }, + workload: { + minFpsRatioGate: minFpsRatio, + worstFpsRatio, + discardLimit, + worstAverageDiscard, + maxMissingRate: round(maxMissingRate, 6), + bindings: bindingStats, + }, + resources, + memoryPool: pool, + nativeMedia: { + decoderBackends, + encoderBackends, + counters, + copyAccountingError, + copyAccountingTolerance, + frameFlow: { encoded, osd, published, osdRatio: round(osdRatio, 6), publishRatio: round(publishRatio, 6) }, + }, + preview: { + mode: previewMode, + expectedStreams: inferredPreviewStreams, + samples: previews.length, + errorSamples: previewErrors, + minSrsStreams: srsStreams.length ? Math.min(...srsStreams) : null, + minSrsPublishingStreams: publishingStreams.length ? Math.min(...publishingStreams) : null, + }, + checks, + failures: failedChecks.map((item) => item.id), + pending: pendingChecks.map((item) => item.id), + }; +} + +export function auditLongRunFile(inputPath, options = {}) { + const absoluteInput = path.resolve(inputPath); + const raw = fs.readFileSync(absoluteInput); + const runResult = JSON.parse(raw.toString('utf8')); + const result = auditLongRun(runResult, options); + result.source = { + path: options.sourceLabel ?? absoluteInput, + localPath: absoluteInput, + sizeBytes: raw.length, + sha256: sha256(raw), + }; + + if (options.identityPath) { + const identityPath = path.resolve(options.identityPath); + const identityRaw = fs.readFileSync(identityPath); + result.identity = { + path: options.identityLabel ?? identityPath, + localPath: identityPath, + sizeBytes: identityRaw.length, + sha256: sha256(identityRaw), + properties: parseIdentity(identityRaw.toString('utf8')), + }; + } + return result; +} + +export function writeLongRunAudit(outputPath, result) { + const absoluteOutput = path.resolve(outputPath); + fs.mkdirSync(path.dirname(absoluteOutput), { recursive: true }); + const temporaryPath = `${absoluteOutput}.tmp-${process.pid}`; + fs.writeFileSync(temporaryPath, `${JSON.stringify(result, null, 2)}\n`, 'utf8'); + fs.renameSync(temporaryPath, absoluteOutput); + return absoluteOutput; +} diff --git a/tools/scenario-bench/src/metrics-sampler.js b/tools/scenario-bench/src/metrics-sampler.js index c347236e6..ea62f0d94 100644 --- a/tools/scenario-bench/src/metrics-sampler.js +++ b/tools/scenario-bench/src/metrics-sampler.js @@ -1,5 +1,9 @@ // metrics-sampler.js — Collect RunningDetail + HardwareResource each tick. -import { isPrimaryThroughputAction, normalizeTaskType } from './task-strategies.js'; +import { + isPrimaryThroughputAction, + isThroughputBearingAction, + normalizeTaskType, +} from './task-strategies.js'; // // Response shapes (verified against source DTOs): // RunningDetail: resData.status[] where each item has @@ -53,14 +57,19 @@ export class MetricsSampler { const activeChannelIds = [...new Set(expected.map((entry) => entry.channelId))]; const activeTaskIds = [...new Set(expected.map((entry) => entry.taskId))]; - // Sample both endpoints in parallel; either may fail independently. - const [taskDetail, hwRes] = await Promise.allSettled([ + // Sample all endpoints in parallel; each may fail independently. + const [taskDetail, hwRes, memoryPoolRes] = await Promise.allSettled([ activeTaskIds.length ? this.client.taskRunningDetail(activeTaskIds) : Promise.resolve({ status: [] }), this.client.queryHardwareResource(), + typeof this.client.queryDeviceMemoryPool === 'function' + ? this.client.queryDeviceMemoryPool() + : Promise.resolve(null), ]); const perBinding = this._parseRunningDetail(taskDetail, expected, ts); const hw = this._parseHardware(hwRes); + const memoryPool = this._parseMemoryPool(memoryPoolRes); + if (memoryPool) hw.memoryPool = memoryPool; return { ts, @@ -144,6 +153,7 @@ export class MetricsSampler { const actionName = String(a.name ?? ''); const actionId = String(a.actionId ?? ''); const primaryThroughputAction = isPrimaryThroughputAction(actionName, actionId, taskType); + const throughputBearingAction = isThroughputBearingAction(actionName, actionId, taskType); if (primaryAction == null && primaryThroughputAction) { primaryAction = a; primaryProcessTotal = num(a.processCount); @@ -158,7 +168,7 @@ export class MetricsSampler { periodMs: actionPeriodMs, }); - if (actionFps != null && actionProcessPeriod > 0) { + if (actionFps != null && actionProcessPeriod > 0 && throughputBearingAction) { pipelineMinFps = Math.min(pipelineMinFps, actionFps); if (primaryFps == null && primaryThroughputAction) { primaryFps = actionFps; @@ -183,8 +193,14 @@ export class MetricsSampler { const firstEffective = actionSummaries.find((a) => a.fps != null && a.processPeriod > 0); primaryFps = firstEffective?.fps ?? null; } - const measuredFps = primaryFps ?? (isVlm ? null : 0); const minPipelineFps = pipelineMinFps !== Infinity ? pipelineMinFps : 0; + // A detector instance may be shared by several channels. Its AA_00001 counter is then the + // aggregate rate and is repeated in every task detail, while downstream per-channel actions + // retain the actual channel rate. CV throughput is therefore the slowest effective pipeline + // frame-throughput action. Terminal event/report actions run only when a + // business event fires and are intentionally excluded. Direct VLM keeps + // its dedicated completion-counter semantics. + const measuredFps = isVlm ? primaryFps : minPipelineFps; const discardRate = maxDiscardRate; const fpsRatio = targetFps && targetFps > 0 && measuredFps != null ? measuredFps / targetFps : null; @@ -229,7 +245,7 @@ export class MetricsSampler { const byKey = new Map(itemList.map((it) => [it.key, it])); for (const key of HW_KEYS) { const it = byKey.get(key); - if (it) { + if (it && it.available !== 0) { hw[key] = { usedPercent: num(it.usedPercent), usedSize: it.usedSize, unusedSize: it.unusedSize }; } } @@ -237,6 +253,30 @@ export class MetricsSampler { hw.accelerator = normalizeAccelerator(hwResult.value?.accelerator); return hw; } + + _parseMemoryPool(poolResult) { + if (poolResult.status !== 'fulfilled') { + return { _error: String(poolResult.reason?.message ?? poolResult.reason) }; + } + if (!poolResult.value || typeof poolResult.value !== 'object') return null; + + const totalAllocatedBytes = num(poolResult.value.totalMalloc); + const totalInUseBytes = num(poolResult.value.totalInUsing); + return { + totalAllocatedBytes, + totalInUseBytes, + utilizationPercent: totalAllocatedBytes > 0 + ? round((totalInUseBytes / totalAllocatedBytes) * 100, 2) + : 0, + pools: Array.isArray(poolResult.value.status) + ? poolResult.value.status.map((pool) => ({ + blockSize: num(pool.poolSize), + usedBlocks: num(pool.mallocCnt), + freeBlocks: num(pool.freeCnt), + })) + : [], + }; + } } function normalizeAccelerator(value) { diff --git a/tools/scenario-bench/src/preview-load.js b/tools/scenario-bench/src/preview-load.js index 7d07b43cd..a2e060c93 100644 --- a/tools/scenario-bench/src/preview-load.js +++ b/tools/scenario-bench/src/preview-load.js @@ -43,6 +43,14 @@ export class PreviewLoad { }; } + async preflight() { + if (this.mode === 'none' || this.clientsPerStream === 0) return; + if (!this.mediaBase) { + throw new Error('--media-base is required when preview clients are enabled'); + } + await assertMediaExecutable(this.ffmpeg, 'ffmpeg'); + } + async sync(entries) { if (this.mode === 'none') return; if (!this.mediaBase && this.clientsPerStream > 0) { @@ -197,6 +205,37 @@ export class PreviewLoad { } } +export async function assertMediaExecutable(command, label, timeoutMs = 10_000) { + await new Promise((resolve, reject) => { + const child = spawn(command, ['-version'], { stdio: 'ignore' }); + let settled = false; + const finish = (callback, value) => { + if (settled) return; + settled = true; + clearTimeout(timer); + callback(value); + }; + const timer = setTimeout(() => { + child.kill('SIGKILL'); + finish(reject, new Error(`${label} preflight timed out after ${timeoutMs}ms: ${command}`)); + }, timeoutMs); + timer.unref?.(); + child.once('error', (err) => { + const detail = err?.code === 'ENOENT' ? 'executable not found' : err.message; + finish(reject, new Error(`${label} preflight failed (${detail}): ${command}`)); + }); + child.once('exit', (code, signal) => { + if (code === 0) finish(resolve); + else { + finish( + reject, + new Error(`${label} preflight exited code=${code} signal=${signal ?? '-'}: ${command}`), + ); + } + }); + }); +} + function desiredStreams(entries, mode, streamLimit) { const byChannel = new Map(); for (const entry of entries ?? []) { diff --git a/tools/scenario-bench/src/preview-validator.js b/tools/scenario-bench/src/preview-validator.js index 96e37ae62..54d754b45 100644 --- a/tools/scenario-bench/src/preview-validator.js +++ b/tools/scenario-bench/src/preview-validator.js @@ -2,6 +2,8 @@ import fs from 'node:fs'; import path from 'node:path'; import { spawn } from 'node:child_process'; +import { assertMediaExecutable } from './preview-load.js'; + const DEFAULT_SAMPLE_WIDTH = 320; const DEFAULT_SAMPLE_HEIGHT = 180; const DEFAULT_SAMPLE_FPS = 5; @@ -47,6 +49,8 @@ export async function runPreviewValidation(client, options) { }; try { + await assertMediaExecutable(context.ffmpeg, 'ffmpeg'); + await assertMediaExecutable(context.ffprobe, 'ffprobe'); const baseline = await client.queryHardwareResource(); report.acceleratorBaseline = baseline.accelerator ?? null; @@ -72,13 +76,7 @@ export async function runPreviewValidation(client, options) { const rawPixels = report.streams.raw?.capture?.maxOverlayPixels ?? 0; const algorithmPixels = report.streams.algorithm.capture.maxOverlayPixels; const minimumDelta = nonNegativeInteger(options.minOverlayPixelDelta ?? 0, 'overlay pixel delta'); - report.osdPixelCheck = { - rawMaxOverlayPixels: rawPixels, - algorithmMaxOverlayPixels: algorithmPixels, - delta: algorithmPixels - rawPixels, - minimumDelta, - pass: algorithmPixels - rawPixels >= minimumDelta, - }; + report.osdPixelCheck = evaluateOsdPixelCheck(rawPixels, algorithmPixels, minimumDelta); if (!report.osdPixelCheck.pass) { throw new Error( `algorithm preview overlay pixel delta ${report.osdPixelCheck.delta} < ${minimumDelta}`, @@ -412,6 +410,19 @@ function countOverlayLikePixels(rgb) { return count; } +function evaluateOsdPixelCheck(rawPixels, algorithmPixels, minimumDelta) { + const deltaValue = algorithmPixels - rawPixels; + const enabled = minimumDelta > 0; + return { + rawMaxOverlayPixels: rawPixels, + algorithmMaxOverlayPixels: algorithmPixels, + delta: deltaValue, + minimumDelta, + enabled, + pass: !enabled || deltaValue >= minimumDelta, + }; +} + async function probeStream(ffprobe, url) { const output = await runProcess(ffprobe, [ '-v', 'error', '-rw_timeout', '5000000', @@ -594,6 +605,7 @@ export const _previewValidatorTest = { captureArgs, captureTimeoutMs, countOverlayLikePixels, + evaluateOsdPixelCheck, lifecycleMetricsReady, streamNameFromFlvUrl, }; diff --git a/tools/scenario-bench/src/report-writer.js b/tools/scenario-bench/src/report-writer.js index 8a9d1d536..9d1812fb7 100644 --- a/tools/scenario-bench/src/report-writer.js +++ b/tools/scenario-bench/src/report-writer.js @@ -65,7 +65,8 @@ export class ReportWriter { _buildSummary(r, stepSummaries) { const ran = stepSummaries.filter((s) => !s.skipped); - const firstFailed = ran.find((s) => s.pass === false) ?? null; + const qualifiedRan = ran.filter((s) => s.qualified !== false); + const firstFailed = qualifiedRan.find((s) => s.pass === false) ?? null; const bottleneck = normalizeBottleneck(r.bottleneck ?? (firstFailed ? { stepIndex: firstFailed.step.index, @@ -75,15 +76,16 @@ export class ReportWriter { } : null), stepSummaries); const hasBottleneck = Boolean(bottleneck); - const verifiedPassed = ran.filter((s) => + const verifiedPassed = qualifiedRan.filter((s) => s.pass && (!hasBottleneck || s.step.index < bottleneck.stepIndex), ); const maxVerifiedPassedChannels = verifiedPassed.length ? Math.max(...verifiedPassed.map((s) => s.channels)) : null; - const continuousProfile = r.profileMode === 'capacity' || isContinuousChannelProfile(stepSummaries); + const continuousProfile = r.profileMode === 'capacity' + || isContinuousChannelProfile(qualifiedRan); const maxStableChannels = continuousProfile ? maxVerifiedPassedChannels : null; - const allRanStepsPass = ran.length > 0 && ran.every((s) => s.pass); + const allRanStepsPass = qualifiedRan.length > 0 && qualifiedRan.every((s) => s.pass); const capacityMeasured = r.status !== 'aborted' && continuousProfile && maxVerifiedPassedChannels != null @@ -143,6 +145,7 @@ export class ReportWriter { startedAt: r.startedAt, endedAt: r.endedAt, sampleCount: (r.samples ?? []).length, + rampProbeChannels: ran.filter((s) => s.qualified === false).map((s) => s.channels), mediaStages: stepSummaries.map((step) => ({ channels: step.channels, ...step.mediaStages })), }; } @@ -156,7 +159,7 @@ export class ReportWriter { : '阶梯汇总使用该阶梯后半段采样点作为稳定窗口。'; const profileText = summary.maxStableChannelsExact ? '当前按连续路数扫描,可直接给出容量上限。容量上限是最后一个完整执行且通过报告阈值的路数。' - : `当前阶梯不是连续通道数,只能给出已验证通过阶梯;连续最大稳定路数需在相邻区间内补测。${summary.capacityBound ? `本次已知 >= ${summary.capacityBound.lowerInclusive ?? 0} 路且 < ${summary.capacityBound.upperExclusive} 路。` : ''}`; + : `当前阶梯不是连续通道数,只能给出已验证通过阶梯;连续最大稳定路数需在相邻区间内补测。爬坡瞬时采样只标记为 PROBE,不计入稳定容量。${summary.capacityBound ? `本次已知 >= ${summary.capacityBound.lowerInclusive ?? 0} 路且 < ${summary.capacityBound.upperExclusive} 路。` : ''}`; const interpretationRows = [ ['容量结论', profileText], ['路数 PASS/FAIL', `每个任务按 task type 选择判定策略。CV 默认使用关键链路、检测节点和丢弃率;VLM 默认使用分析 FPS 达标率和采样缺失率,并可配置端到端延时。全局平均丢弃率阈值为 ${pass.avgDiscardRate ?? pass.maxDiscardRate ?? '-'}。`], @@ -196,6 +199,7 @@ export class ReportWriter { && (summary.bottleneck.channels == null || summary.bottleneck.channels === s.channels)) { return { className: 'warn', label: 'STOPPED' }; } + if (s.qualified === false) return { className: 'na', label: 'PROBE' }; return s.pass ? { className: 'pass', label: 'PASS' } : { className: 'fail', label: 'FAIL' }; }; @@ -216,6 +220,8 @@ export class ReportWriter { <td class="${s.maxAcceleratorMem >= 90 ? 'fail' : ''}">${s.maxAcceleratorMem != null ? s.maxAcceleratorMem + '%' : '-'}</td> <td class="${s.maxCpu >= 90 ? 'fail' : ''}">${s.maxCpu != null ? s.maxCpu + '%' : '-'}</td> <td class="${s.maxMem >= 90 ? 'fail' : ''}">${s.maxMem != null ? s.maxMem + '%' : '-'}</td> + <td class="${s.maxDiskUsedPercent >= 90 ? 'fail' : ''}">${s.maxDiskUsedPercent != null ? s.maxDiskUsedPercent + '%' : '-'}</td> + <td>${formatMib(s.maxPoolInUseBytes)}/${formatMib(s.maxPoolAllocatedBytes)}/${s.maxPoolUtilizationPercent != null ? s.maxPoolUtilizationPercent + '%' : '-'}</td> <td class="${status.className}">${status.label}</td> <td>${esc((s.reasons ?? []).join('; '))}</td> </tr>`; @@ -258,6 +264,25 @@ export class ReportWriter { <td>${metric(m.preprocessAvgMs)}</td> <td>${metric(m.inferAvgMs)}</td> <td>${metric(m.postprocessAvgMs)}</td> + <td>${metric(m.colorConvertAvgMs)}/${metric(m.blobConvertAvgMs)}</td> + <td>${metric(m.graphForwardAvgMs)}/${metric(m.resultParseAvgMs)}</td> + <td>${metric(m.rknnPrepareAvgMs)}/${metric(m.rknnInputsSetAvgMs)}</td> + <td>${metric(m.rknnRunAvgMs)}/${metric(m.rknnOutputsGetAvgMs)}/${metric(m.rknnOutputsReleaseAvgMs)}/${metric(m.rknnOutputTransformAvgMs)}</td> + <td>${metric(m.rknnForwardAvgMs)}/${m.rknnForwardFailures ?? '-'}</td> + <td>${metric(m.rknnDetectorForwardAvgMs)}/${metric(m.rknnDetectorMutexWaitAvgMs)}/${m.rknnDetectorForwardFailures ?? '-'}</td> + <td>${metric(m.rknnRgaFillAvgMs)}/${metric(m.rknnRgaResizeColorAvgMs)}/${metric(m.rknnNativeInputMapAvgMs)}/${m.rknnPreprocessFastHits ?? '-'}/${m.rknnRgaFailures ?? '-'}</td> + <td>${m.rknnCpuResizeFallbacks ?? '-'}/${m.rknnCpuNormalizeFallbacks ?? '-'}/${m.rknnInputCompatibilityFallbacks ?? '-'}</td> + <td>${m.rknnBoundInputBindAttempts ?? '-'}/${m.rknnBoundInputBindFailures ?? '-'}/${m.rknnBoundInputFrames ?? '-'}/${metric(m.rknnBoundInputCopyAvgMs)}/${metric(m.rknnBoundInputSyncAvgMs)}/${formatMib(m.rknnBoundInputCopyAvgBytes)}/${m.rknnBoundInputCopyFailures ?? '-'}/${m.rknnBoundInputSyncFailures ?? '-'}</td> + <td>${m.rknnRgaBoundInputBindAttempts ?? '-'}/${m.rknnRgaBoundInputBindFailures ?? '-'}/${m.rknnRgaBoundInputImportCalls ?? '-'}/${metric(m.rknnRgaBoundInputImportAvgMs)}/${m.rknnRgaBoundInputImportFailures ?? '-'}/${m.rknnRgaBoundInputFrames ?? '-'}/${m.rknnRgaBoundUint8Frames ?? '-'}/${m.rknnRgaBoundNativeInt8Frames ?? '-'}/${m.rknnRgaBoundRequantizeCalls ?? '-'}/${metric(m.rknnRgaBoundRequantizeAvgMs)}/${m.rknnRgaBoundRequantizeFailures ?? '-'}/${m.rknnRgaBoundInputNormalizeBypasses ?? '-'}</td> + <td>${m.rknnMppDmaBufImportCalls ?? '-'}/${metric(m.rknnMppDmaBufImportAvgMs)}/${m.rknnMppDmaBufImportFailures ?? '-'}/${m.rknnMppDmaBufFrames ?? '-'}/${m.rknnMppDmaBufFallbacks ?? '-'}/${formatMib(m.rknnMppDmaBufSourceAvgBytes)}</td> + <td>${m.rknnNativeInt8Outputs ?? '-'}/${m.rknnFloatOutputs ?? '-'}/${m.rknnOutputCompatibilityFallbacks ?? '-'}/${formatMib(m.rknnNativeOutputAvgBytes)}/${formatMib(m.rknnFloatOutputAvgBytes)}</td> + <td>${metric(m.rknnYolov8DflAvgMs)}/${metric(m.rknnYolov8ClassAvgMs)}</td> + <td>${m.rknnYolov8DirectCandidateCalls ?? '-'}/${m.rknnYolov8DirectCandidateFailures ?? '-'}/${metric(m.rknnYolov8DirectAvgPointsScanned)}/${metric(m.rknnYolov8DirectAvgPointsDecoded)}/${metric(m.rknnYolov8ScoreSumAvgPointsRejected)}/${formatMib(m.rknnYolov8LogicalFloatBytesAvoided)}</td> + <td>${metric(m.yolov8PostprocessAvgMs)}/${metric(m.yolov8NmsAvgMs)}</td> + <td>${metric(m.rgaAvgMs)}/${m.rgaFailures ?? '-'}</td> + <td>${metric(m.mppEncodeAvgMs)}/${m.mppEncodeFailures ?? '-'}</td> + <td>${metric(m.mppDecodeAvgMs)}/${m.mppDecodeFailures ?? '-'}/${m.mppDecodeFallbacks ?? '-'}</td> + <td>${metric(m.mppCopyOutAvgMs)}/${m.mppDecodedFrames ?? '-'}/${m.mppCopyOutFrames ?? '-'}/${m.mppEarlyDroppedFrames ?? '-'}/${m.mppCopyOutFailures ?? '-'}</td> <td>${metric(m.osdAvgMs)}</td> <td>${metric(m.publishAvgMs)}</td> <td>${metric(m.firstFrameAvgMs)}/${metric(m.firstFrameMaxMs)}</td> @@ -296,12 +321,12 @@ ${bottleneckBanner} <table>${baseRows.map(([k, v]) => `<tr><th>${esc(k)}</th><td>${esc(v)}</td></tr>`).join('')}</table> <h2>路数结果</h2> <table> - <tr><th>序号</th><th>路数</th><th>保持</th><th>目标FPS(参考)</th><th>处理FPS(参考)</th><th>关键/端到端延时ms</th><th>主节点延时ms</th><th>平均丢弃率</th><th>最差通道丢弃率</th><th>加速器峰值</th><th>加速器内存峰值</th><th>CPU峰值</th><th>内存峰值</th><th>结果</th><th>失败原因</th></tr> + <tr><th>序号</th><th>路数</th><th>保持</th><th>目标FPS(参考)</th><th>处理FPS(参考)</th><th>关键/端到端延时ms</th><th>主节点延时ms</th><th>平均丢弃率</th><th>最差通道丢弃率</th><th>加速器峰值</th><th>加速器内存峰值</th><th>CPU峰值</th><th>内存峰值</th><th>磁盘峰值</th><th>内存池在用/分配MiB/占用率</th><th>结果</th><th>失败原因</th></tr> ${stepRows} </table> <h2>媒体与预览分阶段指标</h2> <table> - <tr><th>路数</th><th>Preprocess ms</th><th>Infer ms</th><th>Postprocess ms</th><th>OSD ms</th><th>Publish ms</th><th>首帧平均/进程最大ms</th><th>预览流/发布器峰值</th><th>原始/算法预览峰值</th><th>SRS流/客户端峰值</th><th>启动/停止/失败增量</th></tr> + <tr><th>路数</th><th>Preprocess ms</th><th>Infer ms</th><th>Postprocess ms</th><th>颜色/Blob ms</th><th>Graph/Parse ms</th><th>RKNN准备/送入 ms</th><th>RKNN执行/取回/释放/转换 ms</th><th>RKNN总计/失败</th><th>Detector总计/等待/失败</th><th>Fast Fill/Resize/Map/命中/失败</th><th>Fallback Resize/Normalize/Compat</th><th>绑定输入 Bind/失败/帧/Copy ms/Sync ms/CopyMiB/Copy失败/Sync失败</th><th>RGA直绑 Bind/失败/Import次数/ms/失败/帧/UINT8融合帧/INT8回退帧/Requant次数/ms/失败/Normalize绕过</th><th>MPP DMA-BUF Import/ms/失败/帧/回退/源MiB</th><th>输出 Native/Float/Compat/NativeMiB/FloatMiB</th><th>量化 DFL/Class ms</th><th>直接候选 调用/失败/扫描/解码/Sum早筛/省略MiB</th><th>YOLO Post/NMS</th><th>RGA/失败</th><th>MPP编码/失败</th><th>MPP解码/失败/回退</th><th>Copy-out ms/解码/复制/早丢/失败</th><th>OSD ms</th><th>Publish ms</th><th>首帧平均/进程最大ms</th><th>预览流/发布器峰值</th><th>原始/算法预览峰值</th><th>SRS流/客户端峰值</th><th>启动/停止/失败增量</th></tr> ${mediaRows} </table> <h2>分任务汇总</h2> @@ -369,9 +394,8 @@ function buildReportSteps(runResult) { const seenChannels = new Set(); for (const step of steps) { - const observedChannels = uniqueObservedChannels( - samples.filter((sample) => sample.stepIndex === step.index), - ); + const stepSamples = samples.filter((sample) => sample.stepIndex === step.index); + const observedChannels = uniqueObservedChannels(stepSamples); const shouldExpand = observedChannels.length > 1 && observedChannels.some((channels) => channels < step.channels); @@ -380,6 +404,8 @@ function buildReportSteps(runResult) { for (const channels of channelsToReport) { if (seenChannels.has(channels)) continue; seenChannels.add(channels); + const qualified = stepSamples.some((sample) => + Number(sample.activeChannels) === channels && sample.phase !== 'ramp'); reportSteps.push({ ...step, index: channels - 1, @@ -388,6 +414,7 @@ function buildReportSteps(runResult) { targetChannels: step.channels, sampleStepIndex: step.index, sampleChannels: channels, + qualified, }); } } @@ -444,6 +471,10 @@ function formatPercent(v) { return `${round(Number(v) * 100, 2)}%`; } +function formatMib(bytes) { + return typeof bytes === 'number' ? round(bytes / (1024 * 1024), 1) : '-'; +} + function round(v, digits) { const f = 10 ** digits; return Math.round(v * f) / f; diff --git a/tools/scenario-bench/src/scenario-package.js b/tools/scenario-bench/src/scenario-package.js index 8476d5556..66cc3a3e8 100644 --- a/tools/scenario-bench/src/scenario-package.js +++ b/tools/scenario-bench/src/scenario-package.js @@ -15,6 +15,7 @@ import { normalizeTaskType } from './task-strategies.js'; const FPS_ACTION_ID = 'AA_00001'; const VLM_ACTION_IDS = new Set(['DA_00003', 'PDA_00003']); +const FPS_ACTION_IDS = new Set([FPS_ACTION_ID, ...VLM_ACTION_IDS]); const SUPPORTED_VIDEO_MODES = new Set(['local', 'rtsp-fidelity', 'rtsp-deterministic']); export const DEFAULT_HOLD_SEC = 30; export const DEFAULT_VLM_HOLD_SEC = 60; @@ -159,10 +160,17 @@ export class ScenarioPackage { const scheduleId = spec.scheduleId ?? ''; const vlm = detectVlmMode(template); const type = vlm.direct ? 'vlm' : (spec.type ?? 'cv'); - const targetFps = spec.targetFps != null ? Number(spec.targetFps) : extractTargetFpsFromTemplate(template); + const explicitTargetFps = spec.targetFps != null ? Number(spec.targetFps) : null; + const targetFps = explicitTargetFps ?? extractTargetFpsFromTemplate(template); const normalizedType = normalizeTaskType(type); const videoReadFps = this.videoMode === 'local' && normalizedType === 'vlm' ? targetFps : null; - const taskConfig = buildTaskConfig(template, this.videoRepeatCount, videoReadFps); + const taskConfig = buildTaskConfig( + template, + this.videoRepeatCount, + videoReadFps, + spec.taskConfig, + `tasks[${index}]`, + ); return { id, @@ -176,7 +184,7 @@ export class ScenarioPackage { template, targetFps: Number.isFinite(targetFps) && targetFps > 0 ? targetFps : null, taskConfig, - layoutSavePayload: buildLayoutSavePayload(template), + layoutSavePayload: buildLayoutSavePayload(template, explicitTargetFps), }; } @@ -281,9 +289,32 @@ export class ScenarioPackage { } } -function buildTaskConfig(template, videoRepeatCount, videoReadFps = null) { +function buildTaskConfig( + template, + videoRepeatCount, + videoReadFps = null, + taskConfigOverride = null, + taskPath = 'task', +) { const base = template.taskConfig ?? { params: [], areas: [] }; - const params = Array.isArray(base.params) ? [...base.params] : []; + if (taskConfigOverride != null + && (typeof taskConfigOverride !== 'object' || Array.isArray(taskConfigOverride))) { + throw new Error(`scenario.yml: ${taskPath}.taskConfig must be an object`); + } + + const override = taskConfigOverride ?? {}; + if (override.params != null && !Array.isArray(override.params)) { + throw new Error(`scenario.yml: ${taskPath}.taskConfig.params must be an array`); + } + if (override.areas != null && !Array.isArray(override.areas)) { + throw new Error(`scenario.yml: ${taskPath}.taskConfig.areas must be an array`); + } + + const params = mergeTaskConfigParams( + Array.isArray(base.params) ? base.params : [], + override.params ?? [], + taskPath, + ); const hasRepeat = params.some((p) => p?.key === 'param.videoRepeatCount'); if (!hasRepeat) { params.push({ key: 'param.videoRepeatCount', value: String(videoRepeatCount) }); @@ -292,7 +323,51 @@ function buildTaskConfig(template, videoRepeatCount, videoReadFps = null) { if (!hasReadFps && Number.isFinite(videoReadFps) && videoReadFps > 0) { params.push({ key: 'param.videoReadFps', value: String(videoReadFps) }); } - return { ...base, params, areas: base.areas ?? [] }; + return { + ...base, + ...override, + params, + areas: override.areas ?? base.areas ?? [], + }; +} + +function mergeTaskConfigParams(baseParams, overrideParams, taskPath) { + const params = baseParams.map((param) => ({ ...param })); + const indexByKey = new Map(); + for (const [index, param] of params.entries()) { + if (param?.key != null && !indexByKey.has(String(param.key))) { + indexByKey.set(String(param.key), index); + } + } + + const overrideKeys = new Set(); + for (const [index, param] of overrideParams.entries()) { + const key = String(param?.key ?? '').trim(); + if (!key) { + throw new Error( + `scenario.yml: ${taskPath}.taskConfig.params[${index}].key must be a non-empty string`, + ); + } + if (param.value == null) { + throw new Error( + `scenario.yml: ${taskPath}.taskConfig.params[${index}].value is required`, + ); + } + if (overrideKeys.has(key)) { + throw new Error(`scenario.yml: ${taskPath}.taskConfig.params has duplicate key "${key}"`); + } + overrideKeys.add(key); + + const normalized = { ...param, key, value: String(param.value) }; + const existingIndex = indexByKey.get(key); + if (existingIndex == null) { + indexByKey.set(key, params.length); + params.push(normalized); + } else { + params[existingIndex] = normalized; + } + } + return params; } export function defaultHoldSecForTasks(tasks) { @@ -303,7 +378,7 @@ export function defaultHoldSecForTasks(tasks) { return hasVlm ? DEFAULT_VLM_HOLD_SEC : DEFAULT_HOLD_SEC; } -function buildLayoutSavePayload(template) { +function buildLayoutSavePayload(template, targetFpsOverride = null) { const algorithmId = String(template.algorithmId ?? template.id ?? template.algorithmCode ?? ''); if (!algorithmId) throw new Error('template: cannot derive algorithmId for layout save'); const str = (v) => (v == null ? undefined : String(v)); @@ -315,12 +390,53 @@ function buildLayoutSavePayload(template) { algorithmUsage: str(template.algorithmUsage), remark: str(template.remark), atomicList: str(template.atomicList), - algorithmProcessdata: str(template.algorithmProcessdata), + algorithmProcessdata: str(overrideProcessTargetFps(template.algorithmProcessdata, targetFpsOverride)), algorithmMetadata: str(template.algorithmMetadata), filePath: str(template.filePath), }; } +function overrideProcessTargetFps(raw, targetFps) { + if (!Number.isFinite(targetFps) || targetFps <= 0 || raw == null) return raw; + + let nodes; + try { + nodes = typeof raw === 'string' ? JSON.parse(raw) : raw; + } catch { + return raw; + } + if (!Array.isArray(nodes)) return raw; + + let updated = false; + const nextNodes = nodes.map((node) => { + if (!FPS_ACTION_IDS.has(String(node?.actionId ?? ''))) return node; + + const configWasString = typeof node.configObject === 'string'; + let configObject = node.configObject; + if (configWasString) { + try { configObject = JSON.parse(configObject); } catch { return node; } + } + if (!Array.isArray(configObject?.params)) return node; + + let nodeUpdated = false; + const params = configObject.params.map((param) => { + if (param?.key !== 'fps') return param; + nodeUpdated = true; + return { ...param, value: String(targetFps) }; + }); + if (!nodeUpdated) return node; + + updated = true; + const nextConfig = { ...configObject, params }; + return { + ...node, + configObject: configWasString ? JSON.stringify(nextConfig) : nextConfig, + }; + }); + + return updated ? JSON.stringify(nextNodes) : raw; +} + function parseProcessData(template) { const raw = template.algorithmProcessdata; if (raw == null) return []; diff --git a/tools/scenario-bench/src/shutdown-signal.js b/tools/scenario-bench/src/shutdown-signal.js new file mode 100644 index 000000000..6facba5dd --- /dev/null +++ b/tools/scenario-bench/src/shutdown-signal.js @@ -0,0 +1,72 @@ +const SIGNAL_EXIT_CODES = { + SIGINT: 130, + SIGTERM: 143, +}; + +export class ShutdownSignalError extends Error { + constructor(signalName) { + super(`received ${signalName}; shutting down`); + this.name = 'ShutdownSignalError'; + this.signalName = signalName; + this.exitCode = SIGNAL_EXIT_CODES[signalName] ?? 1; + } +} + +export function installShutdownSignalHandlers(controller, { + processRef = process, + onSignal = null, +} = {}) { + if (!controller?.signal || typeof controller.abort !== 'function') { + throw new TypeError('an AbortController is required'); + } + + let handled = false; + const handle = (signalName) => { + if (handled) return; + handled = true; + const error = new ShutdownSignalError(signalName); + try { + onSignal?.(error); + } finally { + if (!controller.signal.aborted) controller.abort(error); + } + }; + const onSigint = () => handle('SIGINT'); + const onSigterm = () => handle('SIGTERM'); + + processRef.on('SIGINT', onSigint); + processRef.on('SIGTERM', onSigterm); + + return () => { + processRef.off('SIGINT', onSigint); + processRef.off('SIGTERM', onSigterm); + }; +} + +export function throwIfAborted(signal) { + if (!signal?.aborted) return; + if (signal.reason instanceof Error) throw signal.reason; + throw new Error('operation aborted'); +} + +export function sleepWithSignal(ms, signal) { + throwIfAborted(signal); + if (ms <= 0) return Promise.resolve(); + + return new Promise((resolve, reject) => { + const onAbort = () => { + clearTimeout(timer); + signal?.removeEventListener('abort', onAbort); + try { + throwIfAborted(signal); + } catch (error) { + reject(error); + } + }; + const timer = setTimeout(() => { + signal?.removeEventListener('abort', onAbort); + resolve(); + }, ms); + signal?.addEventListener('abort', onAbort, { once: true }); + }); +} diff --git a/tools/scenario-bench/src/step-evaluator.js b/tools/scenario-bench/src/step-evaluator.js index 49d796d8b..d71fb132c 100644 --- a/tools/scenario-bench/src/step-evaluator.js +++ b/tools/scenario-bench/src/step-evaluator.js @@ -28,6 +28,7 @@ export function summarizeStep(step, samples, thresholds = {}, videoMode = 'local pass: null, reasons: ['未执行,瓶颈提前停止'], skipped: true, + qualified: step.qualified !== false, }; } @@ -124,6 +125,10 @@ export function summarizeStep(step, samples, thresholds = {}, videoMode = 'local }); const maxCpu = peak((tick) => tick.hardware?.cpuUtilization?.usedPercent); const maxMem = peak((tick) => tick.hardware?.generalMemoryUtilization?.usedPercent); + const maxDiskUsedPercent = peak((tick) => tick.hardware?.eMMCUtilization?.usedPercent); + const maxPoolAllocatedBytes = peak((tick) => tick.hardware?.memoryPool?.totalAllocatedBytes); + const maxPoolInUseBytes = peak((tick) => tick.hardware?.memoryPool?.totalInUseBytes); + const maxPoolUtilizationPercent = peak((tick) => tick.hardware?.memoryPool?.utilizationPercent); const taskStats = summarizeTasks(channelStats); const mediaStages = summarizeMediaStages(ticks, maxPrimaryLat); @@ -137,6 +142,24 @@ export function summarizeStep(step, samples, thresholds = {}, videoMode = 'local overall.reasons.push(...verdict.reasons); } } + const diskLimit = thresholds.pass?.maxDiskUsedPercent; + if (diskLimit != null) { + const ok = maxDiskUsedPercent == null || maxDiskUsedPercent <= diskLimit; + perThreshold.push({ + taskKey: '*', + taskDisplayName: 'device', + taskType: 'system', + strategy: 'system', + name: 'maxDiskUsedPercent', + threshold: diskLimit, + actual: maxDiskUsedPercent, + result: maxDiskUsedPercent == null ? 'N/A' : (ok ? 'PASS' : 'FAIL'), + }); + if (!ok) { + overall.pass = false; + overall.reasons.push(`设备磁盘使用率 ${maxDiskUsedPercent}%,阈值 ${diskLimit}%`); + } + } if (videoMode !== 'local') { const pass = thresholds.pass ?? {}; const limit = pass.maxPacketDiscardRate; @@ -172,12 +195,17 @@ export function summarizeStep(step, samples, thresholds = {}, videoMode = 'local maxAcceleratorMem, maxCpu, maxMem, + maxDiskUsedPercent, + maxPoolAllocatedBytes, + maxPoolInUseBytes, + maxPoolUtilizationPercent, mediaStages, channelStats, taskStats, perThreshold, pass: overall.pass, reasons: overall.reasons, + qualified: step.qualified !== false, }; } @@ -209,6 +237,171 @@ function summarizeMediaStages(ticks, inferMs) { preprocessAvgMs: nodeStages.preprocess, inferAvgMs: inferMs, postprocessAvgMs: nodeStages.postprocess, + colorConvertAvgMs: counterAverage('colorConvertMs', 'colorConvertFrames'), + blobConvertAvgMs: counterAverage('blobConvertMs', 'blobConvertFrames'), + graphForwardAvgMs: counterAverage('graphForwardMs', 'graphForwardFrames'), + resultParseAvgMs: counterAverage('resultParseMs', 'resultParseFrames'), + graphForwardFailures: counterDelta('graphForwardFailures'), + resultParseFailures: counterDelta('resultParseFailures'), + rknnPrepareAvgMs: counterAverage('rknnPrepareMs', 'rknnPrepareCalls'), + rknnInputsSetAvgMs: counterAverage('rknnInputsSetMs', 'rknnInputsSetCalls'), + rknnRunAvgMs: counterAverage('rknnRunMs', 'rknnRunCalls'), + rknnOutputsGetAvgMs: counterAverage('rknnOutputsGetMs', 'rknnOutputsGetCalls'), + rknnOutputsReleaseAvgMs: counterAverage( + 'rknnOutputsReleaseMs', + 'rknnOutputsReleaseCalls', + ), + rknnOutputTransformAvgMs: counterAverage( + 'rknnOutputTransformMs', + 'rknnOutputTransformCalls', + ), + rknnForwardAvgMs: counterAverage('rknnForwardMs', 'rknnForwards'), + rknnForwardFailures: counterDelta('rknnForwardFailures'), + rknnMutexWaitAvgMs: counterAverage('rknnMutexWaitMs', 'rknnMutexWaitCalls'), + rknnDetectorPrepareAvgMs: counterAverage( + 'rknnDetectorPrepareMs', + 'rknnDetectorPrepareCalls', + ), + rknnDetectorInputsSetAvgMs: counterAverage( + 'rknnDetectorInputsSetMs', + 'rknnDetectorInputsSetCalls', + ), + rknnDetectorRunAvgMs: counterAverage('rknnDetectorRunMs', 'rknnDetectorRunCalls'), + rknnDetectorOutputsGetAvgMs: counterAverage( + 'rknnDetectorOutputsGetMs', + 'rknnDetectorOutputsGetCalls', + ), + rknnDetectorOutputsReleaseAvgMs: counterAverage( + 'rknnDetectorOutputsReleaseMs', + 'rknnDetectorOutputsReleaseCalls', + ), + rknnDetectorOutputTransformAvgMs: counterAverage( + 'rknnDetectorOutputTransformMs', + 'rknnDetectorOutputTransformCalls', + ), + rknnDetectorForwardAvgMs: counterAverage( + 'rknnDetectorForwardMs', + 'rknnDetectorForwards', + ), + rknnDetectorForwardFailures: counterDelta('rknnDetectorForwardFailures'), + rknnDetectorMutexWaitAvgMs: counterAverage( + 'rknnDetectorMutexWaitMs', + 'rknnDetectorMutexWaitCalls', + ), + rknnPreprocessFastHits: counterDelta('rknnPreprocessFastHits'), + rknnRgaFillAvgMs: counterAverage('rknnRgaFillMs', 'rknnRgaFillCalls'), + rknnRgaResizeColorAvgMs: counterAverage( + 'rknnRgaResizeColorMs', + 'rknnRgaResizeColorCalls', + ), + rknnRgaFailures: counterDelta('rknnRgaFailures'), + rknnCpuResizeFallbackAvgMs: counterAverage( + 'rknnCpuResizeFallbackMs', + 'rknnCpuResizeFallbackCalls', + ), + rknnCpuResizeFallbacks: counterDelta('rknnCpuResizeFallbackCalls'), + rknnCpuNormalizeFallbackAvgMs: counterAverage( + 'rknnCpuNormalizeFallbackMs', + 'rknnCpuNormalizeFallbackCalls', + ), + rknnCpuNormalizeFallbacks: counterDelta('rknnCpuNormalizeFallbackCalls'), + rknnNativeInputMapAvgMs: counterAverage( + 'rknnNativeInputMapMs', + 'rknnNativeInputMapCalls', + ), + rknnNativeInt8Inputs: counterDelta('rknnNativeInt8Inputs'), + rknnFloatInputs: counterDelta('rknnFloatInputs'), + rknnInputCompatibilityFallbacks: counterDelta('rknnInputCompatibilityFallbacks'), + rknnBoundInputBindAttempts: counterDelta('rknnBoundInputBindAttempts'), + rknnBoundInputBindFailures: counterDelta('rknnBoundInputBindFailures'), + rknnBoundInputCopyAvgMs: counterAverage( + 'rknnBoundInputCopyMs', + 'rknnBoundInputCopyCalls', + ), + rknnBoundInputCopyAvgBytes: counterAverage( + 'rknnBoundInputCopyBytes', + 'rknnBoundInputCopyCalls', + ), + rknnBoundInputCopyFailures: counterDelta('rknnBoundInputCopyFailures'), + rknnBoundInputSyncAvgMs: counterAverage( + 'rknnBoundInputSyncMs', + 'rknnBoundInputSyncCalls', + ), + rknnBoundInputSyncFailures: counterDelta('rknnBoundInputSyncFailures'), + rknnBoundInputFrames: counterDelta('rknnBoundInputFrames'), + rknnRgaBoundInputBindAttempts: counterDelta('rknnRgaBoundInputBindAttempts'), + rknnRgaBoundInputBindFailures: counterDelta('rknnRgaBoundInputBindFailures'), + rknnRgaBoundInputImportCalls: counterDelta('rknnRgaBoundInputImportCalls'), + rknnRgaBoundInputImportAvgMs: counterAverage( + 'rknnRgaBoundInputImportMs', + 'rknnRgaBoundInputImportCalls', + ), + rknnRgaBoundInputImportFailures: counterDelta('rknnRgaBoundInputImportFailures'), + rknnRgaBoundInputFrames: counterDelta('rknnRgaBoundInputFrames'), + rknnRgaBoundUint8Frames: counterDelta('rknnRgaBoundUint8Frames'), + rknnRgaBoundNativeInt8Frames: counterDelta('rknnRgaBoundNativeInt8Frames'), + rknnRgaBoundRequantizeCalls: counterDelta('rknnRgaBoundRequantizeCalls'), + rknnRgaBoundRequantizeAvgMs: counterAverage( + 'rknnRgaBoundRequantizeMs', + 'rknnRgaBoundRequantizeCalls', + ), + rknnRgaBoundRequantizeFailures: counterDelta('rknnRgaBoundRequantizeFailures'), + rknnRgaBoundInputNormalizeBypasses: counterDelta( + 'rknnRgaBoundInputNormalizeBypasses', + ), + rknnMppDmaBufImportCalls: counterDelta('rknnMppDmaBufImportCalls'), + rknnMppDmaBufImportAvgMs: counterAverage( + 'rknnMppDmaBufImportMs', + 'rknnMppDmaBufImportCalls', + ), + rknnMppDmaBufImportFailures: counterDelta('rknnMppDmaBufImportFailures'), + rknnMppDmaBufFrames: counterDelta('rknnMppDmaBufFrames'), + rknnMppDmaBufFallbacks: counterDelta('rknnMppDmaBufFallbacks'), + rknnMppDmaBufSourceAvgBytes: counterAverage( + 'rknnMppDmaBufSourceBytes', + 'rknnMppDmaBufFrames', + ), + rknnNativeInt8Outputs: counterDelta('rknnNativeInt8Outputs'), + rknnFloatOutputs: counterDelta('rknnFloatOutputs'), + rknnOutputCompatibilityFallbacks: counterDelta('rknnOutputCompatibilityFallbacks'), + rknnNativeOutputAvgBytes: counterAverage( + 'rknnNativeOutputBytes', + 'rknnNativeInt8Outputs', + ), + rknnFloatOutputAvgBytes: counterAverage('rknnFloatOutputBytes', 'rknnFloatOutputs'), + rknnYolov8DflAvgMs: counterAverage('rknnYolov8DflMs', 'rknnYolov8DflCalls'), + rknnYolov8ClassAvgMs: counterAverage('rknnYolov8ClassMs', 'rknnYolov8ClassCalls'), + rknnYolov8DirectCandidateCalls: counterDelta('rknnYolov8DirectCandidateCalls'), + rknnYolov8DirectCandidateFailures: counterDelta('rknnYolov8DirectCandidateFailures'), + rknnYolov8DirectAvgPointsScanned: counterAverage( + 'rknnYolov8DirectPointsScanned', + 'rknnYolov8DirectCandidateCalls', + ), + rknnYolov8DirectAvgPointsDecoded: counterAverage( + 'rknnYolov8DirectPointsDecoded', + 'rknnYolov8DirectCandidateCalls', + ), + rknnYolov8ScoreSumAvgPointsRejected: counterAverage( + 'rknnYolov8ScoreSumPointsRejected', + 'rknnYolov8DirectCandidateCalls', + ), + rknnYolov8LogicalFloatBytesAvoided: counterDelta( + 'rknnYolov8LogicalFloatBytesAvoided', + ), + yolov8PostprocessAvgMs: counterAverage('yolov8PostprocessMs', 'yolov8PostprocessCalls'), + yolov8NmsAvgMs: counterAverage('yolov8NmsMs', 'yolov8NmsCalls'), + rgaAvgMs: counterAverage('rgaMs', 'rgaFrames'), + rgaFailures: counterDelta('rgaFailures'), + mppEncodeAvgMs: counterAverage('mppEncodeMs', 'mppEncodedFrames'), + mppEncodeFailures: counterDelta('mppEncodeFailures'), + mppDecodeAvgMs: counterAverage('mppDecodeMs', 'mppDecodedFrames'), + mppDecodedFrames: counterDelta('mppDecodedFrames'), + mppDecodeFailures: counterDelta('mppDecodeFailures'), + mppDecodeFallbacks: counterDelta('mppDecodeFallbacks'), + mppCopyOutAvgMs: counterAverage('mppCopyOutMs', 'mppCopyOutFrames'), + mppCopyOutFrames: counterDelta('mppCopyOutFrames'), + mppCopyOutFailures: counterDelta('mppCopyOutFailures'), + mppEarlyDroppedFrames: counterDelta('mppEarlyDroppedFrames'), osdAvgMs: counterAverage('osdMs', 'osdFrames'), publishAvgMs: counterAverage('publishMs', 'publishedFrames'), firstFrameAvgMs: counterAverage('firstFrameMs', 'firstFrames'), diff --git a/tools/scenario-bench/src/task-runner.js b/tools/scenario-bench/src/task-runner.js index a89d4aa4d..471fbcf1d 100644 --- a/tools/scenario-bench/src/task-runner.js +++ b/tools/scenario-bench/src/task-runner.js @@ -3,6 +3,8 @@ // A workload can contain one or many tasks. The single-task case is represented // as one task bound to all active channels, so the run path stays unified. +import { sleepWithSignal, throwIfAborted } from './shutdown-signal.js'; + export class TaskRunner { /** * @param {import('./cosmo-client.js').CosmoClient} client @@ -15,6 +17,7 @@ export class TaskRunner { * @param {object} [ctx.taskConfig] legacy single-task config * @param {number} [ctx.rampBatchSize] * @param {number} [ctx.rampBatchDelaySec] + * @param {AbortSignal} [ctx.signal] * @param {import('./logger.js').Logger} [logger] */ constructor(client, ctx, logger) { @@ -24,6 +27,7 @@ export class TaskRunner { this.bindings = normalizeBindings(ctx.bindings, this.tasks); this.rampBatchSize = Math.max(1, Number(ctx.rampBatchSize ?? 1)); this.rampBatchDelaySec = Math.max(0, Number(ctx.rampBatchDelaySec ?? 15)); + this.signal = ctx.signal; this.log = logger; /** @type {string[]} videoChannelIds in bind order */ this.allChannelIds = []; @@ -71,8 +75,10 @@ export class TaskRunner { async _bind(videoChannelIds) { if (!videoChannelIds.length) return []; + throwIfAborted(this.signal); const failures = []; for (const task of this.tasks) { + throwIfAborted(this.signal); const targetChannelIds = this._channelsForTask(task.id, videoChannelIds); if (!targetChannelIds.length) continue; this.log?.info( @@ -113,7 +119,7 @@ export class TaskRunner { * @param {object} hooks * @param {(step:object, active:string[], added:string[], entries:object[]) => Promise<{stop:boolean, reason?:string}|void>} [hooks.onRampBatch] * @param {(step:object, active:string[], entries:object[]) => Promise<void>} [hooks.onStepStart] - * @param {() => Promise<void>} [hooks.onSample] + * @param {() => Promise<{stop:boolean, reason?:string}|void>} [hooks.onSample] * @param {(step:object, active:string[], entries:object[]) => Promise<{stop:boolean, reason?:string}|void>} [hooks.onStepEnd] * @param {number} sampleIntervalSec * @returns {Promise<{bottleneckStep?:number, bottleneckReason?:string}>} @@ -123,7 +129,9 @@ export class TaskRunner { let bottleneck = null; try { + throwIfAborted(this.signal); for (let i = 0; i < loadProfile.length; i++) { + throwIfAborted(this.signal); const step = { ...loadProfile[i], index: i }; const target = this.allChannelIds.slice(0, step.channels); const toAdd = target.slice(active.length); @@ -134,11 +142,16 @@ export class TaskRunner { ); for (let offset = 0; offset < toAdd.length; offset += this.rampBatchSize) { + throwIfAborted(this.signal); const batch = toAdd.slice(offset, offset + this.rampBatchSize); + // Treat attempted bindings as active for cleanup purposes. If the + // request succeeds remotely but the connection or signal interrupts + // the response, the final OFF remains safe and prevents task leaks. + active = [...new Set([...active, ...batch])]; const failedList = await this._bind(batch); + throwIfAborted(this.signal); if (failedList.length > 0) { const failedIds = failedList.map((f) => f.id ?? f.channelId ?? '?').join(', '); - active = [...new Set([...active, ...batch])]; this.log?.warn(`[step ${i + 1}] bottleneck detected - task bind failed on: ${failedIds}`); bottleneck = { bottleneckStep: i, @@ -148,11 +161,11 @@ export class TaskRunner { }; return bottleneck; } - active = this.allChannelIds.slice(0, active.length + batch.length); const entries = this.expectedTaskEntries(active); if (hooks?.onRampBatch) { const decision = await hooks.onRampBatch(step, active, batch, entries); + throwIfAborted(this.signal); if (decision?.stop) { this.log?.warn(`[step ${i + 1}] ramp fuse tripped: ${decision.reason ?? 'threshold breached'}`); bottleneck = { @@ -167,25 +180,48 @@ export class TaskRunner { const hasMoreBatches = offset + this.rampBatchSize < toAdd.length; if (hasMoreBatches && this.rampBatchDelaySec > 0) { - await sleep(this.rampBatchDelaySec * 1000); + await sleepWithSignal(this.rampBatchDelaySec * 1000, this.signal); } } active = target; - if (hooks?.onStepStart) await hooks.onStepStart(step, active, this.expectedTaskEntries(active)); + if (hooks?.onStepStart) { + await hooks.onStepStart(step, active, this.expectedTaskEntries(active)); + throwIfAborted(this.signal); + } const ticks = Math.max(1, Math.floor(step.holdSec / sampleIntervalSec)); for (let t = 0; t < ticks; t++) { - await sleep(sampleIntervalSec * 1000); + await sleepWithSignal(sampleIntervalSec * 1000, this.signal); try { - if (hooks?.onSample) await hooks.onSample(); + if (hooks?.onSample) { + const decision = await hooks.onSample(); + throwIfAborted(this.signal); + if (decision?.stop) { + this.log?.warn( + `[step ${i + 1}] hold fuse tripped: ${decision.reason ?? 'threshold breached'}`, + ); + bottleneck = { + bottleneckStep: i, + bottleneckChannels: active.length, + bottleneckPhase: 'hold', + bottleneckReason: decision.reason ?? 'hold fuse tripped', + }; + return bottleneck; + } + } } catch (err) { - this.log?.warn(`sample tick failed: ${err.message}`); + throwIfAborted(this.signal); + // Missing the remainder of a hold window can otherwise turn an + // outage into a false PASS based only on pre-failure samples. + // Abort and let the caller write a clearly marked partial report. + throw new Error(`sample tick failed: ${err.message}`, { cause: err }); } } if (hooks?.onStepEnd) { const decision = await hooks.onStepEnd(step, active, this.expectedTaskEntries(active)); + throwIfAborted(this.signal); if (decision?.stop) { this.log?.warn(`[step ${i + 1}] bottleneck detected - stopping staircase: ${decision.reason ?? 'threshold breached'}`); bottleneck = { @@ -202,6 +238,7 @@ export class TaskRunner { return bottleneck ?? {}; } finally { if (active.length) { + this.client.beginCleanup?.(); const entries = this.expectedTaskEntries(active); this.log?.info(`Switching ${entries.length} active task binding(s) OFF.`); try { @@ -293,7 +330,3 @@ function matchesChannelSelector(selector, channelId, oneBasedIndex) { return false; } - -function sleep(ms) { - return new Promise((r) => setTimeout(r, ms)); -} diff --git a/tools/scenario-bench/src/task-strategies.js b/tools/scenario-bench/src/task-strategies.js index 20d77cf71..748186b6d 100644 --- a/tools/scenario-bench/src/task-strategies.js +++ b/tools/scenario-bench/src/task-strategies.js @@ -1,5 +1,22 @@ const DEFAULT_TYPE = 'cv'; +// These actions emit business events after frame processing has completed. +// Their process rate follows the alarm/event rate rather than the video-frame +// rate, so they must not be used as a CV throughput floor. +const CV_TERMINAL_EVENT_ACTION_IDS = new Set([ + 'BA_00004', // event report / task alarm + 'BA_10004', // face-feature report / face alarm +]); + +const CV_TERMINAL_EVENT_NAMES = [ + 'eventreport', + 'event report', + 'taskalarm', + 'facealarm', + '事件上报', + '人脸特征上报', +]; + const TASK_TYPE_ALIASES = new Map([ ['cv', 'cv'], ['detect', 'cv'], @@ -155,6 +172,16 @@ export function isPrimaryThroughputAction(name, actionId, taskType) { || strategy.primaryActionIds.some((pattern) => pattern.test(normalizedActionId)); } +export function isThroughputBearingAction(name, actionId, taskType) { + if (normalizeTaskType(taskType) !== 'cv') return true; + + const normalizedActionId = String(actionId ?? '').trim().toUpperCase(); + if (CV_TERMINAL_EVENT_ACTION_IDS.has(normalizedActionId)) return false; + + const normalizedName = String(name ?? '').trim().toLowerCase(); + return !CV_TERMINAL_EVENT_NAMES.some((pattern) => normalizedName.includes(pattern)); +} + export function latencyMetricsForNodes(nodes, taskType) { const strategy = strategyForTaskType(taskType); const normalizedNodes = (Array.isArray(nodes) ? nodes : []) @@ -253,6 +280,7 @@ export function thresholdLabel(name, strategy = null) { avgDiscardRate: '平均丢弃率', maxDiscardRate: '丢弃率', maxPacketDiscardRate: '网络丢包率', + maxDiskUsedPercent: '设备磁盘使用率', maxPrimaryLatencyMs: s.primaryLatencyLabel, maxDetectorLatencyMs: '检测节点延时', maxAnalysisLatencyMs: '分析节点延时', diff --git a/tools/scenario-bench/test/cosmo-client.test.js b/tools/scenario-bench/test/cosmo-client.test.js index 35b6987f7..00443c61d 100644 --- a/tools/scenario-bench/test/cosmo-client.test.js +++ b/tools/scenario-bench/test/cosmo-client.test.js @@ -1,4 +1,5 @@ import assert from 'node:assert/strict'; +import crypto from 'node:crypto'; import test from 'node:test'; import { CosmoClient } from '../src/cosmo-client.js'; @@ -17,6 +18,57 @@ test('login rejects missing credentials when no token is supplied', async () => await assert.rejects(client.login(), /requires user\/password or an existing token/); }); +test('external shutdown aborts an in-flight device request without rewriting the reason', async () => { + const controller = new AbortController(); + const reason = Object.assign(new Error('received SIGTERM; shutting down'), { exitCode: 143 }); + let requestSignal = null; + const client = new CosmoClient({ + base: 'http://device', + token: 'token', + signal: controller.signal, + fetchImpl: async (_url, options) => { + requestSignal = options.signal; + return new Promise((_resolve, reject) => { + options.signal.addEventListener('abort', () => reject(options.signal.reason), { once: true }); + }); + }, + }); + + const request = client.queryHardwareResource(); + controller.abort(reason); + + await assert.rejects(request, (error) => error === reason && error.exitCode === 143); + assert.equal(requestSignal.aborted, true); +}); + +test('cleanup requests remain available after the run signal is aborted', async () => { + const controller = new AbortController(); + controller.abort(Object.assign(new Error('received SIGTERM; shutting down'), { exitCode: 143 })); + let requestSignal = null; + const client = new CosmoClient({ + base: 'http://device', + token: 'token', + signal: controller.signal, + fetchImpl: async (_url, options) => { + requestSignal = options.signal; + return { + ok: true, + async json() { + return { resCode: 1, resData: { failedList: [] } }; + }, + }; + }, + }); + + client.beginCleanup(); + const result = await client.taskBatchSwitch([ + { id: 'task-1', channelId: 'channel-1', algorithmId: '7463', enable: 0 }, + ]); + + assert.deepEqual(result, { failedList: [] }); + assert.equal(requestSignal.aborted, false); +}); + test('batch task switch uses the wire-level switch field', async () => { const client = new CosmoClient({ base: 'http://device', token: 'token' }); let request = null; @@ -39,3 +91,89 @@ test('batch task switch uses the wire-level switch field', async () => { }, }); }); + +function successResponse(uploadId = crypto.randomUUID()) { + return new Response(JSON.stringify({ + resCode: 1, + resData: { uploadId, complete: true }, + resMsg: [], + }), { status: 200, headers: { 'Content-Type': 'application/json' } }); +} + +test('multipart uploads respect the two-request client concurrency boundary', async () => { + let active = 0; + let maxActive = 0; + const releases = []; + const client = new CosmoClient({ + base: 'http://device', + token: 'token', + fetchImpl: async () => { + active += 1; + maxActive = Math.max(maxActive, active); + await new Promise((resolve) => releases.push(resolve)); + active -= 1; + return successResponse(); + }, + }); + const startUpload = (index) => client.uploadTempChunk(Buffer.from(`image-${index}`), `${index}.jpg`, { + clientRequestId: crypto.randomUUID(), + purpose: 'image', + chunkIndex: 0, + totalChunks: 1, + totalSize: 7, + chunkSize: 7, + }); + + const uploads = [0, 1, 2, 3].map(startUpload); + await new Promise((resolve) => setImmediate(resolve)); + assert.equal(active, 2); + releases.splice(0).forEach((release) => release()); + await new Promise((resolve) => setImmediate(resolve)); + assert.equal(active, 2); + releases.splice(0).forEach((release) => release()); + await Promise.all(uploads); + + assert.equal(maxActive, 2); + assert.equal(client.uploadTelemetry().maxActive, 2); + assert.equal(client.uploadTelemetry().queued, 0); +}); + +test('multipart uploads back off and retry a structured HTTP 503', async () => { + let calls = 0; + const delays = []; + const client = new CosmoClient({ + base: 'http://device', + token: 'token', + uploadBackoffMs: 25, + sleepImpl: async (delay) => delays.push(delay), + fetchImpl: async () => { + calls += 1; + if (calls === 1) { + return new Response(JSON.stringify({ + resCode: 0, + resMsg: [{ + msgCode: 'HTTP_SERVICE_BUSY', + retryable: true, + retryAfterSeconds: 0, + }], + }), { status: 503, headers: { 'Content-Type': 'application/json' } }); + } + return successResponse('recovered-upload'); + }, + }); + + const response = await client.uploadTempChunk(Buffer.from('image'), 'image.jpg', { + clientRequestId: 'stable-request-id', + purpose: 'image', + chunkIndex: 0, + totalChunks: 1, + totalSize: 5, + chunkSize: 5, + }); + + assert.equal(response.resData.uploadId, 'recovered-upload'); + assert.equal(calls, 2); + assert.deepEqual(delays, [25]); + assert.equal(client.uploadTelemetry().retries, 1); + assert.equal(client.uploadTelemetry().busyResponses, 1); +}); diff --git a/tools/scenario-bench/test/hardware-metrics.test.js b/tools/scenario-bench/test/hardware-metrics.test.js index 8a5d6a8c5..db8e3d378 100644 --- a/tools/scenario-bench/test/hardware-metrics.test.js +++ b/tools/scenario-bench/test/hardware-metrics.test.js @@ -18,6 +18,11 @@ test('hardware sampler preserves platform-neutral accelerator metrics', async () osdFrames: 12, }, }), + queryDeviceMemoryPool: async () => ({ + totalMalloc: 1024, + totalInUsing: 256, + status: [{ poolSize: 128, mallocCnt: 2, freeCnt: 6 }], + }), }); const sample = await sampler.sample([]); @@ -28,6 +33,121 @@ test('hardware sampler preserves platform-neutral accelerator metrics', async () assert.equal(sample.hardware.accelerator.activePreviewStreams, 1); assert.equal(sample.hardware.accelerator.activePreviewPublishers, 1); assert.equal(sample.hardware.accelerator.osdFrames, 12); + assert.equal(sample.hardware.memoryPool.totalAllocatedBytes, 1024); + assert.equal(sample.hardware.memoryPool.totalInUseBytes, 256); + assert.equal(sample.hardware.memoryPool.utilizationPercent, 25); + assert.deepEqual(sample.hardware.memoryPool.pools, [ + { blockSize: 128, usedBlocks: 2, freeBlocks: 6 }, + ]); +}); + +test('hardware sampler omits explicitly unavailable NPU utilization', async () => { + const sampler = new MetricsSampler({ + queryHardwareResource: async () => ({ + itemList: [ + { key: 'cpuUtilization', usedPercent: 12, available: 1 }, + { key: 'npuUtilization', usedPercent: 100, available: 0 }, + ], + }), + }); + + const sample = await sampler.sample([]); + + assert.equal(sample.hardware.cpuUtilization.usedPercent, 12); + assert.equal(sample.hardware.npuUtilization, undefined); +}); + +test('CV sampler reports per-channel pipeline FPS when a detector is shared', async () => { + const sampler = new MetricsSampler({ + taskRunningDetail: async () => ({ + status: [{ + taskId: 'ch1_alg', + channelId: 'ch1', + actionStatus: [ + { + actionId: 'AA_00001', + name: '9275710 AiDetector', + processCount: 2400, + processCountPeriod: 2400, + periodMs: 60_000, + }, + { + actionId: 'AA_00003', + name: 'ch1 tracker', + processCount: 300, + processCountPeriod: 300, + periodMs: 60_000, + }, + ], + nodeDurationInfos: [], + }], + }), + queryHardwareResource: async () => ({ itemList: [] }), + }); + + const sample = await sampler.sample([{ + taskKey: 'helmet', + taskType: 'cv', + channelId: 'ch1', + taskId: 'ch1_alg', + targetFps: 5, + }]); + + assert.equal(sample.channels[0].actionSummaries[0].fps, 40); + assert.equal(sample.channels[0].measuredFps, 5); + assert.equal(sample.channels[0].pipelineMinFps, 5); + assert.equal(sample.channels[0].fpsRatio, 1); +}); + +test('CV sampler excludes terminal event rate from frame throughput', async () => { + const sampler = new MetricsSampler({ + taskRunningDetail: async () => ({ + status: [{ + taskId: 'ch1_alg', + channelId: 'ch1', + actionStatus: [ + { + actionId: 'AA_00001', + name: '9275710 AiDetector', + processCount: 2400, + processCountPeriod: 2400, + periodMs: 60_000, + }, + { + actionId: 'AA_00003', + name: 'ch1 tracker', + processCount: 300, + processCountPeriod: 300, + periodMs: 60_000, + }, + { + actionId: 'BA_00004', + name: '事件上报', + processCount: 9, + processCountPeriod: 9, + periodMs: 60_000, + }, + ], + nodeDurationInfos: [], + }], + }), + queryHardwareResource: async () => ({ itemList: [] }), + }); + + const sample = await sampler.sample([{ + taskKey: 'helmet', + taskType: 'cv', + channelId: 'ch1', + taskId: 'ch1_alg', + targetFps: 5, + }]); + + assert.equal(sample.channels[0].actionSummaries[0].fps, 40); + assert.equal(sample.channels[0].actionSummaries[1].fps, 5); + assert.equal(sample.channels[0].actionSummaries[2].fps, 0.15); + assert.equal(sample.channels[0].measuredFps, 5); + assert.equal(sample.channels[0].pipelineMinFps, 5); + assert.equal(sample.channels[0].fpsRatio, 1); }); test('step summary derives platform-neutral preview timings and lifecycle deltas', () => { @@ -52,6 +172,11 @@ test('step summary derives platform-neutral preview timings and lifecycle deltas ], }], hardware: { + memoryPool: { + totalAllocatedBytes: index * 1024, + totalInUseBytes: index * 256, + utilizationPercent: index * 5, + }, accelerator: { osdFrames: index * 10, osdMs: index * 40, @@ -60,6 +185,126 @@ test('step summary derives platform-neutral preview timings and lifecycle deltas firstFrames: index, firstFrameMs: index * 100, firstFrameMaxMs: index * 90, + colorConvertFrames: index * 10, + colorConvertMs: index * 20, + blobConvertFrames: index * 10, + blobConvertMs: index * 30, + graphForwardFrames: index * 10, + graphForwardMs: index * 80, + graphForwardFailures: index, + resultParseFrames: index * 10, + resultParseMs: index * 10, + resultParseFailures: 0, + rknnPrepareCalls: index * 10, + rknnPrepareMs: index * 10, + rknnInputsSetCalls: index * 10, + rknnInputsSetMs: index * 20, + rknnRunCalls: index * 10, + rknnRunMs: index * 300, + rknnOutputsGetCalls: index * 10, + rknnOutputsGetMs: index * 40, + rknnOutputsReleaseCalls: index * 10, + rknnOutputsReleaseMs: index * 5, + rknnOutputTransformCalls: index * 10, + rknnOutputTransformMs: index * 50, + rknnForwards: index * 10, + rknnForwardMs: index * 420, + rknnForwardFailures: 0, + rknnMutexWaitCalls: index * 10, + rknnMutexWaitMs: index * 6, + rknnDetectorPrepareCalls: index * 4, + rknnDetectorPrepareMs: index * 4, + rknnDetectorInputsSetCalls: index * 4, + rknnDetectorInputsSetMs: index * 8, + rknnDetectorRunCalls: index * 4, + rknnDetectorRunMs: index * 120, + rknnDetectorOutputsGetCalls: index * 4, + rknnDetectorOutputsGetMs: index * 16, + rknnDetectorOutputsReleaseCalls: index * 4, + rknnDetectorOutputsReleaseMs: index * 2, + rknnDetectorOutputTransformCalls: index * 4, + rknnDetectorOutputTransformMs: index * 20, + rknnDetectorForwards: index * 4, + rknnDetectorForwardMs: index * 168, + rknnDetectorForwardFailures: 0, + rknnDetectorMutexWaitCalls: index * 4, + rknnDetectorMutexWaitMs: index * 2, + rknnPreprocessFastHits: index * 4, + rknnRgaFillCalls: index * 4, + rknnRgaFillMs: index * 2, + rknnRgaResizeColorCalls: index * 4, + rknnRgaResizeColorMs: index * 8, + rknnRgaFailures: 0, + rknnCpuResizeFallbackCalls: 0, + rknnCpuResizeFallbackMs: 0, + rknnCpuNormalizeFallbackCalls: 0, + rknnCpuNormalizeFallbackMs: 0, + rknnNativeInputMapCalls: index * 4, + rknnNativeInputMapMs: index, + rknnNativeInt8Inputs: index * 4, + rknnFloatInputs: index * 6, + rknnInputCompatibilityFallbacks: 0, + rknnBoundInputBindAttempts: index, + rknnBoundInputBindFailures: 0, + rknnBoundInputCopyCalls: index * 4, + rknnBoundInputCopyMs: index * 2, + rknnBoundInputCopyBytes: index * 4 * 1_228_800, + rknnBoundInputCopyFailures: 0, + rknnBoundInputSyncCalls: index * 4, + rknnBoundInputSyncMs: index, + rknnBoundInputSyncFailures: 0, + rknnBoundInputFrames: index * 4, + rknnRgaBoundInputBindAttempts: index, + rknnRgaBoundInputBindFailures: 0, + rknnRgaBoundInputImportCalls: index, + rknnRgaBoundInputImportMs: index * 0.25, + rknnRgaBoundInputImportFailures: 0, + rknnRgaBoundInputFrames: index * 4, + rknnRgaBoundUint8Frames: index * 4, + rknnRgaBoundNativeInt8Frames: 0, + rknnRgaBoundRequantizeCalls: 0, + rknnRgaBoundRequantizeMs: 0, + rknnRgaBoundRequantizeFailures: 0, + rknnRgaBoundInputNormalizeBypasses: index * 4, + rknnMppDmaBufImportCalls: index * 4, + rknnMppDmaBufImportMs: index, + rknnMppDmaBufImportFailures: 0, + rknnMppDmaBufFrames: index * 4, + rknnMppDmaBufFallbacks: 0, + rknnMppDmaBufSourceBytes: index * 4 * 3_133_440, + rknnNativeInt8Outputs: index * 4, + rknnFloatOutputs: index * 6, + rknnOutputCompatibilityFallbacks: index, + rknnNativeOutputBytes: index * 4 * 1_225_600, + rknnFloatOutputBytes: index * 6 * 4_902_400, + rknnYolov8DflCalls: index * 4, + rknnYolov8DflMs: index * 8, + rknnYolov8ClassCalls: index * 4, + rknnYolov8ClassMs: index * 4, + rknnYolov8DirectCandidateCalls: index * 4, + rknnYolov8DirectCandidateFailures: 0, + rknnYolov8DirectPointsScanned: index * 4 * 8_400, + rknnYolov8DirectPointsDecoded: index * 4 * 17, + rknnYolov8ScoreSumPointsRejected: index * 4 * 8_000, + rknnYolov8LogicalFloatBytesAvoided: index * 4 * 2_822_400, + yolov8PostprocessCalls: index * 4, + yolov8PostprocessMs: index * 12, + yolov8NmsCalls: index * 4, + yolov8NmsMs: index * 4, + rgaFrames: index * 10, + rgaMs: index * 15, + rgaFailures: 0, + mppEncodedFrames: index * 10, + mppEncodeMs: index * 25, + mppEncodeFailures: 0, + mppDecodedFrames: index * 10, + mppDecodeMs: index * 18, + mppDecodeFailures: 0, + mppDecodeFallbacks: 0, + mppCopyOutFrames: index * 6, + mppCopyOutMs: index * 24, + mppCopyOutFailures: 0, + mppEarlyDroppedFrames: index * 4, activePreviewStreams: 1, activePreviewPublishers: 1, activeRawPreviewStreams: 0, @@ -75,10 +320,91 @@ test('step summary derives platform-neutral preview timings and lifecycle deltas const summary = summarizeStep({ index: 0, channels: 1, holdSec: 12 }, samples); assert.equal(summary.mediaStages.preprocessAvgMs, 2); assert.equal(summary.mediaStages.postprocessAvgMs, 3); + assert.equal(summary.mediaStages.colorConvertAvgMs, 2); + assert.equal(summary.mediaStages.blobConvertAvgMs, 3); + assert.equal(summary.mediaStages.graphForwardAvgMs, 8); + assert.equal(summary.mediaStages.resultParseAvgMs, 1); + assert.equal(summary.mediaStages.graphForwardFailures, 1); + assert.equal(summary.mediaStages.resultParseFailures, 0); + assert.equal(summary.mediaStages.rknnPrepareAvgMs, 1); + assert.equal(summary.mediaStages.rknnInputsSetAvgMs, 2); + assert.equal(summary.mediaStages.rknnRunAvgMs, 30); + assert.equal(summary.mediaStages.rknnOutputsGetAvgMs, 4); + assert.equal(summary.mediaStages.rknnOutputsReleaseAvgMs, 0.5); + assert.equal(summary.mediaStages.rknnOutputTransformAvgMs, 5); + assert.equal(summary.mediaStages.rknnForwardAvgMs, 42); + assert.equal(summary.mediaStages.rknnForwardFailures, 0); + assert.equal(summary.mediaStages.rknnMutexWaitAvgMs, 0.6); + assert.equal(summary.mediaStages.rknnDetectorForwardAvgMs, 42); + assert.equal(summary.mediaStages.rknnDetectorOutputsReleaseAvgMs, 0.5); + assert.equal(summary.mediaStages.rknnDetectorMutexWaitAvgMs, 0.5); + assert.equal(summary.mediaStages.rknnPreprocessFastHits, 4); + assert.equal(summary.mediaStages.rknnRgaFillAvgMs, 0.5); + assert.equal(summary.mediaStages.rknnRgaResizeColorAvgMs, 2); + assert.equal(summary.mediaStages.rknnNativeInputMapAvgMs, 0.25); + assert.equal(summary.mediaStages.rknnNativeInt8Inputs, 4); + assert.equal(summary.mediaStages.rknnFloatInputs, 6); + assert.equal(summary.mediaStages.rknnInputCompatibilityFallbacks, 0); + assert.equal(summary.mediaStages.rknnBoundInputBindAttempts, 1); + assert.equal(summary.mediaStages.rknnBoundInputBindFailures, 0); + assert.equal(summary.mediaStages.rknnBoundInputCopyAvgMs, 0.5); + assert.equal(summary.mediaStages.rknnBoundInputCopyAvgBytes, 1_228_800); + assert.equal(summary.mediaStages.rknnBoundInputCopyFailures, 0); + assert.equal(summary.mediaStages.rknnBoundInputSyncAvgMs, 0.25); + assert.equal(summary.mediaStages.rknnBoundInputSyncFailures, 0); + assert.equal(summary.mediaStages.rknnBoundInputFrames, 4); + assert.equal(summary.mediaStages.rknnRgaBoundInputBindAttempts, 1); + assert.equal(summary.mediaStages.rknnRgaBoundInputBindFailures, 0); + assert.equal(summary.mediaStages.rknnRgaBoundInputImportCalls, 1); + assert.equal(summary.mediaStages.rknnRgaBoundInputImportAvgMs, 0.25); + assert.equal(summary.mediaStages.rknnRgaBoundInputImportFailures, 0); + assert.equal(summary.mediaStages.rknnRgaBoundInputFrames, 4); + assert.equal(summary.mediaStages.rknnRgaBoundUint8Frames, 4); + assert.equal(summary.mediaStages.rknnRgaBoundNativeInt8Frames, 0); + assert.equal(summary.mediaStages.rknnRgaBoundRequantizeCalls, 0); + assert.equal(summary.mediaStages.rknnRgaBoundRequantizeAvgMs, null); + assert.equal(summary.mediaStages.rknnRgaBoundRequantizeFailures, 0); + assert.equal(summary.mediaStages.rknnRgaBoundInputNormalizeBypasses, 4); + assert.equal(summary.mediaStages.rknnMppDmaBufImportCalls, 4); + assert.equal(summary.mediaStages.rknnMppDmaBufImportAvgMs, 0.25); + assert.equal(summary.mediaStages.rknnMppDmaBufImportFailures, 0); + assert.equal(summary.mediaStages.rknnMppDmaBufFrames, 4); + assert.equal(summary.mediaStages.rknnMppDmaBufFallbacks, 0); + assert.equal(summary.mediaStages.rknnMppDmaBufSourceAvgBytes, 3_133_440); + assert.equal(summary.mediaStages.rknnNativeInt8Outputs, 4); + assert.equal(summary.mediaStages.rknnFloatOutputs, 6); + assert.equal(summary.mediaStages.rknnOutputCompatibilityFallbacks, 1); + assert.equal(summary.mediaStages.rknnNativeOutputAvgBytes, 1_225_600); + assert.equal(summary.mediaStages.rknnFloatOutputAvgBytes, 4_902_400); + assert.equal(summary.mediaStages.rknnYolov8DflAvgMs, 2); + assert.equal(summary.mediaStages.rknnYolov8ClassAvgMs, 1); + assert.equal(summary.mediaStages.rknnYolov8DirectCandidateCalls, 4); + assert.equal(summary.mediaStages.rknnYolov8DirectCandidateFailures, 0); + assert.equal(summary.mediaStages.rknnYolov8DirectAvgPointsScanned, 8_400); + assert.equal(summary.mediaStages.rknnYolov8DirectAvgPointsDecoded, 17); + assert.equal(summary.mediaStages.rknnYolov8ScoreSumAvgPointsRejected, 8_000); + assert.equal(summary.mediaStages.rknnYolov8LogicalFloatBytesAvoided, 11_289_600); + assert.equal(summary.mediaStages.yolov8PostprocessAvgMs, 3); + assert.equal(summary.mediaStages.yolov8NmsAvgMs, 1); + assert.equal(summary.mediaStages.rgaAvgMs, 1.5); + assert.equal(summary.mediaStages.rgaFailures, 0); + assert.equal(summary.mediaStages.mppEncodeAvgMs, 2.5); + assert.equal(summary.mediaStages.mppEncodeFailures, 0); + assert.equal(summary.mediaStages.mppDecodeAvgMs, 1.8); + assert.equal(summary.mediaStages.mppDecodedFrames, 10); + assert.equal(summary.mediaStages.mppDecodeFailures, 0); + assert.equal(summary.mediaStages.mppDecodeFallbacks, 0); + assert.equal(summary.mediaStages.mppCopyOutAvgMs, 4); + assert.equal(summary.mediaStages.mppCopyOutFrames, 6); + assert.equal(summary.mediaStages.mppCopyOutFailures, 0); + assert.equal(summary.mediaStages.mppEarlyDroppedFrames, 4); assert.equal(summary.mediaStages.osdAvgMs, 4); assert.equal(summary.mediaStages.publishAvgMs, 5); assert.equal(summary.mediaStages.firstFrameAvgMs, 100); assert.equal(summary.mediaStages.firstFrameMaxMs, 270); + assert.equal(summary.maxPoolAllocatedBytes, 3072); + assert.equal(summary.maxPoolInUseBytes, 768); + assert.equal(summary.maxPoolUtilizationPercent, 15); assert.equal(summary.mediaStages.activePreviewStreamsPeak, 1); assert.equal(summary.mediaStages.activePreviewPublishersPeak, 1); assert.equal(summary.mediaStages.activeAlgorithmPreviewStreamsPeak, 1); diff --git a/tools/scenario-bench/test/longrun-auditor.test.js b/tools/scenario-bench/test/longrun-auditor.test.js new file mode 100644 index 000000000..f3fe6769f --- /dev/null +++ b/tools/scenario-bench/test/longrun-auditor.test.js @@ -0,0 +1,246 @@ +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import test from 'node:test'; + +import { + auditLongRun, + auditLongRunFile, + writeLongRunAudit, +} from '../src/longrun-auditor.js'; + +const START = Date.parse('2026-08-04T00:00:00.000Z'); + +function accelerator(index) { + const frames = 1000 + index * 100; + return { + blobConvertFrames: frames, + colorConvertFrames: frames, + graphForwardFrames: frames, + graphForwardFailures: 0, + mppCopyOutFailures: 0, + mppCopyOutFrames: frames * 2, + mppDecodeFailures: 0, + mppDecodeFallbacks: 0, + mppDecodedFrames: frames * 4, + mppEarlyDroppedFrames: frames * 2, + mppEncodeFailures: 0, + mppEncodedFrames: frames * 3, + osdFrames: frames * 3, + previewStreamFailures: 0, + publishedFrames: frames * 3, + resultParseFailures: 0, + resultParseFrames: frames, + rgaFailures: 0, + rgaFrames: frames, + rknnForwardFailures: 0, + rknnRgaFailures: 0, + rknnRgaBoundInputFrames: frames * 3, + rknnRgaBoundUint8Frames: frames * 3, + rknnRgaBoundInputImportFailures: 0, + rknnRgaBoundRequantizeFailures: 0, + rknnForwards: frames * 3, + videoDecoderBackend: 'rockchip-copy-out', + videoEncoderBackend: 'rockchip-copy-first', + }; +} + +function sample(index, overrides = {}) { + return { + ts: START + index * 60_000, + iso: new Date(START + index * 60_000).toISOString(), + phase: 'hold', + stepIndex: 0, + activeChannels: 4, + targetChannels: 4, + channels: Array.from({ length: 4 }, (_, channelIndex) => ({ + taskKey: 'helmet', + channelId: `ch${channelIndex + 1}`, + targetFps: 5, + measuredFps: 5.2, + discardRate: 0, + missing: false, + telemetryMissing: false, + })), + hardware: { + accelerator: accelerator(index), + cpuUtilization: { usedPercent: 50 }, + generalMemoryUtilization: { usedPercent: 25 }, + eMMCUtilization: { usedPercent: 70 }, + memoryPool: { + totalAllocatedBytes: 400 * 1024 * 1024 + index * 1024, + totalInUseBytes: 30 * 1024 * 1024, + utilizationPercent: 7.5, + }, + }, + preview: { + mode: 'algorithm', + requestedStreams: 4, + srsStreams: 4, + srsPublishingStreams: 4, + srsClients: 4, + mediaClients: 0, + errors: [], + }, + ...overrides, + }; +} + +function runResult(count = 5) { + return { + scenarioName: 'RK3576 4ch 5fps 12h', + status: 'running', + startedAt: new Date(START).toISOString(), + endedAt: new Date(START + count * 60_000).toISOString(), + previewProfile: { mode: 'algorithm' }, + thresholds: { pass: { avgDiscardRate: 0.05, maxDiskUsedPercent: 90 } }, + steps: [{ index: 0, channels: 4, holdSec: 259200 }], + samples: Array.from({ length: count }, (_, index) => sample(index + 1)), + }; +} + +const options = { + gateHours: 4 / 60, + nowMs: START + 5 * 60_000 + 10_000, + maxGapSec: 120, + maxFreshnessSec: 120, + minFpsRatio: 0.9, + expectedPreviewStreams: 4, + expectedDecoderBackend: 'rockchip-copy-out', + expectedEncoderBackend: 'rockchip-copy-first', + minRgaBoundUint8Frames: 1, +}; + +test('long-run audit passes only after duration and all native gates pass', () => { + const result = auditLongRun(runResult(), options); + assert.equal(result.verdict, 'PASS'); + assert.equal(result.gate.reached, true); + assert.deepEqual(result.failures, []); + assert.equal(result.nativeMedia.copyAccountingError, 0); + assert.equal(result.workload.bindings.length, 4); +}); + +test('long-run audit reports IN_PROGRESS before the wall-clock gate', () => { + const result = auditLongRun(runResult(), { ...options, gateHours: 1 }); + assert.equal(result.verdict, 'IN_PROGRESS'); + assert.deepEqual(result.pending, ['gate.duration']); + assert.deepEqual(result.failures, []); +}); + +test('completed long-run uses completedAt with a bounded final sampling delay', () => { + const input = runResult(); + input.status = 'completed'; + input.endedAt = new Date(START + 5.5 * 60_000).toISOString(); + + const result = auditLongRun(input, { ...options, gateHours: 5.5 / 60 }); + assert.equal(result.verdict, 'PASS'); + assert.equal(result.gate.finalSampleDelaySec, 30); + assert.equal(result.checks.find((item) => item.id === 'samples.finalDelay')?.status, 'PASS'); +}); + +test('long-run audit fails sampling gaps, FPS regression, and counter reset', () => { + const input = runResult(); + input.samples[2].ts += 180_000; + input.samples[2].iso = new Date(input.samples[2].ts).toISOString(); + input.samples[3].channels[0].measuredFps = 4; + input.samples[3].hardware.accelerator.rknnForwards = 1; + + const result = auditLongRun(input, options); + assert.equal(result.verdict, 'FAIL'); + assert.ok(result.failures.includes('samples.timestamps')); + assert.ok(result.failures.includes('samples.maxGap')); + assert.ok(result.failures.includes('workload.fps')); + assert.ok(result.failures.includes('native.counterContinuity')); +}); + +test('long-run audit fails native failure increments and unhealthy preview', () => { + const input = runResult(); + input.samples.at(-1).hardware.accelerator.mppEncodeFailures = 1; + input.samples.at(-1).preview.srsPublishingStreams = 3; + + const result = auditLongRun(input, options); + assert.equal(result.verdict, 'FAIL'); + assert.ok(result.failures.includes('native.failures')); + assert.ok(result.failures.includes('preview.health')); +}); + +test('memory-pool warm-up keeps cold growth visible and gates the steady-state window', () => { + const input = runResult(7); + const base = 400 * 1024 * 1024; + for (const [index, item] of input.samples.entries()) { + item.hardware.memoryPool.totalAllocatedBytes = base + (index < 2 ? 0 : 32 * 1024 * 1024); + } + const auditOptions = { + ...options, + gateHours: 4 / 60, + nowMs: START + 7 * 60_000 + 10_000, + maxPoolGrowthBytes: 0, + }; + + const cold = auditLongRun(input, auditOptions); + assert.ok(cold.failures.includes('resource.poolGrowth')); + assert.equal(cold.memoryPool.coldStartAllocatedNetGrowthBytes, 32 * 1024 * 1024); + + const steady = auditLongRun(input, { ...auditOptions, poolGrowthWarmupSec: 120 }); + assert.equal(steady.verdict, 'PASS'); + assert.equal(steady.memoryPool.growthWarmupSec, 120); + assert.equal(steady.memoryPool.growthSamples, 5); + assert.equal(steady.memoryPool.allocatedNetGrowthBytes, 0); + assert.equal(steady.memoryPool.allocatedPeakGrowthBytes, 0); + assert.equal(steady.memoryPool.coldStartAllocatedNetGrowthBytes, 32 * 1024 * 1024); +}); + +test('long-run audit fails RGA bound-input import and requantize errors', () => { + const input = runResult(); + input.samples.at(-1).hardware.accelerator.rknnRgaBoundInputImportFailures = 1; + input.samples.at(-1).hardware.accelerator.rknnRgaBoundRequantizeFailures = 1; + + const result = auditLongRun(input, options); + assert.equal(result.verdict, 'FAIL'); + assert.ok(result.failures.includes('native.failures')); + const nativeFailures = result.checks.find((item) => item.id === 'native.failures'); + assert.equal(nativeFailures.actual.rknnRgaBoundInputImportFailures, 1); + assert.equal(nativeFailures.actual.rknnRgaBoundRequantizeFailures, 1); +}); + +test('long-run audit fails when the fused UINT8 bound-input path is inactive', () => { + const input = runResult(); + for (const item of input.samples) item.hardware.accelerator.rknnRgaBoundUint8Frames = 0; + + const result = auditLongRun(input, options); + assert.equal(result.verdict, 'FAIL'); + assert.ok(result.failures.includes('native.rgaBoundUint8')); +}); + +test('file audit binds source and allowlisted candidate identity by SHA-256', () => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'scenario-longrun-audit-')); + try { + const input = path.join(dir, 'metrics.partial.json'); + const identity = path.join(dir, 'identity.txt'); + const output = path.join(dir, 'checkpoint.json'); + fs.writeFileSync(input, JSON.stringify(runResult()), 'utf8'); + fs.writeFileSync(identity, [ + 'engineSourceCommit=88e556a1', + 'sourceCommit=99f667b2', + 'modelSha256=def456', + 'rknnRuntime=2.3.2-429f97ae6b', + 'engineSha256=abc123', + 'password=must-not-be-copied', + ].join('\n'), 'utf8'); + + const result = auditLongRunFile(input, { ...options, identityPath: identity }); + const written = writeLongRunAudit(output, result); + const saved = JSON.parse(fs.readFileSync(written, 'utf8')); + + assert.match(saved.source.sha256, /^[a-f0-9]{64}$/); + assert.match(saved.identity.sha256, /^[a-f0-9]{64}$/); + assert.equal(saved.identity.properties.engineSourceCommit, '88e556a1'); + assert.equal(saved.identity.properties.sourceCommit, '99f667b2'); + assert.equal(saved.identity.properties.modelSha256, 'def456'); + assert.equal(saved.identity.properties.rknnRuntime, '2.3.2-429f97ae6b'); + assert.equal(saved.identity.properties.password, undefined); + } finally { + fs.rmSync(dir, { recursive: true, force: true }); + } +}); diff --git a/tools/scenario-bench/test/preview-load.test.js b/tools/scenario-bench/test/preview-load.test.js index fb5024acc..524e4f698 100644 --- a/tools/scenario-bench/test/preview-load.test.js +++ b/tools/scenario-bench/test/preview-load.test.js @@ -70,3 +70,24 @@ test('preview load does not retry non-warmup start failures', async () => { await assert.rejects(load.sync(entries.slice(0, 1)), /invalid algorithm/); assert.equal(requests, 1); }); + +test('preview load preflight rejects a missing media executable before device work', async () => { + const load = new PreviewLoad({}, { + mode: 'algorithm', + clientsPerStream: 1, + mediaBase: 'http://127.0.0.1:18088', + ffmpeg: `scenario-bench-missing-ffmpeg-${process.pid}`, + }); + + await assert.rejects(load.preflight(), /ffmpeg preflight failed \(executable not found\)/); +}); + +test('preview load preflight is skipped when no media client is requested', async () => { + const load = new PreviewLoad({}, { + mode: 'algorithm', + clientsPerStream: 0, + ffmpeg: `scenario-bench-missing-ffmpeg-${process.pid}`, + }); + + await assert.doesNotReject(load.preflight()); +}); diff --git a/tools/scenario-bench/test/preview-validator.test.js b/tools/scenario-bench/test/preview-validator.test.js index d2ad6d344..7106186e1 100644 --- a/tools/scenario-bench/test/preview-validator.test.js +++ b/tools/scenario-bench/test/preview-validator.test.js @@ -12,6 +12,22 @@ test('preview validator counts saturated overlay-like pixels', () => { assert.equal(_previewValidatorTest.countOverlayLikePixels(rgb), 2); }); +test('preview validator disables the heuristic pixel delta gate at zero', () => { + assert.deepEqual(_previewValidatorTest.evaluateOsdPixelCheck(201, 192, 0), { + rawMaxOverlayPixels: 201, + algorithmMaxOverlayPixels: 192, + delta: -9, + minimumDelta: 0, + enabled: false, + pass: true, + }); +}); + +test('preview validator enforces an explicitly positive pixel delta gate', () => { + assert.equal(_previewValidatorTest.evaluateOsdPixelCheck(100, 105, 6).pass, false); + assert.equal(_previewValidatorTest.evaluateOsdPixelCheck(100, 106, 6).pass, true); +}); + test('preview validator analyzes bounded raw RGB frames and progress timestamps', () => { const first = Buffer.from([255, 0, 0, 10, 10, 10]); const second = Buffer.from([0, 255, 0, 0, 0, 255]); diff --git a/tools/scenario-bench/test/report-writer.test.js b/tools/scenario-bench/test/report-writer.test.js index ac309d70c..ad3e134cf 100644 --- a/tools/scenario-bench/test/report-writer.test.js +++ b/tools/scenario-bench/test/report-writer.test.js @@ -191,11 +191,14 @@ test('HTML rendering splits ramp-only bottleneck samples by observed channels', const summary = writer._buildSummary(runResult, stepSummaries); assert.equal(summary.bottleneck.channels, 7); assert.equal(summary.bottleneck.targetChannels, 16); + assert.equal(summary.maxStableChannels, null); + assert.deepEqual(summary.rampProbeChannels, [1, 2, 3, 4, 5, 6, 7]); const html = writer._renderHtml(runResult, stepSummaries, summary); const routeTable = html.match(/<h2>路数结果<\/h2>[\s\S]*?<h2>媒体与预览分阶段指标<\/h2>/)[0]; assert.equal((routeTable.match(/<tr>/g) ?? []).length - 1, 7); assert.match(routeTable, /<td>7<\/td>[\s\S]*<td class="warn">STOPPED<\/td>/); + assert.match(routeTable, /<td class="na">PROBE<\/td>/); assert.doesNotMatch(routeTable, /<td>16<\/td>/); }); @@ -223,7 +226,9 @@ test('HTML rendering expands single target step from observed channel samples', const summary = writer._buildSummary(runResult, stepSummaries); assert.equal(summary.baselineFps, 5); - assert.equal(summary.maxStableChannels, 16); + assert.equal(summary.maxStableChannels, null); + assert.equal(summary.maxVerifiedPassedChannels, 16); + assert.deepEqual(summary.rampProbeChannels, Array.from({ length: 15 }, (_, i) => i + 1)); const html = writer._renderHtml(runResult, stepSummaries, summary); assert.match(html, /<td>16<\/td>/); diff --git a/tools/scenario-bench/test/scenario-package.test.js b/tools/scenario-bench/test/scenario-package.test.js index 2038fe71f..ba4fd86e7 100644 --- a/tools/scenario-bench/test/scenario-package.test.js +++ b/tools/scenario-bench/test/scenario-package.test.js @@ -156,6 +156,147 @@ loadProfile: assert.deepEqual(pkg.loadProfile.map((step) => step.holdSec), [30, 30]); }); +test('explicit target FPS overrides every detector node in the saved layout', (t) => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'scenario-bench-cv-fps-override-')); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + fs.writeFileSync(path.join(dir, 'scenario.yml'), `name: cv-fps-override +sampleIntervalSec: 5 +channels: + mode: local + repeatCount: 0 + sources: + - name: cv + file: /device/cv.mp4 +tasks: + - id: cv + displayName: CV + type: cv + algorithmId: "7463" + scheduleId: schedule + template: algorithm-template.json + targetFps: 5 +loadProfile: + - channels: 1 + holdSec: 30 +`, 'utf8'); + fs.writeFileSync(path.join(dir, 'algorithm-template.json'), JSON.stringify({ + algorithmId: '7463', + algorithmCode: '7463', + algorithmName: 'CV', + taskConfig: { params: [], areas: [] }, + algorithmProcessdata: JSON.stringify([ + { + actionId: 'AA_00001', + configObject: { params: [{ key: 'fps', value: '7' }] }, + }, + { + actionId: 'AA_00001', + configObject: JSON.stringify({ params: [{ key: 'fps', value: '7' }] }), + }, + ]), + }), 'utf8'); + + const pkg = new ScenarioPackage(dir).load(); + const nodes = JSON.parse(pkg.layoutSavePayload.algorithmProcessdata); + const fpsValues = nodes.map((node) => { + const config = typeof node.configObject === 'string' + ? JSON.parse(node.configObject) + : node.configObject; + return config.params.find((param) => param.key === 'fps')?.value; + }); + + assert.equal(pkg.targetFps, 5); + assert.deepEqual(fpsValues, ['5', '5']); +}); + +test('merges explicit per-task config params for soak-safe workloads', (t) => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'scenario-bench-task-config-')); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + fs.writeFileSync(path.join(dir, 'scenario.yml'), `name: cv-task-config +sampleIntervalSec: 5 +channels: + mode: local + repeatCount: 0 + sources: + - name: cv + file: /device/cv.mp4 +tasks: + - id: cv + displayName: CV + type: cv + algorithmId: "7463" + scheduleId: schedule + template: algorithm-template.json + taskConfig: + params: + - key: param.sensitivity + value: 1 + - key: param.detectionDuration + value: 3600 + areas: + - name: validation-area +loadProfile: + - channels: 1 + holdSec: 30 +`, 'utf8'); + fs.writeFileSync(path.join(dir, 'algorithm-template.json'), JSON.stringify({ + algorithmId: '7463', + algorithmCode: '7463', + algorithmName: 'CV', + taskConfig: { + params: [{ key: 'param.sensitivity', value: '5' }], + areas: [{ name: 'template-area' }], + }, + algorithmProcessdata: '[]', + }), 'utf8'); + + const pkg = new ScenarioPackage(dir).load(); + assert.deepEqual(pkg.taskConfig.params, [ + { key: 'param.sensitivity', value: '1' }, + { key: 'param.detectionDuration', value: '3600' }, + { key: 'param.videoRepeatCount', value: '0' }, + ]); + assert.deepEqual(pkg.taskConfig.areas, [{ name: 'validation-area' }]); +}); + +test('rejects duplicate per-task config override keys', (t) => { + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'scenario-bench-task-config-duplicate-')); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + fs.writeFileSync(path.join(dir, 'scenario.yml'), `name: cv-task-config-duplicate +channels: + mode: local + sources: + - name: cv + file: /device/cv.mp4 +tasks: + - id: cv + algorithmId: "7463" + scheduleId: schedule + template: algorithm-template.json + taskConfig: + params: + - key: param.sensitivity + value: 1 + - key: param.sensitivity + value: 2 +loadProfile: + - channels: 1 + holdSec: 30 +`, 'utf8'); + writeTemplate(path.join(dir, 'algorithm-template.json'), { + actionId: 'AA_00001', + configObject: { params: [{ key: 'fps', value: '5' }] }, + }); + + assert.throws( + () => new ScenarioPackage(dir).load(), + /taskConfig\.params has duplicate key "param\.sensitivity"/, + ); +}); + function writeTemplate(file, processNode) { fs.writeFileSync(file, JSON.stringify({ algorithmId: '55009', diff --git a/tools/scenario-bench/test/shutdown-signal.test.js b/tools/scenario-bench/test/shutdown-signal.test.js new file mode 100644 index 000000000..9fb908bb7 --- /dev/null +++ b/tools/scenario-bench/test/shutdown-signal.test.js @@ -0,0 +1,40 @@ +import assert from 'node:assert/strict'; +import { EventEmitter } from 'node:events'; +import test from 'node:test'; + +import { + ShutdownSignalError, + installShutdownSignalHandlers, + sleepWithSignal, +} from '../src/shutdown-signal.js'; + +test('SIGTERM aborts once with the conventional exit code and handlers are disposable', () => { + const processRef = new EventEmitter(); + const controller = new AbortController(); + const received = []; + const dispose = installShutdownSignalHandlers(controller, { + processRef, + onSignal: (error) => received.push(error), + }); + + processRef.emit('SIGTERM'); + processRef.emit('SIGINT'); + + assert.equal(received.length, 1); + assert.equal(received[0].signalName, 'SIGTERM'); + assert.equal(received[0].exitCode, 143); + assert.equal(controller.signal.reason, received[0]); + + dispose(); + assert.equal(processRef.listenerCount('SIGTERM'), 0); + assert.equal(processRef.listenerCount('SIGINT'), 0); +}); + +test('signal-aware sleep rejects immediately when the run is aborted', async () => { + const controller = new AbortController(); + const sleeping = sleepWithSignal(60_000, controller.signal); + + controller.abort(new ShutdownSignalError('SIGINT')); + + await assert.rejects(sleeping, (error) => error.signalName === 'SIGINT' && error.exitCode === 130); +}); diff --git a/tools/scenario-bench/test/step-evaluator.test.js b/tools/scenario-bench/test/step-evaluator.test.js index 14eb45cce..0981b91cf 100644 --- a/tools/scenario-bench/test/step-evaluator.test.js +++ b/tools/scenario-bench/test/step-evaluator.test.js @@ -11,13 +11,39 @@ test('step summary records accelerator and accelerator-memory peaks', () => { hardware: { npuUtilization: { usedPercent: 20 + index }, specialMemoryUtilization: { usedPercent: 30 + index }, + eMMCUtilization: { usedPercent: 40 + index }, }, })); - const summary = summarizeStep({ index: 0, channels: 0, holdSec: 24 }, samples); + const summary = summarizeStep( + { index: 0, channels: 0, holdSec: 24 }, + samples, + { pass: { maxDiskUsedPercent: 50 } }, + ); assert.equal(summary.maxNpu, 27); assert.equal(summary.maxAcceleratorMem, 37); + assert.equal(summary.maxDiskUsedPercent, 47); + assert.equal(summary.perThreshold.find((item) => item.name === 'maxDiskUsedPercent')?.result, 'PASS'); +}); + +test('step summary fails when device disk usage exceeds the configured gate', () => { + const samples = Array.from({ length: 4 }, (_, index) => ({ + stepIndex: 0, + ts: index * 3000, + channels: [], + hardware: { eMMCUtilization: { usedPercent: 88 + index } }, + })); + + const summary = summarizeStep( + { index: 0, channels: 0, holdSec: 12 }, + samples, + { pass: { maxDiskUsedPercent: 90 } }, + ); + + assert.equal(summary.maxDiskUsedPercent, 91); + assert.equal(summary.pass, false); + assert.match(summary.reasons.join('; '), /磁盘使用率 91%/); }); test('runtime decision stops CV tasks when steady throughput falls below half baseline', () => { diff --git a/tools/scenario-bench/test/task-runner.test.js b/tools/scenario-bench/test/task-runner.test.js new file mode 100644 index 000000000..3dff38c72 --- /dev/null +++ b/tools/scenario-bench/test/task-runner.test.js @@ -0,0 +1,96 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; + +import { ShutdownSignalError } from '../src/shutdown-signal.js'; +import { TaskRunner } from '../src/task-runner.js'; + +test('task runner aborts when a hold sample cannot be captured', async () => { + const client = { + async taskApplyParamsBatch() { + return { failedList: [] }; + }, + async taskBatchSwitch() { + return { failedList: [] }; + }, + }; + const runner = new TaskRunner(client, { + algorithmId: '7463', + scheduleId: 'always', + rampBatchDelaySec: 0, + }); + runner.setChannels(['channel-1']); + + await assert.rejects( + runner.runStaircase( + [{ channels: 1, holdSec: 0.001 }], + { onSample: async () => { throw new Error('preview keepalive failed'); } }, + 0.001, + ), + /sample tick failed: preview keepalive failed/, + ); +}); + +test('task runner stops and disables tasks when a hold fuse trips', async () => { + const switches = []; + const client = { + async taskApplyParamsBatch() { + return { failedList: [] }; + }, + async taskBatchSwitch(tasks) { + switches.push(tasks); + return { failedList: [] }; + }, + }; + const runner = new TaskRunner(client, { + algorithmId: '7463', + scheduleId: 'always', + rampBatchDelaySec: 0, + }); + runner.setChannels(['channel-1']); + + const result = await runner.runStaircase( + [{ channels: 1, holdSec: 0.002 }], + { onSample: async () => ({ stop: true, reason: 'disk 90% >= 90%' }) }, + 0.001, + ); + + assert.equal(result.bottleneckPhase, 'hold'); + assert.equal(result.bottleneckReason, 'disk 90% >= 90%'); + assert.equal(switches.length, 1); + assert.equal(switches[0][0].enable, 0); +}); + +test('task runner interrupts a hold and disables active tasks on SIGTERM', async () => { + const controller = new AbortController(); + const switches = []; + let cleanupStarted = false; + const client = { + async taskApplyParamsBatch() { + return { failedList: [] }; + }, + async taskBatchSwitch(tasks) { + assert.equal(cleanupStarted, true); + switches.push(tasks); + return { failedList: [] }; + }, + beginCleanup() { + cleanupStarted = true; + }, + }; + const runner = new TaskRunner(client, { + algorithmId: '7463', + scheduleId: 'always', + rampBatchDelaySec: 0, + signal: controller.signal, + }); + runner.setChannels(['channel-1']); + + const run = runner.runStaircase([{ channels: 1, holdSec: 60 }], {}, 60); + await new Promise((resolve) => setImmediate(resolve)); + controller.abort(new ShutdownSignalError('SIGTERM')); + + await assert.rejects(run, (error) => error.signalName === 'SIGTERM' && error.exitCode === 143); + assert.equal(cleanupStarted, true); + assert.equal(switches.length, 1); + assert.equal(switches[0][0].enable, 0); +});