From 30ff5b830e61bbd688464e34a72817c33468c59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=96=8C?= <259278618@qq.com> Date: Fri, 4 Sep 2026 16:59:21 +0800 Subject: [PATCH] 1 --- server/README.md | 4 +- server/biz/consts/consts.go | 8 +++ server/biz/service/label_task.go | 101 ++++++++++++++++++++++++++++++- server/common/localai.go | 101 +++++++++++++++++++++++++++++-- server/config.yml | 4 ++ server/data/observer.db | Bin 1097728 -> 1097728 bytes server/技术设计.md | 1 + 7 files changed, 208 insertions(+), 11 deletions(-) diff --git a/server/README.md b/server/README.md index 9f37d17..593e140 100644 --- a/server/README.md +++ b/server/README.md @@ -14,11 +14,11 @@ | 套餐 | `config.yml` `plans` 节点配置三档套餐(改价 = 改配置重启),价格**整数分**(1000 / 5600 / 18000) | | 后台管理端 | `server_admin/`(Vue3 + Element Plus)管理页面:订单查询、账号/授权管理(手动授权/撤销)、App 版本管理;构建产物由后端 `/admin/` 托管,登录页输入 token 后以 `X-Admin-Token` 头鉴权(`config.yml admin.token`) | | 版本管理 | 后台管理端上传 Android APK + 更新说明,APK 存服务器 `app.apkDir`(默认 `./workspace/`,与 `./data` 平级、挂载持久化)**固定文件名 `observer-latest.apk`,上传即覆盖,目录永远只保留最新一个文件**;**版本号从文件名识别**:文件须命名为 `observer-x.y.z.apk`(Flutter 打包产物即此命名,版本号取自 pubspec);客户端启动时 `GET /api/v1/app/update` 检查更新:服务器版本高于本地版本即弹更新提示(不可跳过)。**仅 Android 检查,iOS 不做版本下发**(iOS 走 App Store 自行更新)。版本记录可删除:删最新版本联动删除 APK 文件,删历史版本仅删记录 | -| 数据训练(唯一入口) | 后台管理端「数据训练」一个菜单承载数据集全流程:**数据集卡片列表**(封面图/描述/图片数/已标注数/**训练状态徽标**),**卡片下方直接展示训练任务进度条与状态**(无独立训练页);详情页为**图片与标注一体视图**:分页(每页 20 条)逐行「原图 ‖ 标注图」对照展示;**图片入库(手动上传/AI 生成)自动触发 RF-DETR 全图扫描标注**,进度条展示在页顶;页顶另有「全量标注」按钮可手动重标全部图片(覆盖各图已有标注);点击原图/标注图弹窗放大,弹窗为**审核视图(不做手动画框)**:点击框选中,列表可确认疑似框/删除误检框/清空并保存——AI 自动标注结果直接作为标注,人工仅审核确认;封面(上传/生成统一 1248x704 转 jpg + UUID 命名)/**描述**/AI 生成图片(provider 抽象:dashscope 通义万相付费 API / localai 训练机 local-ai qwen-image,`config.yml imageGen` 节点切换,见配置说明);AI 标注端点与训练机 SSH 为**全局配置,直接读 `config.yml`**(`localAi` / `training.ssh` 节点,改配置需重启服务);图片落服务器 `app.datasetDir`/`datasets/<数据集名>/`,DB 存元数据 + 标注 JSON;**数据清洗(2026-09-02)**:详情页「数据清洗」——按标注目标尺寸细档统计超配,超配桶内整图 dHash 多样性保留、其余进候选清单,执行=打「已排除训练集」标记(可恢复不删图),prepare_yolo 打包跳过 | +| 数据训练(唯一入口) | 后台管理端「数据训练」一个菜单承载数据集全流程:**数据集卡片列表**(封面图/描述/图片数/已标注数/**训练状态徽标**),**卡片下方直接展示训练任务进度条与状态**(无独立训练页);详情页为**图片与标注一体视图**:分页(每页 20 条)逐行「原图 ‖ 标注图」对照展示;**图片入库(手动上传/AI 生成)自动触发 RF-DETR 四级漏斗标注(全图扫描→空检切片扫描→VLM 提议候选区精修,见技术设计.md「预标注四级漏斗」)**,进度条展示在页顶;页顶另有「全量标注」按钮可手动重标全部图片(覆盖各图已有标注);点击原图/标注图弹窗放大,弹窗为**审核视图(不做手动画框)**:点击框选中,列表可确认疑似框/删除误检框/清空并保存——AI 自动标注结果直接作为标注,人工仅审核确认;封面(上传/生成统一 1248x704 转 jpg + UUID 命名)/**描述**/AI 生成图片(provider 抽象:dashscope 通义万相付费 API / localai 训练机 local-ai qwen-image,`config.yml imageGen` 节点切换,见配置说明);AI 标注端点与训练机 SSH 为**全局配置,直接读 `config.yml`**(`localAi` / `training.ssh` 节点,改配置需重启服务);图片落服务器 `app.datasetDir`/`datasets/<数据集名>/`,DB 存元数据 + 标注 JSON;**数据清洗(2026-09-02)**:详情页「数据清洗」——按标注目标尺寸细档统计超配,超配桶内整图 dHash 多样性保留、其余进候选清单,执行=打「已排除训练集」标记(可恢复不删图),prepare_yolo 打包跳过 | | 模型训练 | 从数据集卡片「开始训练」一键触发(参数 imgsz/epochs/batch/device 默认走 `config.yml` `training` 节点,部署级配置);**双档位(2026-09-03)**:一次发起按档位各建一条任务——高识别档 s(基座 `training.model`、imgsz `training.imgsz`=1280)/ 高性能档 n(基座 `training.modelN`=yolov8n.pt、imgsz `training.imgszN`=704),请求传 `variants:["s","n"]` 限定(省略=双档;n 档配置缺失时请求报错),epochs/batch/device 双档共用,任务带 `variant` 快照;**GPU 独占排队(2026-09-03)**:并发度 1 不变——已有 running 时新任务落 `queued` 排队(不再拒绝),10s 轮询在 running 结束后自动按创建顺序晋级启动、一次一个(训练机单 GPU 串行跑多档/多数据集),取消 running=杀进程、queued=直接置失败;进度/日志/指标监控(每 epoch 粒度);训练通道 `training` 节点可配置 subprocess(与 Go 服务同机直接起 python)/ ssh(异机执行,SSH 凭据取 `config.yml` `training.ssh` 节点);训练脚本 `server/training/train_server.py`(随项目迁移,2026-08-26)参数化(task.json 传 model/imgsz),产物(best.tflite/best.pt/曲线)拉回服务器;训练收尾自动做 **tflite 产物自检**(输入/输出 shape 校验,原 `inspect_tflite.py` 逻辑内嵌脚本),自检失败任务置失败并带出原因;`dump_graph.py` 留作训练机人工深度调试 | | 模型版本与热更新 | **每数据集每档位一个模型**(2026-09-03 双档位):训练成功后一键「发布」(训练任务操作列)——tflite 已由训练成功直写最终位置:s 档 `workspace/trainings/<文件名前缀>.tflite`、n 档 `<文件名前缀>_n.tflite`(前缀空回退数据集名),发布仅落 `model_version` 记录(sha256/大小/指标/类别名,带 `variant` 档位列);版本序列每数据集全局共用 m1.0.0 递增(s/n 交替发布走同一序列,无档位独立序列),`is_latest` 按 (数据集, 档位) 各记一条——发布只清同档位旧记录,s/n 两档互不影响,目录可分别发布、分别下发。管理端**无模型管理界面**(版本记录仅支撑客户端下发)。**App 模型热更新**:`GET /api/v1/app/update` 扩展返回 `models` 目录数组,客户端独立检查,新模型下载校验替换,失败回退旧模型——模型迭代不再重打包 APK | | 模型目录与多模型推理 | `GET /api/v1/models`(登录态)返回全部数据集当前生效模型(数据集/档位 `variant` s|n/版本/类别/大小/sha256/下载地址;**每数据集最多 2 条 = s/n 两档各自的 is_latest**),下载 URL s 档 `/download/trainings/<文件名前缀>.tflite`、n 档 `/download/trainings/<文件名前缀>_n.tflite`(前缀空回退数据集名);**App 模型管理页**用户自由下载/删除/启用模型,识别时**按当前识别档位(s 高识别 / n 高性能,全局切换)加载该档位已启用模型**并行推理 + 跨模型 NMS 合并(按类别名),内置 assets 模型兜底 | -| 标注 | **图片入库自动触发**:手动上传/AI 生成成功后,新增图自动调 `config.yml` `localAi` 节点配置的 AI 端点做 RF-DETR 全图扫描(`label_task` 记录进度,页顶进度条展示;**localAi 未配置 → 上传/生成接口直接报错;已有标注任务在跑(忙)→ 不报错**,当前任务成功完成后自动补标未标注图)→ 扫描结果(**重叠去重**:NMS 风格按置信度降序保留,重叠比 > `localAi.overlapThreshold` 默认 0.3 的框剔除——重叠比 = 交叠面积/两框较小面积,RF-DETR 同目标常输出一大一小两框,此判据能命中,同目标只留置信度最高者)**直接写 `dataset_image.labels_json`**(覆盖该图已有标注,即重标语义);点击弹窗放大进入**审核视图(不做手动画框)**:点击框选中,列表确认疑似框/删除误检框/清空 → 保存即整体覆写 `dataset_image.labels_json`(YOLO 归一化 JSON 数组,AI 标注直写、人工仅审核确认);`POST /admin/label-tasks` 详情页「全量标注」按钮入口(另有自动触发),可发起全量/指定图重标;自动/手动/混合并存,训练前自动整理(prepare_yolo 逻辑在服务端) | +| 标注 | **图片入库自动触发**:手动上传/AI 生成成功后,新增图自动调 `config.yml` `localAi` 节点配置的 AI 端点做 RF-DETR 检测(**四级漏斗(2026-09-04)**:全图扫描→空检自动升级切片扫描→仍空 VLM 提议候选区+RF-DETR 精修→全空写空标注等人工,切片块长边/重叠/切片阈值走 `localAi.tileSize`/`tileOverlap`/`tileThreshold`,见技术设计.md「预标注四级漏斗」;`label_task` 记录进度,页顶进度条展示;**localAi 未配置 → 上传/生成接口直接报错;已有标注任务在跑(忙)→ 不报错**,当前任务成功完成后自动补标未标注图)→ 扫描结果(**重叠去重**:NMS 风格按置信度降序保留,重叠比 > `localAi.overlapThreshold` 默认 0.3 的框剔除——重叠比 = 交叠面积/两框较小面积,RF-DETR 同目标常输出一大一小两框,此判据能命中,同目标只留置信度最高者)**直接写 `dataset_image.labels_json`**(覆盖该图已有标注,即重标语义);点击弹窗放大进入**审核视图(不做手动画框)**:点击框选中,列表确认疑似框/删除误检框/清空 → 保存即整体覆写 `dataset_image.labels_json`(YOLO 归一化 JSON 数组,AI 标注直写、人工仅审核确认);`POST /admin/label-tasks` 详情页「全量标注」按钮入口(另有自动触发),可发起全量/指定图重标;自动/手动/混合并存,训练前自动整理(prepare_yolo 逻辑在服务端) | ## 架构与数据流 diff --git a/server/biz/consts/consts.go b/server/biz/consts/consts.go index 2efc18e..91b4e17 100644 --- a/server/biz/consts/consts.go +++ b/server/biz/consts/consts.go @@ -67,6 +67,14 @@ const ( // (与 VlmMaxSuspectPerImage 同量级,单图人工复核工作量可控) MaxPrelabelPerImage = 3 + // 预标注四级漏斗(技术设计.md「预标注四级漏斗」): + // 单图漏斗总超时秒数——L2 切片 ~20 块串行 + L3 VLM 兜底,原 120s 只够单次全图检测 + LabelImageTimeoutSec = 300 + // L3 VLM 提议候选区数上限(图全空时让 VLM 指可疑位置,RF-DETR 精修确认,宁可指错不可遗漏) + VlmLocateMaxRegions = 3 + // L3 候选区扩大倍数(VLM 坐标偏粗,扩大裁剪给 RF-DETR 足够上下文,钳制图片边界) + VlmRegionExpand = 2.0 + // 模型版本号前缀(m1.0.0),同数据集内递增 ModelVersionPrefix = "m" diff --git a/server/biz/service/label_task.go b/server/biz/service/label_task.go index c58dcdd..3f4ab03 100644 --- a/server/biz/service/label_task.go +++ b/server/biz/service/label_task.go @@ -216,8 +216,8 @@ func (s *labelTaskService) runDetection(ctx context.Context, taskId int64, datas doneCount := 0 for i, img := range images { g.Log().Infof(bgCtx, "预标 %s (%d/%d): %s", dataset.Name, i+1, len(images), img.Filename) - // 单张 120s 超时兜底(无超时 + 无取消的独立 ctx 下防检测服务悬挂拖死任务) - detCtx, cancel := context.WithTimeout(bgCtx, 120*time.Second) + // 单图漏斗总超时兜底(L2 切片 + L3 VLM 兜底耗时;无超时 + 无取消的独立 ctx 下防检测服务悬挂拖死任务) + detCtx, cancel := context.WithTimeout(bgCtx, consts.LabelImageTimeoutSec*time.Second) err := common.LabelTaskPoolInstance().Submit(detCtx, func(ctx context.Context) error { data, err := os.ReadFile(filepath.Join(dir, img.Filename)) if err != nil { @@ -228,7 +228,7 @@ func (s *labelTaskService) runDetection(ctx context.Context, taskId int64, datas return gerror.New("无法识别图片尺寸") } mime := imageMime(img.Filename) - detections, err := client.Detect(ctx, data, mime, w, h) + detections, err := s.detectFunnel(ctx, client, data, mime, w, h, dataset) if err != nil { return err } @@ -296,6 +296,101 @@ func (s *labelTaskService) runDetection(ctx context.Context, taskId int64, datas }() } +// detectFunnel 预标注四级漏斗(技术设计.md「预标注四级漏斗」):检测只信 RF-DETR,VLM 永不直接出框。 +// ①全图扫描(threshold)有候选即收(绝大多数图到此命中)→ ②空检则滑窗切片低阈值(tileThreshold)扫描 → +// ③仍空则 VLM 提议候选区逐区裁剪精修 → ④全空返回空(上游写 '[]' 语义不变:等人工画框、不入自动补标池)。 +func (s *labelTaskService) detectFunnel(ctx context.Context, client *common.LocalAi, data []byte, mime string, imgW, imgH int, dataset *entity.Dataset) ([]*common.Detection, error) { + detections, err := client.Detect(ctx, data, mime, imgW, imgH) + if err != nil || len(detections) > 0 { + return detections, err + } + g.Log().Infof(ctx, "全图空检,升级切片扫描: %s", dataset.Name) + detections, err = s.detectTiles(ctx, client, data, mime, imgW, imgH) + if err != nil || len(detections) > 0 { + return detections, err + } + species := dataset.GenSpecies + if species == "" { + species = dataset.Name // 单物种规则:物种 = 数据集名 + } + return s.detectVlmHints(ctx, client, data, mime, imgW, imgH, species), nil +} + +// detectTiles 四级漏斗 L2:滑窗切块逐块 DetectRegion(tileThreshold——小目标置信度天然偏低, +// 低于全图丢弃线的候选仍入库落疑似 class 1,宁多勿漏),块内坐标已在 DetectRegion 内映射回 +// 原图像素,跨块重复检出由上游 minIoU 去重兜住;单图池任务内串行执行,不嵌套协程池。 +func (s *labelTaskService) detectTiles(ctx context.Context, client *common.LocalAi, data []byte, mime string, imgW, imgH int) ([]*common.Detection, error) { + tiles := common.TileRegions(imgW, imgH, client.TileSize, client.TileOverlap) + all := make([]*common.Detection, 0, len(tiles)) + for _, t := range tiles { + ds, err := client.DetectRegion(ctx, data, mime, imgW, imgH, t.X, t.Y, t.W, t.H, client.TileThreshold) + if err != nil { + return nil, gerror.Wrapf(err, "切片检测失败(%d,%d,%dx%d)", t.X, t.Y, t.W, t.H) + } + all = append(all, ds...) + } + return all, nil +} + +// detectVlmHints 四级漏斗 L3:VLM 提议候选区(只提议位置,永不直接出框)。提示词按 +// 「宁可指错不可遗漏」输出 ≤ consts.VlmLocateMaxRegions 个归一化候选区,逐区扩大 +// consts.VlmRegionExpand 倍(VLM 坐标偏粗,扩大给 RF-DETR 足够上下文,钳制图片边界)后 +// DetectRegion 低阈值精修,精修命中的框才采纳(VLM 误报被 RF-DETR 否掉)。 +// VLM 失败/输出非法一律跳过该级返回空,不阻塞任务。 +func (s *labelTaskService) detectVlmHints(ctx context.Context, client *common.LocalAi, data []byte, mime string, imgW, imgH int, species string) []*common.Detection { + prompt := fmt.Sprintf( + "你是野生动物监测照片分析助手。\n物种:%s\n"+ + "画面中很可能存在该物种动物,它可能极小、大半身体被树叶/草丛/枝干遮挡只露出局部,容易看漏。\n"+ + "任务:仔细扫描全图找出它最可能所在的位置,宁可指错不可遗漏——优先检查树冠枝杈间、灌丛草丛、阴影边缘、地面隆起处等可藏身位置。\n"+ + "输出归一化 bbox 的 JSON 数组(cx,cy 为区域中心,w,h 为区域宽高,区域范围可比动物本身大一圈):[{\"cx\":0.5,\"cy\":0.3,\"w\":0.25,\"h\":0.2}],最多 %d 个,按可能性从高到低;确无可能才输出 []。只输出 JSON 数组本身,不要其他文字。", + species, consts.VlmLocateMaxRegions) + content, err := common.QwenVL(ctx, data, mime, prompt) + if err != nil { + g.Log().Infof(ctx, "VLM 提议候选区失败(跳过该级): %v", err) + return nil + } + regions := parseVlmRegions(content) + out := make([]*common.Detection, 0, len(regions)) + for _, r := range regions { + if r.Cx <= 0 || r.Cx >= 1 || r.Cy <= 0 || r.Cy >= 1 || r.W <= 0 || r.W >= 1 || r.H <= 0 || r.H >= 1 { + continue + } + w := math.Min(r.W*consts.VlmRegionExpand, 1) + h := math.Min(r.H*consts.VlmRegionExpand, 1) + x1 := math.Max(0, r.Cx-w/2) + y1 := math.Max(0, r.Cy-h/2) + x2 := math.Min(1, r.Cx+w/2) + y2 := math.Min(1, r.Cy+h/2) + ds, err := client.DetectRegion(ctx, data, mime, imgW, imgH, + int(x1*float64(imgW)), int(y1*float64(imgH)), + int((x2-x1)*float64(imgW)), int((y2-y1)*float64(imgH)), client.TileThreshold) + if err != nil { + g.Log().Infof(ctx, "候选区精修失败(跳过): %v", err) + continue + } + out = append(out, ds...) + } + return out +} + +// vlmRegion VLM 输出的归一化区域(cx,cy 中心 + w,h) +type vlmRegion struct { + Cx, Cy, W, H float64 +} + +// parseVlmRegions 从 VLM 回复中提取首个 JSON 数组并解析为归一化区域;无数组或解析失败返回 nil +func parseVlmRegions(content string) []vlmRegion { + m := regexp.MustCompile(`\[[\s\S]*?\]`).FindString(content) + if m == "" { + return nil + } + var raw []vlmRegion + if err := json.Unmarshal([]byte(m), &raw); err != nil { + return nil + } + return raw +} + // AdminImageVlmReview 单图 VLM 藏匿位补检(两阶段标注第二阶段,须与 z-image 生成显存互斥): // 以当前 labels_json(RF-DETR/人工框)为排除集,调 qwen3.6-35b-a3b(+mmproj) 按「环境/季节/ // 时间/天气/光线/地形 + 物种习性」综合判读画面,推理可能藏身的位置,取前 3 个追加为疑似框(class 1)。 diff --git a/server/common/localai.go b/server/common/localai.go index 122c879..dade92e 100644 --- a/server/common/localai.go +++ b/server/common/localai.go @@ -32,6 +32,10 @@ type LocalAi struct { OverlapThreshold float64 // 提交前整图等比缩放到的最长边(RF-DETR 对小图更稳) InputSize int + // 四级漏斗切片级(技术设计.md「预标注四级漏斗」):切片检测置信度下限 / 块长边(原图像素)/ 相邻块重叠比 + TileThreshold float64 + TileSize int + TileOverlap float64 } // Detection RF-DETR 单目标检测结果;Detect 返回前已映射为原图像素左上角(X/Y)+ 宽高 @@ -57,6 +61,9 @@ func LocalAiClient(ctx context.Context) *LocalAi { ConfConfirmed: g.Cfg().MustGet(ctx, "localAi.confConfirmed", 0.5).Float64(), OverlapThreshold: g.Cfg().MustGet(ctx, "localAi.overlapThreshold", 0.3).Float64(), InputSize: g.Cfg().MustGet(ctx, "localAi.inputSize", 700).Int(), + TileThreshold: g.Cfg().MustGet(ctx, "localAi.tileThreshold", 0.12).Float64(), + TileSize: g.Cfg().MustGet(ctx, "localAi.tileSize", 1024).Int(), + TileOverlap: g.Cfg().MustGet(ctx, "localAi.tileOverlap", 0.25).Float64(), } } @@ -122,10 +129,52 @@ func QwenVL(ctx context.Context, imgData []byte, mime, prompt string) (string, e // imgW/imgH 为原图尺寸;返回坐标均为原图像素尺度。 func (c *LocalAi) Detect(ctx context.Context, data []byte, mime string, imgW, imgH int) ([]*Detection, error) { sub, scale := c.prepare(data, mime, imgW, imgH) + return c.submitDetect(ctx, sub, mime, scale, 0, 0, c.Threshold) +} + +// DetectRegion 对原图中指定像素矩形区域做检测(四级漏斗切片级/VLM 候选区精修): +// 裁剪 → 等比缩放至最长边 InputSize 提交 → 坐标映射回原图像素。 +// threshold 由调用方给定(切片级用低于全图的阈值,小目标置信度天然偏低); +// region 越界内部钳制到图片边界。返回坐标均为原图像素尺度。 +func (c *LocalAi) DetectRegion(ctx context.Context, data []byte, mime string, imgW, imgH int, rx, ry, rw, rh int, threshold float64) ([]*Detection, error) { + rx = maxInt(0, minInt(rx, imgW-1)) + ry = maxInt(0, minInt(ry, imgH-1)) + rw = minInt(rw, imgW-rx) + rh = minInt(rh, imgH-ry) + if rw <= 0 || rh <= 0 { + return nil, nil + } + src, _, err := image.Decode(bytes.NewReader(data)) + if err != nil { + return nil, fmt.Errorf("解码图片失败: %w", err) + } + cropper, ok := src.(interface { + SubImage(image.Rectangle) image.Image + }) + if !ok { + return nil, fmt.Errorf("图片格式不支持区域裁剪") + } + sub := cropper.SubImage(image.Rect(rx, ry, rx+rw, ry+rh)) + var buf bytes.Buffer + if strings.Contains(mime, "png") { + _ = png.Encode(&buf, sub) + } else { + _ = jpeg.Encode(&buf, sub, &jpeg.Options{Quality: 92}) + } + region, scale := c.prepare(buf.Bytes(), mime, rw, rh) + return c.submitDetect(ctx, region, mime, scale, float64(rx), float64(ry), threshold) +} + +// submitDetect 提交检测请求并解析:sub 为已缩放的提交图字节,scale 为提交图→原图(或区域) +// 的缩放比,offX/offY 为提交图坐标系到原图坐标系的偏移(全图 0,0,区域检测为区域左上角), +// threshold 为本次候选置信度下限。响应 x/y 是框中心:先转左上角,再按比例尺映射回原图像素。 +// 不做中心转左上会把中心当角点,下游再加 w/2 时整框偏移半宽半高 +// (实测 RNPHE_133: 响应(403,664) 即目标中心,旧逻辑落库 cx 偏 +w/2)。 +func (c *LocalAi) submitDetect(ctx context.Context, sub []byte, mime string, scale, offX, offY, threshold float64) ([]*Detection, error) { body, err := json.Marshal(map[string]any{ "model": c.Model, "image": fmt.Sprintf("data:%s;base64,%s", mime, base64.StdEncoding.EncodeToString(sub)), - "threshold": c.Threshold, + "threshold": threshold, }) if err != nil { return nil, err @@ -154,20 +203,60 @@ func (c *LocalAi) Detect(ctx context.Context, data []byte, mime string, imgW, im if err := json.Unmarshal(raw, &out); err != nil { return nil, err } - // 响应 x/y 是框中心:先转左上角,再从提交图比例尺映射回原图像素。 - // 不做此转换会把中心当左上角,下游再加 w/2 时整框偏移半宽半高 - // (实测 RNPHE_133: 响应(403,664) 即目标中心,旧逻辑落库 cx 偏 +w/2)。 for _, d := range out.Detections { d.X -= d.Width / 2 d.Y -= d.Height / 2 - d.X /= scale - d.Y /= scale + d.X = d.X/scale + offX + d.Y = d.Y/scale + offY d.Width /= scale d.Height /= scale } return out.Detections, nil } +// TileRegion 滑窗切片块(原图像素) +type TileRegion struct { + X, Y, W, H int +} + +// TileRegions 滑窗切片网格(四级漏斗 L2):tileSize 为块长边(原图像素),tileOverlap 为 +// 相邻块重叠比(步长 = tileSize*(1-tileOverlap)),从左上到右下枚举,边缘块贴边收口保证全覆盖。 +func TileRegions(imgW, imgH, tileSize int, tileOverlap float64) []TileRegion { + if tileSize <= 0 { + tileSize = imgW + } + if tileSize > imgW { + tileSize = imgW + } + if tileSize > imgH { + tileSize = imgH + } + step := maxInt(1, int(float64(tileSize)*(1-tileOverlap))) + tiles := make([]TileRegion, 0, (imgW/step+1)*(imgH/step+1)) + for y := 0; y < imgH; y += step { + ty := y + if ty+tileSize > imgH { + ty = imgH - tileSize + } + th := minInt(tileSize, imgH-ty) + for x := 0; x < imgW; x += step { + tx := x + if tx+tileSize > imgW { + tx = imgW - tileSize + } + tw := minInt(tileSize, imgW-tx) + tiles = append(tiles, TileRegion{X: tx, Y: ty, W: tw, H: th}) + if tx+tw >= imgW { + break + } + } + if ty+th >= imgH { + break + } + } + return tiles +} + // prepare 整图等比缩放至最长边 InputSize(等比,不裁剪),返回提交字节与缩放比(原图/提交图)。 func (c *LocalAi) prepare(data []byte, mime string, imgW, imgH int) ([]byte, float64) { if imgW <= 0 || imgH <= 0 || imgW <= c.InputSize && imgH <= c.InputSize { diff --git a/server/config.yml b/server/config.yml index 94fd3a2..5d1b194 100644 --- a/server/config.yml +++ b/server/config.yml @@ -99,6 +99,10 @@ localAi: confConfirmed: 0.5 # 置信度 ≥ 0.5 视为确认(class 0 真目标);0.2~0.49 落疑似(class 1)待人工复核(2026-09-02 RNPHE_257 实测调定:误检可达 0.46~0.5 且与真目标仅差 ~0.1,误检落 class 0 会污染训练正样本) overlapThreshold: 0.3 # 重叠去重阈值(交叠/较小框面积,NMS 风格;RF-DETR 同目标常输出一大一小两框,minIoU 比 IoU 更能命中) inputSize: 700 # 提交前整图等比缩放最长边;RF-DETR 模型包固定 700x700 输入(stretch 拉伸、不支持动态尺寸,见模型包 inference_config.json),提交更大最终也拉伸到 700 无增益,2026-09-01 实测回退 + # 预标注四级漏斗(技术设计.md「预标注四级漏斗」):全图扫描空检 → 切片扫描 → VLM 提议候选区精修,键见下 + tileThreshold: 0.12 # 切片级候选置信度下限:小目标(切片后 ~40px)置信度天然偏低,量级取 RF-DETR-S 实测经验;低于全图 threshold 的候选仍入库落疑似(class 1)待人工复核,宁多勿漏 + tileSize: 1024 # 切片块长边(原图像素):缩至 inputSize 后约 0.68 倍,画面高 2% 的目标(~64px)保住 ~44px 可检,全图直缩只剩 ~15px;块过小则滑窗块数爆炸,1024 为精度/块数平衡 + tileOverlap: 0.25 # 相邻块重叠比:跨块目标不因切缝丢失;跨块重复检出由 overlapThreshold(minIoU)去重 # 标注类别名(写入 data.yaml,随 result.json 存模型 labels)从数据集表取: # 第一类 = gen_species(空回退数据集名),第二类 = gen_classes(空回退 class0/class1) diff --git a/server/data/observer.db b/server/data/observer.db index 5871695fd5bb76bc2263baf512f9231356a7ecf7..4980777573597eb142555dc0a3f963390b56f339 100644 GIT binary patch delta 65660 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

u)24*_p%P;GYjsdqd>_@&= z2*=E+2`cDu=&zSS$X$C?w=wZ_LrSIcD4{D`z;=)uN&^ImSGX=rH+lhTv{b*tu?l3h zB`(t;tIf3lejx`83TC4g%k*`q>vH`FO`!=ZL1%3IhTb?TvvxX69hA85M4$upYXB^q7|ZKo%SJ=wY7rQFZF1uj(`(nz@s zIM|oERj-aL$XQ_JBaty!ho2@E!EKtgiwrn&`Z}0g^SA0xMCWBL2>Tz?0oHh6I)G{y zC_z%o-K)D400;p9Ib& zu|wZQvR_}=r7we^=zb8#{=J|m82jnW!10p?Z|NJ&;pgDP`}FqVQCu;kNA{-px21i? z9^oc;lkKff#L=hpac~FPKJfpRozW+u;xjt93jCE;Friq*-M-T8G`ewCKf=k^Vet=s zs{f-EIxBMnlvp$ypZG#=1=k#MV9MI(O!7ubpV6b(r45qU-#TBPvOTb!o zsO%7^T%54;bJ&d$dAd4);$^sO_9N{BElzpC*o7Nh(2ofWWd45fgZ>u-+I?lOK&AV% zdk-o&p}?gmU#N*oDqt02FY6=lqKo<{7R{ax?hN)feMdB8F+FB=*EqCsJ!s+?s5#*y zH4&w)u*IPA42ZWIU7%9_fA!OlTPAjdt8c5o;|0N6htgA=uinCuSM+vbgw&hrYBrcr z89K_0{x&Vz>`HQHBngqjEhRT}xPKW4@Q!8mR^8Ge>ITy^0oVMkJ59rT0y=U-pN9)> z>6>X>@we`!vE#OW4h)4<^^S5xo+C_xdqzj^h&4JgB+>X|G?Xz;LI9%jUI1c&ZmfYL zy&j0q{Ky)G5QeYJw+5VqFSABEjW_W|gb3ayd{{HuvoW*^x6XH`^lMy+TErd{3z%6{ zce*2r4Kse{AR3y6Y~hAG8UiJjMOA$7A{vmxSAgZ!Mj2PhQdY@UR|z;K-0&0iI=jj; zWMLArV~w2<;?JofoP^BFy%cP(11)$J5;OL1Q5%t)xMR@q)o?9gy9A>*sD3Uc4fl>R z-h#Yr7gl486v#*2&GyB^#70R&DUJDx5?;4;mmBJS z^^)33c^XG28{H*NzYRyopGYw{eQK5BuHU%<33D%JzP>a?CRM@>L=n8xQ zkAJ|(p;1~}$cTp}?S<)7LxDr`RpG(?ETUsWfVawR#h7`(G6i9zsp#U$G8nR7Xg?w3t`eH!+`jV{5B-o z?(!OtXbS@5LKae1^iiuyM>C@vW}bOU+S_0A~b%V-|I#bx*8{uy^{gA`s7rHI4j!I z(a7N7@^DM(b$RMsf=`kHr=baJV5?4;X$U!R1A0(*H}&}XnzS3P>2NzeByt;aC>GeO zE%O&-?4Vp@H8|K7g-j{v-}F*N1y?k)lM(Pz1qmY_-R)#Rj(&l=+9C}2OBX%67;i$F z3mZ~h%DM*H2~kGRZUF$fFVb{>!PL4?uO7y329D>7J&lVvyPE-eYWv>CVJ4q`nVL@b z2WBl?f&{aD!Wvl-N+~r=@F6HS-_ei_iD+$)J&3=f2|J<+gIKaPuI0ZV=arOXXrYhP}j| zW%sk|*caG2>?rmj$enA!hA}sp@0kyoUCeT(l6j69#`Iv^Od=!E*XS=nQ{PO#oK`pW z#pw#9*Zfo$>`3#aCX=+AZS~=17MQYC%3@f2U$`TtJt zsn>?v%$QS3>VwUcIi;vh)4rjBKR?6#Rj>5_O@dID|HlNO`dtL@oQcm4G2q0J=V4<2 zy@>uH1HJsH5w&RK5AOPtlNQK7+ETY2XW$R)C@1TK%~Qb2hxNgMY51Tn*pU_hZ@3?v z4}aq)Fg?ntIVjp5FEF6xi?;j_U4JzK zr>vD-b?ZP%i;4cydf-4Br?R^q*c%w^YxThXz*zU*4~EqMr@Gnrp8Mfskpg|5sSgfJ z@W*w*V9lD1yi^|?80(AmR@y|6x$&>n2qe&bQm+wDpv%Se!GU4EP#+u^=A!!Gz$k0$ zg7d+)HW9C>3wL+|Yg(;cqdfs)tXlxGmqMV0Q`d-Yn?Nq1Ht>EOaDCh1PnO@bsK$Re^SBFd%$ zqAcRBs4)R?M-uElqN9T=I*Q8ZrAJg0b=>Z#qr-?h;8h23K}KhoQPlVU&Z(-dst#d% zbKiaMncvhjr>m>Z@}2K|>;L2P6L4FbMGsxpX3;|@Z)Pt|lEY;IhxH!OEj!ygNiJ#) z*sNcR#s1mStWKqc>%kDmXZY{dyTwEPW^EP}^IfjFmDdGJ2-^5I*Djg`mHyS*EJ$Xb zwONqNH`ZoBGJCDff@F^VIyA>N!nh2)D*;LFWn@%(qC(Ubpni$v~OS5_=?6y3t zfzM9BXT4iIWQV00K^k;4ZqGG~NvjpJ^Kq`7Pa0w(==P7S&0=;wv^I;``M}yNX6Jo* zvw0T8D_aj(Zx>YXuC-ZE!8U8N80R~d<{Hub2TOBYJo^(vb1T)7s}_BE4VIrl#`P0V z`3cR2gQgb2F*GYb8lJ)*B8LBxwOI`R_ts{?PF}Duc7$>8hd*z*JuV*pnWY)QKh%}y z%*{0^(ZgrW&G66jyFWKJbH*-~`59w7@q2Om)8=M)UHMb~Vs5TUiaC5D$1+ zAL;x)cw^ud=hNOL&MRC$xRQ=X>~p+v+bqMM&Bl(NCGUr!gtGLwp=9)8IgvecwyZd! z?nemAh#=*gIu6&q-!w-?1*FD~3QZDkna@S@j&iNx)P*v1^tPcLeOb$5IhvhtraS{s z26c|B*>C5_kHh3Lcdq<86u*u^+D{hDf;4~bSx^i^;~lG6YQDV15gMO8FkhZbJ|)M7 z?Bs=VA4FVU%PXzG+AhP|?mhva*Pj9sBedOhnDf(6Mc}i*{egL~wgXV62fi&3%7SWe zYU)U6gV=YOOa`$&9dYPt7$0yM8ZVbCV1bcWd&=0(laUd5+PU%+_SA*)DK2@n`>ky0 zMKXc9u6B>jZo60>2K(46*&dh5$2%~21Tw-W&vzb8PE$uxYnXU0e^Ffr1v}#wWM#)L zk_VECKcu5xRTLv^`^EAT*^jS~4|9~b6y)QrwK*$7|8Q(~p62_`vDSCAcVD*jD*03g z(uhVJs|>^|3Ac~Ga`1KHl>{Ne8&0@MERgQb8g;Ww7-6R^lOK2aH@ZGq7g;Xb?Un4U zA|xEWiVgyOdWD>EU_o@mxgN{qxC@rY4mSH77%IoM$?Ms-*U8A1XmSn{R>Ie>mlwNO zQ>7eYqi>df*TZ>+Enu&-OZWO4{QtC1w^#c90eHMy-Bbjn=PLR8h`Z1RLkGyIv4dcZ zxEeQP4fQQMy+igOJoaq+@3Qk&%MaNj-m|%Vi0;+Q*KF}>BDAKCbG4C9U&SYPcn4Xi zX>xmIE7CC4u#YqHOVIK=&J^u%)V_76{5vEI2c7}m(V|;14t(;kx;66i(LhrN19A64!p$&Eo_mvAh=n?)BL{Nv>g_TBLt)LFC(^&dx6A86pswNBEw{@_m=Ju~AATi! zoK^1aFd;0oIq!4MbM_7P_kZGB=k4Lx?RdyN(D|ujq4Xh;@#I0sy5DZ^l|At;*=aAw zPfirujr^EeazkUM$H%I+$%Flkoepi2F|cVf`NFW+32KQxS`-d%b)fS@Z1IWtTo8uc#_t_$%gT4(=S zb{u7Y8JzW3Hf4*lOnx>vH?ZD+o!)AUX z4*~S>>HwSljl79n_Jc=e;{(b}mvaI#&3_wEuJSjo)@GV*3Mg^5IH^%`fyF@N$kFG$RUM8f>$zClh2$Fwqzx*=mu}^-=73%Nk!TNoV z9gnz$)$E(^F>s1tV3!?`Zv+|ZK9ZX6Q~iB3oLjT!a04HB#8_ zDN{!Ak1GLmrEFj~*p<%^PviTNP5J5?nI(FBC$OOOiN~w(b zcl#I<=2n#CDJx+)DtL#{2upW9+F7P_VnkOlJ*b$W==(We82E_Z11!6IP z6eSQ1PB97kbK1wG6>(fF@5frtK>nTOK^=F4e7-0S`R%oA=OlLtoAntA*FDz5T_wd) z5vMwy;!&th#I`fLH(bK1e-GK`rj>{*TRc^X^{=7PfA)oqJeXlvlzk(IIJ_+zr=<`m*BoU z@2u{lG9V^Z(w=EtO`^rU8{isxe6-pdk*FtOf+? zAZ8|stbTHEXkj>P+!5|D@E_7}SW&l@wX&TL9q2PIFfb1 zIY=Q!2fIM)7`8+LFRrggM^Mux7bgusFVF`1jN6g7q<4%BD0dXFZys>_PX;Nb5MIf1 zED-FkzY56`7!^W45u;H%o7d18dtKg1lAQTXUyi#G|T3$Ye#KSal zIm^IIUOrzbBFZtW2AlY0sE-|xwqF4ib86OK#-2Pg5UZr53&4w`Cpzi0rEY-_lCP`8 zwq2qeVqIw$A=d@yCUNW?iXc}P7MSOVhr-f<$^l}o4Jv`AIv6?eRf^)Yw1p)^5(J~C z>R`!7IUPfQ6&oIiAU4Dc>zx8;#9BAh z0XQ9%d2-vn7NckY_5|X!8WJgr{!+=U9;8XPR@VUvtbvwHC$~jEx)f}K##<2C!KW+0 zLKWTjD^Ah0U?ddbLpdhIp;dl_n0>50dQ6e})%rfbCcr;I^~i=qh%U%V4HQlSJq|f1 zDbQyUb4*VXJ=3S_a(%kS9->Ng0;J3N3uUVcd3^iZIn1c*4;2PWjIm8xt~6#{$q_#Ofz?*RXo-aXmUW~JTZ@~wrB_s)?DL9}&@7h(cJ zCGH=o^oOGEpNH6z(?%(XEg8}=4d0UF4CF3VG<l!W?2_&8^b(iUmzn5urIi-7FrC=L=x+2L&e zu_&JBaJ(Z_nwD|OKe*uXG8-~pd9jysl`Y_S!{(mt-|Ft|`cx{DK0+P6U%L)-yy5&b zTQNa74}R^FfMwpX0_KNxla(PwO`R0e3l^GFO(Ag>yaJV+VuQ$v(0QabcJ`~u3hE>` zcIu{?<7e;#qmvSX=pn4%G=+>eow{5WIt`-sohK<-m-ikNEIwt5@*F(sos~kn-85Bs zn0k~yJ!dI@KGN~3tw0dniXmKjXzJ9KMW0TLZ^Lt{L>+~St1X3o1CkE_JiGP= zxeSppodmyzp#fZ{X%SJ|baxcRonAj(+3a#hK|j1O@0+V2!Z%;*DJ^R3oQAoe(=@m2 z4G`gJ*&92jsNb>J98AmjGZo}Koq@QZ(mBer_+%fN{a}uAJt7yc$j&=UX@e`ZTp+ss zxIl3^%N($m*&A&3|FD1OKiPhf*Jp2Vr(74h0CIP(;&x{>$2bD-9+`6`9%4xRncV4iZu zbKrN}AeUyFmMO@L4)%7>W=kFf=I?1&E0;N3p@q&4m=ctt?A~jXEVSbxof=kRgsoYj zJOP8&yc?9KpcgoMW{h-G|wBdG@&GJ7@d9mDV{A%a*TFZa`s% z+4d{fJ=mepCsb}-->F;#lYw5|Vnc@#Ck1errMK+4;i>|d{q<_)^k6HZy9;e!+LXca zg`p>d-v*lkrT&S&8<2=%lN#Oo+;POItaI#i9A^8{^_cT)XMe{Y$3WXWcadwGYmMtv zS1;#w=UvV-oJTnR;&>1+7Dw6l+BeuYK*Pa*fj`@SuWk{9dTIhTe6HLWOqCK@V|mbD zriqR`=hJxVvJH85kV#R{r4DTkIGA#B zX)WYfh^w`D6>h0zOXfRz1ltCu0Rq8=10TESdLc_4e9-mi24p+PC&))iRg+l8JA+tY zsvv`txgiC;P9HSXkp#wtjsPYWS=RbNjLG3rs1PS0bZWz9{iiu1sNI=HHDXdbFW3eL zUbhRuf$spHh4>+eC2_q^5cL{J>VwP&&^eNKRiPEJ^_2EQg%2USps$+Xj`c)WQST5Z zHY6~uOLN%3DzC3N4j3*DQI``$ho$?AUQXIBb9vSQ-40xaH01>AxNO0PaGq}+-hr3+WjDyexZNQMp zpwA%X5=)O6qC7}3UwQeS`$)I^b556=36kd0aw4A9^GoC->`n%;&`1sk z)DEWGpt`iA4-?PnxJ2mAh6!XdUh(&3>GM!~di0f$AhS>UVSyE8)in6WqEh`SGawJ1== z-Z&f8WdHL~%-^b1&=o<_zv)54(-qvh%}#k*DH>^hiiId>BVv(ZV`)G&QciN5e^i5k zCX?WSNEiSq)f_y>RwCcGTNTthEQk2*^*Bp`*k=FtWOs1eWq4YIv zJ;Ak*(+P%LTTOVDm?4c4vHozT^5WdYxbzJJjT*@^bE5Y1CLo`p;uym0i7c${>b3iWnJLq>7l|uG^hrO`-HW1>jDmhk~K(Hf09hjCN znU1nmFL* z`Qav57HniVV{nk-NQ8n;J<<-#1)J?*h<7dNh}dBNk5=t_Gk@U(x452fX#$2<$&kGj5aC7g>L52$9_^KEr@$@Z%41_(@S-`a4*QCq`m zyunB*pcnFhN#NW#zzG9(P_nC+b#)WBSg^Gbr1P#iCE$rBfcas_cqXGBQiRtlCC8{M zWU64tS6WlB=aAS09-e|>Do3GYJRO!s9xR>qzT1Rd$jFD3Ph5TMDYj%e>_Usr2RnN8 zZD-X{U=>IzYRH{X^qeEoNC@D2Xr^HgK{Vw24Z|}asj!YJxvwK$&z4*%Rj~m`);DF#+EJUvoyx0inavo)iX&>7#4E%n0M`CtXi0sc$Fu~M)r9J1V!n`2ll=@CSh zs9EuI{!{F)DZSW)IkMk@xb?ek^%t{#6|kMYG}ar7C9AO$V2LsHDV`p#@d|ePU*%ZH z#9W{U`}#SMOjUJ(5@WlwQmh09OxWklY`Zzl9oA8xz2_fk^Lhm;>`C^A8$(sBbp~wY z1B={M6|g>GH=4RKINdC|((YrI?miSJhKvSQ3szvMPmQ$%--694mBOxug+^xtFzS%a ztG*gph;`f`rb=t|NdTAt9TjpXta3UhU}tZ(lXH4-8fhk~urlSVL-h-b4zyQfT~%sVFVq}pFp&ZD zs75i}%K%z+)}ho0OdM1ma1xY~z=^NRh7gO%(w734$5CxK4j}TvZbzy9NS&?Kbtf<* zQnz3gL|qC>q}6774tr>?y?hEBHL%;`Y=QX=%gAlsLU~G}4Ppk!nIu$=+Mq81cnw{u zucd58ZB23N)RMsvN<#wj0Bbn{0Pr|z28)yCw`VJPZm)e;1p7EJaXX&y6tU?`5j5c& z8th#Rod=M`#tjr~M`{h{ec?)_yVLpSdT%j1IvJGMpQe(RrdKFLbb-WcVw}JD$B+yk z3dSmcnGHpPYn?i?!r^g%Zyl6kUZcdyyChN+s7cpz0f6@ar4bvbWRooFOV>3%3mqMO_25u6HuniD6MO+8lVB*z>+6K^Upsqpo!Ruff z(6<3peM|~eep(%*!fMk3r(+xxk6i#23O0XjS|BPxs;vRxhrWR^0`m{26W<4!=j^Vm>yOHh zN-wg~*w3&9Uk_9P?DZ#PZq!Q;d+e??j_>VfK;#)=KYCeY<*0xS`TT^*cC|8>K-r>E zGe#6aTmi2NrjTlmlm&P)G$DKzRtL<6s!{Zwbi#yDBWA*oK~aCb2WtNYf|%*wB7!vc zJ&@8&-wQO~-1j1HAouU;`d0G~1dOqM1M-ec-(%j){}u+S-2Dya4q`pb_lscY-2L^f zJi;{BAOeXE|F%3J!7XCB?=3R`O^d&9`m!D?kISt^W!Gx~L2Pi{AXqGrDK2K-vRFw1 zf&-;Mt23`m4dfO!VKUG>du)^o*b{Gt3ZWxUcoT{FFTD{eWE=XF~roKR^W0YBzws%(II_gWo^B{mhjk0~%P{ z@}mXxS~zT;oj8#BfbfPhMUZj~uxatZNX5bFhAIl$gq=Ho9uI3q>T>W2XxV`$Fk#<6 zj>~Skyi1pt>9P@*LajskuTb)Dt5VE9Pa@-aM^Y(ZZ_;HmE>X3!%lfPwp>=jFoBg<4 zJQO{trAK7RBEfIw|NLwOa;Wd@F3ub0{jr1 z5Ag^<_`?(v9%9WPD2QN|)}B{4AOjjxe9RNFr*-=5l_Wj2+|gC1I5V9BgglIj0yQk=g92!C*)f8hs9D)wtBHtfRNnTi=`MlVX;)mjzRKrB!F@9)wn(^nk5@)&I|jk{rlpqc>#%+sTROxD8e(N$mZeJwyJ zNqf=4P}mU*rEzT8LTLosLlY5PggH8Dku-(fvPi1UVz&C)gZfs%8nSnvkSp1riC4V% z1T@S4pilSWBC^wZql)M@ROg)phm3Ene{Nua_vFC7;6~@z(3PHsJ=$4FkLzO^-`PZoV_519JMkB!;$+1MW?pJD-GWo?&* zqf-z<0~4ScKS3fmmp~ip2=WY;L6{>U)##c4guq%v)<7u)6f;gKT^B&GLjvXt1jm4A%YOva2eZ^l`2c&DS*Q%nWGY+*PcdtZItblLwOJSsb2^x82~JQ z@D#I6yIiI0r`LTkL}$RM#^Yv;U7DtK>A9Zy}rWxidoae)X0yeDi@2ry*EQ=K=zbbD8s zR?gQ`E9sk~Jyx?{iu5|zILXpGfiDu-IDz;Q>Bf9nb#XA#i)K?O|Jc7quq-k*v7Kkz zOD3o$Os%?=TImYEGwm@7utQ9madG5Lw&nSIr-pB^qq>~w=|j>;D#_b!!d$EGN%MY_ zH`#B-o)e{gK~DeojJCAdTGA)z^G`Nr$Q(I}VoPp@^;yMRh)}qdUd0H$Y?|;5ulS=a zAObPx4bY5e%FJ{g$EIppHAEE$aWmf(JGgcoq`UZe_&iXCX ze&q@|S&9%&s4|9FRI(elq$g_oy`?i4HIHO=Jlxk_&o-oBbt!wrGk8EPHURf0tDBRa zaBLdLaI~83y>b*h69pDmb@8}JEA|!)osbUrpGKJE$A^?>g3IDTzjesXMChmfmpcwH znYsJnnzzy_tbaJ$$jP1SYeCnjX9u~BL^xf#GXQJDc>#qY zh(*N-idb55=<+M8f@#K0rqcwk|K>uq*aU0)T!{i76eb9m1Jx@X!)zid)Ssx^9xy2| zVCTxK()Kg$N;r`aoM{LJ$Fjg8aaH~v>Ss^LeXmWiFS9A5Lzf3P2L2gH zpr+K3-m~HF*@Gg*AGwO16Y=$Ch-_=v>7U6(A`07#WzW7jCeVk)Mx!d(;@e>B8ok{Y zi`4=^Fo_^iBPlE!lSb7N8t;mJ?E2S~7-^_^p!oWs0>c|?8x$&vKq!JSRIl_0vJ)Is ztu+XV2?89g2EQ5%QernFOaxK@>nQV&kO{^Hysi}W z?ve(zZC4MLiE+)BBWIHV5Aoa@^ezpH^94*XJUh9+9ACiMY^q*j-7OGo5wFeN6FTXk zbBjdh-hbmzox?^oPp{CR$=|JrauaO4S*QZ4zlG(`xub zyPJKp4z_P|?^XMVPTepiBUTLEr-*iaLh+9}RKcc@3}|MxM4+Na(3Q!rrv0Z24hgbd zBR&K%LkJSe1qaPp#0E}t6u8=krsoo_9bDnyT?kaLPU@JQt_t?m<+6{hUWpTa`xs~{ zuMG%QmQdYo=&`1W9iE;ecF2|o;Jxc|fb9L}{Z;JuQ^4f++zyA?w5yS)1Y0^>g=WtW z4yWZRc~`RkxZk=;8&H22u@&QQ3>Wo*e+xbeW2s6$DL7j7|G=_N7cA?!`#H6wP{+oY9P79$XjI`(z4NMpzra6 z5~Ujq>ao4dpQmZ|yw+dA{?HNdv;7-AK>oYi<7J*H*tXLa$dw+1=Rmn*6B~g~_v9-0 z`OmwS;7VJ=Zni6o#5R#r00`Cw;9E~a+{IBL+%)C}6zPT->t|!KNP&CyRwXtdfnFkq z#Mn=S5lt8UG=&jCwFZhm4zg~jg0jXqm@NF=^~PePWQq}+Fn7LK4$@gsIXXUtU{8~P z9&))5*?)=6bBA|}YpT1@|5tyL?_$R#?suF+rPIZq?JHX?c7pz&{VJ7moa`_AI1}kc z9)S*ucujba)xR9+(4hzsL(?g=0SNL^MGANwK~%8ti))_jOtch*F)GIbxUP_KihcIL zH%d{+BpR?)=PLc!p53ma*{cIWv0@M~bZ7%1;rA{V`{rRtZIgdKlwbkL5XjFJGNdio zri`aKZPJ}*sc3bWbfgc${;gd>4kp1E1)CvBaIc`)p)`u&=_>>yJN=)0Qy3?it^d?l z!CKFUz}mh5nUVi!_m#0Lt_xL_5?pW{ij$crt|em^6H@#)1=!c!%8v*{(2WW;JP3#% zqfjplqCNSCO)*7ao^X??Xxd<;))C@lh73|`+6dmhNEoT=30u%#{;ou+Ud_S9T8d>> z|HIL#+R6aGx8emQ*4XVY;T=V1_!vl#$B_?)#jkt}OCCfCF-FcAXl1t@K&0fp)5673xRK!-%~@87SF)X307LqETfi%uxjcL8 zD}SUIdja+;(~F0vTLo1-v|lOe{>AWUZFtv*7el!-5Ff?C13$bN;t9c$!%Ixg5hU>G zSL@;-)s7;xP5o#|pT|iGHV&R+YMz3ww42gA?S@2>VHt;D{XKt=*b4Jg4DtxOs?=Xx zu1a*U59C!i-!j%)GE(IlCh4*kf}MG{!EsLVooQYJPukW9uC{yt3x3Z9*@KWHo3J%d zqL#j)6i$fN2%M)Y&${GA>3V?XL}w_By|$sPHjP|)I-3AJ>3&6tLBugWo-G-#RI&pQ zj@dB{s7$7*E)BF4ZQ#=41pZTOP)R(E5U4m??y4`_D~?$Sb=$ zP#MEX4UTJxd#g<&@n7xQO$GT~d-y|NU##-%BSJ;&k0Z5yAxZ&Bka^n4MS?gT_j?Md zFqNfa6we0(YOD=WQ$wyq1`?f-v04c3$gs$*2R942j#Jm8l5KhZP+BjFzp$^5gN_O< z2g$66URJL}>IAY*)GHRGMz@A=%LoomGj)JBAbJ&+yPE<J6^K2IUcnsZ!1qLD^cQiv{I|M+27wEMG5p>zPEi(`|kIx@?GXT z(|3X|IoQ|R7X%dS4)1H;Cw|!tPH2%)v zrgk**Sd_ppYqJ<$z6bIN>*^)gNNLU5vBI-P3%x7-ysP zZZXcmmSzzQ7D$w?by9XM~w?ir6ch_5+#W?G%&0?GhPni*;5jJ=J zkT?{hR-F<-S|~0`!>_eIMU1n?+APLdZE3C+%Xzf5SqyWKrMVT6AoR|oJQtdVUoFNt z&~iH}s?yy9tj%Ja{jJSnoc*LzjSzv7Ehlb8F7r zAh3i3JuSB<#W;Ido5eWGt<7SbW!7df%u;J}9S?vElvvxvIE$^#Vw^?RW--pF_YTwW zMYvxeV!c}|XQ62Bd$krHCZhiW1#-RVDFRA45YBG7HGH~j_3NL`TRrBp8`%7ba=2BD zRk6H41HYBeG(Siz>A}Enl^*81#ZV81eal~2m|Hsy5tYNMIv_eHC&>e51Ry^d+54d| za+QlseGu`CfrDY>vMn6S)nR>y=(%0F&-^g4NH*);oEZH-E4$5i^F{LiWQInr^e_6-~BiDAo1s% zV~?Ri(oWk>`-S!fdxPVB$FCeS95MRqXo&=m;c5ne|7=L&=Ps5pJM#=QOT+$t?7d47 zufhE^Z+<5u-4hvTu-4}!JSdJWnF3+cDENfid5!9nsyMQnQ^;?}uekP)%B36rgaDPB zzeSSyfeR#rhZBkn`9gDwJ;wNy&^rJ~^#8kcE0$;7g7WB15j-U~lUA~)K2c)b84;kK z`-FPF;?qN!8xXfcc8&;a=*9pjsC5^!nztohCBhem;BBf^#yajpfD;*y%@I*;$&3o% z3SY%*dkH|BDd;Hyxx7l&sQPP-J`@sCiXw?)S_*evKpxq=o*vd>vqU~S>%A1bif0=iZW z7v`za9Zy<>1?? z(Q{ZPC`L2!t3w%I;gdqC&Axj9_I-fRnahQbAdBz{DCh%4DUEPa6G zm17#@jKFo;E@*4zyP&~rQL#`P^4(zk(EsQSob{z@MY8thJ3?Tl$OJ&}n!a|Vy^q5- z2V_Zv{U6=tur*?vvz>9N$Y79wNz`b4@xDcvzEWu zi`Wqt2Mbm6T*~M?0HhSr#e}=yLOjMB@+ekg@6MzBkxBqAz`;rOYkd)xRcE|{V_tnB zYyMn`4eoXkxHCc6o0G6hP*q&@O0OS(cA)eqb-SDR0f#rU5Cp~9CRy8DrPzshK6ceE zr5LO-7rqNG7@pa7tkyqNHl+TIK1Bau{KPM{z*&t*0I*hzjRbEmjF~uZ`7WaF4*f;l zHQ0r?sWKyJrb;UZ${aE)PNeb*LPSkWqENVIGsPVHD^3x zKOVme>3rrvvTG)X`>=!ptM)m!!z?s&58^w*!vd}dNKRi(^a#QSuaOpIFMON-l=W6V z<>q`!Acx&I1gF@Jxqzp+_){2H7q0-k@yzv*R0vFBG<@83h?y{LtdQ$M)Rg?r2^gKj zLSKa%BnlR~(EF%snN)`wn@Ln_`i}qApsvqv-50nad%eJY;jFD!n4$}eVhxL)6z=1I zA@8l-axpuj2~I|GS5^Wo4e76@W1)ROCMIZh**R=fWjN2^{M3!G*MFJdzKR%siaDg3u2 zJ3%u4u4D&{g*?d)M@uC?T5xa|ROYRGW;-0hO_89F%|Ab^ur~{Xem3(Dm=wfz#f}8x z3?kPIc%ta1ANl^Os0i$~wwg@2IQ~wN!bOYB3uj@|lmKA}sGxZye=bf`K#UT#s;=Aw z5DYc1mxvJ5b|Tfyh9m`uQG_$YSj~Zg+UqjC)HQEq`+MeF@;}~&h(_6Sj0Yag(G9S z9c&!fn?{eKE}8*r$mBHS{HEq9Y%wagj!Z~n6n!%9w1kX8z%&L)s5#R^u!nuW2}cq6 zVca^JM)1S0f-%}bZM&ce?22L*%37VV0oXu*-N|iTBEzFIC{D)xBIldJ3Erv-MHh7W zbS-#;ka}|QGGw_%o+uz|C^6cQpH2x1xt*oQA0exj0=Nli3fH;@vAU9wj>?2|wAvdk z>OKyz8uhZtBT`OeWeiQBustpU*RxqmfkQ$5vx(5Zgwu22kl zLrbnjEdQKm0MGm0TzjmN>JS4c)%di)0oxB^rdLE*C>W+7vM$z+W|xgW5G+yMfCOu5 z^yhNHVTTlq66TfIDBxtKki|SX7E3}|vUgo16*~c1!XqauaWWbXZ3+ydBNkxKL<~4$ z{~NkE<(GER>}W$J3N@FXDl_Kn7mR2#bB~-)VC(Pi@1+lK^%w{a0;EQfxXoRi3?JP2|S1hy*7ga zjjB)bno$1f^~!K>1*2F(M|~}m%aO2pD?nyTNcTgwq>;G5_M>9YoGgdCb1=^cB93Rq zjbW*ffPwX}6w14YG6D6d9M4txuhE;1&u~nw^F@mAavt2K3oH;d#)$xjTX!f?OCZV> z=gR#ki|(#^6hQulu*aVMDj1Up&tnia0}yZgCra_(^Kba30wep#!`b2We8wh zwqag43TQD(M8uY;vnDhG9e{nXKms;3x7+oe-nMXM6FXzk1-klr>1aEZ!29nSWo?HD-o%GE|)R&FG0EL@#;a))PTs# zUlb7u?L6;IO4;z} z1jcA*&zl7=zpI-oV^IU;iHe!~RA7YLs<+!grA` z>HXgOwD(GHv)AEuAPW8PAo!OC4A+a5l!aqqViKUw7j(uuq#)d_DF`^|S{yj=?LdNB z3O5NS#!hz-qD{ddU2PLwznLtQSh zws6=SMc!3j=Wg&9m08pkv6PTr`{({DiLy2!iZlDmQV|>dFmlg%P973|VBQ@I=JpzZqAGyRiI4*0`@EBF z2UN-|V4i6H0kCrufOJ#Ipv*$cgHoZ99&30+GU8PbKtQ!(^Yna5DUcwPLVT!WHDB4I zY|gb*#I|SHU50pjqm72nuik@khHwzcC@YNSN89|nT`5t!VjMpxte>E;&x-Qjc>hL! z9|tzkk^}w{A=G!GaiUb*s*5iOB?nr3y>7`Q?SYH6Xg2+ajU`?Lv#v2hlbcaZ_P1ITW`Hte)&dNS z6TE?ymxX&FYW^UjrVb$3-4H(sv?6W8Q`G^Wit2_{C@-SNW(Gkam))~~sxvi%FeUL& zJhq8+nlnd`Y~I&uJb2$jyEM)=OorZe%z6kMyQ}2N7!Eyv_)$toPL*nJ$Q-UNx|8)P z&)g)sB&YK!PW}yfY%b(RS2}4El06$IzA8f z7IAxU8v`?m8=7@Ft$lQ+H_3y2yFW5uo-_TYQxKBza^wTVIXW`5`rE#~=8W06q4Efo#cONO?NRs=pbF+YmQMTbDJURLi>Mj9`=6$8AP@f~j_wun0 z%)a<%rPZE!Pm$PX?*e&e`@4AH8+3VwE)Ub?cDh{uF1mFIeVX?!I&(688cCNrx*SfI z2rl*pwsRX{>TJX9Z)`(DoW-{(eRG%}u-CKsTLI}fZ!0}#D}MOqA8~U6pBx~kop0m2 z?Qi3|H{Zs0n{k=P0~(-4IaVGIXiz~DkQA5&_az0Ss$f)3iwSUFaQmTEtmzt88hyswr>8WtOXY2=eMe;*V!Xm-^J zeeamx$NHY{14Pn!zA(G&2uWdI9tDEk*dMf7-&YDFn^bgWd3@yA!A#H3+1qBVX%UIzW{dn@6QPqurJQRrw{1zpXWeoETgva z`M3n;Q`=cVh21s}p9asvr;-`?A~_wGvg!EeE2rX%U8e-Yg(99xhn@l`9h-I(#OkR7 zk-_ez%OwMl1ax(^6KKqJP9M9s&WY7eIK#(TeyWBQ^_~vAwbA<64}!NwMR;llLA;B{ zHN3UDn!$)aBPjQ{j{PL&9wUc>_L86VaOh%5iP9 z`5fzP-g`X_a+&`b-&vj=?xUOw9qY6|X`^(BG}v>%v)OZ%XPC$3e#w0;qHTk&H(aY+ zlUz~fJI-63)0{mWA3N4MPIsIRy?Ch0wb4<`9iQ0AgaZInhi*i>1~%~$r3B#GIC>0e zB6JK-d_gKAZo5QfQD)Ll16w zRw^y-`l)QoSS0I1X(q-3pQ-~`H=93_Dbpk;7n6+44|Se?3(I;S2((s&Q;REWSrdx( zz#g)sKy9>*;0m#g?HGO#yFg(+xVUX)AeIUc|; z$fw8wKaiiqqUyl#V20|D?z2r6-CCiT#!s+8&E1Yar}4BMkvUo&n-Sg_*%|hK@Vs8* z?qX|K1p7GQo?rz%ajGs(0^b=T9Hz>m(X?dh*_H-S7;RCD8TF_$Q4aV&KazdFnCg3( zsh&J~18qO6QxIYQFWSS3QQ#;uh_t&18&wcKME=*mVy{DLkttv$pHp#r9SAw69ik6) zyboZSgt}o>G;iC2+{E=Kg|Ow5Z09q`q5a}xRF!=FXB1|H#~5kj1|<;F9$0GY5YxVV zK#uYt!1{~EbZLLn!7h-PZt^Wcbyfpj;21T=NoXvZ5Qd1EwhhiC#4FoKt1$B?I_j*c^ z^6B#1jypvUuWros5W(dfMyLCfN1zSp6M+O|&8iC9DmScBKGZJ=t^uxcH9Q;KBXMGN zE}PPF4AN=Ec^wAwuj!5e)`L=30}s+nsmO^s0_+q1OtHEO@E$iY`d}F`D!{O`?goY1ljTe+QXr-%SXh`R7sI9_)_C12GT6LXeryYAypV@-2UtOU>+d zLLR#%_1*OaQo?_*xzBZOkgs<95Lk$8p@4U!bX90`uvYzhIe1-gY%mmfGtd#394PW{ z^RJ;l2vvPt-jSk~c9gw{3Ft1o6!DP>HuOw8L>73x4LC%+6cA6`E7O-fFLKlln@a?m zy8+A%-S@9yi&1=wO&FSQs9x(Od^t=a)%)QkQ&O)Z1_B;%sH%6}4!Ptv!<1s+-RwLG zc>23heVSKCg;S2ohXVK?If2ai3=CQb00Im^2~w}gDHnq;gpi_X+v(OGI5Ab+edK)p zP?v8+yX`{iO&#*Y<>pF+VG!V~{s1z%*JqAV`J$bzOy)lzULo~m`~L*!0Yo8{v2pkL zVr~>Z0q&%IYp8_1@(fgwo74Un>-!Au**#J!7ywKd)ao$NnkQkqT78W{;)39#Lj4(c z4L`EksBa;1ef5F><1G6%~H&kPrA@3p4D~Is zVd9Z%j>&&yWlwis*0&L4IqMcwJ%6Lq4`h3)njy;E>OS+}KWtkKnn#xknW}kEE#k*U zgkxRC#5QJBlrWp|^aQRmtY9cbx2!ocioJDTD8eR<4;K}f&IU|%3r%$qn=~|>H_=`5 z5S#(vA$g$(qr}=z9-luU&uxSW9kFIW`TrQ!0{@)>piv+=7?B4#HUci7j237V7ggu; zv#%T>)JK6@dMq}>yPrYDdE#9^iU9#C9(IA;W9UE{p5aAO{wJ7nk(nuD5MU8Qh1j|k z^J=ACRAQ(Aj?S!Ff+YAHG{(6DYSRKS0uoD3@`PbI%bM!)eH&l(^Y(Srs?z3%KJeyO z<5IyGU|Epxl_OJryw%wxlmV3zt|uL5*w=f1Yx|q@CH(~#1Q*!x3i@B$Q0Z~)v-CJ( zGFw`~lOAk7)OiMjkjO*F9#&OsQnbNvFJ?afZs53RRPt6C+jJi$Hfo?f*`eIS&n*W z{c1Dg)b3r%hK|WUiXM9$XBiIjj?3j3`|3Tpsu=bS@I&M3EjuAImenlxMA(6`;iB$+ zAgH!r@}kia@&S?)Ne`&TXPQ_Y%c3uEIt~%>MHR%UcG=64c_}r{PkqaI=la=P$?l<>5X@1NP21i4@010y-skAUcr$wI?!a zIi_V-9P~k9>x0-alVQ}E|EayegJS`1E?$^}J$)PkXU|Q9e2%($cGq_(Z^z3LQAx#t zIOh@DYK~U$&9$pFl2#b;jN`2N>0tD%Zt1^{=brFMhMs4DrKDZOM~M=Vy2XVS2kk<8 zuu=%?SffN-@Y;wdg@FW8Y5Xroc_?dU+&y@amfIo8CWByt#qJG7T~soSQW7Gi*xjSG z-EBOM{x6KQh(=0d(ob9%@Ft04>gf^TLuf#VSmhw%2$)haPXzJ_kv7NYEm2iJ1I`U$ z-o)8k$I3vY13q7lkcqEUXHXrRv%L%1$Wi%(JaH64mgUv3;C=QUWV-MF>M3A5u9ID5 zP#ukfu-QDf@#hp|Mu%gAx+I?Iu)M*=!rx{r;1_3AQ$pRznr;7t_O#cbcpOROxHTY| z9+jpLpsRNPTheB8-;)z4tS4L-hrL%j?Ah!)@OaCoj^0GAwhPSk;TG!_mXKoDl6a zNhHCVCkxj6#qe&UBu}W&v2S3uFxifX1StHr4E#@}0u2ol1qBIwl2tA9MO;+CiQRRX zR6G!9r>0|!&LY7$Q8eBVV@aHg*`rv0%A@KF^Pmaghp5?P-Gn(M0UJFl7!d}d2m+`n zai$Q`y%B(kp1I)_q=FI%Qu84#rl>IqyM$@UmmQN)5rtP2a6z%qUbcbwQetmp@x;yeTZVlE7Z1~su2n6flcVelU@@#>ZBoTwDJ;2nS;6aIq59LX`qCF^zb k8PX9@SdJ(1>wgVq?aUw6j}gf*{*^OP^y$e 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

jG&jh5tymq* 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 Ad;kCd diff --git a/server/技术设计.md b/server/技术设计.md index 958fdd1..d88fc35 100644 --- a/server/技术设计.md +++ b/server/技术设计.md @@ -406,6 +406,7 @@ training: - `localAi` 配置节点:键与取值以 config.yml 为准,文档不复制具体数值(曾多次调整阈值致双源漂移,2026-09-02 起删除此类描述)——**部署前提:RF-DETR 服务须从 Go 服务器可达**(现跑在 Mac 上,部署时搬服务器/训练机;**未配置时图片上传/生成接口直接报错**——标注是强语义,不允许产生无标注图片;配置调不通则任务 failed,页顶错误条展示,不自动重试);**端点为配置唯一来源,无运行时覆盖** - **预标注自动触发(2026-08-26 决策,无手动按钮)**:手动上传/AI 生成图片入库成功后,自动对**本次新增图**发起标注;**`localAi` 未配置 → 上传/生成接口直接报错**(同步检查,生成场景在第一张生成前检查避免付费资产生成后标不了);**已有 running 标注任务(忙)→ 不报错**:上传/生成照常成功,新图由「任务成功完成后自动补标未标注图」机制兜底(每轮任务成功结束时检查该数据集**从未扫描过**的图(labels 为 null/''),有则自动续一轮——失败任务不续,防配置坏时无限重试;**2026-09-02 空检出图不入自动补标池**:检出为空的图写 `labels_json='[]'` 后仍被视作未标注(管理端未标注 tab 照常展示等人工画框),但不入自动池——空检出图若留池,每轮自动续一轮只会扫到别的空图、扫完又轮回来:RNPHE_202(阈值调高后 0 检出,低阈下 12 个候选全为噪声,无一过丢弃线)单张被上一版「排除本轮已扫图」恰好挡住未暴露,2026-09-02 兔子批量 3 张空检出实测 {9}→{10,17}→{9}… 无限交替、每轮白打一次 RF-DETR 方暴露;现自动链条只扫从未扫描的图,每张图至多被自动扫一次,空检出图确需重扫由人工触发(按文件名批量/全量任务,见下));service 逐张调 local-ai 推理(common 池并行,`label_task` 记录 total/done 进度)→ 扫描结果(YOLO 归一化 xywh + 置信度 + 建议类别)**直写 `dataset_image.labels_json`(重跑覆盖该图标注)**;**置信度分档(2026-09-02 起按两档语义调定,具体数值以 config.yml 为准不在此复制)**:conf ≥ confConfirmed 落 class 0 真目标,threshold ≤ conf < confConfirmed 落 class 1 疑似待人工复核,低于 threshold 不入库;背景(RNPHE_257 实测):COCO 通用 rfdetr 对类鸟纹理误检置信度可达 0.46~0.5 且与真目标仅差 ~0.1(真目标 0.562、两误检 0.477/0.462 曾全落 class 0),低置信段是纯噪声候选(该图 21 个原始检出中 17 个落此区间);单阈值无法分离真/假目标(类别名也无用——全部输出 "bird");误检落 class 0 会作为雉鸡正样本直接污染训练集,危害大于真目标降级疑似(后者人工一键确认即可);**重叠去重(2026-08-26 修订)**:NMS 风格、按置信度降序依次保留,与已保留框**重叠比(minIoU = 交叠面积/两框较小面积)> `localAi.overlapThreshold`**的框剔除(同目标被重复检出只留置信度最高者,跨 class 去重;人工画框不参与去重)——**用 minIoU 而非 IoU**:RF-DETR 对同一目标常输出一大一小两个框(标准 IoU 仅 0.3~0.5 会漏杀,实测红黄重叠即此形态),大框套小框时小框被覆盖比例高,minIoU 命中;相邻目标两框互有外露,minIoU 通常 < 0.3;**全图扫描**(项目既定规则:不套用生成规格的位置裁剪,候选宁多勿漏);**单图框数上限(2026-09-02,定义于 consts.go `consts.MaxPrelabelPerImage`)**:去重后仍超上限按置信度取前 N(曾按生成声明数 animal_count 裁剪致漏目标——声明 1 个不代表图内只有 1 个;手动上传图同限);不设候选确认两阶段(2026-08-26 撤销 candidates_json);`POST /admin/label-tasks` 接口保留(服务端 `filenames` 参数支持指定图批量重标,2026-09-02 前端入口收敛后仍可全量——不传 filenames 即全量扫描) +- **预标注四级漏斗(2026-09-04,树栖藏匿难例)**:树冠藏匿生成图(树栖物种目标仅占画面高 ~2%)在全图扫描下不可检——模型包固定 700x700 stretch 输入(见「预标注模型固定 700x700」,不支持动态分辨率,提高提交分辨率无增益),占图高 2% 的目标等比缩入后仅 ~15px 落在检出盲区。单张处理升级为逐级漏斗,**检测只信 RF-DETR,VLM 永不直接出框(只提议候选区)**:①**全图扫描**(现有 `Detect`,`localAi.threshold`)有候选即收(绝大多数图到此命中,不触发后级);②空检出 → **切片扫描**:`common.TileRegions` 滑窗切块(块长边/重叠比 = `localAi.tileSize`/`tileOverlap`,边缘块贴边收口保证全覆盖)逐块 `DetectRegion` 按低阈值(`localAi.tileThreshold`,小目标置信度天然偏低,量级取 RF-DETR-S 实测经验;低于全图丢弃线的候选仍入库落疑似 class 1,宁多勿漏)检测,块内坐标在 DetectRegion 内映射回原图像素,跨块重复检出由既有 minIoU 去重兜住;③仍空 → **VLM 提议候选区**:qwen3-vl-8b 按「宁可指错不可遗漏」提示词输出 ≤`consts.VlmLocateMaxRegions` 个归一化候选区(与手动藏匿位补检不同:此阶段图内无已确认框,无排除集;物种注入同 vlm-review——`gen_species` 空回退数据集名),逐区扩大 `consts.VlmRegionExpand` 倍(VLM 坐标偏粗,扩大给 RF-DETR 足够上下文,钳制图片边界)后 `DetectRegion` 精修,精修命中的框才采纳、未命中丢弃(VLM 误报被 RF-DETR 否掉);**VLM 失败/超时/输出非法一律跳过该级不阻塞任务**(三模型共存 + local-ai 服务端排队串行,无需显存互斥检查,2026-09-02 已放开);④全空 → 写 `'[]'`(语义不变:未标注 tab 展示等人工画框、不入自动补标池防乒乓)。漏斗各级候选同通道处理:conf ≥ confConfirmed 落 class 0、否则 class 1、minIoU 去重、单图上限 `consts.MaxPrelabelPerImage`,全图扫描不套生成规格的项目规则不变。单图超时 120s → `consts.LabelImageTimeoutSec`(切片 ~20 块串行 + VLM 兜底;切片在单图池任务内串行执行,不嵌套协程池) - **手动标注入口收敛(2026-09-02 决策)**:详情页删除「全量标注」按钮与图片卡片「审核」按钮,**标注入口仅两处(勾选图片驱动,顶栏)**:①「预标」= POST `/admin/label-tasks` 传选中图 `filenames`(只扫选中图,覆盖各图已有标注);②「补标」= 对选中图逐张 POST `/datasets/images/vlm-review`(VLM 藏匿位补检,追加疑似框,批量=前端循环单图接口,依赖已确认框作为排除基准)——VLM 补检按钮从标注编辑器迁出(2026-09-02);点卡片缩略图仍进人工编辑器(确认/清理/画框,编辑器内不再有 VLM 按钮),编辑器文案「图片审核」→「图片标注」;服务端全量重标能力保留但不再有 UI 入口 - **详情页布局(2026-09-02 卡片化改版后快照)**:图片以缩略图卡片网格展示(每页 18 张,点卡片进弹窗编辑器);页顶标注/AI 生成任务进度条;**图片列表三 tab(2026-09-02)**:「未标注」(默认,待处理优先)、「已标注」、**「已清洗」**各带计数——已标注判定 = labels_json 非空(空检出 `[]` 的图仍在未标注,等人工画框);**已清洗 tab = clean_excluded=1 的图(数据清洗执行后从已标注 tab 移入,卡片角标同 tab 语义二选一),内提供逐张/批量恢复(= 清除标记,回「已标注」)**,恢复仅动作无删除;「数据清洗」按钮在已标注 tab 工具条(分析/执行入口,见下节);切 tab/翻页均清空勾选(防跨 tab 误标),编辑器「上一张/下一张」仅在当前 tab 列表内导航(连续标注不串到另一分类);**卡片上不再叠「已标注/未标注」角标**(2026-09-02,分类由 tab 表达),仅保留 AI 来源角标(付费资产提示) - **弹窗标注**:点击原图/标注图打开放大弹窗(大 canvas,1152x2048 原尺寸),支持两点画框/点框删除/清空/类别切换(确认 0/疑似 1)/上下一张/保存——**AI 自动标注与人工框同层可编辑**(含清理 AI 框);保存即整体覆写 `dataset_image.labels_json`(JSON 数组,YOLO 归一化 xywh+类别+置信度,空=清空标注);未保存修改切换图片有确认