P4s:模型审计 —— 移出零引用模型,修掉代码里三处悬空 best.pt
先回答"这些模型到底有没有人用",用全仓库引用扫描判定,不靠猜: 在用 yolo/detect_best_0.onnx + .engine ← paths.yolo_weights 在用 hole_insert/detect_best_1.onnx ← hole_detect.weights / workpiece_weights 零引用 detect_hc90(pt/onnx/engine) ← 只剩注释里的历史说明 零引用 detect_yolo26_gongjian.pt 零引用 detect_best(onnx/engine) ← 仅代码兜底候选,而那个候选是 .pt,不存在 所以 detect_hc90 不需要修复,是不用的东西:连同另两个一起移出仓库。 注意**二进制权重被 gitignore**,删掉就找不回来了,因此是移出到 ~/ros2-models-unused-20260923/ 而非 rm。搬回 models/ 即可被 list 重新发现。 顺手挖出并修掉三处悬空引用(和之前 site.yaml 里那个 best.pt 同一类问题): - hole_detector.weights_from_site:兜底路径写死 models/hole_insert/best.pt(不存在) - hole_detector._default_model_path:三个候选路径**全都不存在**,函数却 `return candidates[0]`,于是永远返回不存在的 best.pt;报错路径看着很合理, 极易被误判成"文件被误删"。现改为以 site.yaml 为准,再退到规范模型。 - config/hole_insert.yaml 顶部注释同样写的是 best.pt 新增 test_hole_detector.py(8 项)锁住这个回归。测试刻意**不断言文件存在** ——二进制不进 git,新克隆的仓库里 models/ 是空的——只断言解析结果指向规范模型名。 体检从 4 处问题降到 0:bash scripts/weights.sh doctor --check-engines → "没有发现问题" 测试 233 项通过;18 个包构建通过。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -109,13 +109,12 @@ paths:
|
|||||||
# 2) 这一行改成那个绝对路径(写 .onnx 即可;TensorRT 会找同名 .engine)
|
# 2) 这一行改成那个绝对路径(写 .onnx 即可;TensorRT 会找同名 .engine)
|
||||||
# 3) backend=tensorrt 时必须先导出引擎(只需做一次):
|
# 3) backend=tensorrt 时必须先导出引擎(只需做一次):
|
||||||
# bash ~/ros2/scripts/export_yolo_trt.sh /home/USER/ros2/models/yolo/detect_best_0.onnx 640
|
# bash ~/ros2/scripts/export_yolo_trt.sh /home/USER/ros2/models/yolo/detect_best_0.onnx 640
|
||||||
# 4) yolo.imgsz 必须等于 ONNX 输入边长(本文件 640;旧 hc90 才是 416)
|
# 4) yolo.imgsz 必须等于 ONNX 输入边长(当前 640)
|
||||||
# 5) 改权重/imgsz 后重启:bash ~/ros2/scripts/run_visual_servo_rt.sh [--control]
|
# 5) 改权重/imgsz 后重启:bash ~/ros2/scripts/run_visual_servo_rt.sh [--control]
|
||||||
# 当前:detect_best_0.onnx(2026-09-04 从 ~/下载 移入,640 输入)
|
# 当前:detect_best_0.onnx(2026-09-04 从 ~/下载 移入,640 输入)
|
||||||
yolo_weights: "/home/USER/ros2/models/yolo/detect_best_0.onnx"
|
yolo_weights: "/home/USER/ros2/models/yolo/detect_best_0.onnx"
|
||||||
# yolo_weights: "/home/USER/ros2/models/yolo/detect_best.onnx"
|
# 备选模型:直接换成 models/yolo/ 下的其他 .onnx / .pt 绝对路径即可。
|
||||||
# yolo_weights: "/home/USER/ros2/models/yolo/detect_hc90.pt"
|
# 换完建议确认标签没丢:bash ~/ros2/scripts/weights.sh doctor --check-engines
|
||||||
# yolo_weights: "/home/USER/ros2/models/yolo/detect_yolo26_gongjian.pt"
|
|
||||||
# 入孔 YOLO(backend=yolo 时把孔当框)。two_stage 用上面的工件权重。
|
# 入孔 YOLO(backend=yolo 时把孔当框)。two_stage 用上面的工件权重。
|
||||||
hole_weights: "/home/USER/ros2/models/hole_insert/detect_best_1.onnx"
|
hole_weights: "/home/USER/ros2/models/hole_insert/detect_best_1.onnx"
|
||||||
# 下面是缺省(未匹配到 robots[] 时)。真机以 robots[].paths 为准:89 / 91 各一份。
|
# 下面是缺省(未匹配到 robots[] 时)。真机以 robots[].paths 为准:89 / 91 各一份。
|
||||||
@@ -202,7 +201,7 @@ cameras:
|
|||||||
yolo:
|
yolo:
|
||||||
conf: 0.10 # 检测器门槛:略低于 min_conf,让运动模糊框也能进跟踪
|
conf: 0.10 # 检测器门槛:略低于 min_conf,让运动模糊框也能进跟踪
|
||||||
iou: 0.45
|
iou: 0.45
|
||||||
imgsz: 640 # detect_best.onnx 固定 640;hc90.engine 才是 416
|
imgsz: 640 # 必须等于所用 ONNX 的输入边长(当前 detect_best_0 = 640)
|
||||||
device: "0"
|
device: "0"
|
||||||
half_precision: true
|
half_precision: true
|
||||||
backend: "tensorrt" # 强制 .engine;没有则启动失败。导出:bash ~/ros2/scripts/export_yolo_trt.sh
|
backend: "tensorrt" # 强制 .engine;没有则启动失败。导出:bash ~/ros2/scripts/export_yolo_trt.sh
|
||||||
|
|||||||
+4
-2
@@ -214,8 +214,10 @@ bash ~/ros2/scripts/weights.sh doctor --check-engines
|
|||||||
bash scripts/weights.sh convert models/yolo/<名字>.onnx --name <名字> --to engine --force
|
bash scripts/weights.sh convert models/yolo/<名字>.onnx --name <名字> --to engine --force
|
||||||
```
|
```
|
||||||
|
|
||||||
> 实测本仓库里的 `detect_hc90.engine` 就是这样失效的(用旧版 TensorRT 构建,
|
> 本仓库实测过一次:`detect_hc90.engine` 用旧版 TensorRT 构建,当前的 10.13 直接
|
||||||
> 当前 10.13 无法加载)。另外两个 engine 正常。
|
> 加载不了,而 ONNX 完全正常。该模型已作为零引用模型移出仓库
|
||||||
|
> (见 `models/yolo/README.md`),但这个坑对**任何**要长期存放的 engine 都成立:
|
||||||
|
> 重装环境之后,第一件事就是 `doctor --check-engines`。
|
||||||
|
|
||||||
**「类名显示成 `class_0`」**
|
**「类名显示成 `class_0`」**
|
||||||
|
|
||||||
|
|||||||
@@ -9,22 +9,21 @@
|
|||||||
|
|
||||||
## 现状
|
## 现状
|
||||||
|
|
||||||
- `detect_best_1.onnx` —— 工件检测模型,被 `hole_detect.workpiece_weights` 使用。
|
- `detect_best_1.onnx` —— 被 `hole_detect.workpiece_weights` 使用(`two_stage` 后端)。
|
||||||
|
这是本目录唯一在用的模型。
|
||||||
|
|
||||||
## 历史遗留(已知问题)
|
## 已修掉的悬空引用
|
||||||
|
|
||||||
`config/site.yaml` 的这两处仍指向一个**不存在**的文件 `models/hole_insert/best.pt`:
|
`config/site.yaml` 的 `paths.hole_weights` 与 `hole_detect.weights` 原先都指向
|
||||||
|
**不存在**的文件 `models/hole_insert/best.pt`。`backend: two_stage` 时这两处不被读取,
|
||||||
|
所以一直没暴露;一旦切成 `backend: yolo` 就会启动失败。
|
||||||
|
|
||||||
```yaml
|
现已改为实际存在的 `detect_best_1.onnx`。同一个悬空的 `best.pt` 还藏在代码里
|
||||||
paths:
|
(`hole_detector.py` 的 `weights_from_site` / `_default_model_path`,那里三个候选
|
||||||
hole_weights: ".../models/hole_insert/best.pt" # ← 文件不存在
|
路径全都不存在,函数却总会返回第一个),也一并修成了以 site.yaml 为准、
|
||||||
hole_detect:
|
再退到实际存在的模型。
|
||||||
weights: ".../models/hole_insert/best.pt" # ← 文件不存在
|
|
||||||
```
|
|
||||||
|
|
||||||
`backend: two_stage` 时这两处不会被读,所以现在不影响运行;但一旦切成
|
改权重相关路径后,用 `bash ~/ros2/scripts/weights.sh doctor` 复查悬空引用。
|
||||||
`backend: yolo` 就会启动失败。用 `bash ~/ros2/scripts/weights.sh doctor`
|
|
||||||
能查出来。要么把真实权重按命名规则放进本目录,要么把这两处配置删掉。
|
|
||||||
|
|
||||||
## 加新模型 / 看标签
|
## 加新模型 / 看标签
|
||||||
|
|
||||||
|
|||||||
+15
-6
@@ -38,6 +38,19 @@ bash ~/ros2/scripts/weights.sh labels detect_best_0
|
|||||||
bash ~/ros2/scripts/weights.sh labels detect_best_0 --set "工件,通止规"
|
bash ~/ros2/scripts/weights.sh labels detect_best_0 --set "工件,通止规"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 工作区里有哪些模型
|
||||||
|
|
||||||
|
只保留**真正在用**的两个,避免 `weights.sh list` 被无用模型干扰、也避免误选到废模型:
|
||||||
|
|
||||||
|
| 模型 | 用途 |
|
||||||
|
|---|---|
|
||||||
|
| `yolo/detect_best_0.onnx` + `.engine` | 工件/跟踪模型,即 `config/site.yaml → paths.yolo_weights` |
|
||||||
|
| `hole_insert/detect_best_1.onnx` | 孔/工件检测,即 `hole_detect.weights` 与 `workpiece_weights` |
|
||||||
|
|
||||||
|
曾经在这里、现已移出仓库的模型(`detect_hc90`、`detect_best`、`detect_yolo26_gongjian`)
|
||||||
|
是零引用的历史遗留,二进制权重不进 git,所以是**移出到备份目录**而非直接删除;
|
||||||
|
需要时搬回本目录即可,`weights.sh list` 会自动重新发现。
|
||||||
|
|
||||||
## 排错
|
## 排错
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -46,9 +59,5 @@ bash ~/ros2/scripts/weights.sh doctor --check-engines
|
|||||||
|
|
||||||
`engine` 和 TensorRT 版本绑死:换过 TensorRT 后旧 engine 会加载失败,重导即可
|
`engine` 和 TensorRT 版本绑死:换过 TensorRT 后旧 engine 会加载失败,重导即可
|
||||||
(`convert <同名>.onnx --name <名字> --to engine --force`)。
|
(`convert <同名>.onnx --name <名字> --to engine --force`)。
|
||||||
|
**注意 `doctor` 能查出这类静默失效** —— engine 反序列化返回空时不会报错,
|
||||||
## 历史遗留
|
只会安静地不退任何检测框,很容易被当成"模型效果差"。
|
||||||
|
|
||||||
`active.pt` 是个指向 `detect_hc90.pt` 的符号链接,早期用来"切换当前模型",
|
|
||||||
现在没有任何节点会读它 —— 换模型请改 `config/site.yaml` 的 `paths.yolo_weights`。
|
|
||||||
留着只是不想动别人的文件,可以安全删除。
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
# 模型类别标签(class names)
|
|
||||||
#
|
|
||||||
# 一个模型对应一份标签,放在权重旁边、同名前缀:
|
|
||||||
# detect_best_0.engine ← 权重
|
|
||||||
# detect_best_0.labels.yaml ← 本文件
|
|
||||||
#
|
|
||||||
# 写法:names 下面一行一个类名,第 1 行对应类别 0,第 2 行对应类别 1,依次类推。
|
|
||||||
# 改完保存即生效,不需要重新转换模型、也不用重启环境(重跑节点即可)。
|
|
||||||
#
|
|
||||||
# 命令行查看/修改(推荐,不用手改本文件):
|
|
||||||
# bash ~/ros2/scripts/weights.sh labels <模型名>
|
|
||||||
# bash ~/ros2/scripts/weights.sh labels <模型名> --set "工件,通止规"
|
|
||||||
|
|
||||||
model: detect_best
|
|
||||||
names:
|
|
||||||
- workpiece
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# 模型类别标签(class names)
|
|
||||||
#
|
|
||||||
# 一个模型对应一份标签,放在权重旁边、同名前缀:
|
|
||||||
# detect_best_0.engine ← 权重
|
|
||||||
# detect_best_0.labels.yaml ← 本文件
|
|
||||||
#
|
|
||||||
# 写法:names 下面一行一个类名,第 1 行对应类别 0,第 2 行对应类别 1,依次类推。
|
|
||||||
# 改完保存即生效,不需要重新转换模型、也不用重启环境(重跑节点即可)。
|
|
||||||
#
|
|
||||||
# 命令行查看/修改(推荐,不用手改本文件):
|
|
||||||
# bash ~/ros2/scripts/weights.sh labels <模型名>
|
|
||||||
# bash ~/ros2/scripts/weights.sh labels <模型名> --set "工件,通止规"
|
|
||||||
|
|
||||||
model: detect_hc90
|
|
||||||
names:
|
|
||||||
- workpiece
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# 模型类别标签(class names)
|
|
||||||
#
|
|
||||||
# 一个模型对应一份标签,放在权重旁边、同名前缀:
|
|
||||||
# detect_best_0.engine ← 权重
|
|
||||||
# detect_best_0.labels.yaml ← 本文件
|
|
||||||
#
|
|
||||||
# 写法:names 下面一行一个类名,第 1 行对应类别 0,第 2 行对应类别 1,依次类推。
|
|
||||||
# 改完保存即生效,不需要重新转换模型、也不用重启环境(重跑节点即可)。
|
|
||||||
#
|
|
||||||
# 命令行查看/修改(推荐,不用手改本文件):
|
|
||||||
# bash ~/ros2/scripts/weights.sh labels <模型名>
|
|
||||||
# bash ~/ros2/scripts/weights.sh labels <模型名> --set "工件,通止规"
|
|
||||||
|
|
||||||
model: detect_yolo26_gongjian
|
|
||||||
names:
|
|
||||||
- gongjian
|
|
||||||
@@ -20,7 +20,7 @@ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
source "${ROOT}/scripts/lib/load_site_config.sh" >/dev/null 2>&1 || true
|
source "${ROOT}/scripts/lib/load_site_config.sh" >/dev/null 2>&1 || true
|
||||||
|
|
||||||
WEIGHTS="${1:-${SITE_YOLO_WEIGHTS:-${ROOT}/models/yolo/detect_best.onnx}}"
|
WEIGHTS="${1:-${SITE_YOLO_WEIGHTS:-${ROOT}/models/yolo/detect_best_0.onnx}}"
|
||||||
IMGSZ="${2:-${SITE_YOLO_IMGSZ:-640}}"
|
IMGSZ="${2:-${SITE_YOLO_IMGSZ:-640}}"
|
||||||
|
|
||||||
if [[ ! -f "${WEIGHTS}" ]]; then
|
if [[ ! -f "${WEIGHTS}" ]]; then
|
||||||
|
|||||||
@@ -15,7 +15,13 @@ import yaml
|
|||||||
|
|
||||||
_PKG_SHARE_FALLBACK = Path(__file__).resolve().parents[1] / "config"
|
_PKG_SHARE_FALLBACK = Path(__file__).resolve().parents[1] / "config"
|
||||||
DEFAULT_CONFIG = _PKG_SHARE_FALLBACK / "hole_insert.yaml"
|
DEFAULT_CONFIG = _PKG_SHARE_FALLBACK / "hole_insert.yaml"
|
||||||
DEFAULT_MODEL_DIR = Path.home() / "ros2" / "models" / "hole_insert"
|
|
||||||
|
# 仓库里**实际存在**的孔/工件检测模型,相对仓库根。
|
||||||
|
# 以前这个位置上写的是 ``models/hole_insert/best.pt`` —— 文件根本不存在,属于悬空引用:
|
||||||
|
# 配置齐全时永远走不到这条分支,一旦 site.yaml 缺键就报"模型文件不存在",
|
||||||
|
# 而打印出来的路径看着特别合理,很容易被误判成"文件被人误删了"。
|
||||||
|
# 改动这个常量时,顺手跑 ``bash scripts/weights.sh doctor`` 确认没有悬空引用。
|
||||||
|
_CANONICAL_HOLE_MODEL = "models/hole_insert/detect_best_1.onnx"
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -91,20 +97,29 @@ def weights_from_site(data: dict[str, Any] | None = None) -> str:
|
|||||||
return str(
|
return str(
|
||||||
hd.get("weights")
|
hd.get("weights")
|
||||||
or paths.get("hole_weights")
|
or paths.get("hole_weights")
|
||||||
or str(ros2_root() / "models" / "hole_insert" / "best.pt")
|
or str(ros2_root() / _CANONICAL_HOLE_MODEL)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _default_model_path() -> Path:
|
def _default_model_path() -> Path:
|
||||||
candidates = [
|
"""未显式给 ``model_path`` 时的兜底模型路径。
|
||||||
DEFAULT_MODEL_DIR / "best.pt",
|
|
||||||
DEFAULT_MODEL_DIR / "hole_best.pt",
|
以前这里枚举了 ``hole_insert/best.pt`` / ``hole_best.pt`` / ``yolo/detect_best.pt``,
|
||||||
Path.home() / "ros2" / "models" / "yolo" / "detect_best.pt",
|
三个文件在本仓库里**都不存在**,函数却会 ``return candidates[0]`` ——
|
||||||
]
|
于是永远返回一个不存在的路径(同 ``weights_from_site`` 里那个悬空的 best.pt)。
|
||||||
for p in candidates:
|
|
||||||
if p.exists():
|
现在以 site.yaml 为准(它才是真正的来源),它给的路径存在就用它;
|
||||||
|
否则退到仓库里实际存在的规范模型。这样报错信息里的路径至少是对的。
|
||||||
|
"""
|
||||||
|
configured = weights_from_site()
|
||||||
|
if configured:
|
||||||
|
p = Path(configured).expanduser()
|
||||||
|
if p.is_file():
|
||||||
return p
|
return p
|
||||||
return candidates[0]
|
|
||||||
|
from arm_application.site_io import ros2_root
|
||||||
|
|
||||||
|
return ros2_root() / _CANONICAL_HOLE_MODEL
|
||||||
|
|
||||||
|
|
||||||
class HoleDetector:
|
class HoleDetector:
|
||||||
|
|||||||
@@ -15,7 +15,10 @@
|
|||||||
所以 engine 构建完就只剩张量,标签无从附着。实测:
|
所以 engine 构建完就只剩张量,标签无从附着。实测:
|
||||||
|
|
||||||
detect_best_0.engine 二进制里搜不到 "workpiece" → 标签已丢
|
detect_best_0.engine 二进制里搜不到 "workpiece" → 标签已丢
|
||||||
detect_hc90.engine 能搜到 "workpiece" → 旧版 TRT 建的,且已无法加载
|
detect_hc90.engine 能搜到 "workpiece" → 旧版 TRT 建的,但当前环境已无法加载
|
||||||
|
|
||||||
|
(`detect_hc90` 已作为零引用模型移出仓库,这里保留这行是因为它同时印证了两件事:
|
||||||
|
旧版 TRT 建的 engine 里其实是有标签的,以及 engine 与 TRT 版本绑死。)
|
||||||
|
|
||||||
后果很隐蔽:`yolo_detector` 读不到名字时会退化成 `str(cid)`,也就是类名变成字符串
|
后果很隐蔽:`yolo_detector` 读不到名字时会退化成 `str(cid)`,也就是类名变成字符串
|
||||||
`"0"`;而预览界面又不绘制类名,所以**没有任何地方看得出标签丢了**。
|
`"0"`;而预览界面又不绘制类名,所以**没有任何地方看得出标签丢了**。
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# 孔定位检测配置(改 conf / 内参 / 双孔间距即可,不必改代码)
|
# 孔定位检测配置(改 conf / 内参 / 双孔间距即可,不必改代码)
|
||||||
# 权重默认:~/ros2/models/hole_insert/best.pt
|
# 权重来源:优先 site.yaml(hole_detect.weights / paths.hole_weights);
|
||||||
|
# 两者都缺时兜底到 models/hole_insert/detect_best_1.onnx。
|
||||||
|
# 原先这里注释写的是 best.pt —— 该文件不存在,已修正。
|
||||||
# backend: yolo | hough | two_stage(two_stage 请用 hole_detect.yaml)
|
# backend: yolo | hough | two_stage(two_stage 请用 hole_detect.yaml)
|
||||||
|
|
||||||
model_path: ""
|
model_path: ""
|
||||||
|
|||||||
@@ -0,0 +1,86 @@
|
|||||||
|
"""`hole_detector` 权重路径解析的回归测试。
|
||||||
|
|
||||||
|
重点是挡住一类**悬空引用**:代码里写死的默认权重路径指向一个根本不存在的文件。
|
||||||
|
这种 bug 特别难查,因为
|
||||||
|
|
||||||
|
* 配置齐全时永远走不到那条分支,日常运行完全正常;
|
||||||
|
* 一旦 site.yaml 缺键才会触发,而报错信息里打印的路径看起来非常合理
|
||||||
|
(`.../models/hole_insert/best.pt`),很容易被误判成"文件被人误删了"。
|
||||||
|
|
||||||
|
这里**不断言文件存在** —— 二进制权重不进 git,新克隆的仓库里 `models/` 是空的。
|
||||||
|
只断言"解析结果指向规范模型名",这样在任何环境下都成立。
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from arm_application.hole_detector import _default_model_path, weights_from_site
|
||||||
|
|
||||||
|
CANONICAL = "detect_best_1.onnx"
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# weights_from_site:site.yaml 缺键时的兜底
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def test_weights_from_site_prefers_explicit_config():
|
||||||
|
data = {
|
||||||
|
"hole_detect": {"backend": "yolo", "weights": "/custom/my_holes.onnx"},
|
||||||
|
"paths": {"hole_weights": "/custom/ignored.onnx"},
|
||||||
|
}
|
||||||
|
assert weights_from_site(data) == "/custom/my_holes.onnx"
|
||||||
|
|
||||||
|
|
||||||
|
def test_weights_from_site_falls_back_to_paths():
|
||||||
|
data = {
|
||||||
|
"hole_detect": {"backend": "yolo"},
|
||||||
|
"paths": {"hole_weights": "/custom/from_paths.onnx"},
|
||||||
|
}
|
||||||
|
assert weights_from_site(data) == "/custom/from_paths.onnx"
|
||||||
|
|
||||||
|
|
||||||
|
def test_weights_from_site_yolo_fallback_is_not_dangling():
|
||||||
|
"""回归:以前这里兜底到不存在 best.pt,现在必须指向规范模型。"""
|
||||||
|
out = weights_from_site({"hole_detect": {"backend": "yolo"}})
|
||||||
|
assert out.endswith(CANONICAL)
|
||||||
|
assert "best.pt" not in out
|
||||||
|
|
||||||
|
|
||||||
|
def test_weights_from_site_two_stage_uses_workpiece_weights():
|
||||||
|
data = {
|
||||||
|
"hole_detect": {"backend": "two_stage", "workpiece_weights": "/w/wp.onnx"},
|
||||||
|
"paths": {"hole_weights": "/should/not/be/used.onnx"},
|
||||||
|
}
|
||||||
|
assert weights_from_site(data) == "/w/wp.onnx"
|
||||||
|
|
||||||
|
|
||||||
|
def test_weights_from_site_two_stage_falls_back_to_yolo_weights():
|
||||||
|
data = {
|
||||||
|
"hole_detect": {"backend": "two_stage"},
|
||||||
|
"paths": {"yolo_weights": "/w/track.onnx"},
|
||||||
|
}
|
||||||
|
assert weights_from_site(data) == "/w/track.onnx"
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# _default_model_path:没有任何配置时的兜底
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_model_path_is_not_the_dangling_best_pt():
|
||||||
|
"""回归:以前枚举的三个候选全不存在,函数却 `return candidates[0]`。
|
||||||
|
|
||||||
|
于是它永远返回一个不存在的 `hole_insert/best.pt`,而调用方拿到之后
|
||||||
|
只会在真正加载模型时才炸,报错路径还很有迷惑性。
|
||||||
|
"""
|
||||||
|
p = _default_model_path()
|
||||||
|
assert p.name not in ("best.pt", "hole_best.pt"), f"又指回悬空文件了: {p}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_model_path_is_canonical_name():
|
||||||
|
assert _default_model_path().name == CANONICAL
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_model_path_is_absolute():
|
||||||
|
"""必须是绝对路径:相对路径会随 CWD 漂移,节点从不同目录启动就找不到。"""
|
||||||
|
assert _default_model_path().is_absolute()
|
||||||
Reference in New Issue
Block a user