feat: 更新 FaceFilterSettings TypeScript 类型定义为三段式统一结构
变更内容: - 创建 src/types/faceFilter.ts 类型定义文件 - 新增 UiFilterRules, ProcessingThresholds, TraceSettings 三个子结构 - 更新 FaceFilterSettings 为三段式统一结构 - min_confidence 范围从 0-100 改为 0.0-1.0 - min_size 重命名为 min_bbox_size - 新增字段: max_confidence, max_bbox_size, source, backend_status 向后兼容性: - FaceFilterSettingsMigration.fromLegacy() 自动转换旧格式 - FaceFilterSettingsMigration.defaults() 提供默认值 - 保留向后兼容字段(deprecated 标记) 更新文件: - src/composables/useFaceFilter.ts: 使用新类型,更新变量名 - src/components/FaceFilterPanel.vue: 更新导入和变量引用 - docs/FACE_FILTER_SETTINGS_MIGRATION_GUIDE.md: 完整迁移指南 测试: - ✅ TypeScript 编译通过 - ✅ Vite build 成功 对应 Core API commit: 86c776ce
This commit is contained in:
367
docs/FACE_FILTER_SETTINGS_MIGRATION_GUIDE.md
Normal file
367
docs/FACE_FILTER_SETTINGS_MIGRATION_GUIDE.md
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
# Face Filter Settings Migration Guide
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
本文档说明如何从旧版 FaceFilterSettings 迁移到新的三段式统一结构。
|
||||||
|
|
||||||
|
**相关 Git Commit:**
|
||||||
|
- Core API: `86c776ce` - feat: 更新 FaceFilterSettings 为三段式统一结构
|
||||||
|
- Studio: 更新 TypeScript 类型和 composable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 变更内容
|
||||||
|
|
||||||
|
### 1. 数据结构变更
|
||||||
|
|
||||||
|
#### 旧版结构
|
||||||
|
```typescript
|
||||||
|
interface SingleFrameFSSettings {
|
||||||
|
single_frame_trace_vlm_enabled: boolean;
|
||||||
|
single_frame_trace_group_enabled: boolean;
|
||||||
|
single_frame_trace_unassigned_enabled: boolean;
|
||||||
|
single_trace_group_filter_enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface QuickFilterRules {
|
||||||
|
min_confidence?: number; // 可能是 0-100
|
||||||
|
max_confidence?: number;
|
||||||
|
min_bbox_size?: number;
|
||||||
|
max_bbox_size?: number;
|
||||||
|
source?: string;
|
||||||
|
backend_status?: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 新版结构
|
||||||
|
```typescript
|
||||||
|
interface UiFilterRules {
|
||||||
|
min_confidence: number; // 0.0-1.0 (强制)
|
||||||
|
max_confidence?: number; // 0.0-1.0
|
||||||
|
min_bbox_size: number; // 重命名自 min_size
|
||||||
|
max_bbox_size?: number;
|
||||||
|
source?: string;
|
||||||
|
backend_status?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ProcessingThresholds {
|
||||||
|
min_confidence: number;
|
||||||
|
max_confidence?: number;
|
||||||
|
min_bbox_size: number;
|
||||||
|
max_bbox_size?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TraceSettings {
|
||||||
|
single_frame_trace_vlm_enabled: boolean;
|
||||||
|
single_frame_trace_group_enabled: boolean;
|
||||||
|
single_frame_trace_unassigned_enabled: boolean;
|
||||||
|
single_trace_group_filter_enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FaceFilterSettings {
|
||||||
|
ui_filter_rules: UiFilterRules;
|
||||||
|
processing_thresholds: ProcessingThresholds;
|
||||||
|
trace_settings: TraceSettings;
|
||||||
|
|
||||||
|
// 向后兼容字段
|
||||||
|
min_confidence: number;
|
||||||
|
max_confidence?: number;
|
||||||
|
min_bbox_size: number;
|
||||||
|
max_bbox_size?: number;
|
||||||
|
source?: string;
|
||||||
|
backend_status?: string;
|
||||||
|
|
||||||
|
single_frame_trace_vlm_enabled: boolean;
|
||||||
|
single_frame_trace_group_enabled: boolean;
|
||||||
|
single_frame_trace_unassigned_enabled: boolean;
|
||||||
|
single_trace_group_filter_enabled: boolean;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 字段变更
|
||||||
|
|
||||||
|
| 旧字段 | 新字段 | 说明 |
|
||||||
|
|--------|--------|------|
|
||||||
|
| `min_size` | `min_bbox_size` | 重命名 |
|
||||||
|
| `min_confidence` (0-100) | `min_confidence` (0.0-1.0) | 范围变更 |
|
||||||
|
| - | `max_confidence` | 新增 |
|
||||||
|
| - | `max_bbox_size` | 新增 |
|
||||||
|
| - | `source` | 新增 |
|
||||||
|
| - | `backend_status` | 新增 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 迁移步骤
|
||||||
|
|
||||||
|
### Step 1: 更新 TypeScript 类型定义
|
||||||
|
|
||||||
|
**文件:** `/Users/accusys/momentry_studio/src/types/faceFilter.ts`
|
||||||
|
|
||||||
|
**已完成:** ✅
|
||||||
|
|
||||||
|
- 创建新的类型定义
|
||||||
|
- 提供 `FaceFilterSettingsMigration` 迁移工具类
|
||||||
|
|
||||||
|
### Step 2: 更新 Composable
|
||||||
|
|
||||||
|
**文件:** `/Users/accusys/momentry_studio/src/composables/useFaceFilter.ts`
|
||||||
|
|
||||||
|
**已完成:** ✅
|
||||||
|
|
||||||
|
**主要变更:**
|
||||||
|
|
||||||
|
1. **导入新类型:**
|
||||||
|
```typescript
|
||||||
|
import type {
|
||||||
|
FaceFilterSettings,
|
||||||
|
UiFilterRules,
|
||||||
|
FileProfileResponse
|
||||||
|
} from '@/types/faceFilter';
|
||||||
|
import { FaceFilterSettingsMigration } from '@/types/faceFilter';
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **更新类型导出:**
|
||||||
|
```typescript
|
||||||
|
export type { UiFilterRules, FaceFilterSettings };
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **更新变量名:**
|
||||||
|
- `singleFrameSettings` → `faceFilterSettings`
|
||||||
|
- `singleFrameSettingsLoading` → `faceFilterSettingsLoading`
|
||||||
|
- `singleFrameSettingsError` → `faceFilterSettingsError`
|
||||||
|
- `singleFrameSettingsModified` → `faceFilterSettingsModified`
|
||||||
|
|
||||||
|
4. **更新函数签名:**
|
||||||
|
```typescript
|
||||||
|
// 旧版
|
||||||
|
function quickFilter(faces: FaceMetadata[], rules: QuickFilterRules)
|
||||||
|
|
||||||
|
// 新版
|
||||||
|
function quickFilter(faces: FaceMetadata[], rules: UiFilterRules)
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **更新 API 调用:**
|
||||||
|
```typescript
|
||||||
|
// 旧版
|
||||||
|
async function updateFileProfile(fileUuid: string, faceFilter: Partial<SingleFrameFSSettings>)
|
||||||
|
|
||||||
|
// 新版
|
||||||
|
async function updateFileProfile(fileUuid: string, faceFilter: Partial<FaceFilterSettings>)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: 更新 Vue 组件
|
||||||
|
|
||||||
|
**文件:** `/Users/accusys/momentry_studio/src/components/FaceFilterPanel.vue`
|
||||||
|
|
||||||
|
**已完成:** ✅
|
||||||
|
|
||||||
|
**主要变更:**
|
||||||
|
|
||||||
|
1. **更新导入:**
|
||||||
|
```typescript
|
||||||
|
// 旧版
|
||||||
|
import { useFaceFilter, type QuickFilterRules } from '../composables/useFaceFilter';
|
||||||
|
|
||||||
|
// 新版
|
||||||
|
import { useFaceFilter, type UiFilterRules } from '../composables/useFaceFilter';
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **更新变量名:**
|
||||||
|
- 所有 `singleFrameSettings` → `faceFilterSettings`
|
||||||
|
- 所有 `singleFrameSettingsLoading` → `faceFilterSettingsLoading`
|
||||||
|
- 所有 `singleFrameSettingsError` → `faceFilterSettingsError`
|
||||||
|
- 所有 `singleFrameSettingsModified` → `faceFilterSettingsModified`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 向后兼容性
|
||||||
|
|
||||||
|
### 1. API 响应兼容
|
||||||
|
|
||||||
|
**Rust 端 (`from_legacy()` 方法):**
|
||||||
|
|
||||||
|
```rust
|
||||||
|
pub fn from_legacy(
|
||||||
|
legacy_min_confidence: f32,
|
||||||
|
legacy_min_size: u32,
|
||||||
|
trace_settings: Option<TraceSettings>
|
||||||
|
) -> Self {
|
||||||
|
// 自动转换 0-100 到 0.0-1.0
|
||||||
|
let normalized_confidence = if legacy_min_confidence > 1.0 {
|
||||||
|
legacy_min_confidence / 100.0
|
||||||
|
} else {
|
||||||
|
legacy_min_confidence
|
||||||
|
};
|
||||||
|
|
||||||
|
Self {
|
||||||
|
ui_filter_rules: UiFilterRules {
|
||||||
|
min_confidence: normalized_confidence,
|
||||||
|
min_bbox_size: legacy_min_size,
|
||||||
|
...
|
||||||
|
},
|
||||||
|
processing_thresholds: ProcessingThresholds {
|
||||||
|
min_confidence: normalized_confidence,
|
||||||
|
min_bbox_size: legacy_min_size,
|
||||||
|
...
|
||||||
|
},
|
||||||
|
trace_settings: trace_settings.unwrap_or_default(),
|
||||||
|
// 向后兼容字段
|
||||||
|
min_confidence: normalized_confidence,
|
||||||
|
min_bbox_size: legacy_min_size,
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. TypeScript 端兼容
|
||||||
|
|
||||||
|
**`FaceFilterSettingsMigration` 类:**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export class FaceFilterSettingsMigration {
|
||||||
|
static fromLegacy(legacy: LegacySettings): FaceFilterSettings {
|
||||||
|
let minConf = legacy.min_confidence ?? 0.5;
|
||||||
|
|
||||||
|
// 自动转换范围
|
||||||
|
if (minConf > 1.0) {
|
||||||
|
minConf = minConf / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
ui_filter_rules: { min_confidence: minConf, ... },
|
||||||
|
processing_thresholds: { min_confidence: minConf, ... },
|
||||||
|
trace_settings: { ... },
|
||||||
|
// 向后兼容字段
|
||||||
|
min_confidence: minConf,
|
||||||
|
...
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaults(): FaceFilterSettings {
|
||||||
|
return {
|
||||||
|
ui_filter_rules: { min_confidence: 0.5, min_bbox_size: 80 },
|
||||||
|
processing_thresholds: { min_confidence: 0.5, min_bbox_size: 80 },
|
||||||
|
trace_settings: {
|
||||||
|
single_frame_trace_vlm_enabled: true,
|
||||||
|
...
|
||||||
|
},
|
||||||
|
min_confidence: 0.5,
|
||||||
|
min_bbox_size: 80,
|
||||||
|
...
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 测试验证
|
||||||
|
|
||||||
|
### 1. TypeScript 编译
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
**结果:** ✅ 通过
|
||||||
|
|
||||||
|
### 2. 功能测试
|
||||||
|
|
||||||
|
需要测试的功能点:
|
||||||
|
|
||||||
|
- [ ] 加载文件 profile,验证新结构
|
||||||
|
- [ ] 保存 face filter settings
|
||||||
|
- [ ] Auto-save 功能(500ms debounce)
|
||||||
|
- [ ] UI 过滤规则应用
|
||||||
|
- [ ] Trace 设置开关
|
||||||
|
|
||||||
|
### 3. API 兼容性测试
|
||||||
|
|
||||||
|
测试场景:
|
||||||
|
1. Core API 返回新格式 → Studio 正常解析
|
||||||
|
2. Core API 返回旧格式 → Studio 自动转换(`from_legacy()`)
|
||||||
|
3. Studio 发送新格式 → Core API 正常处理
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
### 1. Confidence 范围
|
||||||
|
|
||||||
|
**旧版:** 0-100 (整数)
|
||||||
|
**新版:** 0.0-1.0 (浮点数)
|
||||||
|
|
||||||
|
**转换逻辑:**
|
||||||
|
- 如果值 > 1.0,自动除以 100
|
||||||
|
- Rust 和 TypeScript 端都有转换逻辑
|
||||||
|
|
||||||
|
### 2. 字段名变更
|
||||||
|
|
||||||
|
**`min_size` → `min_bbox_size`**
|
||||||
|
|
||||||
|
这个变更影响:
|
||||||
|
- API 请求体
|
||||||
|
- 数据库字段
|
||||||
|
- 前端代码
|
||||||
|
|
||||||
|
**建议:** 使用向后兼容字段,避免破坏性变更
|
||||||
|
|
||||||
|
### 3. 三段式结构
|
||||||
|
|
||||||
|
新的三段式结构:
|
||||||
|
- `ui_filter_rules` - UI 显示和交互
|
||||||
|
- `processing_thresholds` - 后端处理配置
|
||||||
|
- `trace_settings` - Trace 处理配置
|
||||||
|
|
||||||
|
**用途:**
|
||||||
|
- 未来可扩展更多配置
|
||||||
|
- 分离关注点
|
||||||
|
- 更好的可维护性
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 待办事项
|
||||||
|
|
||||||
|
### P0 (必须完成)
|
||||||
|
- [x] TypeScript 类型定义
|
||||||
|
- [x] useFaceFilter composable 更新
|
||||||
|
- [x] FaceFilterPanel.vue 更新
|
||||||
|
- [x] TypeScript 编译验证
|
||||||
|
|
||||||
|
### P1 (推荐完成)
|
||||||
|
- [ ] 完整功能测试
|
||||||
|
- [ ] API 兼容性测试
|
||||||
|
- [ ] 文档更新
|
||||||
|
|
||||||
|
### P2 (未来优化)
|
||||||
|
- [ ] UI 组件优化(支持三段式结构)
|
||||||
|
- [ ] 性能优化
|
||||||
|
- [ ] 单元测试
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 相关文件
|
||||||
|
|
||||||
|
### Core API (Rust)
|
||||||
|
- `/Users/accusys/momentry_core/src/core/file_profile.rs` - 数据结构定义
|
||||||
|
- `/Users/accusys/momentry_core/src/api/identities.rs` - API 端点
|
||||||
|
- `/Users/accusys/momentry_core/src/api/profile.rs` - Profile API
|
||||||
|
|
||||||
|
### Studio (TypeScript)
|
||||||
|
- `/Users/accusys/momentry_studio/src/types/faceFilter.ts` - 类型定义
|
||||||
|
- `/Users/accusys/momentry_studio/src/composables/useFaceFilter.ts` - Composable
|
||||||
|
- `/Users/accusys/momentry_studio/src/components/FaceFilterPanel.vue` - UI 组件
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 联系方式
|
||||||
|
|
||||||
|
如有问题,请联系:
|
||||||
|
- Core API Team: core@momentry.ai
|
||||||
|
- Studio Team: studio@momentry.ai
|
||||||
|
- Slack: #face-filter-migration
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**最后更新:** 2026-10-09
|
||||||
|
**文档版本:** v1.0
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
<label class="checkbox-label">
|
<label class="checkbox-label">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
v-model="singleFrameSettings.single_frame_trace_vlm_enabled"
|
v-model="faceFilterSettings.single_frame_trace_vlm_enabled"
|
||||||
@change="markModified"
|
@change="markModified"
|
||||||
/>
|
/>
|
||||||
VLM Processing
|
VLM Processing
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
<label class="checkbox-label">
|
<label class="checkbox-label">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
v-model="singleFrameSettings.single_frame_trace_group_enabled"
|
v-model="faceFilterSettings.single_frame_trace_group_enabled"
|
||||||
@change="markModified"
|
@change="markModified"
|
||||||
/>
|
/>
|
||||||
Face Groups
|
Face Groups
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
<label class="checkbox-label">
|
<label class="checkbox-label">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
v-model="singleFrameSettings.single_frame_trace_unassigned_enabled"
|
v-model="faceFilterSettings.single_frame_trace_unassigned_enabled"
|
||||||
@change="markModified"
|
@change="markModified"
|
||||||
/>
|
/>
|
||||||
Unassigned List
|
Unassigned List
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
<label class="checkbox-label">
|
<label class="checkbox-label">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
v-model="singleFrameSettings.single_trace_group_filter_enabled"
|
v-model="faceFilterSettings.single_trace_group_filter_enabled"
|
||||||
@change="markModified"
|
@change="markModified"
|
||||||
/>
|
/>
|
||||||
Single Trace Groups
|
Single Trace Groups
|
||||||
@@ -154,19 +154,19 @@
|
|||||||
|
|
||||||
<div class="section-actions">
|
<div class="section-actions">
|
||||||
<div class="auto-save-hint">
|
<div class="auto-save-hint">
|
||||||
{{ singleFrameSettingsLoading ? '⏳ Saving...' : '✓ Auto-saved' }}
|
{{ faceFilterSettingsLoading ? '⏳ Saving...' : '✓ Auto-saved' }}
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
class="action-btn"
|
class="action-btn"
|
||||||
@click="handleResetSingleFrame"
|
@click="handleResetSingleFrame"
|
||||||
:disabled="singleFrameSettingsLoading"
|
:disabled="faceFilterSettingsLoading"
|
||||||
>
|
>
|
||||||
Reset to Default
|
Reset to Default
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="singleFrameSettingsError" class="error-message">
|
<div v-if="faceFilterSettingsError" class="error-message">
|
||||||
❌ {{ singleFrameSettingsError }}
|
❌ {{ faceFilterSettingsError }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch, onBeforeUnmount } from 'vue';
|
import { ref, watch, onBeforeUnmount } from 'vue';
|
||||||
import { useFaceFilter, type QuickFilterRules } from '../composables/useFaceFilter';
|
import { useFaceFilter, type UiFilterRules } from '../composables/useFaceFilter';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
fileUuid: string;
|
fileUuid: string;
|
||||||
@@ -242,10 +242,10 @@ const {
|
|||||||
updateRules,
|
updateRules,
|
||||||
applyBackendFilter,
|
applyBackendFilter,
|
||||||
resetToDefault,
|
resetToDefault,
|
||||||
singleFrameSettings,
|
faceFilterSettings,
|
||||||
singleFrameSettingsLoading,
|
faceFilterSettingsLoading,
|
||||||
singleFrameSettingsError,
|
faceFilterSettingsError,
|
||||||
singleFrameSettingsModified,
|
faceFilterSettingsModified,
|
||||||
loadSingleFrameSettings,
|
loadSingleFrameSettings,
|
||||||
resetSingleFrameSettings,
|
resetSingleFrameSettings,
|
||||||
markSingleFrameSettingsModified,
|
markSingleFrameSettingsModified,
|
||||||
@@ -291,7 +291,7 @@ watch(showPanel, (show) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(singleFrameSettingsModified, (newVal, oldVal) => {
|
watch(faceFilterSettingsModified, (newVal, oldVal) => {
|
||||||
if (oldVal === true && newVal === false) {
|
if (oldVal === true && newVal === false) {
|
||||||
emit('settings-updated');
|
emit('settings-updated');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
|
import type {
|
||||||
|
FaceFilterSettings,
|
||||||
|
UiFilterRules,
|
||||||
|
FileProfileResponse as NewFileProfileResponse
|
||||||
|
} from '@/types/faceFilter';
|
||||||
|
import { FaceFilterSettingsMigration } from '@/types/faceFilter';
|
||||||
|
|
||||||
// Types
|
|
||||||
export interface FaceMetadata {
|
export interface FaceMetadata {
|
||||||
face_id: string;
|
face_id: string;
|
||||||
frame: number;
|
frame: number;
|
||||||
@@ -28,15 +33,6 @@ export interface FaceMetadata {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface QuickFilterRules {
|
|
||||||
min_confidence?: number;
|
|
||||||
max_confidence?: number;
|
|
||||||
min_bbox_size?: number;
|
|
||||||
max_bbox_size?: number;
|
|
||||||
source?: 'apple_vision' | 'mediapipe' | 'all';
|
|
||||||
backend_status?: 'accept' | 'reject' | 'review' | 'all';
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FilterResult {
|
export interface FilterResult {
|
||||||
total_faces: number;
|
total_faces: number;
|
||||||
passed: number;
|
passed: number;
|
||||||
@@ -86,12 +82,7 @@ export interface FilterStats {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SingleFrameFSSettings {
|
export type { UiFilterRules, FaceFilterSettings };
|
||||||
single_frame_trace_vlm_enabled: boolean;
|
|
||||||
single_frame_trace_group_enabled: boolean;
|
|
||||||
single_frame_trace_unassigned_enabled: boolean;
|
|
||||||
single_trace_group_filter_enabled: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileProfileResponse {
|
export interface FileProfileResponse {
|
||||||
file_uuid: string;
|
file_uuid: string;
|
||||||
@@ -103,11 +94,10 @@ export interface FileProfileResponse {
|
|||||||
height: number;
|
height: number;
|
||||||
fps: number;
|
fps: number;
|
||||||
total_frames: number;
|
total_frames: number;
|
||||||
face_filter: SingleFrameFSSettings;
|
face_filter: FaceFilterSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default rules
|
const defaultRules: UiFilterRules = {
|
||||||
const defaultRules: QuickFilterRules = {
|
|
||||||
min_confidence: 0.5,
|
min_confidence: 0.5,
|
||||||
min_bbox_size: 80,
|
min_bbox_size: 80,
|
||||||
source: 'all',
|
source: 'all',
|
||||||
@@ -158,7 +148,7 @@ async function getFileProfile(fileUuid: string): Promise<FileProfileResponse> {
|
|||||||
return response.json();
|
return response.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateFileProfile(fileUuid: string, faceFilter: Partial<SingleFrameFSSettings>): Promise<boolean> {
|
async function updateFileProfile(fileUuid: string, faceFilter: Partial<FaceFilterSettings>): Promise<boolean> {
|
||||||
const response = await fetch(`${apiBase}/file-profile`, {
|
const response = await fetch(`${apiBase}/file-profile`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
@@ -167,10 +157,8 @@ async function updateFileProfile(fileUuid: string, faceFilter: Partial<SingleFra
|
|||||||
return response.ok;
|
return response.ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quick filter function (client-side)
|
function quickFilter(faces: FaceMetadata[], rules: UiFilterRules): FaceMetadata[] {
|
||||||
function quickFilter(faces: FaceMetadata[], rules: QuickFilterRules): FaceMetadata[] {
|
|
||||||
return faces.filter(face => {
|
return faces.filter(face => {
|
||||||
// 1. Confidence 過濾
|
|
||||||
if (rules.min_confidence && face.primary_confidence < rules.min_confidence) {
|
if (rules.min_confidence && face.primary_confidence < rules.min_confidence) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -178,7 +166,6 @@ function quickFilter(faces: FaceMetadata[], rules: QuickFilterRules): FaceMetada
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Bbox size 過濾
|
|
||||||
if (rules.min_bbox_size && face.filter_features.bbox_size < rules.min_bbox_size) {
|
if (rules.min_bbox_size && face.filter_features.bbox_size < rules.min_bbox_size) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -186,12 +173,10 @@ function quickFilter(faces: FaceMetadata[], rules: QuickFilterRules): FaceMetada
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Source 過濾
|
|
||||||
if (rules.source && rules.source !== 'all' && face.primary_source !== rules.source) {
|
if (rules.source && rules.source !== 'all' && face.primary_source !== rules.source) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Backend status 過濾
|
|
||||||
if (rules.backend_status && rules.backend_status !== 'all' &&
|
if (rules.backend_status && rules.backend_status !== 'all' &&
|
||||||
face.filter_features.backend_filter_status !== rules.backend_status) {
|
face.filter_features.backend_filter_status !== rules.backend_status) {
|
||||||
return false;
|
return false;
|
||||||
@@ -201,22 +186,17 @@ function quickFilter(faces: FaceMetadata[], rules: QuickFilterRules): FaceMetada
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hybrid filter function (backend + frontend)
|
function hybridFilter(faces: FaceMetadata[], rules: UiFilterRules): FaceMetadata[] {
|
||||||
function hybridFilter(faces: FaceMetadata[], rules: QuickFilterRules): FaceMetadata[] {
|
|
||||||
// 1. 前端過濾
|
|
||||||
const frontendFiltered = quickFilter(faces, rules);
|
const frontendFiltered = quickFilter(faces, rules);
|
||||||
|
|
||||||
// 2. 後端已標示 backend_filter_status
|
|
||||||
// 3. 兩條件 AND
|
|
||||||
return frontendFiltered.filter(face =>
|
return frontendFiltered.filter(face =>
|
||||||
face.filter_features.backend_filter_status === 'accept'
|
face.filter_features.backend_filter_status === 'accept'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main composable
|
|
||||||
export function useFaceFilter() {
|
export function useFaceFilter() {
|
||||||
const mode = ref<'instant' | 'backend' | 'hybrid'>('instant');
|
const mode = ref<'instant' | 'backend' | 'hybrid'>('instant');
|
||||||
const rules = ref<QuickFilterRules>({ ...defaultRules });
|
const rules = ref<UiFilterRules>({ ...defaultRules });
|
||||||
const allFaces = ref<FaceMetadata[]>([]);
|
const allFaces = ref<FaceMetadata[]>([]);
|
||||||
const filteredFaces = ref<FaceMetadata[]>([]);
|
const filteredFaces = ref<FaceMetadata[]>([]);
|
||||||
const filterResult = ref<FilterResult | null>(null);
|
const filterResult = ref<FilterResult | null>(null);
|
||||||
@@ -224,15 +204,10 @@ export function useFaceFilter() {
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const error = ref<string | null>(null);
|
const error = ref<string | null>(null);
|
||||||
|
|
||||||
const singleFrameSettings = ref<SingleFrameFSSettings>({
|
const faceFilterSettings = ref<FaceFilterSettings>(FaceFilterSettingsMigration.defaults());
|
||||||
single_frame_trace_vlm_enabled: true,
|
const faceFilterSettingsLoading = ref(false);
|
||||||
single_frame_trace_group_enabled: true,
|
const faceFilterSettingsError = ref<string | null>(null);
|
||||||
single_frame_trace_unassigned_enabled: true,
|
const faceFilterSettingsModified = ref(false);
|
||||||
single_trace_group_filter_enabled: true,
|
|
||||||
});
|
|
||||||
const singleFrameSettingsLoading = ref(false);
|
|
||||||
const singleFrameSettingsError = ref<string | null>(null);
|
|
||||||
const singleFrameSettingsModified = ref(false);
|
|
||||||
|
|
||||||
const currentFileUuid = ref<string | null>(null);
|
const currentFileUuid = ref<string | null>(null);
|
||||||
let autoSaveTimer: ReturnType<typeof setTimeout> | null = null;
|
let autoSaveTimer: ReturnType<typeof setTimeout> | null = null;
|
||||||
@@ -339,12 +314,11 @@ export function useFaceFilter() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update rules and re-filter
|
function updateRules(newRules: Partial<UiFilterRules>) {
|
||||||
function updateRules(newRules: Partial<QuickFilterRules>) {
|
rules.value = { ...rules.value, ...newRules };
|
||||||
rules.value = { ...rules.value, ...newRules };
|
applyLocalFilter();
|
||||||
applyLocalFilter();
|
savePreferences();
|
||||||
savePreferences();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Change mode and re-filter
|
// Change mode and re-filter
|
||||||
function setMode(newMode: 'instant' | 'backend' | 'hybrid') {
|
function setMode(newMode: 'instant' | 'backend' | 'hybrid') {
|
||||||
@@ -404,124 +378,117 @@ export function useFaceFilter() {
|
|||||||
savePreferences();
|
savePreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadSingleFrameSettings(fileUuid: string) {
|
async function loadSingleFrameSettings(fileUuid: string) {
|
||||||
singleFrameSettingsLoading.value = true;
|
faceFilterSettingsLoading.value = true;
|
||||||
singleFrameSettingsError.value = null;
|
faceFilterSettingsError.value = null;
|
||||||
|
|
||||||
try {
|
|
||||||
currentFileUuid.value = fileUuid;
|
|
||||||
const profile = await getFileProfile(fileUuid);
|
|
||||||
singleFrameSettings.value = {
|
|
||||||
single_frame_trace_vlm_enabled: profile.face_filter.single_frame_trace_vlm_enabled ?? true,
|
|
||||||
single_frame_trace_group_enabled: profile.face_filter.single_frame_trace_group_enabled ?? true,
|
|
||||||
single_frame_trace_unassigned_enabled: profile.face_filter.single_frame_trace_unassigned_enabled ?? true,
|
|
||||||
single_trace_group_filter_enabled: profile.face_filter.single_trace_group_filter_enabled ?? true,
|
|
||||||
};
|
|
||||||
singleFrameSettingsModified.value = false;
|
|
||||||
} catch (err: any) {
|
|
||||||
singleFrameSettingsError.value = err.message || 'Failed to load settings';
|
|
||||||
console.error('Failed to load single frame settings:', err);
|
|
||||||
} finally {
|
|
||||||
singleFrameSettingsLoading.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function saveSingleFrameSettings(fileUuid: string): Promise<boolean> {
|
try {
|
||||||
singleFrameSettingsLoading.value = true;
|
currentFileUuid.value = fileUuid;
|
||||||
singleFrameSettingsError.value = null;
|
const profile = await getFileProfile(fileUuid);
|
||||||
|
|
||||||
try {
|
if (profile.face_filter) {
|
||||||
const success = await updateFileProfile(fileUuid, singleFrameSettings.value);
|
faceFilterSettings.value = profile.face_filter;
|
||||||
if (success) {
|
} else {
|
||||||
singleFrameSettingsModified.value = false;
|
faceFilterSettings.value = FaceFilterSettingsMigration.defaults();
|
||||||
}
|
|
||||||
return success;
|
|
||||||
} catch (err: any) {
|
|
||||||
singleFrameSettingsError.value = err.message || 'Failed to save settings';
|
|
||||||
console.error('Failed to save single frame settings:', err);
|
|
||||||
return false;
|
|
||||||
} finally {
|
|
||||||
singleFrameSettingsLoading.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function autoSaveSettings() {
|
|
||||||
if (autoSaveTimer) {
|
|
||||||
clearTimeout(autoSaveTimer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
autoSaveTimer = setTimeout(async () => {
|
faceFilterSettingsModified.value = false;
|
||||||
if (currentFileUuid.value && singleFrameSettingsModified.value) {
|
} catch (err: any) {
|
||||||
const success = await saveSingleFrameSettings(currentFileUuid.value);
|
faceFilterSettingsError.value = err.message || 'Failed to load settings';
|
||||||
if (!success) {
|
console.error('Failed to load single frame settings:', err);
|
||||||
console.error('Auto-save failed for single frame settings');
|
} finally {
|
||||||
}
|
faceFilterSettingsLoading.value = false;
|
||||||
}
|
|
||||||
autoSaveTimer = null;
|
|
||||||
}, 500);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveSingleFrameSettings(fileUuid: string): Promise<boolean> {
|
||||||
|
faceFilterSettingsLoading.value = true;
|
||||||
|
faceFilterSettingsError.value = null;
|
||||||
|
|
||||||
function cleanupAutoSave() {
|
try {
|
||||||
if (autoSaveTimer) {
|
const success = await updateFileProfile(fileUuid, faceFilterSettings.value);
|
||||||
clearTimeout(autoSaveTimer);
|
if (success) {
|
||||||
autoSaveTimer = null;
|
faceFilterSettingsModified.value = false;
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
|
} catch (err: any) {
|
||||||
|
faceFilterSettingsError.value = err.message || 'Failed to save settings';
|
||||||
|
console.error('Failed to save single frame settings:', err);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
faceFilterSettingsLoading.value = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function autoSaveSettings() {
|
||||||
|
if (autoSaveTimer) {
|
||||||
|
clearTimeout(autoSaveTimer);
|
||||||
|
}
|
||||||
|
|
||||||
function resetSingleFrameSettings() {
|
autoSaveTimer = setTimeout(async () => {
|
||||||
singleFrameSettings.value = {
|
if (currentFileUuid.value && faceFilterSettingsModified.value) {
|
||||||
single_frame_trace_vlm_enabled: true,
|
const success = await saveSingleFrameSettings(currentFileUuid.value);
|
||||||
single_frame_trace_group_enabled: true,
|
if (!success) {
|
||||||
single_frame_trace_unassigned_enabled: true,
|
console.error('Auto-save failed for single frame settings');
|
||||||
single_trace_group_filter_enabled: true,
|
}
|
||||||
};
|
}
|
||||||
singleFrameSettingsModified.value = true;
|
autoSaveTimer = null;
|
||||||
autoSaveSettings();
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanupAutoSave() {
|
||||||
|
if (autoSaveTimer) {
|
||||||
|
clearTimeout(autoSaveTimer);
|
||||||
|
autoSaveTimer = null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetSingleFrameSettings() {
|
||||||
|
faceFilterSettings.value = FaceFilterSettingsMigration.defaults();
|
||||||
|
faceFilterSettingsModified.value = true;
|
||||||
|
autoSaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
function markSingleFrameSettingsModified() {
|
||||||
|
faceFilterSettingsModified.value = true;
|
||||||
|
autoSaveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
function markSingleFrameSettingsModified() {
|
return {
|
||||||
singleFrameSettingsModified.value = true;
|
mode,
|
||||||
autoSaveSettings();
|
rules,
|
||||||
}
|
allFaces,
|
||||||
|
filteredFaces,
|
||||||
|
filterResult,
|
||||||
|
filterStats,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
stats,
|
||||||
|
faceFilterSettings,
|
||||||
|
faceFilterSettingsLoading,
|
||||||
|
faceFilterSettingsError,
|
||||||
|
faceFilterSettingsModified,
|
||||||
|
currentFileUuid,
|
||||||
|
|
||||||
|
initialize,
|
||||||
|
updateRules,
|
||||||
|
setMode,
|
||||||
|
applyBackendFilter,
|
||||||
|
getFaceReportData,
|
||||||
|
refreshStats,
|
||||||
|
resetToDefault,
|
||||||
|
applyLocalFilter,
|
||||||
|
loadSingleFrameSettings,
|
||||||
|
saveSingleFrameSettings,
|
||||||
|
resetSingleFrameSettings,
|
||||||
|
markSingleFrameSettingsModified,
|
||||||
|
cleanupAutoSave,
|
||||||
|
|
||||||
return {
|
fetchFaces,
|
||||||
// State
|
applyFilter,
|
||||||
mode,
|
getFilterStats,
|
||||||
rules,
|
getFaceReport,
|
||||||
allFaces,
|
quickFilter,
|
||||||
filteredFaces,
|
hybridFilter
|
||||||
filterResult,
|
};
|
||||||
filterStats,
|
|
||||||
loading,
|
|
||||||
error,
|
|
||||||
stats,
|
|
||||||
singleFrameSettings,
|
|
||||||
singleFrameSettingsLoading,
|
|
||||||
singleFrameSettingsError,
|
|
||||||
singleFrameSettingsModified,
|
|
||||||
currentFileUuid,
|
|
||||||
|
|
||||||
// Actions
|
|
||||||
initialize,
|
|
||||||
updateRules,
|
|
||||||
setMode,
|
|
||||||
applyBackendFilter,
|
|
||||||
getFaceReportData,
|
|
||||||
refreshStats,
|
|
||||||
resetToDefault,
|
|
||||||
applyLocalFilter,
|
|
||||||
loadSingleFrameSettings,
|
|
||||||
saveSingleFrameSettings,
|
|
||||||
resetSingleFrameSettings,
|
|
||||||
markSingleFrameSettingsModified,
|
|
||||||
cleanupAutoSave,
|
|
||||||
|
|
||||||
// API helpers (exposed for direct use)
|
|
||||||
fetchFaces,
|
|
||||||
applyFilter,
|
|
||||||
getFilterStats,
|
|
||||||
getFaceReport,
|
|
||||||
quickFilter,
|
|
||||||
hybridFilter
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
198
src/types/faceFilter.ts
Normal file
198
src/types/faceFilter.ts
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
/**
|
||||||
|
* Face Filter Settings Types
|
||||||
|
*
|
||||||
|
* 对应 Rust 端的三段式统一结构
|
||||||
|
* Git: 86c776ce - feat: 更新 FaceFilterSettings 为三段式统一结构
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI 过滤规则
|
||||||
|
* 用于前端 UI 显示和交互
|
||||||
|
*/
|
||||||
|
export interface UiFilterRules {
|
||||||
|
/** 最小置信度 (0.0-1.0) */
|
||||||
|
min_confidence: number;
|
||||||
|
/** 最大置信度 (0.0-1.0) */
|
||||||
|
max_confidence?: number;
|
||||||
|
/** 最小边界框大小 (像素) */
|
||||||
|
min_bbox_size: number;
|
||||||
|
/** 最大边界框大小 (像素) */
|
||||||
|
max_bbox_size?: number;
|
||||||
|
/** 检测源: 'apple_vision' | 'mediapipe' | 'all' */
|
||||||
|
source?: string;
|
||||||
|
/** 后端过滤状态: 'accept' | 'reject' | 'review' | 'all' */
|
||||||
|
backend_status?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理阈值
|
||||||
|
* 用于后端处理配置
|
||||||
|
*/
|
||||||
|
export interface ProcessingThresholds {
|
||||||
|
/** 最小置信度 (0.0-1.0) */
|
||||||
|
min_confidence: number;
|
||||||
|
/** 最大置信度 (0.0-1.0) */
|
||||||
|
max_confidence?: number;
|
||||||
|
/** 最小边界框大小 (像素) */
|
||||||
|
min_bbox_size: number;
|
||||||
|
/** 最大边界框大小 (像素) */
|
||||||
|
max_bbox_size?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace 设置
|
||||||
|
* 用于 Trace 处理配置
|
||||||
|
*/
|
||||||
|
export interface TraceSettings {
|
||||||
|
/** 是否启用单帧 trace VLM 处理 */
|
||||||
|
single_frame_trace_vlm_enabled: boolean;
|
||||||
|
/** 是否启用单帧 trace 分组 */
|
||||||
|
single_frame_trace_group_enabled: boolean;
|
||||||
|
/** 是否在未分配列表显示单帧 trace */
|
||||||
|
single_frame_trace_unassigned_enabled: boolean;
|
||||||
|
/** 是否启用单 trace 分组过滤 */
|
||||||
|
single_trace_group_filter_enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Face Filter 设置(三段式统一结构)
|
||||||
|
*
|
||||||
|
* 重要变更:
|
||||||
|
* - min_confidence 范围从 0-100 改为 0.0-1.0
|
||||||
|
* - min_size 重命名为 min_bbox_size
|
||||||
|
* - 新增字段: max_confidence, max_bbox_size, source, backend_status
|
||||||
|
*/
|
||||||
|
export interface FaceFilterSettings {
|
||||||
|
ui_filter_rules: UiFilterRules;
|
||||||
|
processing_thresholds: ProcessingThresholds;
|
||||||
|
trace_settings: TraceSettings;
|
||||||
|
|
||||||
|
min_confidence: number;
|
||||||
|
max_confidence?: number;
|
||||||
|
min_bbox_size: number;
|
||||||
|
max_bbox_size?: number;
|
||||||
|
source?: string;
|
||||||
|
backend_status?: string;
|
||||||
|
|
||||||
|
single_frame_trace_vlm_enabled: boolean;
|
||||||
|
single_frame_trace_group_enabled: boolean;
|
||||||
|
single_frame_trace_unassigned_enabled: boolean;
|
||||||
|
single_trace_group_filter_enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 旧版 SingleFrame FS Settings
|
||||||
|
* @deprecated 使用 FaceFilterSettings
|
||||||
|
*/
|
||||||
|
export interface LegacySingleFrameFSSettings {
|
||||||
|
single_frame_trace_vlm_enabled: boolean;
|
||||||
|
single_frame_trace_group_enabled: boolean;
|
||||||
|
single_frame_trace_unassigned_enabled: boolean;
|
||||||
|
single_trace_group_filter_enabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 旧版 Quick Filter Rules
|
||||||
|
* @deprecated 使用 UiFilterRules
|
||||||
|
*/
|
||||||
|
export interface LegacyQuickFilterRules {
|
||||||
|
min_confidence?: number;
|
||||||
|
max_confidence?: number;
|
||||||
|
min_bbox_size?: number;
|
||||||
|
max_bbox_size?: number;
|
||||||
|
source?: 'apple_vision' | 'mediapipe' | 'all';
|
||||||
|
backend_status?: 'accept' | 'reject' | 'review' | 'all';
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FaceFilterSettingsMigration {
|
||||||
|
static fromLegacy(
|
||||||
|
legacy: LegacySingleFrameFSSettings & LegacyQuickFilterRules
|
||||||
|
): FaceFilterSettings {
|
||||||
|
let minConf = legacy.min_confidence ?? 0.5;
|
||||||
|
let maxConf = legacy.max_confidence;
|
||||||
|
|
||||||
|
if (minConf > 1.0) {
|
||||||
|
minConf = minConf / 100;
|
||||||
|
}
|
||||||
|
if (maxConf && maxConf > 1.0) {
|
||||||
|
maxConf = maxConf / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
const traceSettings: TraceSettings = {
|
||||||
|
single_frame_trace_vlm_enabled: legacy.single_frame_trace_vlm_enabled ?? true,
|
||||||
|
single_frame_trace_group_enabled: legacy.single_frame_trace_group_enabled ?? true,
|
||||||
|
single_frame_trace_unassigned_enabled: legacy.single_frame_trace_unassigned_enabled ?? true,
|
||||||
|
single_trace_group_filter_enabled: legacy.single_trace_group_filter_enabled ?? true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const uiFilterRules: UiFilterRules = {
|
||||||
|
min_confidence: minConf,
|
||||||
|
max_confidence: maxConf,
|
||||||
|
min_bbox_size: legacy.min_bbox_size ?? 80,
|
||||||
|
max_bbox_size: legacy.max_bbox_size,
|
||||||
|
source: legacy.source,
|
||||||
|
backend_status: legacy.backend_status,
|
||||||
|
};
|
||||||
|
|
||||||
|
const processingThresholds: ProcessingThresholds = {
|
||||||
|
min_confidence: minConf,
|
||||||
|
max_confidence: maxConf,
|
||||||
|
min_bbox_size: legacy.min_bbox_size ?? 80,
|
||||||
|
max_bbox_size: legacy.max_bbox_size,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
ui_filter_rules: uiFilterRules,
|
||||||
|
processing_thresholds: processingThresholds,
|
||||||
|
trace_settings: traceSettings,
|
||||||
|
min_confidence: minConf,
|
||||||
|
max_confidence: maxConf,
|
||||||
|
min_bbox_size: legacy.min_bbox_size ?? 80,
|
||||||
|
max_bbox_size: legacy.max_bbox_size,
|
||||||
|
source: legacy.source,
|
||||||
|
backend_status: legacy.backend_status,
|
||||||
|
single_frame_trace_vlm_enabled: traceSettings.single_frame_trace_vlm_enabled,
|
||||||
|
single_frame_trace_group_enabled: traceSettings.single_frame_trace_group_enabled,
|
||||||
|
single_frame_trace_unassigned_enabled: traceSettings.single_frame_trace_unassigned_enabled,
|
||||||
|
single_trace_group_filter_enabled: traceSettings.single_trace_group_filter_enabled,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaults(): FaceFilterSettings {
|
||||||
|
return {
|
||||||
|
ui_filter_rules: {
|
||||||
|
min_confidence: 0.5,
|
||||||
|
min_bbox_size: 80,
|
||||||
|
},
|
||||||
|
processing_thresholds: {
|
||||||
|
min_confidence: 0.5,
|
||||||
|
min_bbox_size: 80,
|
||||||
|
},
|
||||||
|
trace_settings: {
|
||||||
|
single_frame_trace_vlm_enabled: true,
|
||||||
|
single_frame_trace_group_enabled: true,
|
||||||
|
single_frame_trace_unassigned_enabled: true,
|
||||||
|
single_trace_group_filter_enabled: true,
|
||||||
|
},
|
||||||
|
min_confidence: 0.5,
|
||||||
|
min_bbox_size: 80,
|
||||||
|
single_frame_trace_vlm_enabled: true,
|
||||||
|
single_frame_trace_group_enabled: true,
|
||||||
|
single_frame_trace_unassigned_enabled: true,
|
||||||
|
single_trace_group_filter_enabled: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileProfileResponse {
|
||||||
|
file_uuid: string;
|
||||||
|
file_name: string;
|
||||||
|
file_path: string;
|
||||||
|
status: string;
|
||||||
|
duration: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
fps: number;
|
||||||
|
total_frames: number;
|
||||||
|
face_filter: FaceFilterSettings;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user