class DetectionResult { final String label; final double score; final double left; final double top; final double right; final double bottom; /// 轨迹已确认(多帧稳定/高分/活动确认),false = 候选,渲染为虚线 final bool confirmed; /// 类别索引:单物种模型 0 = 目标物种、1 = suspect;综合模型 0..N-1 = 各物种、 /// 末位 = suspect。仅作展示索引,类别语义看 label 文本(2026-09-09 综合模型) final int classId; /// 产出该框的模型(数据集 id 与名称;无来源为 -1/空) final int modelId; final String modelName; const DetectionResult({ required this.label, required this.score, required this.left, required this.top, required this.right, required this.bottom, this.confirmed = true, this.classId = -1, this.modelId = -1, this.modelName = '', }); double get width => right - left; double get height => bottom - top; double get centerX => (left + right) / 2; double get centerY => (top + bottom) / 2; /// 疑似(生境预警)类别:训练标签为 suspect。单物种模型 suspect 在索引 1, /// 综合模型在末位——统一按标签名判定,不能按 classId>0(综合模型其他物种 /// 索引也 >0,2026-09-09) bool get isSuspect => label == 'suspect'; DetectionResult copyWith({ double? score, double? left, double? top, double? right, double? bottom, bool? confirmed, }) => DetectionResult( label: label, score: score ?? this.score, left: left ?? this.left, top: top ?? this.top, right: right ?? this.right, bottom: bottom ?? this.bottom, confirmed: confirmed ?? this.confirmed, classId: classId, modelId: modelId, modelName: modelName, ); } class MotionRegion { final double left; final double top; final double right; final double bottom; const MotionRegion(this.left, this.top, this.right, this.bottom); double get centerX => (left + right) / 2; double get centerY => (top + bottom) / 2; }