feat: initialize managed portal
This commit is contained in:
136
managed/people_flow_project/main.py
Normal file
136
managed/people_flow_project/main.py
Normal file
@@ -0,0 +1,136 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def build_parser() -> argparse.ArgumentParser:
|
||||
parser = argparse.ArgumentParser(
|
||||
description="People-flow counting with YOLO tracking and DeepFace demographics."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--config",
|
||||
default="configs/default_config.yaml",
|
||||
help="Path to the YAML config file.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output-dir",
|
||||
default=None,
|
||||
help="Directory for generated artifacts.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--line",
|
||||
help="Override counting line as x1,y1,x2,y2.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--line-mode",
|
||||
choices=["normalized", "pixel"],
|
||||
help="Coordinate mode for --line.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--device",
|
||||
help="Override inference device, for example cuda:0 or cpu.",
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(dest="command", required=True)
|
||||
|
||||
video_parser = subparsers.add_parser("video", help="Process one video.")
|
||||
video_parser.add_argument("--input", required=True, help="Path to the video file.")
|
||||
video_parser.add_argument(
|
||||
"--skip-video-save",
|
||||
action="store_true",
|
||||
help="Do not write the annotated video.",
|
||||
)
|
||||
|
||||
batch_parser = subparsers.add_parser("batch", help="Process a directory of videos.")
|
||||
batch_parser.add_argument(
|
||||
"--input-dir",
|
||||
required=True,
|
||||
help="Directory scanned recursively for videos.",
|
||||
)
|
||||
batch_parser.add_argument(
|
||||
"--pattern",
|
||||
default="*.mp4",
|
||||
help="Glob pattern used during recursive discovery.",
|
||||
)
|
||||
batch_parser.add_argument(
|
||||
"--skip-video-save",
|
||||
action="store_true",
|
||||
help="Do not write annotated videos.",
|
||||
)
|
||||
|
||||
rtsp_parser = subparsers.add_parser("rtsp", help="Process a live RTSP stream.")
|
||||
rtsp_parser.add_argument("--input", help="RTSP URL.")
|
||||
|
||||
manage_api_parser = subparsers.add_parser("manage-api", help="Start the management API.")
|
||||
manage_api_parser.add_argument("--host", default="0.0.0.0", help="Host for the management API.")
|
||||
manage_api_parser.add_argument("--port", type=int, default=18082, help="Port for the management API.")
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def build_config(args: argparse.Namespace):
|
||||
from src.people_flow.config import load_config, merge_cli_overrides
|
||||
|
||||
save_video = None
|
||||
if hasattr(args, "skip_video_save"):
|
||||
save_video = not args.skip_video_save
|
||||
|
||||
config = load_config(Path(args.config))
|
||||
return merge_cli_overrides(
|
||||
config=config,
|
||||
line=args.line,
|
||||
line_mode=args.line_mode,
|
||||
device=args.device,
|
||||
save_video=save_video,
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = build_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == "manage-api":
|
||||
from src.people_flow.manage_api import run_manage_api
|
||||
|
||||
run_manage_api(args.config, host=args.host, port=args.port)
|
||||
return 0
|
||||
|
||||
config = build_config(args)
|
||||
from src.people_flow.pipeline import PeopleFlowPipeline, discover_videos
|
||||
|
||||
output_root = Path(args.output_dir or config.runtime.output_dir)
|
||||
pipeline = PeopleFlowPipeline(config=config, output_root=output_root)
|
||||
|
||||
if args.command == "rtsp":
|
||||
paths = pipeline.get_rtsp_output_paths()
|
||||
print(f"rtsp_output_dir={paths['root']}", flush=True)
|
||||
print(f"latest_json={paths['latest_json']}", flush=True)
|
||||
source = args.input or config.runtime.rtsp_url
|
||||
if not source:
|
||||
raise SystemExit("RTSP source is required. Pass --input or set runtime.rtsp_url in the config.")
|
||||
pipeline.process_rtsp(source)
|
||||
return 0
|
||||
|
||||
if args.command == "video":
|
||||
result = pipeline.process_video(Path(args.input))
|
||||
print(f"processed_video={result['video_name']}")
|
||||
print(f"total_people={result['total_people']}")
|
||||
print(f"unknown_attributes={result['unknown_attributes']}")
|
||||
print(f"json={result['json_path']}")
|
||||
if result.get("video_output_path"):
|
||||
print(f"annotated_video={result['video_output_path']}")
|
||||
return 0
|
||||
|
||||
videos = discover_videos(Path(args.input_dir), pattern=args.pattern)
|
||||
if not videos:
|
||||
raise SystemExit(f"No videos found under {args.input_dir} with pattern {args.pattern}")
|
||||
|
||||
summary = pipeline.process_batch(videos)
|
||||
print(f"videos_processed={len(summary['videos'])}")
|
||||
print(f"csv={summary['csv_path']}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user