- 标注:AI 预标注直写 labels_json(去候选确认两阶段);重叠去重(minIoU);全量标注按钮 - 训练:脚本迁移入 server/training/(Go 化 prepare_yolo/analyze_rfdetr,保留 train_server.py);tflite 产物自检并入训练流程(check_tflite) - 数据目录/权重不进 git;.gitignore 迁移至仓库根
142 lines
4.8 KiB
Go
142 lines
4.8 KiB
Go
package dao
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
|
|
"observer-server/biz/consts"
|
|
"observer-server/biz/model/entity"
|
|
"observer-server/common"
|
|
)
|
|
|
|
// DatasetImage 数据集图片表 DAO:文件名唯一(防重名),按数据集查询;表小不做缓存。
|
|
type datasetImageDao struct{}
|
|
|
|
var DatasetImage = &datasetImageDao{}
|
|
|
|
func init() {
|
|
ctx := context.Background()
|
|
_, err := g.DB().Exec(ctx, `CREATE TABLE IF NOT EXISTS dataset_image (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
dataset_id INTEGER NOT NULL,
|
|
filename TEXT NOT NULL,
|
|
source TEXT NOT NULL DEFAULT 'manual',
|
|
prompt TEXT,
|
|
labels_json TEXT,
|
|
created_at TEXT NOT NULL,
|
|
UNIQUE (dataset_id, filename)
|
|
)`)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// 存量库迁移:标注列缺失时追加(新库建表已含列,幂等跳过);candidates_json 已随 v10 删除
|
|
common.EnsureColumn(ctx, consts.TableDatasetImage, "labels_json", "labels_json TEXT")
|
|
}
|
|
|
|
// Insert 插入图片记录
|
|
func (d *datasetImageDao) Insert(ctx context.Context, m *entity.DatasetImage) (int64, error) {
|
|
res, err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).Data(g.Map{
|
|
"dataset_id": m.DatasetId,
|
|
"filename": m.Filename,
|
|
"source": m.Source,
|
|
"prompt": m.Prompt,
|
|
"created_at": m.CreatedAt,
|
|
}).Insert()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return res.LastInsertId()
|
|
}
|
|
|
|
// ListByDataset 某数据集全部图片(文件名倒序,详情页逐行展示用)
|
|
func (d *datasetImageDao) ListByDataset(ctx context.Context, datasetId int64) ([]*entity.DatasetImage, error) {
|
|
var list []*entity.DatasetImage
|
|
err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).
|
|
Where("dataset_id", datasetId).OrderDesc("filename").Scan(&list)
|
|
if err != nil {
|
|
if common.IsNoRows(err) {
|
|
return []*entity.DatasetImage{}, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
// ListUnlabeledByDataset 未标注图片(labels_json 为空/null/'[]';自动补标轮次用)
|
|
func (d *datasetImageDao) ListUnlabeledByDataset(ctx context.Context, datasetId int64) ([]*entity.DatasetImage, error) {
|
|
var list []*entity.DatasetImage
|
|
err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).
|
|
Where("dataset_id", datasetId).
|
|
Where("labels_json IS NULL OR labels_json = '' OR labels_json = '[]'").
|
|
OrderAsc("id").Scan(&list)
|
|
if err != nil {
|
|
if common.IsNoRows(err) {
|
|
return []*entity.DatasetImage{}, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
// GetByIds 按 id 批量取(删除图片定位文件用)
|
|
func (d *datasetImageDao) GetByIds(ctx context.Context, ids []int64) ([]*entity.DatasetImage, error) {
|
|
var list []*entity.DatasetImage
|
|
err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).WhereIn("id", ids).Scan(&list)
|
|
if err != nil {
|
|
if common.IsNoRows(err) {
|
|
return []*entity.DatasetImage{}, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
// GetByFilename 按文件名取(图片访问校验归属)
|
|
func (d *datasetImageDao) GetByFilename(ctx context.Context, datasetId int64, filename string) (*entity.DatasetImage, error) {
|
|
var e entity.DatasetImage
|
|
err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).
|
|
Where("dataset_id", datasetId).Where("filename", filename).Scan(&e)
|
|
if err != nil {
|
|
if common.IsNoRows(err) {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
return &e, nil
|
|
}
|
|
|
|
// CountByDataset 某数据集图片数
|
|
func (d *datasetImageDao) CountByDataset(ctx context.Context, datasetId int64) (int64, error) {
|
|
n, err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).Where("dataset_id", datasetId).Count()
|
|
return int64(n), err
|
|
}
|
|
|
|
// UpdateLabels 覆写标注 JSON(整图粒度;空串=清空标注;AI 自动标注与人工保存共用)
|
|
func (d *datasetImageDao) UpdateLabels(ctx context.Context, id int64, labelsJson string) error {
|
|
_, err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).Where("id", id).
|
|
Data(g.Map{"labels_json": labelsJson}).Update()
|
|
return err
|
|
}
|
|
|
|
// CountLabeledByDataset 某数据集已标注图片数(labels_json 非空数组的图片行数)
|
|
func (d *datasetImageDao) CountLabeledByDataset(ctx context.Context, datasetId int64) (int64, error) {
|
|
n, err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).
|
|
Where("dataset_id", datasetId).
|
|
Where("labels_json IS NOT NULL AND labels_json != '' AND labels_json != '[]'").
|
|
Count()
|
|
return int64(n), err
|
|
}
|
|
|
|
// DeleteByIds 按 id 批量删除(标注随行删除)
|
|
func (d *datasetImageDao) DeleteByIds(ctx context.Context, ids []int64) error {
|
|
_, err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).WhereIn("id", ids).Delete()
|
|
return err
|
|
}
|
|
|
|
// DeleteByDataset 删除某数据集全部图片记录(删数据集联动)
|
|
func (d *datasetImageDao) DeleteByDataset(ctx context.Context, datasetId int64) error {
|
|
_, err := g.DB().Model(consts.TableDatasetImage).Ctx(ctx).Where("dataset_id", datasetId).Delete()
|
|
return err
|
|
}
|