验收1
This commit is contained in:
@@ -11,6 +11,8 @@ from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
import numpy as np
|
||||
|
||||
from app.logging_config import format_json_pretty
|
||||
from app.settings import Settings
|
||||
from app.state import MeasureSnapshot
|
||||
@@ -187,12 +189,15 @@ def _safe_media_prefix(stem: str) -> str:
|
||||
|
||||
|
||||
def _result_from_weight_prediction(data: Dict[str, Any]) -> List[Dict[str, Any]]:
|
||||
"""按 track_id 聚合:体重取 max(predicted_weight_g),体长取达到 max 的那条 PLY 的 length_input (mm)。"""
|
||||
"""按 track_id 聚合:对每个 track_id 的点云,取 predicted_weight_g 最大的 top5 平均值作为体重,
|
||||
体长取这 top5 点云的平均 length_input (mm)。只使用通过点云分类器的好点云(used_for_prediction=True)。"""
|
||||
items = data.get("per_cloud") or data.get("per_file") or []
|
||||
if not isinstance(items, list):
|
||||
return []
|
||||
# tid -> (max_weight_g, length_mm at max weight)
|
||||
best: Dict[int, Tuple[float, float]] = {}
|
||||
|
||||
# tid -> list of (weight_g, length_mm) for this track
|
||||
track_predictions: Dict[int, List[Tuple[float, float]]] = {}
|
||||
|
||||
for it in items:
|
||||
if not isinstance(it, dict):
|
||||
continue
|
||||
@@ -202,24 +207,55 @@ def _result_from_weight_prediction(data: Dict[str, Any]) -> List[Dict[str, Any]]
|
||||
tid = _parse_tid_from_ply_name(Path(str(ply)).name)
|
||||
if tid is None:
|
||||
continue
|
||||
|
||||
# 只使用通过点云分类器的好点云
|
||||
if not it.get("used_for_prediction", True):
|
||||
continue
|
||||
|
||||
try:
|
||||
wg = float(it.get("predicted_weight_g", float("nan")))
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
if not math.isfinite(wg):
|
||||
continue
|
||||
|
||||
try:
|
||||
ln = float(it.get("length_input", float("nan")))
|
||||
except (TypeError, ValueError):
|
||||
ln = float("nan")
|
||||
if tid not in best or wg > best[tid][0]:
|
||||
best[tid] = (wg, ln)
|
||||
|
||||
if tid not in track_predictions:
|
||||
track_predictions[tid] = []
|
||||
track_predictions[tid].append((wg, ln))
|
||||
|
||||
out: List[Dict[str, Any]] = []
|
||||
for tid in sorted(best.keys()):
|
||||
wg, ln = best[tid]
|
||||
if not math.isfinite(ln):
|
||||
TOP_K = 5
|
||||
|
||||
for tid in sorted(track_predictions.keys()):
|
||||
predictions = track_predictions[tid]
|
||||
if not predictions:
|
||||
continue
|
||||
out.append({"id": tid, "weight": wg, "length": ln})
|
||||
|
||||
# 按重量降序排序,取 top5
|
||||
predictions_sorted = sorted(predictions, key=lambda x: x[0], reverse=True)
|
||||
top5 = predictions_sorted[:min(TOP_K, len(predictions_sorted))]
|
||||
|
||||
# 计算 top5 平均重量和平均长度
|
||||
avg_weight = float(np.mean([p[0] for p in top5]))
|
||||
valid_lengths = [p[1] for p in top5 if math.isfinite(p[1])]
|
||||
avg_length = float(np.mean(valid_lengths)) if valid_lengths else float("nan")
|
||||
|
||||
if not math.isfinite(avg_length):
|
||||
continue
|
||||
|
||||
out.append({
|
||||
"id": tid,
|
||||
"type": "大黄鱼",
|
||||
"weight": str(round(avg_weight)),
|
||||
"length": str(round(avg_length)),
|
||||
"date": datetime.now(timezone.utc).strftime("%Y-%m-%d"),
|
||||
})
|
||||
|
||||
return out
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user