单目3D初始代码

This commit is contained in:
zhao.zhu
2026-06-24 09:35:46 +08:00
commit 04a5895b6b
1153 changed files with 340700 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
#!/bin/bash
# Batch inference over all cases in a mined eval dataset directory.
#
# Directory layout expected (produced by mine_balanced_eval_subset.py):
# EVAL_DIR/<date>/<case_uuid>/images/
# EVAL_DIR/<date>/<case_uuid>/calib/L2_calib/camera4.json
#
# Output mirrors the same structure under OUTPUT_DIR:
# OUTPUT_DIR/<date>/<case_uuid>/visualizations/
# OUTPUT_DIR/<date>/<case_uuid>/predictions/
# OUTPUT_DIR/<date>/<case_uuid>/predictions.json
#
# Usage:
# bash tools/model_inference/scripts/run_evalset_infer.sh
#
# Override defaults with environment variables:
# EVAL_DIR=... EXPORTED_MODEL=... OUTPUT_DIR=... bash tools/model_inference/scripts/run_evalset_infer.sh
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
EVAL_DIR="${EVAL_DIR:-/data1/dongying/Mono3d/G1M3/data_for_alignment/mono3d_mining_val300}"
EXPORTED_MODEL="${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_202603291430-raw-fuse/merged_model.torchscript}"
OUTPUT_DIR="${OUTPUT_DIR:-${PROJECT_ROOT}/runs/test/evalset_infer_$(basename "${EVAL_DIR}")_new}"
ENABLE_ATTR="${ENABLE_ATTR:-1}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-0}"
ENABLE_VRU_MERGE="${ENABLE_VRU_MERGE:-1}"
if [[ ! -d "${EVAL_DIR}" ]]; then
echo "ERROR: EVAL_DIR does not exist: ${EVAL_DIR}" >&2
exit 1
fi
if [[ ! -f "${EXPORTED_MODEL}" ]]; then
echo "ERROR: EXPORTED_MODEL does not exist: ${EXPORTED_MODEL}" >&2
exit 1
fi
echo "Eval dir: ${EVAL_DIR}"
echo "Model : ${EXPORTED_MODEL}"
echo "Output : ${OUTPUT_DIR}"
echo ""
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/core/run_two_roi_exported_onnx_infer.py"
--eval-dir "${EVAL_DIR}"
--exported-model "${EXPORTED_MODEL}"
--output-dir "${OUTPUT_DIR}"
)
if [[ "${ENABLE_ATTR}" == "1" ]]; then
CMD+=(--enable-attr)
fi
if [[ "${ENABLE_CROSS_CLASS_MERGE_PRIOR}" == "1" ]]; then
CMD+=(--enable-cross-class-merge-prior)
fi
if [[ "${ENABLE_VRU_MERGE}" == "1" ]]; then
CMD+=(--enable-vru-merge)
fi
"${CMD[@]}"

View File

@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for Excel/CSV column extraction.
#
# Usage:
# bash tools/model_inference/scripts/run_extract_excel_column.sh
#
# Common env overrides:
# INPUT_FILE, COLUMN_NAME, SHEET_NAME, OUTPUT_FILE, JSON_FILE,
# DEDUPE, LIST_COLUMNS, EXTRA_ARGS
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
INPUT_FILE="${INPUT_FILE:-${MODEL_INFERENCE_DIR}/examples/cncap/G1M3_AFS1616_CNCAP-2024_11月_0306.xlsx}"
COLUMN_NAME="${COLUMN_NAME:-原始数据地址}"
SHEET_NAME="${SHEET_NAME:-}"
OUTPUT_FILE="${OUTPUT_FILE:-}"
JSON_FILE="${JSON_FILE:-}"
DEDUPE="${DEDUPE:-0}"
LIST_COLUMNS="${LIST_COLUMNS:-0}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/data_tools/extract_excel_column.py"
--input-file "${INPUT_FILE}"
--column-name "${COLUMN_NAME}"
)
if [[ -n "${SHEET_NAME}" ]]; then
CMD+=(--sheet-name "${SHEET_NAME}")
fi
if [[ -n "${OUTPUT_FILE}" ]]; then
CMD+=(--output-file "${OUTPUT_FILE}")
fi
if [[ -n "${JSON_FILE}" ]]; then
CMD+=(--json-file "${JSON_FILE}")
fi
if [[ "${DEDUPE}" == "1" ]]; then
CMD+=(--dedupe)
fi
if [[ "${LIST_COLUMNS}" == "1" ]]; then
CMD+=(--list-columns)
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
CMD+=("$@")
"${CMD[@]}"

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for scene-keyed CSV -> JSON conversion.
#
# Usage:
# bash tools/model_inference/scripts/run_parse_scene_csv_to_json.sh
#
# Common env overrides:
# INPUT_FILE, SCENE_COLUMN, OUTPUT_FILE, KEEP_SCENE_FIELD, EXTRA_ARGS
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
INPUT_FILE="${INPUT_FILE:-${MODEL_INFERENCE_DIR}/examples/events/G1Q3_场地评测数据集_0418.csv}"
SCENE_COLUMN="${SCENE_COLUMN:-scene}"
OUTPUT_FILE="${OUTPUT_FILE:-}"
KEEP_SCENE_FIELD="${KEEP_SCENE_FIELD:-0}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/data_tools/parse_scene_csv_to_json.py"
--input-file "${INPUT_FILE}"
--scene-column "${SCENE_COLUMN}"
)
if [[ -n "${OUTPUT_FILE}" ]]; then
CMD+=(--output-file "${OUTPUT_FILE}")
fi
if [[ "${KEEP_SCENE_FIELD}" == "1" ]]; then
CMD+=(--keep-scene-field)
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
CMD+=("$@")
"${CMD[@]}"

View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
# Navigation launcher kept for convenience.
#
# Prefer using one of the mode-specific scripts directly:
# bash tools/model_inference/scripts/run_two_roi_exported_onnx_infer_case.sh
# bash tools/model_inference/scripts/run_two_roi_exported_onnx_infer_clip_list.sh
# bash tools/model_inference/scripts/run_two_roi_exported_onnx_infer_cncap_json.sh
# bash tools/model_inference/scripts/run_two_roi_exported_onnx_infer_event_json.sh
# bash tools/model_inference/scripts/run_two_roi_exported_onnx_infer_video_case.sh
# bash tools/model_inference/scripts/run_two_roi_exported_onnx_infer_video_root.sh
# bash tools/model_inference/scripts/run_two_roi_exported_onnx_infer_mcap.sh
cat <<'EOF'
Available launchers:
1. run_two_roi_exported_onnx_infer_case.sh
2. run_two_roi_exported_onnx_infer_clip_list.sh
3. run_two_roi_exported_onnx_infer_cncap_json.sh
4. run_two_roi_exported_onnx_infer_event_json.sh
5. run_two_roi_exported_onnx_infer_video_case.sh
6. run_two_roi_exported_onnx_infer_video_root.sh
7. run_two_roi_exported_onnx_infer_mcap.sh
EOF

View File

@@ -0,0 +1,461 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for single case / eval-dir inference.
#
# Supported modes:
# 1. CASE_DIR=<case-dir>
# 2. EVAL_DIR=<eval-root>
# 3. INPUT_DIR=<case-dir-or-eval-root>
# 4. POSTPROCESS_ONLY=1 OUTPUT_DIR=<inference-output-root>
# 5. ENABLE_PARALLEL=1 GPU_IDS="0 1" INPUT_DIR=<eval-root>
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
CASE_DIR="${CASE_DIR:-}"
EVAL_DIR="${EVAL_DIR:-}"
# /data1/dongying/Mono3d/G1Q3/dataset_for_evaluation/DL_KPI_SCENE
# /data1/dongying/Mono3d/G1Q3/dataset_for_evaluation/OP_KPI_SCENE
# /data1/dongying/Mono3d/G1Q3/dataset_for_evaluation/OP_KPI_TRAFFIC_SCENARIO
# /data1/xdzhu/Testdata_0129
# /data1/xdzhu/Testdata_0129019b4415-d171-7ae9-88ed-0065c4c6e1e0
INPUT_DIR="${INPUT_DIR:-${EVAL_DIR:-/data1/dongying/Mono3d/G1Q3/dataset_for_evaluation/OP_KPI_SCENE}}"
# INPUT_DIR="${INPUT_DIR:-${CASE_DIR}}"
# The core inference script now auto-detects whether the exported model keeps the edge branch.
EXPORTED_MODEL="${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_20260506-keep_fake_3d_branch/merged_model.torchscript}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/KPI/OP_KPI_SCENE/model_20260506_all_cases}"
ENABLE_ATTR="${ENABLE_ATTR:-1}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}"
ENABLE_VRU_MERGE="${ENABLE_VRU_MERGE:-0}"
DEVICE="${DEVICE:-}"
ATTR_DEVICE="${ATTR_DEVICE:-}"
VIS_CLASSES="${VIS_CLASSES:-}"
VIS_CLASS_NAMES="${VIS_CLASS_NAMES:-}"
SAVE_VISUALIZATION="${SAVE_VISUALIZATION:-0}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
POSTPROCESS_ONLY="${POSTPROCESS_ONLY:-1}"
ENABLE_PARALLEL="${ENABLE_PARALLEL:-0}"
GPU_IDS="${GPU_IDS:-}"
NUM_SHARDS="${NUM_SHARDS:-1}"
SHARD_INDEX="${SHARD_INDEX:-0}"
SHARD_STRATEGY="${SHARD_STRATEGY:-round_robin}"
CASE_INDEX_START="${CASE_INDEX_START:-}"
CASE_INDEX_END="${CASE_INDEX_END:-}"
PARALLEL_LOG_DIR="${PARALLEL_LOG_DIR:-${OUTPUT_DIR%/}/parallel_logs}"
FORWARD_ARGS=("$@")
# Optional post-inference tracking stage. When enabled, the launcher reuses
# the exported-inference tracking wrapper, which runs track_objects.py over
# predictions/{roi0,roi1,merge} and merges the results per case.
ENABLE_TRACKING="${ENABLE_TRACKING:-0}"
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING:-0}"
TRACK_STRICT="${TRACK_STRICT:-1}"
TRACK_RESULTS_ROOT="${TRACK_RESULTS_ROOT:-${OUTPUT_DIR}}"
TRACK_CLASSES="${TRACK_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12}"
TRACK_IOU_THRESH="${TRACK_IOU_THRESH:-0.3}"
TRACK_MAX_AGE="${TRACK_MAX_AGE:-5}"
TRACK_MIN_HITS="${TRACK_MIN_HITS:-1}"
TRACK_DIST_THRESH="${TRACK_DIST_THRESH:-100}"
TRACK_ENABLE_USE_3D="${TRACK_ENABLE_USE_3D:-0}"
TRACK_MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE:-10.0}"
TRACK_MAX_FRAMES="${TRACK_MAX_FRAMES:-}"
TRACK_MODEL_VERSION="${TRACK_MODEL_VERSION:-20260506}"
TRACK_FILE_PATTERN="${TRACK_FILE_PATTERN:-*.json}"
TRACK_MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME:-combined_tracking.json}"
TRACK_PARALLEL_JOBS="${TRACK_PARALLEL_JOBS:-4}"
TRACKING_WRAPPER="${PROJECT_ROOT}/tools/temporal_analysis/track_objects_exported_onnx_infer_case.sh"
# Optional post-tracking protocol-conversion stage.
# Runs convert_merge_tracking_exported_onnx_infer_case.sh on the tracked
# case/eval-root output tree. By default, each case writes converted protocol
# artifacts into its own objectlist/ subdirectory. Set CONVERT_OUTPUT_ROOT to
# write only converted artifacts into a separate root while preserving case
# relative paths.
ENABLE_CONVERT="${ENABLE_CONVERT:-1}"
CONVERT_STRICT="${CONVERT_STRICT:-1}"
CONVERT_RESULTS_ROOT="${CONVERT_RESULTS_ROOT:-${TRACK_RESULTS_ROOT}}"
CONVERT_OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT:-/data1/dongying/Mono3d/G1Q3/model_inference/KPI/OP_KPI_SCENE/model_20260506_objectlist}"
if [[ -z "${CONVERT_OUTPUT_LAYOUT+x}" ]]; then
if [[ -n "${CONVERT_OUTPUT_ROOT}" ]]; then
CONVERT_OUTPUT_LAYOUT="parallel_root"
else
CONVERT_OUTPUT_LAYOUT="case_subdir"
fi
else
CONVERT_OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT:-case_subdir}"
fi
CONVERT_OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME:-objectlist}"
CONVERT_MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME:-${TRACK_MERGE_OUTPUT_NAME}}"
CONVERT_CAM_ID="${CONVERT_CAM_ID:-}"
CONVERT_CASE_LIST_FILE="${CONVERT_CASE_LIST_FILE:-}"
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS:-8}"
CONVERT_WRAPPER="${PROJECT_ROOT}/tools/convert_merge_tracking_bundle/convert_merge_tracking_exported_onnx_infer_case.sh"
is_eval_case_dir() {
local case_dir="$1"
[[ -d "${case_dir}/images" ]] || return 1
[[ -f "${case_dir}/calib/L2_calib/camera4.json" || -f "${case_dir}/calib/camera4.json" ]]
}
collect_eval_case_dirs() {
local eval_root="${1%/}"
local first_level_dir
local second_level_dir
while IFS= read -r -d '' first_level_dir; do
if is_eval_case_dir "${first_level_dir}"; then
printf '%s\n' "${first_level_dir}"
continue
fi
while IFS= read -r -d '' second_level_dir; do
if is_eval_case_dir "${second_level_dir}"; then
printf '%s\n' "${second_level_dir}"
fi
done < <(find "${first_level_dir}" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
done < <(find "${eval_root}" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)
}
write_convert_case_list() {
local target_mode="$1"
local convert_root="${2%/}"
local list_file="$3"
local eval_root="${EVAL_DIR:-${INPUT_DIR}}"
local -a case_dirs=()
local case_index_start="${CASE_INDEX_START:-0}"
local case_index_end="${CASE_INDEX_END:-}"
local total_cases
local relative_case_dir
local case_dir
local index
mkdir -p "$(dirname "${list_file}")"
: > "${list_file}"
if [[ "${target_mode}" == "case" ]]; then
printf '%s\n' "${convert_root}" > "${list_file}"
return 0
fi
mapfile -t case_dirs < <(collect_eval_case_dirs "${eval_root}")
total_cases="${#case_dirs[@]}"
if [[ -z "${case_index_end}" ]]; then
case_index_end="${total_cases}"
fi
for ((index = case_index_start; index < case_index_end; index++)); do
case_dir="${case_dirs[${index}]}"
relative_case_dir="${case_dir#${eval_root%/}/}"
printf '%s\n' "${convert_root}/${relative_case_dir}" >> "${list_file}"
done
}
resolve_target_mode() {
if [[ -n "${CASE_DIR}" ]]; then
printf 'case\n'
elif [[ -n "${EVAL_DIR}" ]]; then
printf 'eval\n'
elif [[ -d "${INPUT_DIR}/images" ]]; then
printf 'case\n'
else
printf 'eval\n'
fi
}
launch_parallel_eval_workers() {
local target_mode="$1"
local num_shards="${NUM_SHARDS}"
local failed=0
local -a gpu_ids_arr=()
local -a pids=()
local -a log_files=()
if [[ "${target_mode}" != "eval" ]]; then
echo "ENABLE_PARALLEL=1 only supports eval-root inference." >&2
echo "Please point INPUT_DIR/EVAL_DIR to an eval root instead of a single case." >&2
exit 1
fi
if [[ -z "${GPU_IDS}" ]]; then
echo "ENABLE_PARALLEL=1 requires GPU_IDS, for example: GPU_IDS=\"0 1 2 3\"." >&2
exit 1
fi
# shellcheck disable=SC2206
gpu_ids_arr=(${GPU_IDS})
if [[ "${num_shards}" == "1" ]]; then
num_shards="${#gpu_ids_arr[@]}"
fi
if [[ "${num_shards}" -lt 2 ]]; then
echo "Parallel mode requires at least 2 shards, got NUM_SHARDS=${num_shards}." >&2
exit 1
fi
if [[ "${#gpu_ids_arr[@]}" -ne "${num_shards}" ]]; then
echo "GPU_IDS count (${#gpu_ids_arr[@]}) must match NUM_SHARDS (${num_shards}) in ENABLE_PARALLEL mode." >&2
exit 1
fi
mkdir -p "${PARALLEL_LOG_DIR}"
echo ""
echo "######################################################################"
echo "# Parallel eval-dir inference"
echo "######################################################################"
echo "Eval root : ${INPUT_DIR}"
echo "Output root : ${OUTPUT_DIR}"
echo "Shards : ${num_shards}"
echo "Shard strategy : ${SHARD_STRATEGY}"
echo "GPU ids : ${GPU_IDS}"
echo "Worker logs : ${PARALLEL_LOG_DIR}"
for shard_index in "${!gpu_ids_arr[@]}"; do
local gpu_id="${gpu_ids_arr[${shard_index}]}"
local device="cuda:${gpu_id}"
local attr_device="${ATTR_DEVICE:-${device}}"
local log_file="${PARALLEL_LOG_DIR}/shard_${shard_index}_gpu_${gpu_id}.log"
echo "Launching shard ${shard_index}/${num_shards} on ${device} -> ${log_file}"
ENABLE_PARALLEL=0 \
ENABLE_TRACKING=0 \
ENABLE_CONVERT=0 \
NUM_SHARDS="${num_shards}" \
SHARD_INDEX="${shard_index}" \
SHARD_STRATEGY="${SHARD_STRATEGY}" \
DEVICE="${device}" \
ATTR_DEVICE="${attr_device}" \
bash "${BASH_SOURCE[0]}" "${FORWARD_ARGS[@]}" >"${log_file}" 2>&1 &
pids+=("$!")
log_files+=("${log_file}")
done
for shard_index in "${!pids[@]}"; do
if wait "${pids[${shard_index}]}"; then
echo "Shard ${shard_index}/${num_shards} finished successfully. Log: ${log_files[${shard_index}]}"
else
echo "[ERROR] Shard ${shard_index}/${num_shards} failed. Log: ${log_files[${shard_index}]}" >&2
failed=1
fi
done
if [[ "${failed}" == "1" ]]; then
echo "Parallel inference did not finish cleanly. Postprocess was skipped." >&2
exit 1
fi
}
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/core/run_two_roi_exported_onnx_infer.py"
--exported-model "${EXPORTED_MODEL}"
--output-dir "${OUTPUT_DIR}"
)
if [[ -n "${DEVICE}" ]]; then
CMD+=(--device "${DEVICE}")
fi
if [[ -n "${ATTR_DEVICE}" ]]; then
CMD+=(--attr-device "${ATTR_DEVICE}")
fi
if [[ -n "${CASE_INDEX_START}" ]]; then
CMD+=(--case-index-start "${CASE_INDEX_START}")
fi
if [[ -n "${CASE_INDEX_END}" ]]; then
CMD+=(--case-index-end "${CASE_INDEX_END}")
fi
if [[ "${ENABLE_ATTR}" == "1" ]]; then
CMD+=(--enable-attr)
fi
if [[ "${ENABLE_CROSS_CLASS_MERGE_PRIOR}" == "1" ]]; then
CMD+=(--enable-cross-class-merge-prior)
fi
if [[ "${ENABLE_VRU_MERGE}" == "1" ]]; then
CMD+=(--enable-vru-merge)
fi
if [[ -n "${VIS_CLASSES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASSES_ARR=(${VIS_CLASSES})
CMD+=(--vis-classes "${VIS_CLASSES_ARR[@]}")
fi
if [[ -n "${VIS_CLASS_NAMES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASS_NAMES_ARR=(${VIS_CLASS_NAMES})
CMD+=(--vis-class-names "${VIS_CLASS_NAMES_ARR[@]}")
fi
if [[ "${NUM_SHARDS}" != "1" ]] || [[ "${SHARD_INDEX}" != "0" ]] || [[ "${SHARD_STRATEGY}" != "round_robin" ]]; then
CMD+=(--num-shards "${NUM_SHARDS}" --shard-index "${SHARD_INDEX}" --shard-strategy "${SHARD_STRATEGY}")
fi
if [[ -n "${CASE_DIR}" ]]; then
CMD+=(--case-dir "${CASE_DIR}")
elif [[ -n "${EVAL_DIR}" ]]; then
CMD+=(--eval-dir "${EVAL_DIR}")
elif [[ -d "${INPUT_DIR}/images" ]]; then
CMD+=(--case-dir "${INPUT_DIR}")
else
CMD+=(--eval-dir "${INPUT_DIR}")
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
if [[ "${SAVE_VISUALIZATION}" != "1" ]]; then
CMD+=(--skip-visualizations)
fi
CMD+=("$@")
TARGET_MODE="$(resolve_target_mode)"
if [[ "${ENABLE_PARALLEL}" == "1" ]] && [[ "${POSTPROCESS_ONLY}" != "1" ]]; then
launch_parallel_eval_workers "${TARGET_MODE}"
POSTPROCESS_ONLY="1"
fi
if [[ "${POSTPROCESS_ONLY}" == "1" ]]; then
echo ""
echo "######################################################################"
echo "# POSTPROCESS_ONLY=1, skipping inference"
echo "######################################################################"
echo "Postprocess root: ${OUTPUT_DIR}"
else
"${CMD[@]}"
fi
if [[ "${ENABLE_TRACKING}" == "1" ]]; then
echo ""
echo "######################################################################"
echo "# Post-inference tracking for exported case/eval-root outputs"
echo "######################################################################"
echo "Tracking root: ${TRACK_RESULTS_ROOT}"
if [[ "${TRACK_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
RESULTS_ROOT="${TRACK_RESULTS_ROOT}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
IOU_THRESH="${TRACK_IOU_THRESH}" \
MAX_AGE="${TRACK_MAX_AGE}" \
MIN_HITS="${TRACK_MIN_HITS}" \
DIST_THRESH="${TRACK_DIST_THRESH}" \
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
MAX_FRAMES="${TRACK_MAX_FRAMES}" \
MODEL_VERSION="${TRACK_MODEL_VERSION}" \
FILE_PATTERN="${TRACK_FILE_PATTERN}" \
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
TRACK_PARALLEL_JOBS="${TRACK_PARALLEL_JOBS}" \
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}" \
bash "${TRACKING_WRAPPER}" "${TRACK_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
RESULTS_ROOT="${TRACK_RESULTS_ROOT}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
IOU_THRESH="${TRACK_IOU_THRESH}" \
MAX_AGE="${TRACK_MAX_AGE}" \
MIN_HITS="${TRACK_MIN_HITS}" \
DIST_THRESH="${TRACK_DIST_THRESH}" \
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
MAX_FRAMES="${TRACK_MAX_FRAMES}" \
MODEL_VERSION="${TRACK_MODEL_VERSION}" \
FILE_PATTERN="${TRACK_FILE_PATTERN}" \
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
TRACK_PARALLEL_JOBS="${TRACK_PARALLEL_JOBS}" \
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}" \
bash "${TRACKING_WRAPPER}" "${TRACK_RESULTS_ROOT}"; then
echo "[WARN] Tracking failed, but inference outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi
elif [[ "${ENABLE_CONVERT}" != "1" ]]; then
exit 0
fi
if [[ "${ENABLE_CONVERT}" != "1" ]]; then
exit 0
fi
CONVERT_OUTPUT_ROOT_EFFECTIVE="${CONVERT_OUTPUT_ROOT}"
CONVERT_OUTPUT_LAYOUT_EFFECTIVE="${CONVERT_OUTPUT_LAYOUT}"
CONVERT_CASE_LIST_FILE_EFFECTIVE="${CONVERT_CASE_LIST_FILE}"
case "${CONVERT_OUTPUT_LAYOUT}" in
same_dir)
if [[ -f "${CONVERT_RESULTS_ROOT}" ]] || [[ "$(basename "${CONVERT_RESULTS_ROOT}")" == "${CONVERT_MERGE_JSON_NAME}" ]]; then
CONVERT_OUTPUT_ROOT_EFFECTIVE="$(dirname "${CONVERT_RESULTS_ROOT}")"
else
CONVERT_OUTPUT_ROOT_EFFECTIVE="${CONVERT_RESULTS_ROOT%/}"
fi
CONVERT_OUTPUT_LAYOUT_EFFECTIVE="parallel_root"
;;
case_subdir|parallel_root)
;;
*)
echo "Unsupported CONVERT_OUTPUT_LAYOUT: ${CONVERT_OUTPUT_LAYOUT}" >&2
echo "Expected one of: same_dir, case_subdir, parallel_root" >&2
exit 1
;;
esac
echo ""
echo "######################################################################"
echo "# Post-tracking protocol conversion for exported case/eval-root outputs"
echo "######################################################################"
echo "Conversion target: ${CONVERT_RESULTS_ROOT}"
echo "Conversion layout: ${CONVERT_OUTPUT_LAYOUT}"
if [[ "${CONVERT_OUTPUT_LAYOUT}" == "same_dir" ]]; then
echo "Conversion output: same directory as tracking results"
elif [[ "${CONVERT_OUTPUT_LAYOUT}" == "case_subdir" ]]; then
echo "Conversion subdir: ${CONVERT_OUTPUT_DIR_NAME}"
elif [[ -n "${CONVERT_OUTPUT_ROOT_EFFECTIVE}" ]]; then
echo "Conversion output root: ${CONVERT_OUTPUT_ROOT_EFFECTIVE}"
fi
if [[ -z "${CONVERT_CASE_LIST_FILE_EFFECTIVE}" ]]; then
CONVERT_CASE_LIST_FILE_EFFECTIVE="${OUTPUT_DIR%/}/_status/convert_case_list.txt"
fi
if [[ -d "${CONVERT_RESULTS_ROOT}" ]]; then
write_convert_case_list "${TARGET_MODE}" "${CONVERT_RESULTS_ROOT}" "${CONVERT_CASE_LIST_FILE_EFFECTIVE}"
echo "Conversion case list: ${CONVERT_CASE_LIST_FILE_EFFECTIVE}"
fi
if [[ "${CONVERT_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
CASE_LIST_FILE="${CONVERT_CASE_LIST_FILE_EFFECTIVE}" \
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT_EFFECTIVE}" \
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT_EFFECTIVE}" \
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
CASE_LIST_FILE="${CONVERT_CASE_LIST_FILE_EFFECTIVE}" \
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT_EFFECTIVE}" \
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT_EFFECTIVE}" \
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"; then
echo "[WARN] Protocol conversion failed, but tracking outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for PDCL clip-list batch inference.
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
CLIP_LIST_FILE="${CLIP_LIST_FILE:-${MODEL_INFERENCE_DIR}/examples/clip_lists/clips_aeb.txt}"
EXPORT_ROOT="${EXPORT_ROOT:-/data1/dongying/Mono3d/G1Q3/model_inference/test/clips_aeb_export}"
OUTPUT_PREFIX="${OUTPUT_PREFIX:-clip_export}"
CAMERA_TOPIC="${CAMERA_TOPIC:-camera4}"
MAX_FRAMES_PER_CLIP="${MAX_FRAMES_PER_CLIP:-0}"
LIMIT_CLIPS="${LIMIT_CLIPS:-0}"
SKIP_DONE="${SKIP_DONE:-1}"
EXPORTED_MODEL="${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_20260413-raw/merged_model.torchscript}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/test/clips_aeb_no_cls}"
ENABLE_ATTR="${ENABLE_ATTR:-0}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}"
ENABLE_VRU_MERGE="${ENABLE_VRU_MERGE:-1}"
VIS_CLASSES="${VIS_CLASSES:-9 10 11 12}"
VIS_CLASS_NAMES="${VIS_CLASS_NAMES:-}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/core/run_two_roi_exported_onnx_infer.py"
--clip-list-file "${CLIP_LIST_FILE}"
--export-root "${EXPORT_ROOT}"
--output-prefix "${OUTPUT_PREFIX}"
--camera-topic "${CAMERA_TOPIC}"
--max-frames-per-clip "${MAX_FRAMES_PER_CLIP}"
--exported-model "${EXPORTED_MODEL}"
--output-dir "${OUTPUT_DIR}"
)
if [[ "${ENABLE_ATTR}" == "1" ]]; then
CMD+=(--enable-attr)
fi
if [[ "${ENABLE_CROSS_CLASS_MERGE_PRIOR}" == "1" ]]; then
CMD+=(--enable-cross-class-merge-prior)
fi
if [[ "${ENABLE_VRU_MERGE}" == "1" ]]; then
CMD+=(--enable-vru-merge)
fi
if [[ -n "${VIS_CLASSES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASSES_ARR=(${VIS_CLASSES})
CMD+=(--vis-classes "${VIS_CLASSES_ARR[@]}")
fi
if [[ -n "${VIS_CLASS_NAMES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASS_NAMES_ARR=(${VIS_CLASS_NAMES})
CMD+=(--vis-class-names "${VIS_CLASS_NAMES_ARR[@]}")
fi
if [[ "${LIMIT_CLIPS}" != "0" ]]; then
CMD+=(--limit-clips "${LIMIT_CLIPS}")
fi
if [[ "${SKIP_DONE}" == "1" ]]; then
CMD+=(--skip-done)
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
CMD+=("$@")
"${CMD[@]}"

View File

@@ -0,0 +1,141 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for CNCAP JSON batch video inference.
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
CNCAP_JSON_FILE="${CNCAP_JSON_FILE:-${MODEL_INFERENCE_DIR}/examples/cncap/G1M3_AFS1616_CNCAP-202411.json}"
CNCAP_VALUES_KEY="${CNCAP_VALUES_KEY:-values}"
CNCAP_PATH_PREFIX_SRC="${CNCAP_PATH_PREFIX_SRC:-/mnt/hfs/project-G1M3}"
CNCAP_PATH_PREFIX_DST="${CNCAP_PATH_PREFIX_DST:-/mnt/G1M3}"
VIDEO_STRIDE="${VIDEO_STRIDE:-1}"
EXPORTED_MODEL="${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_20260506-keep_fake_3d_branch/merged_model.torchscript}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/cncap/cncap_2024_with_cls_ego/model_20260506_keep_fake3d_validate}"
MAX_IMAGES="${MAX_IMAGES:-0}"
ENABLE_ATTR="${ENABLE_ATTR:-1}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}"
ENABLE_VRU_MERGE="${ENABLE_VRU_MERGE:-0}"
DEVICE="${DEVICE:-cuda:2}"
VIS_CLASSES="${VIS_CLASSES:-}"
VIS_CLASS_NAMES="${VIS_CLASS_NAMES:-}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
# ---------------------------------------------------------------------------
# Auto-tracking: run tracking immediately after inference completes.
# Set AUTO_TRACK=1 to enable. All TRACK_* variables mirror the defaults in
# track_objects_exported_onnx_infer_cncap_json.sh and can be overridden.
# ---------------------------------------------------------------------------
AUTO_TRACK="${AUTO_TRACK:-1}"
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING:-0}"
TRACK_CLASSES="${TRACK_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12 17 18 19}"
TRACK_IOU_THRESH="${TRACK_IOU_THRESH:-0.3}"
TRACK_MAX_AGE="${TRACK_MAX_AGE:-5}"
TRACK_MIN_HITS="${TRACK_MIN_HITS:-1}"
TRACK_DIST_THRESH="${TRACK_DIST_THRESH:-100}"
TRACK_MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE:-10.0}"
TRACK_MAX_FRAMES="${TRACK_MAX_FRAMES:-}"
TRACK_MODEL_VERSION="${TRACK_MODEL_VERSION:-20260506}"
TRACK_FILE_PATTERN="${TRACK_FILE_PATTERN:-*.json}"
TRACK_ENABLE_USE_3D="${TRACK_ENABLE_USE_3D:-0}"
TRACK_MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME:-combined_tracking.json}"
if [[ -z "${CNCAP_JSON_FILE}" ]]; then
echo "CNCAP_JSON_FILE is required." >&2
exit 1
fi
# /data1/dongying/Mono3d/G1Q3/model_inference/cncap/cncap_2024_with_cls_ego/model_20260407/20251115/CVE/CPLA_RL_AEB_20_5_1_20251115140740/predictions/roi0/camera4_345630.json
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/core/run_two_roi_exported_onnx_infer.py"
--cncap-json-file "${CNCAP_JSON_FILE}"
--cncap-values-key "${CNCAP_VALUES_KEY}"
--cncap-path-prefix-src "${CNCAP_PATH_PREFIX_SRC}"
--cncap-path-prefix-dst "${CNCAP_PATH_PREFIX_DST}"
--video-stride "${VIDEO_STRIDE}"
--exported-model "${EXPORTED_MODEL}"
--output-dir "${OUTPUT_DIR}"
--device "${DEVICE}"
)
if [[ "${ENABLE_ATTR}" == "1" ]]; then
CMD+=(--enable-attr)
fi
if [[ "${ENABLE_CROSS_CLASS_MERGE_PRIOR}" == "1" ]]; then
CMD+=(--enable-cross-class-merge-prior)
fi
if [[ "${ENABLE_VRU_MERGE}" == "1" ]]; then
CMD+=(--enable-vru-merge)
fi
if [[ -n "${VIS_CLASSES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASSES_ARR=(${VIS_CLASSES})
CMD+=(--vis-classes "${VIS_CLASSES_ARR[@]}")
fi
if [[ -n "${VIS_CLASS_NAMES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASS_NAMES_ARR=(${VIS_CLASS_NAMES})
CMD+=(--vis-class-names "${VIS_CLASS_NAMES_ARR[@]}")
fi
if [[ "${MAX_IMAGES}" != "0" ]]; then
CMD+=(--max-images "${MAX_IMAGES}")
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
CMD+=("$@")
"${CMD[@]}"
# ---------------------------------------------------------------------------
# Auto-tracking step
# ---------------------------------------------------------------------------
if [[ "${AUTO_TRACK}" == "1" ]]; then
TRACKING_SCRIPT="${PROJECT_ROOT}/tools/temporal_analysis/track_objects_exported_onnx_infer_cncap_json.sh"
if [[ ! -f "${TRACKING_SCRIPT}" ]]; then
echo "[AUTO_TRACK] ERROR: tracking script not found: ${TRACKING_SCRIPT}" >&2
exit 1
fi
echo ""
echo "######################################################################"
echo "# AUTO_TRACK=1 — starting CNCAP tracking on ${OUTPUT_DIR}"
echo "######################################################################"
TRACK_ENV=(
PYTHON_BIN="${PYTHON_BIN}"
RESULTS_ROOT="${OUTPUT_DIR}"
TRACK_CLASSES="${TRACK_CLASSES}"
IOU_THRESH="${TRACK_IOU_THRESH}"
MAX_AGE="${TRACK_MAX_AGE}"
MIN_HITS="${TRACK_MIN_HITS}"
DIST_THRESH="${TRACK_DIST_THRESH}"
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}"
FILE_PATTERN="${TRACK_FILE_PATTERN}"
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}"
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}"
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}"
)
if [[ -n "${TRACK_MAX_FRAMES}" ]]; then
TRACK_ENV+=(MAX_FRAMES="${TRACK_MAX_FRAMES}")
fi
if [[ -n "${TRACK_MODEL_VERSION}" ]]; then
TRACK_ENV+=(MODEL_VERSION="${TRACK_MODEL_VERSION}")
fi
env "${TRACK_ENV[@]}" bash "${TRACKING_SCRIPT}"
fi

View File

@@ -0,0 +1,218 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
BASE_SCRIPT="${SCRIPT_DIR}/run_two_roi_exported_onnx_infer_event_json.sh"
# Launcher for CNCAP scene/rawid batch inference based on scene-grouped JSON
# records that contain direct clip-id lists.
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
EVENT_JSON_FILE="${EVENT_JSON_FILE:-${MODEL_INFERENCE_DIR}/examples/cncap/aeb_clips-20260429.json}"
SCENE="${SCENE:-SCP}"
EVENT_ID_FIELD="${EVENT_ID_FIELD:-rawid}"
EVENT_CLIP_IDS_FIELD="${EVENT_CLIP_IDS_FIELD:-clips}"
CONDITION_FIELDS="${CONDITION_FIELDS:-偏置 目标速度 自车速度}"
MAX_RECORDS_PER_CONDITION="${MAX_RECORDS_PER_CONDITION:-1}"
CONDITION_SELECT_STRATEGY="${CONDITION_SELECT_STRATEGY:-first}"
SELECTION_ONLY="${SELECTION_ONLY:-0}"
MAX_EVENTS="${MAX_EVENTS:-0}"
EVENT_CACHE_FILE="${EVENT_CACHE_FILE:-${MODEL_INFERENCE_DIR}/.cache/event_clip_cache.json}"
EVENT_RESOLVE_WORKERS="${EVENT_RESOLVE_WORKERS:-4}"
EVENT_REQUEST_TIMEOUT="${EVENT_REQUEST_TIMEOUT:-60}"
EVENT_REQUEST_RETRIES="${EVENT_REQUEST_RETRIES:-3}"
EVENT_REQUEST_RETRY_BACKOFF_SEC="${EVENT_REQUEST_RETRY_BACKOFF_SEC:-2.0}"
EXPORT_ROOT="${EXPORT_ROOT:-/data1/dongying/Mono3d/G1Q3/model_inference/cncap/aeb_clips_20260429_selected/event_exports}"
OUTPUT_PREFIX="${OUTPUT_PREFIX:-clip}"
CAMERA_TOPIC="${CAMERA_TOPIC:-camera4}"
MAX_FRAMES_PER_CLIP="${MAX_FRAMES_PER_CLIP:-0}"
LIMIT_CLIPS="${LIMIT_CLIPS:-0}"
SKIP_DONE="${SKIP_DONE:-1}"
EXPORTED_MODEL="${EXPORTED_MODEL:-${MODEL_INFERENCE_DIR}/../../runs/export/train_mono3d_two_roi_20260506-drop_fake_3d_branch/merged_model.torchscript}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/cncap/aeb_clips_20260429_selected/model_20260506_vis_distance}"
ENABLE_ATTR="${ENABLE_ATTR:-0}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}"
SHOW_DISTANCE_LABEL="${SHOW_DISTANCE_LABEL:-1}"
DISTANCE_LABEL_MODE="${DISTANCE_LABEL_MODE:-depth_lateral}"
DISTANCE_LABEL_PANELS="${DISTANCE_LABEL_PANELS:-3d}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
# Optional rawid L2 package download through mdi.
ENABLE_RAW_L2_DOWNLOAD="${ENABLE_RAW_L2_DOWNLOAD:-1}"
RAW_L2_DOWNLOAD_ONLY="${RAW_L2_DOWNLOAD_ONLY:-0}"
RAW_L2_DOWNLOAD_ROOT="${RAW_L2_DOWNLOAD_ROOT:-/data1/dongying/Mono3d/G1Q3/model_inference/cncap/aeb_clips_20260429_selected/raw_l2}"
RAW_L2_DOWNLOAD_MANIFEST="${RAW_L2_DOWNLOAD_MANIFEST:-${RAW_L2_DOWNLOAD_ROOT}/download_manifest.json}"
RAW_L2_DOWNLOAD_DRY_RUN="${RAW_L2_DOWNLOAD_DRY_RUN:-0}"
RAW_L2_DOWNLOAD_SKIP_DONE="${RAW_L2_DOWNLOAD_SKIP_DONE:-1}"
RAW_L2_DOWNLOAD_STRICT="${RAW_L2_DOWNLOAD_STRICT:-1}"
# Auto-tracking is delegated to the shared event-json launcher.
# Set TRACK_ONLY=1 to skip clip export/inference and run tracking on OUTPUT_DIR.
# Set CONVERT_ONLY=1 to skip clip export/inference and tracking, then convert.
TRACK_ONLY="${TRACK_ONLY:-0}"
CONVERT_ONLY="${CONVERT_ONLY:-0}"
AUTO_TRACK="${AUTO_TRACK:-1}"
TRACK_CLASSES="${TRACK_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12 17 18 19}"
TRACK_IOU_THRESH="${TRACK_IOU_THRESH:-0.3}"
TRACK_MAX_AGE="${TRACK_MAX_AGE:-5}"
TRACK_MIN_HITS="${TRACK_MIN_HITS:-1}"
TRACK_DIST_THRESH="${TRACK_DIST_THRESH:-100}"
TRACK_MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE:-10.0}"
TRACK_MODEL_VERSION="${TRACK_MODEL_VERSION:-20260506}"
TRACK_FILE_PATTERN="${TRACK_FILE_PATTERN:-*.json}"
TRACK_ENABLE_USE_3D="${TRACK_ENABLE_USE_3D:-0}"
TRACK_MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME:-combined_tracking.json}"
TRACK_MANIFEST_NAME="${TRACK_MANIFEST_NAME:-frame_order_manifest.json}"
TRACK_EVENT_TRACKING_DIRNAME="${TRACK_EVENT_TRACKING_DIRNAME:-}"
# Post-tracking protocol conversion. This scene launcher converts only the
# event-level merge.json by default.
ENABLE_CONVERT="${ENABLE_CONVERT:-1}"
CONVERT_STRICT="${CONVERT_STRICT:-1}"
CONVERT_RESULTS_ROOT="${CONVERT_RESULTS_ROOT:-${OUTPUT_DIR}}"
CONVERT_OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT:-${OUTPUT_DIR%/}_objectlist}"
CONVERT_OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT:-parallel_root}"
CONVERT_OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME:-objectlist}"
CONVERT_MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME:-merge.json}"
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS:-4}"
CONVERT_CAM_ID="${CONVERT_CAM_ID:-}"
if [[ ! -f "${BASE_SCRIPT}" ]]; then
echo "Base launcher not found: ${BASE_SCRIPT}" >&2
exit 1
fi
run_raw_l2_download() {
local downloader="${MODEL_INFERENCE_DIR}/core/download_rawid_l2_by_event_json.py"
if [[ ! -f "${downloader}" ]]; then
echo "Raw L2 downloader not found: ${downloader}" >&2
exit 1
fi
local -a cmd=(
"${PYTHON_BIN}" "${downloader}"
--event-json-file "${EVENT_JSON_FILE}"
--event-id-field "${EVENT_ID_FIELD}"
--event-clip-ids-field "${EVENT_CLIP_IDS_FIELD}"
--event-cache-file "${EVENT_CACHE_FILE}"
--event-resolve-workers "${EVENT_RESOLVE_WORKERS}"
--event-request-timeout "${EVENT_REQUEST_TIMEOUT}"
--event-request-retries "${EVENT_REQUEST_RETRIES}"
--event-request-retry-backoff-sec "${EVENT_REQUEST_RETRY_BACKOFF_SEC}"
--output-root "${RAW_L2_DOWNLOAD_ROOT}"
--manifest-path "${RAW_L2_DOWNLOAD_MANIFEST}"
)
if [[ -n "${SCENE}" ]]; then
cmd+=(--scene "${SCENE}")
fi
if [[ -n "${CONDITION_FIELDS}" ]]; then
# shellcheck disable=SC2206
CONDITION_FIELDS_ARR=(${CONDITION_FIELDS})
cmd+=(--condition-fields "${CONDITION_FIELDS_ARR[@]}")
fi
if [[ "${MAX_RECORDS_PER_CONDITION}" != "0" ]]; then
cmd+=(--max-records-per-condition "${MAX_RECORDS_PER_CONDITION}")
fi
if [[ -n "${CONDITION_SELECT_STRATEGY}" ]]; then
cmd+=(--condition-select-strategy "${CONDITION_SELECT_STRATEGY}")
fi
if [[ "${MAX_EVENTS}" != "0" ]]; then
cmd+=(--max-events "${MAX_EVENTS}")
fi
if [[ "${RAW_L2_DOWNLOAD_DRY_RUN}" == "1" ]]; then
cmd+=(--dry-run)
fi
if [[ "${RAW_L2_DOWNLOAD_SKIP_DONE}" == "1" ]]; then
cmd+=(--skip-done)
fi
if [[ "${RAW_L2_DOWNLOAD_STRICT}" == "1" ]]; then
cmd+=(--strict)
fi
echo ""
echo "######################################################################"
echo "# Rawid L2 package download through mdi"
echo "######################################################################"
echo "Download root : ${RAW_L2_DOWNLOAD_ROOT}"
echo "Manifest : ${RAW_L2_DOWNLOAD_MANIFEST}"
"${cmd[@]}"
}
if [[ "${ENABLE_RAW_L2_DOWNLOAD}" == "1" || "${RAW_L2_DOWNLOAD_ONLY}" == "1" ]]; then
if [[ "${RAW_L2_DOWNLOAD_STRICT}" == "1" ]]; then
run_raw_l2_download
else
if ! run_raw_l2_download; then
echo "[WARN] Raw L2 download failed, continuing because RAW_L2_DOWNLOAD_STRICT=0" >&2
fi
fi
fi
if [[ "${RAW_L2_DOWNLOAD_ONLY}" == "1" ]]; then
exit 0
fi
env \
PYTHON_BIN="${PYTHON_BIN}" \
EVENT_JSON_FILE="${EVENT_JSON_FILE}" \
SCENE="${SCENE}" \
EVENT_ID_FIELD="${EVENT_ID_FIELD}" \
EVENT_CLIP_IDS_FIELD="${EVENT_CLIP_IDS_FIELD}" \
CONDITION_FIELDS="${CONDITION_FIELDS}" \
MAX_RECORDS_PER_CONDITION="${MAX_RECORDS_PER_CONDITION}" \
CONDITION_SELECT_STRATEGY="${CONDITION_SELECT_STRATEGY}" \
SELECTION_ONLY="${SELECTION_ONLY}" \
MAX_EVENTS="${MAX_EVENTS}" \
EVENT_CACHE_FILE="${EVENT_CACHE_FILE}" \
EVENT_RESOLVE_WORKERS="${EVENT_RESOLVE_WORKERS}" \
EVENT_REQUEST_TIMEOUT="${EVENT_REQUEST_TIMEOUT}" \
EVENT_REQUEST_RETRIES="${EVENT_REQUEST_RETRIES}" \
EVENT_REQUEST_RETRY_BACKOFF_SEC="${EVENT_REQUEST_RETRY_BACKOFF_SEC}" \
EXPORT_ROOT="${EXPORT_ROOT}" \
OUTPUT_PREFIX="${OUTPUT_PREFIX}" \
CAMERA_TOPIC="${CAMERA_TOPIC}" \
MAX_FRAMES_PER_CLIP="${MAX_FRAMES_PER_CLIP}" \
LIMIT_CLIPS="${LIMIT_CLIPS}" \
SKIP_DONE="${SKIP_DONE}" \
EXPORTED_MODEL="${EXPORTED_MODEL}" \
OUTPUT_DIR="${OUTPUT_DIR}" \
ENABLE_ATTR="${ENABLE_ATTR}" \
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR}" \
SHOW_DISTANCE_LABEL="${SHOW_DISTANCE_LABEL}" \
DISTANCE_LABEL_MODE="${DISTANCE_LABEL_MODE}" \
DISTANCE_LABEL_PANELS="${DISTANCE_LABEL_PANELS}" \
EXTRA_ARGS="${EXTRA_ARGS}" \
TRACK_ONLY="${TRACK_ONLY}" \
CONVERT_ONLY="${CONVERT_ONLY}" \
AUTO_TRACK="${AUTO_TRACK}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
TRACK_IOU_THRESH="${TRACK_IOU_THRESH}" \
TRACK_MAX_AGE="${TRACK_MAX_AGE}" \
TRACK_MIN_HITS="${TRACK_MIN_HITS}" \
TRACK_DIST_THRESH="${TRACK_DIST_THRESH}" \
TRACK_MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
TRACK_MODEL_VERSION="${TRACK_MODEL_VERSION}" \
TRACK_FILE_PATTERN="${TRACK_FILE_PATTERN}" \
TRACK_ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
TRACK_MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
TRACK_MANIFEST_NAME="${TRACK_MANIFEST_NAME}" \
TRACK_EVENT_TRACKING_DIRNAME="${TRACK_EVENT_TRACKING_DIRNAME}" \
ENABLE_CONVERT="${ENABLE_CONVERT}" \
CONVERT_STRICT="${CONVERT_STRICT}" \
CONVERT_RESULTS_ROOT="${CONVERT_RESULTS_ROOT}" \
CONVERT_OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT}" \
CONVERT_OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT}" \
CONVERT_OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
CONVERT_MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS}" \
CONVERT_CAM_ID="${CONVERT_CAM_ID}" \
bash "${BASE_SCRIPT}" "$@"

View File

@@ -0,0 +1,287 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for scene event-json batch inference.
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
EVENT_JSON_FILE="${EVENT_JSON_FILE:-${MODEL_INFERENCE_DIR}/examples/events/G1Q3_场地评测数据集.json}"
SCENE="${SCENE:-}"
EVENT_ID_FIELD="${EVENT_ID_FIELD:-data_path}"
EVENT_CLIP_IDS_FIELD="${EVENT_CLIP_IDS_FIELD:-clips}"
CONDITION_FIELDS="${CONDITION_FIELDS:-}"
MAX_RECORDS_PER_CONDITION="${MAX_RECORDS_PER_CONDITION:-0}"
CONDITION_SELECT_STRATEGY="${CONDITION_SELECT_STRATEGY:-first}"
SELECTION_ONLY="${SELECTION_ONLY:-0}"
MAX_EVENTS="${MAX_EVENTS:-0}"
EVENT_CACHE_FILE="${EVENT_CACHE_FILE:-${MODEL_INFERENCE_DIR}/.cache/event_clip_cache.json}"
EVENT_RESOLVE_WORKERS="${EVENT_RESOLVE_WORKERS:-4}"
EVENT_REQUEST_TIMEOUT="${EVENT_REQUEST_TIMEOUT:-60}"
EVENT_REQUEST_RETRIES="${EVENT_REQUEST_RETRIES:-3}"
EVENT_REQUEST_RETRY_BACKOFF_SEC="${EVENT_REQUEST_RETRY_BACKOFF_SEC:-2.0}"
EXPORT_ROOT="${EXPORT_ROOT:-/data1/dongying/Mono3d/G1Q3/model_inference/cncap/cncap_2021_with_cls_ego/event_exports}"
OUTPUT_PREFIX="${OUTPUT_PREFIX:-clip}"
CAMERA_TOPIC="${CAMERA_TOPIC:-camera4}"
MAX_FRAMES_PER_CLIP="${MAX_FRAMES_PER_CLIP:-0}"
LIMIT_CLIPS="${LIMIT_CLIPS:-0}"
SKIP_DONE="${SKIP_DONE:-1}"
EXPORTED_MODEL="${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_20260506-keep_fake_3d_branch/merged_model.torchscript}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/cncap/cncap_2021_with_cls_ego/model_20260506_keep_fake3d_validate}"
ENABLE_ATTR="${ENABLE_ATTR:-1}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}"
ENABLE_VRU_MERGE="${ENABLE_VRU_MERGE:-0}"
VIS_CLASSES="${VIS_CLASSES:-}"
VIS_CLASS_NAMES="${VIS_CLASS_NAMES:-}"
SHOW_DISTANCE_LABEL="${SHOW_DISTANCE_LABEL:-0}"
DISTANCE_LABEL_MODE="${DISTANCE_LABEL_MODE:-depth}"
DISTANCE_LABEL_PANELS="${DISTANCE_LABEL_PANELS:-3d}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
# ---------------------------------------------------------------------------
# Auto-tracking: run tracking immediately after inference completes, or set
# TRACK_ONLY=1 to skip clip export/inference and run tracking on OUTPUT_DIR.
# Set CONVERT_ONLY=1 to skip clip export/inference and tracking, then convert.
# Set AUTO_TRACK=1 to enable. All TRACK_* variables mirror the defaults in
# track_objects_exported_onnx_infer_event_json.sh and can be overridden.
# ---------------------------------------------------------------------------
TRACK_ONLY="${TRACK_ONLY:-0}"
CONVERT_ONLY="${CONVERT_ONLY:-0}"
AUTO_TRACK="${AUTO_TRACK:-1}"
if [[ "${TRACK_ONLY}" == "1" ]] && [[ "${CONVERT_ONLY}" != "1" ]]; then
AUTO_TRACK="1"
fi
if [[ "${CONVERT_ONLY}" == "1" ]]; then
AUTO_TRACK="0"
fi
TRACK_CLASSES="${TRACK_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12 17 18 19}"
TRACK_IOU_THRESH="${TRACK_IOU_THRESH:-0.3}"
TRACK_MAX_AGE="${TRACK_MAX_AGE:-5}"
TRACK_MIN_HITS="${TRACK_MIN_HITS:-1}"
TRACK_DIST_THRESH="${TRACK_DIST_THRESH:-100}"
TRACK_MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE:-10.0}"
TRACK_MODEL_VERSION="${TRACK_MODEL_VERSION:-20260506}"
TRACK_FILE_PATTERN="${TRACK_FILE_PATTERN:-*.json}"
TRACK_ENABLE_USE_3D="${TRACK_ENABLE_USE_3D:-0}"
TRACK_MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME:-combined_tracking.json}"
TRACK_MANIFEST_NAME="${TRACK_MANIFEST_NAME:-frame_order_manifest.json}"
TRACK_EVENT_TRACKING_DIRNAME="${TRACK_EVENT_TRACKING_DIRNAME:-}"
# ---------------------------------------------------------------------------
# Post-tracking protocol conversion.
# Only merge.json is converted by default; override CONVERT_MERGE_JSON_NAME if
# another tracking result needs conversion.
# ---------------------------------------------------------------------------
ENABLE_CONVERT="${ENABLE_CONVERT:-0}"
if [[ "${CONVERT_ONLY}" == "1" ]]; then
ENABLE_CONVERT="1"
fi
CONVERT_STRICT="${CONVERT_STRICT:-1}"
CONVERT_RESULTS_ROOT="${CONVERT_RESULTS_ROOT:-${OUTPUT_DIR}}"
CONVERT_OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT:-${OUTPUT_DIR%/}_objectlist}"
CONVERT_OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT:-parallel_root}"
CONVERT_OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME:-objectlist}"
CONVERT_MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME:-merge.json}"
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS:-4}"
CONVERT_CAM_ID="${CONVERT_CAM_ID:-}"
CONVERT_WRAPPER="${PROJECT_ROOT}/tools/convert_merge_tracking_bundle/convert_merge_tracking_exported_onnx_infer_case.sh"
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/core/run_two_roi_exported_onnx_infer.py"
--event-json-file "${EVENT_JSON_FILE}"
--event-id-field "${EVENT_ID_FIELD}"
--event-clip-ids-field "${EVENT_CLIP_IDS_FIELD}"
--event-cache-file "${EVENT_CACHE_FILE}"
--event-resolve-workers "${EVENT_RESOLVE_WORKERS}"
--event-request-timeout "${EVENT_REQUEST_TIMEOUT}"
--event-request-retries "${EVENT_REQUEST_RETRIES}"
--event-request-retry-backoff-sec "${EVENT_REQUEST_RETRY_BACKOFF_SEC}"
--export-root "${EXPORT_ROOT}"
--output-prefix "${OUTPUT_PREFIX}"
--camera-topic "${CAMERA_TOPIC}"
--max-frames-per-clip "${MAX_FRAMES_PER_CLIP}"
--exported-model "${EXPORTED_MODEL}"
--output-dir "${OUTPUT_DIR}"
)
if [[ "${ENABLE_ATTR}" == "1" ]]; then
CMD+=(--enable-attr)
fi
if [[ "${ENABLE_CROSS_CLASS_MERGE_PRIOR}" == "1" ]]; then
CMD+=(--enable-cross-class-merge-prior)
fi
if [[ "${ENABLE_VRU_MERGE}" == "1" ]]; then
CMD+=(--enable-vru-merge)
fi
if [[ -n "${VIS_CLASSES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASSES_ARR=(${VIS_CLASSES})
CMD+=(--vis-classes "${VIS_CLASSES_ARR[@]}")
fi
if [[ -n "${VIS_CLASS_NAMES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASS_NAMES_ARR=(${VIS_CLASS_NAMES})
CMD+=(--vis-class-names "${VIS_CLASS_NAMES_ARR[@]}")
fi
if [[ "${SHOW_DISTANCE_LABEL}" == "1" ]]; then
CMD+=(--show-distance-label)
if [[ -n "${DISTANCE_LABEL_MODE}" ]]; then
CMD+=(--distance-label-mode "${DISTANCE_LABEL_MODE}")
fi
if [[ -n "${DISTANCE_LABEL_PANELS}" ]]; then
# shellcheck disable=SC2206
DISTANCE_LABEL_PANELS_ARR=(${DISTANCE_LABEL_PANELS})
CMD+=(--distance-label-panels "${DISTANCE_LABEL_PANELS_ARR[@]}")
fi
fi
if [[ -n "${SCENE}" ]]; then
CMD+=(--scene "${SCENE}")
fi
if [[ -n "${CONDITION_FIELDS}" ]]; then
# shellcheck disable=SC2206
CONDITION_FIELDS_ARR=(${CONDITION_FIELDS})
CMD+=(--condition-fields "${CONDITION_FIELDS_ARR[@]}")
fi
if [[ "${MAX_RECORDS_PER_CONDITION}" != "0" ]]; then
CMD+=(--max-records-per-condition "${MAX_RECORDS_PER_CONDITION}")
fi
if [[ -n "${CONDITION_SELECT_STRATEGY}" ]]; then
CMD+=(--condition-select-strategy "${CONDITION_SELECT_STRATEGY}")
fi
if [[ "${SELECTION_ONLY}" == "1" ]]; then
CMD+=(--selection-only)
fi
if [[ "${MAX_EVENTS}" != "0" ]]; then
CMD+=(--max-events "${MAX_EVENTS}")
fi
if [[ "${LIMIT_CLIPS}" != "0" ]]; then
CMD+=(--limit-clips "${LIMIT_CLIPS}")
fi
if [[ "${SKIP_DONE}" == "1" ]]; then
CMD+=(--skip-done)
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
CMD+=("$@")
if [[ "${CONVERT_ONLY}" == "1" ]]; then
echo ""
echo "######################################################################"
echo "# CONVERT_ONLY=1, skipping event-json clip export/inference and tracking"
echo "######################################################################"
echo "Conversion target: ${CONVERT_RESULTS_ROOT}"
elif [[ "${TRACK_ONLY}" == "1" ]]; then
echo ""
echo "######################################################################"
echo "# TRACK_ONLY=1, skipping event-json clip export/inference"
echo "######################################################################"
echo "Tracking root: ${OUTPUT_DIR}"
else
"${CMD[@]}"
fi
# ---------------------------------------------------------------------------
# Auto-tracking step
# ---------------------------------------------------------------------------
if [[ "${AUTO_TRACK}" == "1" ]]; then
TRACKING_SCRIPT="${PROJECT_ROOT}/tools/temporal_analysis/track_objects_exported_onnx_infer_event_json.sh"
if [[ ! -f "${TRACKING_SCRIPT}" ]]; then
echo "[AUTO_TRACK] ERROR: tracking script not found: ${TRACKING_SCRIPT}" >&2
exit 1
fi
echo ""
echo "######################################################################"
echo "# AUTO_TRACK=1 — starting event-level tracking on ${OUTPUT_DIR}"
echo "######################################################################"
TRACK_ENV=(
PYTHON_BIN="${PYTHON_BIN}"
RESULTS_ROOT="${OUTPUT_DIR}"
TRACK_CLASSES="${TRACK_CLASSES}"
IOU_THRESH="${TRACK_IOU_THRESH}"
MAX_AGE="${TRACK_MAX_AGE}"
MIN_HITS="${TRACK_MIN_HITS}"
DIST_THRESH="${TRACK_DIST_THRESH}"
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}"
FILE_PATTERN="${TRACK_FILE_PATTERN}"
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}"
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}"
MANIFEST_NAME="${TRACK_MANIFEST_NAME}"
)
if [[ -n "${TRACK_MODEL_VERSION}" ]]; then
TRACK_ENV+=(MODEL_VERSION="${TRACK_MODEL_VERSION}")
fi
if [[ -n "${TRACK_EVENT_TRACKING_DIRNAME}" ]]; then
TRACK_ENV+=(EVENT_TRACKING_DIRNAME="${TRACK_EVENT_TRACKING_DIRNAME}")
fi
# Propagate SCENE as SCENE_FILTER so tracking processes only the same scene.
if [[ -n "${SCENE}" ]]; then
TRACK_ENV+=(SCENE_FILTER="${SCENE}")
fi
env "${TRACK_ENV[@]}" bash "${TRACKING_SCRIPT}"
fi
# ---------------------------------------------------------------------------
# Post-tracking protocol conversion step
# ---------------------------------------------------------------------------
if [[ "${ENABLE_CONVERT}" == "1" ]]; then
if [[ ! -f "${CONVERT_WRAPPER}" ]]; then
echo "[ENABLE_CONVERT] ERROR: conversion script not found: ${CONVERT_WRAPPER}" >&2
exit 1
fi
echo ""
echo "######################################################################"
echo "# ENABLE_CONVERT=1 — converting tracking ${CONVERT_MERGE_JSON_NAME}"
echo "######################################################################"
echo "Conversion target: ${CONVERT_RESULTS_ROOT}"
echo "Conversion layout: ${CONVERT_OUTPUT_LAYOUT}"
if [[ "${CONVERT_OUTPUT_LAYOUT}" == "case_subdir" ]]; then
echo "Conversion subdir: ${CONVERT_OUTPUT_DIR_NAME}"
elif [[ -n "${CONVERT_OUTPUT_ROOT}" ]]; then
echo "Conversion output root: ${CONVERT_OUTPUT_ROOT}"
fi
CONVERT_ENV=(
PYTHON_BIN="${PYTHON_BIN}"
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT}"
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT}"
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}"
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}"
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS}"
CAM_ID="${CONVERT_CAM_ID}"
)
if [[ "${CONVERT_STRICT}" == "1" ]]; then
env "${CONVERT_ENV[@]}" bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"
else
if ! env "${CONVERT_ENV[@]}" bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"; then
echo "[WARN] Protocol conversion failed, but tracking outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi
fi

View File

@@ -0,0 +1,307 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Parallel launcher for event-json inference by scene.
#
# Strategy:
# 1. Read scene names from the top-level keys of EVENT_JSON_FILE.
# 2. Distribute scenes across GPU_IDS using round-robin or contiguous mode.
# 3. Each scene runs the existing event-json launcher in an isolated temp root.
# 4. After a scene succeeds, move scene artifacts into the final roots.
#
# This avoids concurrent writes to the same root-level manifest/status files while
# preserving the existing single-scene inference, tracking, and conversion logic.
WORKER_SCRIPT="${SCRIPT_DIR}/run_two_roi_exported_onnx_infer_event_json.sh"
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
EVENT_JSON_FILE="${EVENT_JSON_FILE:-${MODEL_INFERENCE_DIR}/examples/events/G1Q3_场地评测数据集.json}"
EVENT_ID_FIELD="${EVENT_ID_FIELD:-event_uuid}"
EVENT_CLIP_IDS_FIELD="${EVENT_CLIP_IDS_FIELD:-clips}"
GPU_IDS="${GPU_IDS:-0 1}"
SCENES="${SCENES:-}"
SCENE_REGEX="${SCENE_REGEX:-}"
MAX_SCENES="${MAX_SCENES:-0}"
SCENE_DISTRIBUTION="${SCENE_DISTRIBUTION:-round_robin}"
DRY_RUN="${DRY_RUN:-0}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/cncap/cncap_2021_with_cls_ego/model_20260506_keep_fake3d_validate}"
EXPORT_ROOT="${EXPORT_ROOT:-/data1/dongying/Mono3d/G1Q3/model_inference/cncap/cncap_2021_with_cls_ego/event_exports_new}"
CONVERT_OUTPUT_ROOT_BASE="${CONVERT_OUTPUT_ROOT:-${OUTPUT_DIR%/}_objectlist}"
PARALLEL_RUN_ID="${PARALLEL_RUN_ID:-$(date +%Y%m%d_%H%M%S)}"
PARALLEL_TMP_ROOT="${PARALLEL_TMP_ROOT:-${OUTPUT_DIR%/}/_parallel_scene_tmp/${PARALLEL_RUN_ID}}"
PARALLEL_LOG_DIR="${PARALLEL_LOG_DIR:-${OUTPUT_DIR%/}/parallel_scene_logs/${PARALLEL_RUN_ID}}"
SKIP_EXISTING_SCENES="${SKIP_EXISTING_SCENES:-0}"
FORWARD_ARGS=("$@")
discover_scenes() {
if [[ -n "${SCENES}" ]]; then
# shellcheck disable=SC2206
DISCOVERED_SCENES=(${SCENES})
else
mapfile -t DISCOVERED_SCENES < <(
"${PYTHON_BIN}" - "${EVENT_JSON_FILE}" <<'PY'
import json
import sys
json_path = sys.argv[1]
with open(json_path, encoding="utf-8") as file:
payload = json.load(file)
if not isinstance(payload, dict):
raise SystemExit(f"Expected top-level object in {json_path}, got {type(payload).__name__}")
for scene_name in sorted(payload):
print(scene_name)
PY
)
fi
if [[ -n "${SCENE_REGEX}" ]]; then
local -a filtered_scenes=()
local scene_name
for scene_name in "${DISCOVERED_SCENES[@]}"; do
if [[ "${scene_name}" =~ ${SCENE_REGEX} ]]; then
filtered_scenes+=("${scene_name}")
fi
done
DISCOVERED_SCENES=("${filtered_scenes[@]}")
fi
if [[ "${MAX_SCENES}" != "0" ]] && [[ "${MAX_SCENES}" -lt "${#DISCOVERED_SCENES[@]}" ]]; then
DISCOVERED_SCENES=("${DISCOVERED_SCENES[@]:0:${MAX_SCENES}}")
fi
if [[ "${#DISCOVERED_SCENES[@]}" -eq 0 ]]; then
echo "No scenes selected from ${EVENT_JSON_FILE}" >&2
exit 1
fi
}
scene_assigned_to_worker() {
local scene_index="$1"
local worker_index="$2"
local worker_count="$3"
case "${SCENE_DISTRIBUTION}" in
round_robin)
(( scene_index % worker_count == worker_index ))
;;
contiguous)
local start=$(( ${#DISCOVERED_SCENES[@]} * worker_index / worker_count ))
local end=$(( ${#DISCOVERED_SCENES[@]} * (worker_index + 1) / worker_count ))
(( scene_index >= start && scene_index < end ))
;;
*)
echo "Unsupported SCENE_DISTRIBUTION: ${SCENE_DISTRIBUTION}" >&2
exit 1
;;
esac
}
print_scene_plan() {
local worker_count="$1"
local worker_index
local scene_index
local scene_name
echo ""
echo "######################################################################"
echo "# Dry Run: scene to GPU assignment"
echo "######################################################################"
echo "Event JSON : ${EVENT_JSON_FILE}"
echo "Event id field : ${EVENT_ID_FIELD}"
echo "Clip ids field : ${EVENT_CLIP_IDS_FIELD}"
echo "Scenes : ${#DISCOVERED_SCENES[@]}"
echo "GPU ids : ${GPU_IDS}"
echo "Distribution : ${SCENE_DISTRIBUTION}"
echo "Output root : ${OUTPUT_DIR}"
echo "Export root : ${EXPORT_ROOT}"
echo "Convert root : ${CONVERT_OUTPUT_ROOT_BASE}"
echo "Temp root : ${PARALLEL_TMP_ROOT}"
echo "Worker logs : ${PARALLEL_LOG_DIR}"
for worker_index in "${!GPU_IDS_ARR[@]}"; do
echo ""
echo "[worker ${worker_index}] gpu=${GPU_IDS_ARR[${worker_index}]}"
for scene_index in "${!DISCOVERED_SCENES[@]}"; do
if ! scene_assigned_to_worker "${scene_index}" "${worker_index}" "${worker_count}"; then
continue
fi
scene_name="${DISCOVERED_SCENES[${scene_index}]}"
echo " - ${scene_name}"
done
done
}
move_scene_tree() {
local src_dir="$1"
local dst_dir="$2"
[[ -d "${src_dir}" ]] || return 0
if [[ -e "${dst_dir}" ]]; then
echo "Target already exists, refusing to overwrite: ${dst_dir}" >&2
return 1
fi
mkdir -p "$(dirname "${dst_dir}")"
mv "${src_dir}" "${dst_dir}"
}
run_one_scene() {
local gpu_id="$1"
local worker_index="$2"
local scene_name="$3"
local scene_tmp_root="${PARALLEL_TMP_ROOT%/}/worker_${worker_index}_gpu_${gpu_id}/${scene_name}"
local worker_output_root="${scene_tmp_root}/output_root"
local worker_export_root="${scene_tmp_root}/export_root"
local worker_convert_root="${scene_tmp_root}/convert_root"
local final_scene_output_dir="${OUTPUT_DIR%/}/${scene_name}"
local final_scene_export_dir="${EXPORT_ROOT%/}/${scene_name}"
local final_scene_convert_dir="${CONVERT_OUTPUT_ROOT_BASE%/}/${scene_name}"
local output_status_dir="${OUTPUT_DIR%/}/_status"
if [[ "${SKIP_EXISTING_SCENES}" == "1" ]] && [[ -d "${final_scene_output_dir}" ]]; then
echo "[GPU ${gpu_id}] skip existing scene: ${scene_name}"
return 0
fi
mkdir -p "${scene_tmp_root}"
echo "[GPU ${gpu_id}] start scene: ${scene_name}"
CUDA_VISIBLE_DEVICES="${gpu_id}" \
SCENE="${scene_name}" \
EVENT_ID_FIELD="${EVENT_ID_FIELD}" \
EVENT_CLIP_IDS_FIELD="${EVENT_CLIP_IDS_FIELD}" \
OUTPUT_DIR="${worker_output_root}" \
EXPORT_ROOT="${worker_export_root}" \
CONVERT_OUTPUT_ROOT="${worker_convert_root}" \
bash "${WORKER_SCRIPT}" "${FORWARD_ARGS[@]}"
move_scene_tree "${worker_output_root}/${scene_name}" "${final_scene_output_dir}"
move_scene_tree "${worker_export_root}/${scene_name}" "${final_scene_export_dir}"
if [[ "${CONVERT_OUTPUT_LAYOUT:-parallel_root}" == "parallel_root" ]]; then
move_scene_tree "${worker_convert_root}/${scene_name}" "${final_scene_convert_dir}"
fi
if [[ -f "${worker_output_root}/_status/event_scene_manifest.json" ]]; then
mkdir -p "${output_status_dir}"
cp "${worker_output_root}/_status/event_scene_manifest.json" \
"${output_status_dir}/${scene_name}_event_scene_manifest.json"
fi
echo "[GPU ${gpu_id}] finished scene: ${scene_name}"
}
launch_worker() {
local worker_index="$1"
local gpu_id="$2"
local worker_count="$3"
local log_file="${PARALLEL_LOG_DIR%/}/worker_${worker_index}_gpu_${gpu_id}.log"
local scene_index
local scene_name
local worker_failed=0
local worker_scene_count=0
for scene_index in "${!DISCOVERED_SCENES[@]}"; do
if scene_assigned_to_worker "${scene_index}" "${worker_index}" "${worker_count}"; then
((worker_scene_count+=1))
fi
done
echo "Launch worker ${worker_index} on GPU ${gpu_id}: ${worker_scene_count} scenes -> ${log_file}"
(
echo "Worker index : ${worker_index}"
echo "GPU id : ${gpu_id}"
echo "Scene count : ${worker_scene_count}"
echo "Distribution : ${SCENE_DISTRIBUTION}"
echo "Event JSON : ${EVENT_JSON_FILE}"
echo "Event id field : ${EVENT_ID_FIELD}"
echo "Clip ids field : ${EVENT_CLIP_IDS_FIELD}"
echo "Output root : ${OUTPUT_DIR}"
echo "Export root : ${EXPORT_ROOT}"
echo "Convert root : ${CONVERT_OUTPUT_ROOT_BASE}"
echo "Temp root : ${PARALLEL_TMP_ROOT}"
for scene_index in "${!DISCOVERED_SCENES[@]}"; do
if ! scene_assigned_to_worker "${scene_index}" "${worker_index}" "${worker_count}"; then
continue
fi
scene_name="${DISCOVERED_SCENES[${scene_index}]}"
if ! run_one_scene "${gpu_id}" "${worker_index}" "${scene_name}"; then
worker_failed=1
echo "[GPU ${gpu_id}] failed scene: ${scene_name}" >&2
fi
done
exit "${worker_failed}"
) >"${log_file}" 2>&1 &
WORKER_PIDS+=("$!")
WORKER_LOGS+=("${log_file}")
}
if [[ ! -f "${WORKER_SCRIPT}" ]]; then
echo "Worker script not found: ${WORKER_SCRIPT}" >&2
exit 1
fi
discover_scenes
# shellcheck disable=SC2206
GPU_IDS_ARR=(${GPU_IDS})
if [[ "${#GPU_IDS_ARR[@]}" -lt 1 ]]; then
echo "GPU_IDS must contain at least one GPU id." >&2
exit 1
fi
worker_count="${#GPU_IDS_ARR[@]}"
if [[ "${DRY_RUN}" == "1" ]]; then
print_scene_plan "${worker_count}"
exit 0
fi
mkdir -p "${PARALLEL_LOG_DIR}" "${OUTPUT_DIR}" "${EXPORT_ROOT}"
if [[ "${CONVERT_OUTPUT_LAYOUT:-parallel_root}" == "parallel_root" ]]; then
mkdir -p "${CONVERT_OUTPUT_ROOT_BASE}"
fi
echo ""
echo "######################################################################"
echo "# Parallel event-json inference by scene"
echo "######################################################################"
echo "Event JSON : ${EVENT_JSON_FILE}"
echo "Event id field : ${EVENT_ID_FIELD}"
echo "Clip ids field : ${EVENT_CLIP_IDS_FIELD}"
echo "Scenes : ${#DISCOVERED_SCENES[@]}"
echo "GPU ids : ${GPU_IDS}"
echo "Distribution : ${SCENE_DISTRIBUTION}"
echo "Output root : ${OUTPUT_DIR}"
echo "Export root : ${EXPORT_ROOT}"
echo "Convert root : ${CONVERT_OUTPUT_ROOT_BASE}"
echo "Temp root : ${PARALLEL_TMP_ROOT}"
echo "Worker logs : ${PARALLEL_LOG_DIR}"
WORKER_PIDS=()
WORKER_LOGS=()
for worker_index in "${!GPU_IDS_ARR[@]}"; do
launch_worker "${worker_index}" "${GPU_IDS_ARR[${worker_index}]}" "${worker_count}"
done
failed=0
for worker_index in "${!WORKER_PIDS[@]}"; do
if wait "${WORKER_PIDS[${worker_index}]}"; then
echo "Worker ${worker_index}/${worker_count} finished successfully. Log: ${WORKER_LOGS[${worker_index}]}"
else
echo "[ERROR] Worker ${worker_index}/${worker_count} failed. Log: ${WORKER_LOGS[${worker_index}]}" >&2
failed=1
fi
done
if [[ "${failed}" == "1" ]]; then
exit 1
fi
echo "All scene workers finished successfully."

View File

@@ -0,0 +1,280 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for one local .mcap file.
#
# Example:
# MCAP_FILE=/path/to/case.mcap bash tools/model_inference/scripts/run_two_roi_exported_onnx_infer_mcap.sh
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
MCAP_FILE="${MCAP_FILE:-/data1/dongying/Mono3d/G1Q3/tmp/mcap/20260428201929.mcap}"
MCAP_CLIP_ID="${MCAP_CLIP_ID:-}"
MCAP_DATE_NAME="${MCAP_DATE_NAME:-}"
MCAP_VEHICLE_NAME="${MCAP_VEHICLE_NAME:-local_mcap}"
EXPORT_ROOT="${EXPORT_ROOT:-/data1/dongying/Mono3d/G1Q3/model_inference/mcap/exports}"
OUTPUT_PREFIX="${OUTPUT_PREFIX:-mcap}"
CAMERA_TOPIC="${CAMERA_TOPIC:-camera4}"
CALIB_FILE="${CALIB_FILE:-}"
MAX_FRAMES_PER_CLIP="${MAX_FRAMES_PER_CLIP:-0}"
MAX_IMAGES="${MAX_IMAGES:-0}"
SKIP_DONE="${SKIP_DONE:-1}"
EXPORTED_MODEL="${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_20260423-raw_no_edge/merged_model.torchscript}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/mcap/model_20260423}"
DEVICE="${DEVICE:-}"
ATTR_DEVICE="${ATTR_DEVICE:-}"
ENABLE_ATTR="${ENABLE_ATTR:-0}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}"
ENABLE_VRU_MERGE="${ENABLE_VRU_MERGE:-1}"
VIS_CLASSES="${VIS_CLASSES:-}"
VIS_CLASS_NAMES="${VIS_CLASS_NAMES:-}"
SAVE_VISUALIZATION="${SAVE_VISUALIZATION:-1}"
SAVE_AGGREGATE_PREDICTIONS="${SAVE_AGGREGATE_PREDICTIONS:-0}"
SHOW_DISTANCE_LABEL="${SHOW_DISTANCE_LABEL:-1}"
DISTANCE_LABEL_MODE="${DISTANCE_LABEL_MODE:-depth}"
DISTANCE_LABEL_PANELS="${DISTANCE_LABEL_PANELS:-3d}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
# Optional post-inference tracking stage.
ENABLE_TRACKING="${ENABLE_TRACKING:-1}"
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING:-1}"
TRACK_STRICT="${TRACK_STRICT:-1}"
TRACK_RESULTS_ROOT="${TRACK_RESULTS_ROOT:-${OUTPUT_DIR}}"
TRACK_CLASSES="${TRACK_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12}"
TRACK_IOU_THRESH="${TRACK_IOU_THRESH:-0.3}"
TRACK_MAX_AGE="${TRACK_MAX_AGE:-5}"
TRACK_MIN_HITS="${TRACK_MIN_HITS:-1}"
TRACK_DIST_THRESH="${TRACK_DIST_THRESH:-100}"
TRACK_ENABLE_USE_3D="${TRACK_ENABLE_USE_3D:-0}"
TRACK_MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE:-10.0}"
TRACK_MAX_FRAMES="${TRACK_MAX_FRAMES:-}"
TRACK_MODEL_VERSION="${TRACK_MODEL_VERSION:-20260427}"
TRACK_FILE_PATTERN="${TRACK_FILE_PATTERN:-*.json}"
TRACK_MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME:-combined_tracking.json}"
TRACK_PARALLEL_JOBS="${TRACK_PARALLEL_JOBS:-1}"
TRACKING_WRAPPER="${PROJECT_ROOT}/tools/temporal_analysis/track_objects_exported_onnx_infer_case.sh"
# Optional post-tracking protocol conversion stage.
ENABLE_CONVERT="${ENABLE_CONVERT:-1}"
CONVERT_STRICT="${CONVERT_STRICT:-1}"
CONVERT_RESULTS_ROOT="${CONVERT_RESULTS_ROOT:-${TRACK_RESULTS_ROOT}}"
CONVERT_OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT:-}"
CONVERT_OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT:-case_subdir}"
CONVERT_OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME:-objectlist}"
CONVERT_MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME:-${TRACK_MERGE_OUTPUT_NAME}}"
CONVERT_CAM_ID="${CONVERT_CAM_ID:-}"
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS:-1}"
CONVERT_WRAPPER="${PROJECT_ROOT}/tools/convert_merge_tracking_bundle/convert_merge_tracking_exported_onnx_infer_case.sh"
if [[ -z "${MCAP_FILE}" ]]; then
echo "MCAP_FILE is required." >&2
exit 1
fi
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/core/run_two_roi_exported_onnx_infer.py"
--mcap-file "${MCAP_FILE}"
--export-root "${EXPORT_ROOT}"
--output-prefix "${OUTPUT_PREFIX}"
--camera-topic "${CAMERA_TOPIC}"
--max-frames-per-clip "${MAX_FRAMES_PER_CLIP}"
--exported-model "${EXPORTED_MODEL}"
--output-dir "${OUTPUT_DIR}"
)
if [[ -n "${MCAP_CLIP_ID}" ]]; then
CMD+=(--mcap-clip-id "${MCAP_CLIP_ID}")
fi
if [[ -n "${MCAP_DATE_NAME}" ]]; then
CMD+=(--mcap-date-name "${MCAP_DATE_NAME}")
fi
if [[ -n "${MCAP_VEHICLE_NAME}" ]]; then
CMD+=(--mcap-vehicle-name "${MCAP_VEHICLE_NAME}")
fi
if [[ -n "${CALIB_FILE}" ]]; then
CMD+=(--calib-file "${CALIB_FILE}")
fi
if [[ -n "${DEVICE}" ]]; then
CMD+=(--device "${DEVICE}")
fi
if [[ -n "${ATTR_DEVICE}" ]]; then
CMD+=(--attr-device "${ATTR_DEVICE}")
fi
if [[ "${ENABLE_ATTR}" == "1" ]]; then
CMD+=(--enable-attr)
fi
if [[ "${ENABLE_CROSS_CLASS_MERGE_PRIOR}" == "1" ]]; then
CMD+=(--enable-cross-class-merge-prior)
fi
if [[ "${ENABLE_VRU_MERGE}" == "1" ]]; then
CMD+=(--enable-vru-merge)
fi
if [[ -n "${VIS_CLASSES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASSES_ARR=(${VIS_CLASSES})
CMD+=(--vis-classes "${VIS_CLASSES_ARR[@]}")
fi
if [[ -n "${VIS_CLASS_NAMES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASS_NAMES_ARR=(${VIS_CLASS_NAMES})
CMD+=(--vis-class-names "${VIS_CLASS_NAMES_ARR[@]}")
fi
if [[ "${SHOW_DISTANCE_LABEL}" == "1" ]]; then
CMD+=(--show-distance-label)
CMD+=(--distance-label-mode "${DISTANCE_LABEL_MODE}")
if [[ -n "${DISTANCE_LABEL_PANELS}" ]]; then
# shellcheck disable=SC2206
DISTANCE_LABEL_PANELS_ARR=(${DISTANCE_LABEL_PANELS})
CMD+=(--distance-label-panels "${DISTANCE_LABEL_PANELS_ARR[@]}")
fi
fi
if [[ "${MAX_IMAGES}" != "0" ]]; then
CMD+=(--max-images "${MAX_IMAGES}")
fi
if [[ "${SKIP_DONE}" == "1" ]]; then
CMD+=(--skip-done)
fi
if [[ "${SAVE_VISUALIZATION}" != "1" ]]; then
CMD+=(--skip-visualizations)
fi
if [[ "${SAVE_AGGREGATE_PREDICTIONS}" == "1" ]]; then
CMD+=(--save-aggregate-predictions)
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
CMD+=("$@")
"${CMD[@]}"
if [[ "${ENABLE_TRACKING}" != "1" ]]; then
exit 0
fi
echo ""
echo "######################################################################"
echo "# Post-inference tracking for exported mcap output"
echo "######################################################################"
echo "Tracking target: ${TRACK_RESULTS_ROOT}"
if [[ "${TRACK_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
RESULTS_ROOT="${TRACK_RESULTS_ROOT}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
IOU_THRESH="${TRACK_IOU_THRESH}" \
MAX_AGE="${TRACK_MAX_AGE}" \
MIN_HITS="${TRACK_MIN_HITS}" \
DIST_THRESH="${TRACK_DIST_THRESH}" \
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
MAX_FRAMES="${TRACK_MAX_FRAMES}" \
MODEL_VERSION="${TRACK_MODEL_VERSION}" \
FILE_PATTERN="${TRACK_FILE_PATTERN}" \
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
TRACK_PARALLEL_JOBS="${TRACK_PARALLEL_JOBS}" \
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}" \
bash "${TRACKING_WRAPPER}" "${TRACK_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
RESULTS_ROOT="${TRACK_RESULTS_ROOT}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
IOU_THRESH="${TRACK_IOU_THRESH}" \
MAX_AGE="${TRACK_MAX_AGE}" \
MIN_HITS="${TRACK_MIN_HITS}" \
DIST_THRESH="${TRACK_DIST_THRESH}" \
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
MAX_FRAMES="${TRACK_MAX_FRAMES}" \
MODEL_VERSION="${TRACK_MODEL_VERSION}" \
FILE_PATTERN="${TRACK_FILE_PATTERN}" \
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
TRACK_PARALLEL_JOBS="${TRACK_PARALLEL_JOBS}" \
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}" \
bash "${TRACKING_WRAPPER}" "${TRACK_RESULTS_ROOT}"; then
echo "[WARN] Tracking failed, but inference outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi
if [[ "${ENABLE_CONVERT}" != "1" ]]; then
exit 0
fi
CONVERT_OUTPUT_ROOT_EFFECTIVE="${CONVERT_OUTPUT_ROOT}"
CONVERT_OUTPUT_LAYOUT_EFFECTIVE="${CONVERT_OUTPUT_LAYOUT}"
case "${CONVERT_OUTPUT_LAYOUT}" in
same_dir)
if [[ -f "${CONVERT_RESULTS_ROOT}" ]] || [[ "$(basename "${CONVERT_RESULTS_ROOT}")" == "${CONVERT_MERGE_JSON_NAME}" ]]; then
CONVERT_OUTPUT_ROOT_EFFECTIVE="$(dirname "${CONVERT_RESULTS_ROOT}")"
else
CONVERT_OUTPUT_ROOT_EFFECTIVE="${CONVERT_RESULTS_ROOT%/}"
fi
CONVERT_OUTPUT_LAYOUT_EFFECTIVE="parallel_root"
;;
case_subdir|parallel_root)
;;
*)
echo "Unsupported CONVERT_OUTPUT_LAYOUT: ${CONVERT_OUTPUT_LAYOUT}" >&2
echo "Expected one of: same_dir, case_subdir, parallel_root" >&2
exit 1
;;
esac
echo ""
echo "######################################################################"
echo "# Post-tracking protocol conversion for exported mcap output"
echo "######################################################################"
echo "Conversion target: ${CONVERT_RESULTS_ROOT}"
echo "Conversion layout: ${CONVERT_OUTPUT_LAYOUT}"
if [[ "${CONVERT_OUTPUT_LAYOUT}" == "same_dir" ]]; then
echo "Conversion output: same directory as tracking results"
elif [[ "${CONVERT_OUTPUT_LAYOUT}" == "case_subdir" ]]; then
echo "Conversion subdir: ${CONVERT_OUTPUT_DIR_NAME}"
elif [[ -n "${CONVERT_OUTPUT_ROOT_EFFECTIVE}" ]]; then
echo "Conversion output root: ${CONVERT_OUTPUT_ROOT_EFFECTIVE}"
fi
if [[ "${CONVERT_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT_EFFECTIVE}" \
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT_EFFECTIVE}" \
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT_EFFECTIVE}" \
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT_EFFECTIVE}" \
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CONVERT_PARALLEL_JOBS="${CONVERT_PARALLEL_JOBS}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"; then
echo "[WARN] Protocol conversion failed, but tracking outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi

View File

@@ -0,0 +1,232 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for single video-case inference.
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
VIDEO_CASE_DIR="${VIDEO_CASE_DIR:-/data1/dongying/Mono3d/G1Q3/tmp/20260507/20260507165034/sigmastar.1/camera4.bin}"
# VIDEO_CASE_DIR="${VIDEO_CASE_DIR:-/mnt/G1M3/gt_org_data/G1M3_AFS1616/CNCAP2024数采/20251118/CVE/CPTN_LF_AEB_30_4_20251118162753/sigmastar.1/camera4.bin}"
# VIDEO_CASE_DIR="${VIDEO_CASE_DIR:-/mnt/G1M3/gt_org_data/G1M3_AFS1616/CNCAP2024数采/20251118/CVE/CPTN_LN_AEB_30_1_20251118155909/sigmastar.1/camera4.bin}"
# VIDEO_CASE_DIR="${VIDEO_CASE_DIR:-/mnt/G1M3/gt_org_data/G1M3_AFS1616/CNCAP2024数采/20251121/CVE/CPLA_RL_FCW_NIGHT_60_1_20251120201141/sigmastar.1/camera4.bin}"
VIDEO_STRIDE="${VIDEO_STRIDE:-1}"
EXPORTED_MODEL="${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_20260427-raw_no_edge/merged_model.torchscript}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/tmp/20260507_results/model_20260427/20260507165034}"
# OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/tmp/20260416/CPLA_RL_FCW_NIGHT_60_1_20251120201141}"
MAX_IMAGES="${MAX_IMAGES:-1000}"
ENABLE_ATTR="${ENABLE_ATTR:-0}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}"
ENABLE_VRU_MERGE="${ENABLE_VRU_MERGE:-1}"
VIS_CLASSES="${VIS_CLASSES:-}"
VIS_CLASS_NAMES="${VIS_CLASS_NAMES:-}"
SHOW_DISTANCE_LABEL="${SHOW_DISTANCE_LABEL:-1}"
DISTANCE_LABEL_MODE="${DISTANCE_LABEL_MODE:-depth}"
DISTANCE_LABEL_PANELS="${DISTANCE_LABEL_PANELS:-3d}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
# Optional post-inference tracking stage. When enabled, the launcher reuses
# the exported-inference tracking wrapper, which runs track_objects.py over
# predictions/{roi0,roi1,merge} and merges the results for this case.
ENABLE_TRACKING="${ENABLE_TRACKING:-1}"
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING:-1}"
TRACK_STRICT="${TRACK_STRICT:-1}"
TRACK_RESULTS_ROOT="${TRACK_RESULTS_ROOT:-${OUTPUT_DIR}}"
TRACK_CLASSES="${TRACK_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12 17 18 19}"
TRACK_IOU_THRESH="${TRACK_IOU_THRESH:-0.3}"
TRACK_MAX_AGE="${TRACK_MAX_AGE:-5}"
TRACK_MIN_HITS="${TRACK_MIN_HITS:-1}"
TRACK_DIST_THRESH="${TRACK_DIST_THRESH:-100}"
TRACK_ENABLE_USE_3D="${TRACK_ENABLE_USE_3D:-0}"
TRACK_MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE:-10.0}"
TRACK_MAX_FRAMES="${TRACK_MAX_FRAMES:-}"
TRACK_MODEL_VERSION="${TRACK_MODEL_VERSION:-20260506}"
TRACK_FILE_PATTERN="${TRACK_FILE_PATTERN:-*.json}"
TRACK_MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME:-combined_tracking.json}"
TRACKING_WRAPPER="${PROJECT_ROOT}/tools/temporal_analysis/track_objects_exported_onnx_infer_case.sh"
# Optional post-tracking protocol-conversion stage.
# Runs convert_merge_tracking_exported_onnx_infer_case.sh on the case output
# directory to produce ObjectPerceptionObjectList.{data.json,bin,index.json}.
# By default, converted protocol files are written into the same directory as
# the tracking result. Override CONVERT_OUTPUT_LAYOUT=case_subdir to emit into
# {case_dir}/{CONVERT_OUTPUT_DIR_NAME}/, or use parallel_root with an explicit
# CONVERT_OUTPUT_ROOT to mirror outputs into another root.
ENABLE_CONVERT="${ENABLE_CONVERT:-1}"
CONVERT_STRICT="${CONVERT_STRICT:-1}"
CONVERT_RESULTS_ROOT="${CONVERT_RESULTS_ROOT:-${OUTPUT_DIR}}"
CONVERT_OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT:-}"
CONVERT_OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT:-case_subdir}"
CONVERT_OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME:-objectlist}"
CONVERT_MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME:-${TRACK_MERGE_OUTPUT_NAME}}"
CONVERT_CAM_ID="${CONVERT_CAM_ID:-}"
CONVERT_WRAPPER="${PROJECT_ROOT}/tools/convert_merge_tracking_bundle/convert_merge_tracking_exported_onnx_infer_case.sh"
if [[ -z "${VIDEO_CASE_DIR}" ]]; then
echo "VIDEO_CASE_DIR is required." >&2
exit 1
fi
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/core/run_two_roi_exported_onnx_infer.py"
--video-case-dir "${VIDEO_CASE_DIR}"
--video-stride "${VIDEO_STRIDE}"
--exported-model "${EXPORTED_MODEL}"
--output-dir "${OUTPUT_DIR}"
)
if [[ "${ENABLE_ATTR}" == "1" ]]; then
CMD+=(--enable-attr)
fi
if [[ "${ENABLE_CROSS_CLASS_MERGE_PRIOR}" == "1" ]]; then
CMD+=(--enable-cross-class-merge-prior)
fi
if [[ "${ENABLE_VRU_MERGE}" == "1" ]]; then
CMD+=(--enable-vru-merge)
fi
if [[ -n "${VIS_CLASSES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASSES_ARR=(${VIS_CLASSES})
CMD+=(--vis-classes "${VIS_CLASSES_ARR[@]}")
fi
if [[ -n "${VIS_CLASS_NAMES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASS_NAMES_ARR=(${VIS_CLASS_NAMES})
CMD+=(--vis-class-names "${VIS_CLASS_NAMES_ARR[@]}")
fi
if [[ "${SHOW_DISTANCE_LABEL}" == "1" ]]; then
CMD+=(--show-distance-label)
CMD+=(--distance-label-mode "${DISTANCE_LABEL_MODE}")
if [[ -n "${DISTANCE_LABEL_PANELS}" ]]; then
# shellcheck disable=SC2206
DISTANCE_LABEL_PANELS_ARR=(${DISTANCE_LABEL_PANELS})
CMD+=(--distance-label-panels "${DISTANCE_LABEL_PANELS_ARR[@]}")
fi
fi
if [[ "${MAX_IMAGES}" != "0" ]]; then
CMD+=(--max-images "${MAX_IMAGES}")
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
CMD+=("$@")
"${CMD[@]}"
if [[ "${ENABLE_TRACKING}" != "1" ]]; then
exit 0
fi
echo ""
echo "######################################################################"
echo "# Post-inference tracking for exported video-case output"
echo "######################################################################"
echo "Tracking target: ${TRACK_RESULTS_ROOT}"
if [[ "${TRACK_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
RESULTS_ROOT="${TRACK_RESULTS_ROOT}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
IOU_THRESH="${TRACK_IOU_THRESH}" \
MAX_AGE="${TRACK_MAX_AGE}" \
MIN_HITS="${TRACK_MIN_HITS}" \
DIST_THRESH="${TRACK_DIST_THRESH}" \
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
MAX_FRAMES="${TRACK_MAX_FRAMES}" \
MODEL_VERSION="${TRACK_MODEL_VERSION}" \
FILE_PATTERN="${TRACK_FILE_PATTERN}" \
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}" \
bash "${TRACKING_WRAPPER}" "${TRACK_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
RESULTS_ROOT="${TRACK_RESULTS_ROOT}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
IOU_THRESH="${TRACK_IOU_THRESH}" \
MAX_AGE="${TRACK_MAX_AGE}" \
MIN_HITS="${TRACK_MIN_HITS}" \
DIST_THRESH="${TRACK_DIST_THRESH}" \
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
MAX_FRAMES="${TRACK_MAX_FRAMES}" \
MODEL_VERSION="${TRACK_MODEL_VERSION}" \
FILE_PATTERN="${TRACK_FILE_PATTERN}" \
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}" \
bash "${TRACKING_WRAPPER}" "${TRACK_RESULTS_ROOT}"; then
echo "[WARN] Tracking failed, but inference outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi
if [[ "${ENABLE_CONVERT}" != "1" ]]; then
exit 0
fi
CONVERT_OUTPUT_ROOT_EFFECTIVE="${CONVERT_OUTPUT_ROOT}"
CONVERT_OUTPUT_LAYOUT_EFFECTIVE="${CONVERT_OUTPUT_LAYOUT}"
case "${CONVERT_OUTPUT_LAYOUT}" in
same_dir)
if [[ -f "${CONVERT_RESULTS_ROOT}" ]] || [[ "$(basename "${CONVERT_RESULTS_ROOT}")" == "${CONVERT_MERGE_JSON_NAME}" ]]; then
CONVERT_OUTPUT_ROOT_EFFECTIVE="$(dirname "${CONVERT_RESULTS_ROOT}")"
else
CONVERT_OUTPUT_ROOT_EFFECTIVE="${CONVERT_RESULTS_ROOT%/}"
fi
CONVERT_OUTPUT_LAYOUT_EFFECTIVE="parallel_root"
;;
case_subdir|parallel_root)
;;
*)
echo "Unsupported CONVERT_OUTPUT_LAYOUT: ${CONVERT_OUTPUT_LAYOUT}" >&2
echo "Expected one of: same_dir, case_subdir, parallel_root" >&2
exit 1
;;
esac
echo ""
echo "######################################################################"
echo "# Post-tracking protocol conversion for exported video-case output"
echo "######################################################################"
echo "Conversion target: ${CONVERT_RESULTS_ROOT}"
echo "Conversion layout: ${CONVERT_OUTPUT_LAYOUT}"
if [[ "${CONVERT_OUTPUT_LAYOUT}" == "same_dir" ]]; then
echo "Conversion output: same directory as tracking results"
elif [[ "${CONVERT_OUTPUT_LAYOUT}" == "case_subdir" ]]; then
echo "Conversion subdir: ${CONVERT_OUTPUT_DIR_NAME}"
elif [[ -n "${CONVERT_OUTPUT_ROOT_EFFECTIVE}" ]]; then
echo "Conversion output root: ${CONVERT_OUTPUT_ROOT_EFFECTIVE}"
fi
if [[ "${CONVERT_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT_EFFECTIVE}" \
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT_EFFECTIVE}" \
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT_EFFECTIVE}" \
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT_EFFECTIVE}" \
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"; then
echo "[WARN] Protocol conversion failed, but tracking outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi

View File

@@ -0,0 +1,262 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
# Launcher for batch video-root inference.
#
# Supported postprocess-only mode:
# POSTPROCESS_ONLY=1 OUTPUT_DIR=<inference-output-root> bash run_two_roi_exported_onnx_infer_video_root.sh
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
VIDEO_ROOT_DIR="${VIDEO_ROOT_DIR:-/data1/dongying/Mono3d/G1Q3/tmp/20260507}"
# VIDEO_ROOT_DIR="${VIDEO_ROOT_DIR:-/data1/dongying/Mono3d/G1Q3/dataset_for_evaluation/CNCAP/CSTA_LN}"
VIDEO_STRIDE="${VIDEO_STRIDE:-1}"
EXPORTED_MODEL="${EXPORTED_MODEL:-${PROJECT_ROOT}/runs/export/train_mono3d_two_roi_20260506-drop_fake_3d_branch/merged_model.torchscript}"
# OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1M3/test_outputs/video_case_model_20260416_with_cls}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/tmp/20260507_results/model_20260507_drop_fake3d}"
MAX_IMAGES="${MAX_IMAGES:-0}"
ENABLE_ATTR="${ENABLE_ATTR:-1}"
ENABLE_CROSS_CLASS_MERGE_PRIOR="${ENABLE_CROSS_CLASS_MERGE_PRIOR:-1}"
ENABLE_VRU_MERGE="${ENABLE_VRU_MERGE:-1}"
VIS_CLASSES="${VIS_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12 17 18 19}"
VIS_CLASS_NAMES="${VIS_CLASS_NAMES:-}"
SHOW_DISTANCE_LABEL="${SHOW_DISTANCE_LABEL:-1}"
# depth_lateral keeps the existing longitudinal z label and adds signed
# camera-frame lateral x offset. Override with depth/lateral/xz/etc if needed.
DISTANCE_LABEL_MODE="${DISTANCE_LABEL_MODE:-depth_lateral}"
DISTANCE_LABEL_PANELS="${DISTANCE_LABEL_PANELS:-3d}"
EXTRA_ARGS="${EXTRA_ARGS:-}"
POSTPROCESS_ONLY="${POSTPROCESS_ONLY:-0}"
# Optional post-inference tracking stage. When enabled, the launcher reuses
# the exported-inference tracking wrapper, which runs track_objects.py over
# predictions/{roi0,roi1,merge} and merges the results per case.
ENABLE_TRACKING="${ENABLE_TRACKING:-1}"
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING:-0}"
TRACK_STRICT="${TRACK_STRICT:-1}"
TRACK_RESULTS_ROOT="${TRACK_RESULTS_ROOT:-${OUTPUT_DIR}}"
TRACK_CLASSES="${TRACK_CLASSES:-0 1 2 3 4 5 6 7 8 9 10 11 12 17 18 19}"
TRACK_IOU_THRESH="${TRACK_IOU_THRESH:-0.3}"
TRACK_MAX_AGE="${TRACK_MAX_AGE:-5}"
TRACK_MIN_HITS="${TRACK_MIN_HITS:-1}"
TRACK_DIST_THRESH="${TRACK_DIST_THRESH:-100}"
TRACK_ENABLE_USE_3D="${TRACK_ENABLE_USE_3D:-0}"
TRACK_MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE:-10.0}"
TRACK_MAX_FRAMES="${TRACK_MAX_FRAMES:-}"
TRACK_MODEL_VERSION="${TRACK_MODEL_VERSION:-20260427}"
TRACK_FILE_PATTERN="${TRACK_FILE_PATTERN:-*.json}"
TRACK_MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME:-combined_tracking.json}"
TRACKING_WRAPPER="${PROJECT_ROOT}/tools/temporal_analysis/track_objects_exported_onnx_infer_case.sh"
# Optional post-tracking protocol-conversion stage.
# Runs convert_merge_tracking_exported_onnx_infer_case.sh on the tracked
# video-root output tree. By default, each case writes converted protobuf
# artifacts into its own objectlist/ subdirectory.
ENABLE_CONVERT="${ENABLE_CONVERT:-1}"
CONVERT_STRICT="${CONVERT_STRICT:-1}"
CONVERT_RESULTS_ROOT="${CONVERT_RESULTS_ROOT:-${TRACK_RESULTS_ROOT}}"
CONVERT_OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT:-}"
CONVERT_OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT:-case_subdir}"
CONVERT_OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME:-objectlist}"
CONVERT_MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME:-${TRACK_MERGE_OUTPUT_NAME}}"
CONVERT_CAM_ID="${CONVERT_CAM_ID:-}"
CONVERT_WRAPPER="${PROJECT_ROOT}/tools/convert_merge_tracking_bundle/convert_merge_tracking_exported_onnx_infer_case.sh"
ENABLE_CONVERT_VRU="${ENABLE_CONVERT_VRU:-0}"
CONVERT_VRU_OUTPUT_ROOT="${CONVERT_VRU_OUTPUT_ROOT:-}"
CONVERT_VRU_OUTPUT_LAYOUT="${CONVERT_VRU_OUTPUT_LAYOUT:-case_subdir}"
CONVERT_VRU_OUTPUT_DIR_NAME="${CONVERT_VRU_OUTPUT_DIR_NAME:-objectlist_vru}"
CONVERT_VRU_MERGE_JSON_NAME="${CONVERT_VRU_MERGE_JSON_NAME:-merge_vru.json}"
if [[ "${POSTPROCESS_ONLY}" != "1" && -z "${VIDEO_ROOT_DIR}" ]]; then
echo "VIDEO_ROOT_DIR is required." >&2
exit 1
fi
CMD=(
"${PYTHON_BIN}" "${MODEL_INFERENCE_DIR}/core/run_two_roi_exported_onnx_infer.py"
--video-root-dir "${VIDEO_ROOT_DIR}"
--video-stride "${VIDEO_STRIDE}"
--exported-model "${EXPORTED_MODEL}"
--output-dir "${OUTPUT_DIR}"
)
if [[ "${ENABLE_ATTR}" == "1" ]]; then
CMD+=(--enable-attr)
fi
if [[ "${ENABLE_CROSS_CLASS_MERGE_PRIOR}" == "1" ]]; then
CMD+=(--enable-cross-class-merge-prior)
fi
if [[ "${ENABLE_VRU_MERGE}" == "1" ]]; then
CMD+=(--enable-vru-merge)
fi
if [[ -n "${VIS_CLASSES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASSES_ARR=(${VIS_CLASSES})
CMD+=(--vis-classes "${VIS_CLASSES_ARR[@]}")
fi
if [[ -n "${VIS_CLASS_NAMES}" ]]; then
# shellcheck disable=SC2206
VIS_CLASS_NAMES_ARR=(${VIS_CLASS_NAMES})
CMD+=(--vis-class-names "${VIS_CLASS_NAMES_ARR[@]}")
fi
if [[ "${SHOW_DISTANCE_LABEL}" == "1" ]]; then
CMD+=(--show-distance-label)
CMD+=(--distance-label-mode "${DISTANCE_LABEL_MODE}")
if [[ -n "${DISTANCE_LABEL_PANELS}" ]]; then
# shellcheck disable=SC2206
DISTANCE_LABEL_PANELS_ARR=(${DISTANCE_LABEL_PANELS})
CMD+=(--distance-label-panels "${DISTANCE_LABEL_PANELS_ARR[@]}")
fi
fi
if [[ "${MAX_IMAGES}" != "0" ]]; then
CMD+=(--max-images "${MAX_IMAGES}")
fi
if [[ -n "${EXTRA_ARGS}" ]]; then
# shellcheck disable=SC2206
EXTRA_ARR=(${EXTRA_ARGS})
CMD+=("${EXTRA_ARR[@]}")
fi
CMD+=("$@")
if [[ "${POSTPROCESS_ONLY}" == "1" ]]; then
echo ""
echo "######################################################################"
echo "# POSTPROCESS_ONLY=1, skipping inference"
echo "######################################################################"
echo "Postprocess root: ${OUTPUT_DIR}"
else
"${CMD[@]}"
fi
if [[ "${ENABLE_TRACKING}" == "1" ]]; then
echo ""
echo "######################################################################"
echo "# Post-inference tracking for exported video-root outputs"
echo "######################################################################"
echo "Tracking root: ${TRACK_RESULTS_ROOT}"
if [[ "${TRACK_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
RESULTS_ROOT="${TRACK_RESULTS_ROOT}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
IOU_THRESH="${TRACK_IOU_THRESH}" \
MAX_AGE="${TRACK_MAX_AGE}" \
MIN_HITS="${TRACK_MIN_HITS}" \
DIST_THRESH="${TRACK_DIST_THRESH}" \
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
MAX_FRAMES="${TRACK_MAX_FRAMES}" \
MODEL_VERSION="${TRACK_MODEL_VERSION}" \
FILE_PATTERN="${TRACK_FILE_PATTERN}" \
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}" \
bash "${TRACKING_WRAPPER}" "${TRACK_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
RESULTS_ROOT="${TRACK_RESULTS_ROOT}" \
TRACK_CLASSES="${TRACK_CLASSES}" \
IOU_THRESH="${TRACK_IOU_THRESH}" \
MAX_AGE="${TRACK_MAX_AGE}" \
MIN_HITS="${TRACK_MIN_HITS}" \
DIST_THRESH="${TRACK_DIST_THRESH}" \
ENABLE_USE_3D="${TRACK_ENABLE_USE_3D}" \
MAX_3D_DISTANCE="${TRACK_MAX_3D_DISTANCE}" \
MAX_FRAMES="${TRACK_MAX_FRAMES}" \
MODEL_VERSION="${TRACK_MODEL_VERSION}" \
FILE_PATTERN="${TRACK_FILE_PATTERN}" \
MERGE_OUTPUT_NAME="${TRACK_MERGE_OUTPUT_NAME}" \
ENABLE_VRU_TRACKING="${ENABLE_VRU_TRACKING}" \
bash "${TRACKING_WRAPPER}" "${TRACK_RESULTS_ROOT}"; then
echo "[WARN] Tracking failed, but inference outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi
elif [[ "${ENABLE_CONVERT}" != "1" ]]; then
exit 0
fi
if [[ "${ENABLE_CONVERT}" != "1" ]]; then
exit 0
fi
echo ""
echo "######################################################################"
echo "# Post-tracking protocol conversion for exported video-root outputs"
echo "######################################################################"
echo "Conversion target: ${CONVERT_RESULTS_ROOT}"
echo "Conversion layout: ${CONVERT_OUTPUT_LAYOUT}"
if [[ "${CONVERT_OUTPUT_LAYOUT}" == "case_subdir" ]]; then
echo "Conversion subdir: ${CONVERT_OUTPUT_DIR_NAME}"
elif [[ -n "${CONVERT_OUTPUT_ROOT}" ]]; then
echo "Conversion output root: ${CONVERT_OUTPUT_ROOT}"
fi
if [[ "${CONVERT_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT}" \
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT}" \
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
OUTPUT_ROOT="${CONVERT_OUTPUT_ROOT}" \
OUTPUT_LAYOUT="${CONVERT_OUTPUT_LAYOUT}" \
OUTPUT_DIR_NAME="${CONVERT_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_MERGE_JSON_NAME}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"; then
echo "[WARN] Protocol conversion failed, but tracking outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi
if [[ "${ENABLE_CONVERT_VRU}" == "1" ]]; then
echo ""
echo "######################################################################"
echo "# Post-tracking protocol conversion for VRU tracking outputs"
echo "######################################################################"
echo "VRU conversion target: ${CONVERT_RESULTS_ROOT}"
echo "VRU conversion layout: ${CONVERT_VRU_OUTPUT_LAYOUT}"
if [[ "${CONVERT_VRU_OUTPUT_LAYOUT}" == "case_subdir" ]]; then
echo "VRU conversion subdir: ${CONVERT_VRU_OUTPUT_DIR_NAME}"
elif [[ -n "${CONVERT_VRU_OUTPUT_ROOT}" ]]; then
echo "VRU conversion output root: ${CONVERT_VRU_OUTPUT_ROOT}"
fi
if [[ -d "${CONVERT_RESULTS_ROOT}" ]] && [[ -n "$(find "${CONVERT_RESULTS_ROOT}" -type f -name "${CONVERT_VRU_MERGE_JSON_NAME}" -print -quit)" ]]; then
if [[ "${CONVERT_STRICT}" == "1" ]]; then
PYTHON_BIN="${PYTHON_BIN}" \
OUTPUT_ROOT="${CONVERT_VRU_OUTPUT_ROOT}" \
OUTPUT_LAYOUT="${CONVERT_VRU_OUTPUT_LAYOUT}" \
OUTPUT_DIR_NAME="${CONVERT_VRU_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_VRU_MERGE_JSON_NAME}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"
else
if ! PYTHON_BIN="${PYTHON_BIN}" \
OUTPUT_ROOT="${CONVERT_VRU_OUTPUT_ROOT}" \
OUTPUT_LAYOUT="${CONVERT_VRU_OUTPUT_LAYOUT}" \
OUTPUT_DIR_NAME="${CONVERT_VRU_OUTPUT_DIR_NAME}" \
MERGE_JSON_NAME="${CONVERT_VRU_MERGE_JSON_NAME}" \
CAM_ID="${CONVERT_CAM_ID}" \
bash "${CONVERT_WRAPPER}" "${CONVERT_RESULTS_ROOT}"; then
echo "[WARN] VRU protocol conversion failed, but tracking outputs were kept under ${OUTPUT_DIR}" >&2
fi
fi
else
echo "Info: no ${CONVERT_VRU_MERGE_JSON_NAME} files found under ${CONVERT_RESULTS_ROOT}, skipping VRU protocol conversion"
fi
fi

View File

@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LAUNCHER="${SCRIPT_DIR}/run_two_roi_exported_onnx_infer_case.sh"
# 用途:在重跑 worker 全部完成后,统一执行 tracking 和 convert。
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/KPI/OP_KPI_SCENE/model_20260427-raw_no_edge}"
ENABLE_TRACKING="${ENABLE_TRACKING:-1}"
ENABLE_CONVERT="${ENABLE_CONVERT:-1}"
echo "Running postprocess only"
echo "Launcher : ${LAUNCHER}"
echo "Postprocess dir: ${OUTPUT_DIR}"
echo "Tracking : ${ENABLE_TRACKING}"
echo "Convert : ${ENABLE_CONVERT}"
env \
POSTPROCESS_ONLY=1 \
ENABLE_TRACKING="${ENABLE_TRACKING}" \
ENABLE_CONVERT="${ENABLE_CONVERT}" \
OUTPUT_DIR="${OUTPUT_DIR}" \
bash "${LAUNCHER}"

View File

@@ -0,0 +1,73 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LAUNCHER="${SCRIPT_DIR}/run_two_roi_exported_onnx_infer_case.sh"
# 用途:重跑最后 4 个未处理的 case且不保存 visualizations。
# 前置条件:
# 1. 已停止旧的推理进程
# 2. 已按步骤 3 清理目标 case 的旧输出目录
# 区间语义CASE_INDEX_START/END 使用 0-based 且为 [start, end)
# 当前默认区间对应 2026-04-28 的运行快照:
# - GPU0: 第 70 到第 71 个 case -> [69, 71)
# - GPU1: 第 72 到第 73 个 case -> [71, 73)
INPUT_DIR="${INPUT_DIR:-/data1/dongying/Mono3d/G1Q3/dataset_for_evaluation/OP_KPI_SCENE}"
OUTPUT_DIR="${OUTPUT_DIR:-/data1/dongying/Mono3d/G1Q3/model_inference/KPI/OP_KPI_SCENE/model_20260427-raw_no_edge}"
EXPORTED_MODEL="${EXPORTED_MODEL:-/deeplearning_team/ydong/dongying/projects/yolo26-3d/runs/export/train_mono3d_two_roi_20260427-raw_no_edge/merged_model.torchscript}"
PARALLEL_LOG_DIR="${PARALLEL_LOG_DIR:-${OUTPUT_DIR%/}/parallel_logs}"
GPU0_ID="${GPU0_ID:-0}"
GPU0_CASE_INDEX_START="${GPU0_CASE_INDEX_START:-69}"
GPU0_CASE_INDEX_END="${GPU0_CASE_INDEX_END:-71}"
GPU0_LOG="${GPU0_LOG:-${PARALLEL_LOG_DIR}/rerun_gpu${GPU0_ID}_${GPU0_CASE_INDEX_START}_${GPU0_CASE_INDEX_END}.log}"
GPU1_ID="${GPU1_ID:-1}"
GPU1_CASE_INDEX_START="${GPU1_CASE_INDEX_START:-71}"
GPU1_CASE_INDEX_END="${GPU1_CASE_INDEX_END:-73}"
GPU1_LOG="${GPU1_LOG:-${PARALLEL_LOG_DIR}/rerun_gpu${GPU1_ID}_${GPU1_CASE_INDEX_START}_${GPU1_CASE_INDEX_END}.log}"
mkdir -p "${PARALLEL_LOG_DIR}"
echo "Starting rerun workers with SAVE_VISUALIZATION=0"
echo "Launcher : ${LAUNCHER}"
echo "Input dir : ${INPUT_DIR}"
echo "Output dir : ${OUTPUT_DIR}"
echo "Exported model : ${EXPORTED_MODEL}"
echo "GPU${GPU0_ID} slice : [${GPU0_CASE_INDEX_START}, ${GPU0_CASE_INDEX_END}) -> ${GPU0_LOG}"
echo "GPU${GPU1_ID} slice : [${GPU1_CASE_INDEX_START}, ${GPU1_CASE_INDEX_END}) -> ${GPU1_LOG}"
nohup env \
SAVE_VISUALIZATION=0 \
ENABLE_TRACKING=0 \
ENABLE_CONVERT=0 \
DEVICE="cuda:${GPU0_ID}" \
ATTR_DEVICE="cuda:${GPU0_ID}" \
INPUT_DIR="${INPUT_DIR}" \
OUTPUT_DIR="${OUTPUT_DIR}" \
EXPORTED_MODEL="${EXPORTED_MODEL}" \
CASE_INDEX_START="${GPU0_CASE_INDEX_START}" \
CASE_INDEX_END="${GPU0_CASE_INDEX_END}" \
bash "${LAUNCHER}" \
>"${GPU0_LOG}" 2>&1 &
gpu0_pid=$!
nohup env \
SAVE_VISUALIZATION=0 \
ENABLE_TRACKING=0 \
ENABLE_CONVERT=0 \
DEVICE="cuda:${GPU1_ID}" \
ATTR_DEVICE="cuda:${GPU1_ID}" \
INPUT_DIR="${INPUT_DIR}" \
OUTPUT_DIR="${OUTPUT_DIR}" \
EXPORTED_MODEL="${EXPORTED_MODEL}" \
CASE_INDEX_START="${GPU1_CASE_INDEX_START}" \
CASE_INDEX_END="${GPU1_CASE_INDEX_END}" \
bash "${LAUNCHER}" \
>"${GPU1_LOG}" 2>&1 &
gpu1_pid=$!
echo "Started GPU${GPU0_ID} worker, PID=${gpu0_pid}"
echo "Started GPU${GPU1_ID} worker, PID=${gpu1_pid}"
echo "Use 'tail -f ${GPU0_LOG}' or 'tail -f ${GPU1_LOG}' to monitor progress."

View File

@@ -0,0 +1,346 @@
#!/usr/bin/env bash
set -euo pipefail
# 用法说明:
# 适配 run_two_roi_exported_onnx_infer_video_root.sh 的输出目录,对每个 case 执行:
# {case_dir}/merge.json -> {case_dir}/temporal_observation/stability_report.json
#
# 支持三种模式:
# 1) 批量模式(默认):遍历 RESULTS_ROOT 下所有包含 merge.json 的 case
# bash run_two_roi_exported_onnx_temporal_observe_video_root.sh
# 2) 指定根目录模式:第一个参数传推理/跟踪输出根目录
# bash run_two_roi_exported_onnx_temporal_observe_video_root.sh /path/to/inference_output_root
# 3) 单 case 模式:第一个参数传 case 目录,或直接传 case_dir/merge.json
# bash run_two_roi_exported_onnx_temporal_observe_video_root.sh /path/to/one_case --track-id 32
# bash run_two_roi_exported_onnx_temporal_observe_video_root.sh /path/to/one_case/merge.json --track-id 32
#
# 默认读取 merge.json因为 combined_tracking.json 会给不同 source 的 track_id 加偏移,
# 不利于按单个目标 track_id 做精确筛选。
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MODEL_INFERENCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
PROJECT_ROOT="$(cd "${MODEL_INFERENCE_DIR}/../.." && pwd)"
export PYTHONPATH="${PROJECT_ROOT}:${PYTHONPATH:-}"
RESULTS_ROOT="${RESULTS_ROOT:-/data1/dongying/Mono3d/G1M3/test_data/cncap_20260414/20260416103945}"
OUTPUT_ROOT="${OUTPUT_ROOT:-}"
OUTPUT_DIR_NAME="${OUTPUT_DIR_NAME:-temporal_observation}"
PYTHON_BIN="${PYTHON_BIN:-/deeplearning_team/ydong/dongying/miniconda/envs/dev/bin/python}"
TEMPORAL_SCRIPT="${TEMPORAL_SCRIPT:-${PROJECT_ROOT}/tools/temporal_analysis/evaluate_temporal_stability.py}"
TRACKING_JSON_NAME="${TRACKING_JSON_NAME:-merge.json}"
TEMPORAL_MIN_LENGTH="${TEMPORAL_MIN_LENGTH:-3}"
TEMPORAL_CLASS_ID="${TEMPORAL_CLASS_ID:-}"
TEMPORAL_TRACK_IDS="${TEMPORAL_TRACK_IDS:-20}"
TEMPORAL_FRAME_ID_START="${TEMPORAL_FRAME_ID_START:-325000}"
TEMPORAL_FRAME_ID_END="${TEMPORAL_FRAME_ID_END:-325200}"
TEMPORAL_PLOTS="${TEMPORAL_PLOTS:-0}"
TEMPORAL_EXPORT_SERIES="${TEMPORAL_EXPORT_SERIES:-1}"
TEMPORAL_FOCUS_TRACK_PLOTS="${TEMPORAL_FOCUS_TRACK_PLOTS:-1}"
TEMPORAL_PREFER_EGO="${TEMPORAL_PREFER_EGO:-1}"
TEMPORAL_X_AXIS="${TEMPORAL_X_AXIS:-frame_id}"
TEMPORAL_HEADING_SOURCE="${TEMPORAL_HEADING_SOURCE:-camera_reg}"
TARGET_PATH="/data1/dongying/Mono3d/G1Q3/dataset_for_evaluation/CNCAP/CSTA_LN_outputs/model_20260416/CSTA-LN_AEB_10_20_20260414141804"
CLI_TRACK_IDS=()
CLI_CLASS_ID=""
CLI_FRAME_ID_START=""
CLI_FRAME_ID_END=""
while (($# > 0)); do
case "$1" in
--track-id)
if (($# < 2)); then
echo "Error: --track-id requires a value" >&2
exit 1
fi
CLI_TRACK_IDS+=("$2")
shift 2
;;
--track-id=*)
CLI_TRACK_IDS+=("${1#*=}")
shift
;;
--class-id)
if (($# < 2)); then
echo "Error: --class-id requires a value" >&2
exit 1
fi
CLI_CLASS_ID="$2"
shift 2
;;
--class-id=*)
CLI_CLASS_ID="${1#*=}"
shift
;;
--frame-id-start)
if (($# < 2)); then
echo "Error: --frame-id-start requires a value" >&2
exit 1
fi
CLI_FRAME_ID_START="$2"
shift 2
;;
--frame-id-start=*)
CLI_FRAME_ID_START="${1#*=}"
shift
;;
--frame-id-end)
if (($# < 2)); then
echo "Error: --frame-id-end requires a value" >&2
exit 1
fi
CLI_FRAME_ID_END="$2"
shift 2
;;
--frame-id-end=*)
CLI_FRAME_ID_END="${1#*=}"
shift
;;
-*)
echo "Error: unsupported option: $1" >&2
exit 1
;;
*)
if [[ -n "${TARGET_PATH}" ]]; then
echo "Error: multiple target paths provided: ${TARGET_PATH} and $1" >&2
exit 1
fi
TARGET_PATH="$1"
shift
;;
esac
done
if [[ -z "${TARGET_PATH}" ]]; then
TARGET_PATH="${RESULTS_ROOT}"
fi
if [[ ! -e "${TARGET_PATH}" ]]; then
echo "Error: target path does not exist: ${TARGET_PATH}" >&2
exit 1
fi
resolve_abs_path() {
local target_path="$1"
if [[ -d "${target_path}" ]]; then
(
cd "${target_path}"
pwd -P
)
return 0
fi
local parent_dir
parent_dir=$(
cd "$(dirname "${target_path}")"
pwd -P
)
printf '%s/%s\n' "${parent_dir}" "$(basename "${target_path}")"
}
RESULTS_ROOT_ABS="$(resolve_abs_path "${RESULTS_ROOT}")"
is_case_dir() {
local dir_path="$1"
[[ -d "${dir_path}" ]] && [[ -f "${dir_path}/${TRACKING_JSON_NAME}" ]]
}
resolve_case_dir() {
local target_path="$1"
if is_case_dir "${target_path}"; then
printf '%s\n' "${target_path}"
return 0
fi
if [[ -f "${target_path}" ]] && [[ "$(basename "${target_path}")" == "${TRACKING_JSON_NAME}" ]]; then
dirname "${target_path}"
return 0
fi
return 1
}
derive_output_dir() {
local case_dir="$1"
local case_abs
local rel_case_dir
case_abs="$(resolve_abs_path "${case_dir}")"
if [[ -n "${OUTPUT_ROOT}" ]]; then
if [[ "${case_abs}" == "${RESULTS_ROOT_ABS}" ]]; then
printf '%s\n' "${OUTPUT_ROOT}"
return 0
fi
if [[ "${case_abs}" == "${RESULTS_ROOT_ABS}"/* ]]; then
rel_case_dir="${case_abs#"${RESULTS_ROOT_ABS}/"}"
printf '%s/%s\n' "${OUTPUT_ROOT%/}" "${rel_case_dir}"
return 0
fi
printf '%s/%s\n' "${OUTPUT_ROOT%/}" "$(basename "${case_abs}")"
return 0
fi
printf '%s/%s\n' "${case_abs}" "${OUTPUT_DIR_NAME}"
}
build_track_id_args() {
local -n out_ref=$1
out_ref=()
if [[ "${#CLI_TRACK_IDS[@]}" -gt 0 ]]; then
for track_id in "${CLI_TRACK_IDS[@]}"; do
out_ref+=(--track-ids "${track_id}")
done
return 0
fi
if [[ -n "${TEMPORAL_TRACK_IDS}" ]]; then
# shellcheck disable=SC2206
local track_id_arr=(${TEMPORAL_TRACK_IDS})
for track_id in "${track_id_arr[@]}"; do
out_ref+=(--track-ids "${track_id}")
done
fi
}
run_single_case() {
local case_dir="$1"
local tracking_json="${case_dir}/${TRACKING_JSON_NAME}"
local output_dir
local cmd
local track_id_args
local class_id_value=""
local frame_id_start_value=""
local frame_id_end_value=""
if [[ ! -f "${tracking_json}" ]]; then
echo "[ERROR] ${TRACKING_JSON_NAME} not found in case directory: ${case_dir}" >&2
return 1
fi
output_dir="$(derive_output_dir "${case_dir}")"
build_track_id_args track_id_args
if [[ -n "${CLI_CLASS_ID}" ]]; then
class_id_value="${CLI_CLASS_ID}"
elif [[ -n "${TEMPORAL_CLASS_ID}" ]]; then
class_id_value="${TEMPORAL_CLASS_ID}"
fi
if [[ -n "${CLI_FRAME_ID_START}" ]]; then
frame_id_start_value="${CLI_FRAME_ID_START}"
elif [[ -n "${TEMPORAL_FRAME_ID_START}" ]]; then
frame_id_start_value="${TEMPORAL_FRAME_ID_START}"
fi
if [[ -n "${CLI_FRAME_ID_END}" ]]; then
frame_id_end_value="${CLI_FRAME_ID_END}"
elif [[ -n "${TEMPORAL_FRAME_ID_END}" ]]; then
frame_id_end_value="${TEMPORAL_FRAME_ID_END}"
fi
cmd=(
"${PYTHON_BIN}" "${TEMPORAL_SCRIPT}"
--input "${tracking_json}"
--output "${output_dir}/stability_report.json"
--min-length "${TEMPORAL_MIN_LENGTH}"
--x-axis "${TEMPORAL_X_AXIS}"
--heading-source "${TEMPORAL_HEADING_SOURCE}"
)
if [[ -n "${class_id_value}" ]]; then
cmd+=(--class-id "${class_id_value}")
fi
if [[ -n "${frame_id_start_value}" ]]; then
cmd+=(--frame-id-start "${frame_id_start_value}")
fi
if [[ -n "${frame_id_end_value}" ]]; then
cmd+=(--frame-id-end "${frame_id_end_value}")
fi
if [[ "${#track_id_args[@]}" -gt 0 ]]; then
cmd+=("${track_id_args[@]}")
fi
if [[ "${TEMPORAL_PLOTS}" == "1" ]]; then
cmd+=(--plots)
fi
if [[ "${TEMPORAL_EXPORT_SERIES}" == "1" ]]; then
cmd+=(--export-series)
fi
if [[ "${TEMPORAL_FOCUS_TRACK_PLOTS}" == "1" ]]; then
cmd+=(--focus-track-plots)
fi
if [[ "${TEMPORAL_PREFER_EGO}" == "1" ]]; then
cmd+=(--prefer-ego)
else
cmd+=(--no-prefer-ego)
fi
echo ""
echo "######################################################################"
echo "# Exported video-root temporal observation"
echo "######################################################################"
echo "Case : ${case_dir}"
echo "Track : ${tracking_json}"
echo "Output : ${output_dir}"
if [[ -n "${class_id_value}" ]]; then
echo "Class : ${class_id_value}"
fi
if [[ -n "${frame_id_start_value}" || -n "${frame_id_end_value}" ]]; then
echo "Frame ID Range: [${frame_id_start_value:-"-inf"}, ${frame_id_end_value:-"+inf"}]"
fi
echo "Heading Source: ${TEMPORAL_HEADING_SOURCE}"
if [[ "${#CLI_TRACK_IDS[@]}" -gt 0 ]]; then
echo "Track IDs: ${CLI_TRACK_IDS[*]}"
elif [[ -n "${TEMPORAL_TRACK_IDS}" ]]; then
echo "Track IDs: ${TEMPORAL_TRACK_IDS}"
fi
"${cmd[@]}"
}
run_batch_root() {
local batch_root="$1"
local total_cases=0
local success_cases=0
local failed_cases=0
while IFS= read -r -d '' tracking_json; do
local case_dir
case_dir="$(dirname "${tracking_json}")"
((total_cases += 1))
if run_single_case "${case_dir}"; then
((success_cases += 1))
else
((failed_cases += 1))
printf '[FAIL] case=%s\n' "${case_dir}" >&2
fi
done < <(
find "${batch_root}" -type f -name "${TRACKING_JSON_NAME}" -print0 | sort -z
)
if [[ "${total_cases}" -eq 0 ]]; then
echo "[ERROR] No ${TRACKING_JSON_NAME} files were found under: ${batch_root}" >&2
return 1
fi
echo ""
printf '[DONE] cases=%d success=%d failed=%d\n' \
"${total_cases}" "${success_cases}" "${failed_cases}"
[[ "${failed_cases}" -eq 0 ]]
}
if RESOLVED_CASE_DIR="$(resolve_case_dir "${TARGET_PATH}")"; then
run_single_case "${RESOLVED_CASE_DIR}"
elif [[ -d "${TARGET_PATH}" ]]; then
run_batch_root "${TARGET_PATH}"
else
echo "Error: unsupported target path: ${TARGET_PATH}" >&2
exit 1
fi