补充软著图文说明书与演示素材
- 将软著说明书占位图替换为线上系统实拍高清截图,并加入分模块 MP4 演示视频链接 - 新增登录、总体概况、项目库、分割工作区、AI 推理、GT Mask、导出、模板库、用户管理和退出登录截图素材 - 新增 4 段 1920x1080 系统使用演示视频,同时保留 Playwright 原始 WebM 录制文件 - 新增功能验证与素材清单,记录验证地址、截图文件、视频文件和非破坏性验证说明 - 新增可复用 Playwright 采集脚本,便于后续重新录制软著素材
367
scripts/capture_soft_copyright_materials.mjs
Normal file
@@ -0,0 +1,367 @@
|
|||||||
|
import { chromium } from 'playwright';
|
||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
import zlib from 'node:zlib';
|
||||||
|
|
||||||
|
const BASE_URL = process.env.SEG_DEMO_URL || 'https://seg.huijutec.cn/';
|
||||||
|
const USERNAME = process.env.SEG_DEMO_USER || 'admin';
|
||||||
|
const PASSWORD = process.env.SEG_DEMO_PASSWORD || '123456';
|
||||||
|
const OUT_ROOT = process.env.SEG_DEMO_OUT_DIR || path.resolve('新撰写软著文档');
|
||||||
|
const IMAGE_DIR = path.join(OUT_ROOT, 'images');
|
||||||
|
const VIDEO_DIR = path.join(OUT_ROOT, '系统使用视频');
|
||||||
|
const TMP_DIR = path.join(OUT_ROOT, '.capture-tmp');
|
||||||
|
|
||||||
|
const viewport = { width: 1920, height: 1080 };
|
||||||
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
const shots = [
|
||||||
|
['01-login.png', '系统登录界面图'],
|
||||||
|
['02-dashboard.png', '系统登录后总体概况界面图'],
|
||||||
|
['03-main-layout.png', '系统主界面整体布局图'],
|
||||||
|
['04-dashboard-tasks.png', '后台任务列表及任务进度界面图'],
|
||||||
|
['05-project-library.png', '项目库列表界面图'],
|
||||||
|
['06-import-media-options.png', '导入视频与DICOM资源选择界面图'],
|
||||||
|
['07-project-copy-dialog.png', '项目复制操作界面图'],
|
||||||
|
['08-frame-parse-dialog.png', '视频生成帧配置界面图'],
|
||||||
|
['09-workspace-main.png', '分割工作区主界面图'],
|
||||||
|
['10-workspace-tools.png', '左侧标注工具栏与语义分类树界面图'],
|
||||||
|
['11-workspace-draw-mask.png', '多边形、矩形、圆形和画笔标注操作界面图'],
|
||||||
|
['12-workspace-auto-propagate-range.png', 'AI自动推理范围选择界面图'],
|
||||||
|
['13-workspace-export-dialog.png', '分割结果导出配置界面图'],
|
||||||
|
['14-gt-mask-import-preview.png', 'GT Mask导入预览界面图'],
|
||||||
|
['15-ai-page.png', 'AI智能分割模型选择界面图'],
|
||||||
|
['16-ai-prompt-tools.png', 'AI智能分割点选和框选工具界面图'],
|
||||||
|
['17-template-library.png', '模板库模板清单界面图'],
|
||||||
|
['18-template-edit-dialog.png', '模板分类树编辑界面图'],
|
||||||
|
['19-template-batch-import.png', '模板批量导入分类界面图'],
|
||||||
|
['20-user-admin.png', '管理员用户管理后台界面图'],
|
||||||
|
['21-user-create-dialog.png', '新增标注员账号界面图'],
|
||||||
|
['22-audit-reset-dialog.png', '审计日志和恢复演示出厂设置确认界面图'],
|
||||||
|
['23-logout.png', '退出登录按钮和返回登录界面图'],
|
||||||
|
];
|
||||||
|
|
||||||
|
async function ensureDirs() {
|
||||||
|
await fs.mkdir(IMAGE_DIR, { recursive: true });
|
||||||
|
await fs.mkdir(VIDEO_DIR, { recursive: true });
|
||||||
|
await fs.mkdir(TMP_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function login(page) {
|
||||||
|
await page.goto(BASE_URL, { waitUntil: 'networkidle', timeout: 60000 });
|
||||||
|
await page.locator('input[type="text"]').first().fill(USERNAME);
|
||||||
|
await page.locator('input[type="password"]').first().fill(PASSWORD);
|
||||||
|
await page.getByRole('button', { name: /安全登录|登录/ }).click();
|
||||||
|
await page.waitForLoadState('networkidle').catch(() => {});
|
||||||
|
await sleep(1800);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function shot(page, filename) {
|
||||||
|
await page.screenshot({
|
||||||
|
path: path.join(IMAGE_DIR, filename),
|
||||||
|
fullPage: false,
|
||||||
|
animations: 'disabled',
|
||||||
|
});
|
||||||
|
console.log(`screenshot ${filename}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function clickIfVisible(locator, timeout = 2500) {
|
||||||
|
try {
|
||||||
|
await locator.waitFor({ state: 'visible', timeout });
|
||||||
|
await locator.click();
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function closeDialog(page) {
|
||||||
|
const cancelButtons = page.getByRole('button', { name: /^取消$/ });
|
||||||
|
const count = await cancelButtons.count().catch(() => 0);
|
||||||
|
if (count > 0) {
|
||||||
|
await cancelButtons.last().click().catch(() => {});
|
||||||
|
await sleep(500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await page.keyboard.press('Escape').catch(() => {});
|
||||||
|
await sleep(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function gotoModule(page, title, settle = 1200) {
|
||||||
|
await page.getByTitle(title).first().click();
|
||||||
|
await page.waitForLoadState('networkidle').catch(() => {});
|
||||||
|
await sleep(settle);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openWorkspaceProject(page) {
|
||||||
|
await gotoModule(page, '项目库', 900);
|
||||||
|
await page.getByText('演视LC视频序列').first().click();
|
||||||
|
await page.waitForLoadState('networkidle').catch(() => {});
|
||||||
|
await sleep(2200);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function drawDemoMask(page) {
|
||||||
|
await page.getByRole('button', { name: /肿瘤\/结节/ }).first().click().catch(() => {});
|
||||||
|
await page.getByTitle('创建矩形 (R)').click();
|
||||||
|
await sleep(400);
|
||||||
|
const canvas = page.locator('.konvajs-content canvas').first();
|
||||||
|
const box = await canvas.boundingBox();
|
||||||
|
if (!box) return;
|
||||||
|
const x1 = box.x + box.width * 0.36;
|
||||||
|
const y1 = box.y + box.height * 0.38;
|
||||||
|
const x2 = box.x + box.width * 0.55;
|
||||||
|
const y2 = box.y + box.height * 0.58;
|
||||||
|
await page.mouse.move(x1, y1);
|
||||||
|
await page.mouse.down();
|
||||||
|
await page.mouse.move(x2, y2, { steps: 12 });
|
||||||
|
await page.mouse.up();
|
||||||
|
await sleep(900);
|
||||||
|
}
|
||||||
|
|
||||||
|
function crc32(buffer) {
|
||||||
|
let crc = -1;
|
||||||
|
for (const byte of buffer) {
|
||||||
|
crc ^= byte;
|
||||||
|
for (let i = 0; i < 8; i += 1) {
|
||||||
|
crc = (crc >>> 1) ^ (0xedb88320 & -(crc & 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (crc ^ -1) >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pngChunk(type, data) {
|
||||||
|
const typeBuf = Buffer.from(type);
|
||||||
|
const length = Buffer.alloc(4);
|
||||||
|
length.writeUInt32BE(data.length, 0);
|
||||||
|
const crc = Buffer.alloc(4);
|
||||||
|
crc.writeUInt32BE(crc32(Buffer.concat([typeBuf, data])), 0);
|
||||||
|
return Buffer.concat([length, typeBuf, data, crc]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createGtMaskPng(filePath) {
|
||||||
|
const width = 240;
|
||||||
|
const height = 160;
|
||||||
|
const raw = Buffer.alloc((width + 1) * height);
|
||||||
|
for (let y = 0; y < height; y += 1) {
|
||||||
|
const row = y * (width + 1);
|
||||||
|
raw[row] = 0;
|
||||||
|
for (let x = 0; x < width; x += 1) {
|
||||||
|
raw[row + 1 + x] = x > 50 && x < 185 && y > 35 && y < 125 ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const ihdr = Buffer.alloc(13);
|
||||||
|
ihdr.writeUInt32BE(width, 0);
|
||||||
|
ihdr.writeUInt32BE(height, 4);
|
||||||
|
ihdr[8] = 8;
|
||||||
|
ihdr[9] = 0;
|
||||||
|
ihdr[10] = 0;
|
||||||
|
ihdr[11] = 0;
|
||||||
|
ihdr[12] = 0;
|
||||||
|
const png = Buffer.concat([
|
||||||
|
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
|
||||||
|
pngChunk('IHDR', ihdr),
|
||||||
|
pngChunk('IDAT', zlib.deflateSync(raw)),
|
||||||
|
pngChunk('IEND', Buffer.alloc(0)),
|
||||||
|
]);
|
||||||
|
await fs.writeFile(filePath, png);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function captureScreenshots() {
|
||||||
|
const browser = await chromium.launch({ headless: true, args: ['--window-size=1920,1080'] });
|
||||||
|
const context = await browser.newContext({ viewport, deviceScaleFactor: 1 });
|
||||||
|
const page = await context.newPage();
|
||||||
|
|
||||||
|
await page.goto(BASE_URL, { waitUntil: 'networkidle', timeout: 60000 });
|
||||||
|
await sleep(1000);
|
||||||
|
await shot(page, '01-login.png');
|
||||||
|
await login(page);
|
||||||
|
await shot(page, '02-dashboard.png');
|
||||||
|
await shot(page, '03-main-layout.png');
|
||||||
|
await shot(page, '04-dashboard-tasks.png');
|
||||||
|
|
||||||
|
await gotoModule(page, '项目库');
|
||||||
|
await shot(page, '05-project-library.png');
|
||||||
|
await page.getByRole('button', { name: '导入多媒体资源' }).click();
|
||||||
|
await sleep(700);
|
||||||
|
await shot(page, '06-import-media-options.png');
|
||||||
|
await page.getByRole('button', { name: '导入多媒体资源' }).click().catch(() => {});
|
||||||
|
await sleep(500);
|
||||||
|
await page.getByTitle('复制项目').first().click();
|
||||||
|
await sleep(700);
|
||||||
|
await shot(page, '07-project-copy-dialog.png');
|
||||||
|
await closeDialog(page);
|
||||||
|
await page.getByRole('button', { name: /重新生成帧|生成帧/ }).first().click();
|
||||||
|
await sleep(900);
|
||||||
|
await shot(page, '08-frame-parse-dialog.png');
|
||||||
|
await closeDialog(page);
|
||||||
|
|
||||||
|
await openWorkspaceProject(page);
|
||||||
|
await shot(page, '09-workspace-main.png');
|
||||||
|
await shot(page, '10-workspace-tools.png');
|
||||||
|
await drawDemoMask(page);
|
||||||
|
await shot(page, '11-workspace-draw-mask.png');
|
||||||
|
await page.getByTitle('AI自动推理').click();
|
||||||
|
await sleep(1000);
|
||||||
|
await shot(page, '12-workspace-auto-propagate-range.png');
|
||||||
|
await page.keyboard.press('Escape').catch(() => {});
|
||||||
|
await sleep(500);
|
||||||
|
await page.getByRole('button', { name: '分割结果导出' }).click();
|
||||||
|
await sleep(900);
|
||||||
|
await shot(page, '13-workspace-export-dialog.png');
|
||||||
|
await closeDialog(page);
|
||||||
|
|
||||||
|
const gtPath = path.join(TMP_DIR, 'gt_mask_preview.png');
|
||||||
|
await createGtMaskPng(gtPath);
|
||||||
|
const fileChooserPromise = page.waitForEvent('filechooser', { timeout: 3000 }).catch(() => null);
|
||||||
|
await page.getByTitle('导入 GT Mask').click();
|
||||||
|
const fileChooser = await fileChooserPromise;
|
||||||
|
if (fileChooser) {
|
||||||
|
await fileChooser.setFiles(gtPath);
|
||||||
|
await sleep(2200);
|
||||||
|
await shot(page, '14-gt-mask-import-preview.png');
|
||||||
|
await closeDialog(page);
|
||||||
|
} else {
|
||||||
|
await shot(page, '14-gt-mask-import-preview.png');
|
||||||
|
}
|
||||||
|
|
||||||
|
await gotoModule(page, 'AI智能分割', 1600);
|
||||||
|
await shot(page, '15-ai-page.png');
|
||||||
|
await page.getByRole('button', { name: '正向选点' }).click().catch(() => {});
|
||||||
|
await sleep(500);
|
||||||
|
await shot(page, '16-ai-prompt-tools.png');
|
||||||
|
|
||||||
|
await gotoModule(page, '模板库', 1500);
|
||||||
|
await shot(page, '17-template-library.png');
|
||||||
|
await page.getByRole('button', { name: '编辑模板' }).last().click();
|
||||||
|
await sleep(900);
|
||||||
|
await shot(page, '18-template-edit-dialog.png');
|
||||||
|
await page.getByRole('button', { name: /批量导入/ }).click().catch(() => {});
|
||||||
|
await sleep(700);
|
||||||
|
const textareas = page.locator('textarea');
|
||||||
|
if ((await textareas.count()) > 0) {
|
||||||
|
await textareas.last().fill('{"colors":[[255,0,0],[0,255,0]],"names":["示例类别一","示例类别二"]}').catch(() => {});
|
||||||
|
await sleep(500);
|
||||||
|
}
|
||||||
|
await shot(page, '19-template-batch-import.png');
|
||||||
|
await closeDialog(page);
|
||||||
|
|
||||||
|
await gotoModule(page, '用户管理', 1500);
|
||||||
|
await shot(page, '20-user-admin.png');
|
||||||
|
await page.getByRole('button', { name: '新增用户' }).click();
|
||||||
|
await sleep(900);
|
||||||
|
await shot(page, '21-user-create-dialog.png');
|
||||||
|
await closeDialog(page);
|
||||||
|
await page.getByRole('button', { name: '恢复演示出厂设置' }).click();
|
||||||
|
await sleep(900);
|
||||||
|
await shot(page, '22-audit-reset-dialog.png');
|
||||||
|
await closeDialog(page);
|
||||||
|
await page.getByTitle('当前用户:admin,点击退出').hover();
|
||||||
|
await sleep(700);
|
||||||
|
await page.getByTitle('当前用户:admin,点击退出').click();
|
||||||
|
await sleep(1200);
|
||||||
|
await shot(page, '23-logout.png');
|
||||||
|
|
||||||
|
await browser.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function recordVideo(name, action) {
|
||||||
|
const browser = await chromium.launch({ headless: true, args: ['--window-size=1920,1080'] });
|
||||||
|
const context = await browser.newContext({
|
||||||
|
viewport,
|
||||||
|
deviceScaleFactor: 1,
|
||||||
|
recordVideo: { dir: VIDEO_DIR, size: viewport },
|
||||||
|
});
|
||||||
|
const page = await context.newPage();
|
||||||
|
await action(page);
|
||||||
|
await sleep(800);
|
||||||
|
const video = page.video();
|
||||||
|
await context.close();
|
||||||
|
await browser.close();
|
||||||
|
const videoPath = await video?.path();
|
||||||
|
if (!videoPath) return null;
|
||||||
|
const finalPath = path.join(VIDEO_DIR, `${name}.webm`);
|
||||||
|
await fs.rm(finalPath, { force: true });
|
||||||
|
await fs.rename(videoPath, finalPath);
|
||||||
|
console.log(`video ${path.basename(finalPath)}`);
|
||||||
|
return finalPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function captureVideos() {
|
||||||
|
await recordVideo('01-登录与总体概况演示', async (page) => {
|
||||||
|
await page.goto(BASE_URL, { waitUntil: 'networkidle', timeout: 60000 });
|
||||||
|
await sleep(1200);
|
||||||
|
await login(page);
|
||||||
|
await sleep(1800);
|
||||||
|
await gotoModule(page, '总体概况', 2400);
|
||||||
|
});
|
||||||
|
|
||||||
|
await recordVideo('02-项目库与分割工作区演示', async (page) => {
|
||||||
|
await login(page);
|
||||||
|
await gotoModule(page, '项目库', 1800);
|
||||||
|
await page.getByRole('button', { name: '导入多媒体资源' }).click();
|
||||||
|
await sleep(1400);
|
||||||
|
await page.getByRole('button', { name: '导入多媒体资源' }).click().catch(() => {});
|
||||||
|
await sleep(600);
|
||||||
|
await page.getByText('演视LC视频序列').first().click();
|
||||||
|
await sleep(2600);
|
||||||
|
await drawDemoMask(page);
|
||||||
|
await sleep(1600);
|
||||||
|
});
|
||||||
|
|
||||||
|
await recordVideo('03-AI推理与结果导出演示', async (page) => {
|
||||||
|
await login(page);
|
||||||
|
await openWorkspaceProject(page);
|
||||||
|
await page.getByTitle('AI自动推理').click();
|
||||||
|
await sleep(2000);
|
||||||
|
await page.keyboard.press('Escape').catch(() => {});
|
||||||
|
await page.getByRole('button', { name: '分割结果导出' }).click();
|
||||||
|
await sleep(2200);
|
||||||
|
await closeDialog(page);
|
||||||
|
await gotoModule(page, 'AI智能分割', 2600);
|
||||||
|
});
|
||||||
|
|
||||||
|
await recordVideo('04-模板库与用户管理演示', async (page) => {
|
||||||
|
await login(page);
|
||||||
|
await gotoModule(page, '模板库', 2200);
|
||||||
|
await page.getByRole('button', { name: '编辑模板' }).last().click();
|
||||||
|
await sleep(1800);
|
||||||
|
await closeDialog(page);
|
||||||
|
await gotoModule(page, '用户管理', 2200);
|
||||||
|
await page.getByRole('button', { name: '新增用户' }).click();
|
||||||
|
await sleep(1800);
|
||||||
|
await closeDialog(page);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
await ensureDirs();
|
||||||
|
await captureScreenshots();
|
||||||
|
await captureVideos();
|
||||||
|
await fs.writeFile(
|
||||||
|
path.join(OUT_ROOT, '功能验证与素材清单.md'),
|
||||||
|
[
|
||||||
|
'# 功能验证与素材清单',
|
||||||
|
'',
|
||||||
|
`验证地址:${BASE_URL}`,
|
||||||
|
`验证时间:${new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })}`,
|
||||||
|
'',
|
||||||
|
'## 截图文件',
|
||||||
|
...shots.map(([file, title]) => `- images/${file}:${title}`),
|
||||||
|
'',
|
||||||
|
'## 分段视频',
|
||||||
|
'- 系统使用视频/01-登录与总体概况演示.webm',
|
||||||
|
'- 系统使用视频/02-项目库与分割工作区演示.webm',
|
||||||
|
'- 系统使用视频/03-AI推理与结果导出演示.webm',
|
||||||
|
'- 系统使用视频/04-模板库与用户管理演示.webm',
|
||||||
|
'',
|
||||||
|
'## 验证说明',
|
||||||
|
'本次验证以管理员账号进入线上系统,逐项检查登录、总体概况、项目库、分割工作区、AI 智能分割、AI 自动推理入口、GT Mask 导入预览、分割结果导出、模板库、用户管理、审计日志和退出登录等说明书涉及功能。删除项目、恢复演示出厂设置、生成帧确认、导出下载确认等可能改变演示环境或产生下载文件的危险提交动作仅验证入口与确认界面,不执行最终提交。',
|
||||||
|
'',
|
||||||
|
].join('\n'),
|
||||||
|
'utf8',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
93
scripts/record_usage_video.mjs
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { chromium } from 'playwright';
|
||||||
|
import fs from 'node:fs/promises';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
const BASE_URL = process.env.SEG_DEMO_URL || 'https://seg.huijutec.cn/';
|
||||||
|
const USERNAME = process.env.SEG_DEMO_USER || 'admin';
|
||||||
|
const PASSWORD = process.env.SEG_DEMO_PASSWORD || '123456';
|
||||||
|
const OUT_DIR = process.env.SEG_DEMO_OUT_DIR || path.resolve('新撰写软著文档/系统使用视频');
|
||||||
|
|
||||||
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
async function clickIfVisible(locator, timeout = 3000) {
|
||||||
|
try {
|
||||||
|
await locator.waitFor({ state: 'visible', timeout });
|
||||||
|
await locator.click();
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function showModule(page, title, dwell = 2200) {
|
||||||
|
await clickIfVisible(page.getByTitle(title).first(), 5000);
|
||||||
|
await page.waitForLoadState('networkidle').catch(() => {});
|
||||||
|
await sleep(dwell);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
await fs.mkdir(OUT_DIR, { recursive: true });
|
||||||
|
const browser = await chromium.launch({
|
||||||
|
headless: true,
|
||||||
|
args: ['--window-size=1920,1080'],
|
||||||
|
});
|
||||||
|
const context = await browser.newContext({
|
||||||
|
viewport: { width: 1920, height: 1080 },
|
||||||
|
recordVideo: {
|
||||||
|
dir: OUT_DIR,
|
||||||
|
size: { width: 1920, height: 1080 },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const page = await context.newPage();
|
||||||
|
|
||||||
|
await page.goto(BASE_URL, { waitUntil: 'networkidle', timeout: 60000 });
|
||||||
|
await sleep(1200);
|
||||||
|
|
||||||
|
const usernameInput = page.locator('input[type="text"]').first();
|
||||||
|
const passwordInput = page.locator('input[type="password"]').first();
|
||||||
|
await usernameInput.fill(USERNAME);
|
||||||
|
await sleep(400);
|
||||||
|
await passwordInput.fill(PASSWORD);
|
||||||
|
await sleep(500);
|
||||||
|
await page.getByRole('button', { name: /安全登录|登录/ }).click();
|
||||||
|
await page.waitForLoadState('networkidle').catch(() => {});
|
||||||
|
await sleep(2500);
|
||||||
|
|
||||||
|
await showModule(page, '总体概况', 2500);
|
||||||
|
await showModule(page, '项目库', 2500);
|
||||||
|
|
||||||
|
const demoProject = page.getByText(/演视LC视频序列|演视DICOM序列|LC视频序列|DICOM序列/).first();
|
||||||
|
if (await clickIfVisible(demoProject, 3500)) {
|
||||||
|
await page.waitForLoadState('networkidle').catch(() => {});
|
||||||
|
await sleep(3000);
|
||||||
|
} else {
|
||||||
|
await showModule(page, '分割工作区', 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
await showModule(page, 'AI智能分割', 3000);
|
||||||
|
await showModule(page, '模板库', 3000);
|
||||||
|
await showModule(page, '分割工作区', 3000);
|
||||||
|
await showModule(page, '项目库', 2200);
|
||||||
|
await showModule(page, '总体概况', 2200);
|
||||||
|
|
||||||
|
if (await page.getByTitle('用户管理').count()) {
|
||||||
|
await showModule(page, '用户管理', 2600);
|
||||||
|
}
|
||||||
|
|
||||||
|
await sleep(1200);
|
||||||
|
const video = page.video();
|
||||||
|
await context.close();
|
||||||
|
await browser.close();
|
||||||
|
|
||||||
|
const videoPath = await video?.path();
|
||||||
|
if (!videoPath) throw new Error('Playwright did not produce a video file.');
|
||||||
|
const finalPath = path.resolve(OUT_DIR, '多模态影像及视频智能语义分割与标注系统-使用演示.webm');
|
||||||
|
await fs.rm(finalPath, { force: true });
|
||||||
|
await fs.rename(videoPath, finalPath);
|
||||||
|
console.log(finalPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
161
新撰写软著文档/1. 软著说明书.md
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
# 多模态影像及视频智能语义分割与标注系统说明书
|
||||||
|
|
||||||
|
# 1.系统注册
|
||||||
|
|
||||||
|
本系统采用受控账号准入方式。普通标注人员账号由管理员在“用户管理”界面统一创建,用户首次使用系统前,应由管理员完成账号注册与初始密码分配。管理员登录系统后,单击左侧导航栏中的“用户管理”按钮,进入用户与权限管理界面。在新增用户区域中,依次填写用户名、初始密码等信息,系统默认将新增账号设置为标注员角色。填写完成后,单击“新增用户”按钮,系统完成账号创建,并在用户列表中显示该账号信息。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
若需调整账号状态,管理员可在用户列表中查看当前用户的启用状态,并根据实际管理需要对用户执行启用、停用、修改密码或删除操作。系统仅保留唯一管理员账号,其余业务使用人员均作为标注员参与项目管理和分割标注工作。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# 2.系统登录
|
||||||
|
|
||||||
|
打开系统后,系统自动显示登录界面。用户在登录界面中依次输入账号和密码,确认信息无误后,单击“安全登录”按钮。系统验证通过后,将进入系统主界面,并默认显示“总体概况”页面。若账号或密码填写错误,系统将在登录表单区域显示错误提示,用户可重新填写后再次登录。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
登录成功后,左侧显示系统功能导航栏,包括“总体概况”“项目库”“分割工作区”“AI智能分割”“模板库”等功能入口。管理员账号还可看到“用户管理”入口。用户可根据业务需求单击相应按钮进入对应功能页面。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[查看分段演示视频:登录与总体概况](系统使用视频/01-登录与总体概况演示.mp4)
|
||||||
|
|
||||||
|
# 3.系统核心管理界面
|
||||||
|
|
||||||
|
系统主界面采用左侧功能导航与右侧业务工作区布局。左侧导航用于切换系统模块,右侧区域根据当前选择显示项目数据、分割工作区、模型状态、模板分类或用户管理内容。系统左下角显示当前模型运行状态,底部用户按钮可用于退出登录。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 3.1 总体概况
|
||||||
|
|
||||||
|
用户登录后,系统默认进入“总体概况”页面。该页面用于查看系统全局数据监控情况,包括项目总数、处理任务数量、已保存标注数量、系统负载等摘要信息。页面中还展示后台任务列表与活动记录,用户可了解视频解析、DICOM 解析、自动推理等任务的处理进度。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在任务列表中,用户可查看任务名称、处理进度、当前状态和更新时间。对于正在执行的任务,可根据系统提供的操作按钮进行取消处理;对于失败或已取消的任务,可根据需要重新执行。任务执行过程中,系统会在界面中持续更新进度提示,便于用户掌握当前处理状态。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 3.2 项目库管理
|
||||||
|
|
||||||
|
单击左侧“项目库”按钮后,系统进入视频与连续帧项目库页面。该页面用于管理多媒体项目,支持导入视频文件、DICOM 序列文件,并对已有项目进行查看、重命名、复制、删除和进入工作区等操作。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
用户单击“导入多媒体资源”按钮后,系统显示导入选项。选择“导入视频”时,用户在本地选择目标视频文件,系统显示视频导入配置界面。用户确认后,系统开始上传视频并显示导入进度。上传完成后,项目卡片会出现在项目库中。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
视频项目导入完成后,若项目尚未生成帧序列,用户可单击项目卡片中的“生成帧”按钮。系统弹出帧生成配置界面,用户可选择抽帧帧率。确认后,系统开始生成帧,并在项目库与任务列表中显示处理进度。帧生成完成后,项目封面与帧数量会自动更新。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
选择“导入DICOM序列”时,用户可批量选择 DICOM 文件。系统会按照文件名自然顺序读取序列,避免切片顺序错位。上传及解析过程中,项目库会显示导入进度、文件数量和处理状态。解析完成后,DICOM 项目可与普通帧序列项目一样进入分割工作区进行标注。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
项目卡片中提供项目名称编辑入口。用户单击编辑按钮后,可修改项目名称,确认后系统更新项目列表中的显示名称。项目卡片旁还提供复制功能,用户可选择“新项目重置”或“全内容复制”;前者复制项目媒体和帧序列但不复制标注,后者复制项目内容及已有标注信息。删除项目时,系统会弹出确认提示,用户确认后系统移除该项目。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[查看分段演示视频:项目库与分割工作区](系统使用视频/02-项目库与分割工作区演示.mp4)
|
||||||
|
|
||||||
|
## 3.3 分割工作区
|
||||||
|
|
||||||
|
在项目库中选择项目后,系统进入“分割工作区”。分割工作区中部为影像或视频帧显示区域,左侧为标注工具栏,右侧为语义分类树,底部为帧序列时间轴。用户可在此完成帧浏览、手工标注、AI 自动推理、GT Mask 导入、标注保存与结果导出等工作。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
用户可通过底部时间轴切换当前帧,也可使用播放控制按钮浏览连续帧。右下角显示当前帧序号及总帧数。若某一帧已经存在人工标注、AI 标注或自动传播结果,时间轴会用不同颜色进行提示,便于用户快速定位已处理帧。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
左侧工具栏提供多边形、矩形、圆形、画笔、橡皮擦、区域合并、重叠区域去除、删除遮罩、清空遮罩、导入 GT Mask 和 AI 智能分割等工具。用户在右侧语义分类树中选择分类后,可使用绘制工具在当前图像上创建新的标注区域;若当前已有选中遮罩,绘制内容可并入当前选中区域。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
使用多边形工具时,用户可依次单击图像边界点形成标注轮廓,完成闭合后系统生成遮罩。使用矩形或圆形工具时,用户可拖拽生成规则区域。使用画笔工具时,用户可调节画笔大小并在图像上连续涂画;使用橡皮擦工具时,用户可调节橡皮擦大小并对选中遮罩进行擦除修正。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
当需要处理多个相邻或相关区域时,用户可选择“区域合并”功能,将多个遮罩合并为同一区域;选择“重叠区域去除”功能,可对重叠遮罩进行裁决处理。对于传播产生的连续帧遮罩,系统会提示用户选择操作范围,包括当前帧、指定范围帧或所有传播帧。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
用户可通过“DEL”按钮或键盘删除选中遮罩,也可通过“清空遮罩”按钮清除当前帧或传播范围内的遮罩。若选择的范围包含人工标注帧,系统会提示用户确认是否同步处理人工标注内容,避免误删重要数据。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
右侧“语义分类树”用于管理当前项目的标注类别。用户单击分类项后,后续新建遮罩将应用该语义分类。若没有选中任何遮罩,单击分类仅改变后续新建遮罩的默认分类;若已选中遮罩,单击分类可修改该遮罩的语义类别。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 3.4 AI 智能分割
|
||||||
|
|
||||||
|
单击左侧导航栏中的“AI智能分割”按钮,系统进入模型端推理可视化界面。用户可选择 SAM 2.1 Tiny、Small、Base+、Large 等模型权重。系统会显示当前模型是否可用以及设备状态,若模型不可用,对应选项将不可执行。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
用户可在图像中添加正向点、反向点或边界框提示,系统根据提示生成候选分割结果。生成结果后,用户可查看候选遮罩边界,并可继续添加提示点进行细化。确认结果后,用户可将分割结果推送至分割工作区,并在工作区中继续进行语义分类、顶点调整和保存。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在分割工作区中,用户也可单击左侧工具栏的“AI自动推理”按钮,选择需要传播的帧范围,并单击“开始传播”。系统会以当前帧已有遮罩为参考,在指定范围内自动生成连续帧分割结果。传播期间,系统在顶部显示当前处理进度;完成后,时间轴中会显示自动传播产生的帧段。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[查看分段演示视频:AI推理与结果导出](系统使用视频/03-AI推理与结果导出演示.mp4)
|
||||||
|
|
||||||
|
## 3.5 GT Mask 导入与结果预览
|
||||||
|
|
||||||
|
在分割工作区中,用户可单击“导入 GT Mask”按钮,选择本地 GT Mask 图片。系统会检查图片是否符合要求:GT 图片应为灰度图,或 RGB 三通道像素值一致的图像,像素值代表对应 maskid,0 代表背景。若图片尺寸与当前帧不同,系统会自动按当前帧尺寸适配。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
导入后,系统显示导入结果预览。若图片中存在当前模板未定义的类别,系统会提示用户选择处理方式:可舍弃未知类别,也可将其作为“待分类”遮罩导入,后续再重新命名。若图片不符合要求或没有非背景区域,系统会显示错误提示并拒绝导入。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 3.6 分割结果导出
|
||||||
|
|
||||||
|
完成标注后,用户可在分割工作区单击“分割结果导出”按钮。系统弹出导出配置界面,用户可选择导出范围,包括当前图片、特定范围帧或整体视频。系统默认导出当前帧结果,用户也可在时间轴上拖拽选择导出范围。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
导出内容可包括分开二值 mask、GT_label 黑白图、Pro_label 彩色图、Mix_label 原图叠加图及标注数据文件。用户确认后,系统生成压缩包并下载到本地。导出的 GT_label 文件中,像素值与语义分类的 maskid 对应;“待分类”与背景均以 0 值表示。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 3.7 模板库管理
|
||||||
|
|
||||||
|
单击左侧“模板库”按钮,系统进入生效中模板架构清单页面。模板库用于管理语义分类模板,系统内置腹腔镜胆囊切除术、头颈部 CT 分割等默认模板。用户可查看模板名称、描述和分类树,并可复制模板形成新的可编辑模板。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
进入模板详情后,用户可查看“语义分类树(拖拽调层级)”。用户可单击“编辑模板”按钮新增或修改分类,也可通过拖拽调整分类层级。每个分类包含名称、颜色和 maskid 信息,其中“待分类”分类固定为 maskid 0,不可删除,且始终位于分类树最后。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
系统支持批量导入分类。用户可在批量导入区域粘贴颜色和名称数据,系统预览分类数量、颜色和 maskid 分配结果。确认后,分类将加入模板并可在分割工作区中使用。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[查看分段演示视频:模板库与用户管理](系统使用视频/04-模板库与用户管理演示.mp4)
|
||||||
|
|
||||||
|
## 3.8 用户管理与审计
|
||||||
|
|
||||||
|
管理员可单击左侧“用户管理”进入用户管理后台。该页面显示当前用户列表、用户角色、启用状态和操作按钮。管理员可创建标注员账号、修改用户密码、停用或启用用户,也可删除不再使用的账号。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
用户管理页面还显示安全审计日志。管理员可查看登录、用户管理、恢复演示环境等操作记录,用于追踪系统使用情况。若需要恢复演示环境,管理员可单击“恢复演示出厂设置”,并按界面提示输入确认文本。系统完成恢复后,仅保留默认管理员、演示视频项目、演示 DICOM 项目和默认模板数据。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 3.9 退出系统
|
||||||
|
|
||||||
|
用户完成工作后,可单击左下角当前用户图标旁的退出按钮。系统清除当前登录状态并返回登录界面。再次使用时,用户需重新输入账号和密码登录系统。
|
||||||
|
|
||||||
|

|
||||||
62
新撰写软著文档/2. 软著登记表.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
受理号
|
||||||
|
|
||||||
|
分类号
|
||||||
|
|
||||||
|
登记号
|
||||||
|
|
||||||
|
# 计算机软件著作权登记申请表
|
||||||
|
|
||||||
|
中国版权保护中心
|
||||||
|
|
||||||
|
注意:表中红色字体栏的部分为必填项。
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr><td rowspan="3">软件基本信息</td><td>软件名称</td><td colspan="2">多模态影像及视频智能语义分割与标注系统</td><td colspan="2">版本号</td><td colspan="2">V1.0</td></tr>
|
||||||
|
<tr><td>软件简称</td><td colspan="2">智能语义分割系统</td><td colspan="2">分类号</td><td colspan="2">应用软件</td></tr>
|
||||||
|
<tr><td>软件作品说明</td><td colspan="6">☑原创 □修改(含翻译软件、合成软件) 修改软件须经原权利人授权 原有软件已经登记 ·原登记号:____ ·修改(翻译或合成)软件作品说明:____</td></tr>
|
||||||
|
<tr><td colspan="2">开发完成日期</td><td colspan="6">____年____月____日</td></tr>
|
||||||
|
<tr><td colspan="2">发表状态</td><td colspan="6">□已发表 首次发表日期:____年____月____日 首次发表地点:____ ☑未发表(允许公众查询)</td></tr>
|
||||||
|
<tr><td colspan="2">开发方式</td><td colspan="6">☑独立开发 □合作开发 □委托开发 □下达任务开发</td></tr>
|
||||||
|
<tr><td rowspan="6">著作权人</td><td>姓名或名称</td><td>证件类型</td><td colspan="2">证件号</td><td>国籍</td><td>省份/城市</td><td>园区(非必填)</td></tr>
|
||||||
|
<tr><td>待填写</td><td>待填写</td><td colspan="2">待填写</td><td>中国</td><td>待填写</td><td></td></tr>
|
||||||
|
<tr><td>待填写</td><td>待填写</td><td colspan="2">待填写</td><td>中国</td><td>待填写</td><td></td></tr>
|
||||||
|
<tr><td>待填写</td><td>待填写</td><td colspan="2">待填写</td><td>中国</td><td>待填写</td><td></td></tr>
|
||||||
|
<tr><td>待填写</td><td>待填写</td><td colspan="2">待填写</td><td>中国</td><td>待填写</td><td></td></tr>
|
||||||
|
<tr><td>待填写</td><td>待填写</td><td colspan="2">待填写</td><td>中国</td><td>待填写</td><td></td></tr>
|
||||||
|
<tr><td rowspan="2">权利说明</td><td>权利取得方式</td><td colspan="6">☑原始取得 □继受取得(□受让 □承受 □继承) □原软件已登记(原登记号:____) □原登记做过变更或补充(变更或补充证明书编号:____)</td></tr>
|
||||||
|
<tr><td>权利范围</td><td colspan="6">☑全部 □部分(□发表权 □署名权 □修改权 □复制权 □发行权 □出租权 □信息网络传播权 □翻译权 □应当由著作权人享有的其他权利)</td></tr>
|
||||||
|
<tr><td>鉴别材料</td><td>一般交存☑</td><td colspan="6">提交源程序前连续的30页和后连续的30页;提交任何一种文档的前连续的30页和后连续的30页;☑一种文档</td></tr>
|
||||||
|
<tr><td>鉴别材料</td><td>例外交存□</td><td colspan="6">不填</td></tr>
|
||||||
|
<tr><td rowspan="9">软件功能和技术特点</td><td>开发的硬件环境(50字以内)</td><td colspan="6">采用具备多核处理器、32GB以上内存、SSD存储及NVIDIA GPU的工作站或服务器进行开发和调试。</td></tr>
|
||||||
|
<tr><td>运行的硬件环境(50字以内)</td><td colspan="6">支持部署于标准服务器或工作站;建议配置多核CPU、16GB以上内存、SSD存储,AI推理建议配置NVIDIA GPU。</td></tr>
|
||||||
|
<tr><td>开发该软件的操作系统(50字以内)</td><td colspan="6">基于Linux操作系统进行开发,主要使用Ubuntu环境完成前后端开发、Docker部署和模型联调。</td></tr>
|
||||||
|
<tr><td>软件开发环境/开发工具(50字以内)</td><td colspan="6">前端采用React、TypeScript、Vite开发;后端采用FastAPI;数据库为PostgreSQL,配合Redis、MinIO和Docker。</td></tr>
|
||||||
|
<tr><td>该软件的运行平台/操作系统(50字以内)</td><td colspan="6">采用B/S架构,服务端支持Linux和Docker环境,客户端可通过Chrome、Edge等现代浏览器访问。</td></tr>
|
||||||
|
<tr><td>软件运行支撑环境/支持软件(50字以内)</td><td colspan="6">运行依赖Docker、PostgreSQL、Redis、MinIO、Python运行环境、Node构建环境及可选NVIDIA Container Toolkit。</td></tr>
|
||||||
|
<tr><td>编程语言及版本号</td><td>前端采用TypeScript 5与React 19;后端采用Python 3.11与FastAPI。</td><td>源程序量</td><td colspan="4">约23337行代码</td></tr>
|
||||||
|
<tr><td>开发目的(50字以内)</td><td>为医学影像与视频数据提供智能语义分割、标注管理和结果导出工具,提升标注效率与数据质量。</td><td>面向领域/行业(50字以内)</td><td colspan="4">面向医疗影像、医学视频分析、科研标注、智能诊疗辅助和多模态数据管理等领域。</td></tr>
|
||||||
|
<tr><td>主要功能(200字以内)</td><td colspan="6">本系统支持用户登录、项目库管理、视频与DICOM序列导入、帧序列生成、交互式图像标注、语义分类模板管理、SAM 2.1智能分割、连续帧AI自动推理、GT Mask导入校验、遮罩编辑、区域合并、重叠去除、任务进度监控、用户与审计管理及分割结果导出。系统可对多模态影像和视频数据进行规范化标注,支持生成GT_label、Pro_label、Mix_label等结果文件。</td></tr>
|
||||||
|
<tr><td></td><td>技术特点(100字以内)</td><td colspan="6">系统采用前后端分离B/S架构,集成React交互式Canvas标注、FastAPI服务、Celery任务队列、MinIO对象存储和SAM 2.1模型推理,支持CPU/GPU部署及Docker自包含发布。</td></tr>
|
||||||
|
<tr><td rowspan="4">申请人信息</td><td>姓名或名称(必须包括著作权人)</td><td>待填写</td><td>电话</td><td colspan="4">待填写</td></tr>
|
||||||
|
<tr><td>详细地址</td><td>待填写</td><td>邮编</td><td colspan="4">待填写</td></tr>
|
||||||
|
<tr><td>联系人</td><td>待填写</td><td>手机</td><td colspan="4">待填写</td></tr>
|
||||||
|
<tr><td>E-mail</td><td>待填写</td><td>传真</td><td colspan="4">待填写</td></tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
注:以上表格中未标注非必填的内容均为必填项,请申请人根据实际主体信息补充完整。
|
||||||
|
|
||||||
|
现申请之前需要先提供材料,帮著作权人进行实名认证,周期通常为1-3个工作日。材料如下:
|
||||||
|
|
||||||
|
著作权人为企业的:
|
||||||
|
|
||||||
|
1. 申请人营业执照扫描件;
|
||||||
|
2. 被授权人或企业联系人身份证正反面扫描件,需保持清晰;
|
||||||
|
3. 提供真实有效的手机号码和邮箱号码;
|
||||||
|
4. 提供授权联系人相关盖章扫描件。
|
||||||
|
|
||||||
|
著作权人为个人的:
|
||||||
|
|
||||||
|
1. 提供联系人身份证正反面扫描件及手持身份证正面照片;
|
||||||
|
2. 提供真实有效的手机号码和邮箱号码。
|
||||||
|
|
||||||
|
注册时,版权登记平台可能向预留手机号发送验证码,请及时提供。注册成功后,在系统中填写申请表时,也可能再次向预留手机号发送验证码,请按要求配合完成验证。
|
||||||
1023
新撰写软著文档/3. 代码汇总.md
Normal file
BIN
新撰写软著文档/images/01-login.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
新撰写软著文档/images/02-dashboard.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
新撰写软著文档/images/03-main-layout.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
新撰写软著文档/images/04-dashboard-tasks.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
新撰写软著文档/images/05-project-library.png
Normal file
|
After Width: | Height: | Size: 257 KiB |
BIN
新撰写软著文档/images/06-import-media-options.png
Normal file
|
After Width: | Height: | Size: 263 KiB |
BIN
新撰写软著文档/images/07-project-copy-dialog.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
新撰写软著文档/images/08-frame-parse-dialog.png
Normal file
|
After Width: | Height: | Size: 132 KiB |
BIN
新撰写软著文档/images/09-workspace-main.png
Normal file
|
After Width: | Height: | Size: 784 KiB |
BIN
新撰写软著文档/images/10-workspace-tools.png
Normal file
|
After Width: | Height: | Size: 784 KiB |
BIN
新撰写软著文档/images/11-workspace-draw-mask.png
Normal file
|
After Width: | Height: | Size: 783 KiB |
BIN
新撰写软著文档/images/12-workspace-auto-propagate-range.png
Normal file
|
After Width: | Height: | Size: 792 KiB |
BIN
新撰写软著文档/images/13-workspace-export-dialog.png
Normal file
|
After Width: | Height: | Size: 838 KiB |
BIN
新撰写软著文档/images/14-gt-mask-import-preview.png
Normal file
|
After Width: | Height: | Size: 638 KiB |
BIN
新撰写软著文档/images/15-ai-page.png
Normal file
|
After Width: | Height: | Size: 641 KiB |
BIN
新撰写软著文档/images/16-ai-prompt-tools.png
Normal file
|
After Width: | Height: | Size: 652 KiB |
BIN
新撰写软著文档/images/17-template-library.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
新撰写软著文档/images/18-template-edit-dialog.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
新撰写软著文档/images/19-template-batch-import.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
新撰写软著文档/images/20-user-admin.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
新撰写软著文档/images/21-user-create-dialog.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
新撰写软著文档/images/22-audit-reset-dialog.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
新撰写软著文档/images/23-logout.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
42
新撰写软著文档/功能验证与素材清单.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# 功能验证与素材清单
|
||||||
|
|
||||||
|
验证地址:https://seg.huijutec.cn/
|
||||||
|
验证时间:2026/5/8 01:38:02
|
||||||
|
|
||||||
|
## 截图文件
|
||||||
|
- images/01-login.png:系统登录界面图
|
||||||
|
- images/02-dashboard.png:系统登录后总体概况界面图
|
||||||
|
- images/03-main-layout.png:系统主界面整体布局图
|
||||||
|
- images/04-dashboard-tasks.png:后台任务列表及任务进度界面图
|
||||||
|
- images/05-project-library.png:项目库列表界面图
|
||||||
|
- images/06-import-media-options.png:导入视频与DICOM资源选择界面图
|
||||||
|
- images/07-project-copy-dialog.png:项目复制操作界面图
|
||||||
|
- images/08-frame-parse-dialog.png:视频生成帧配置界面图
|
||||||
|
- images/09-workspace-main.png:分割工作区主界面图
|
||||||
|
- images/10-workspace-tools.png:左侧标注工具栏与语义分类树界面图
|
||||||
|
- images/11-workspace-draw-mask.png:多边形、矩形、圆形和画笔标注操作界面图
|
||||||
|
- images/12-workspace-auto-propagate-range.png:AI自动推理范围选择界面图
|
||||||
|
- images/13-workspace-export-dialog.png:分割结果导出配置界面图
|
||||||
|
- images/14-gt-mask-import-preview.png:GT Mask导入预览界面图
|
||||||
|
- images/15-ai-page.png:AI智能分割模型选择界面图
|
||||||
|
- images/16-ai-prompt-tools.png:AI智能分割点选和框选工具界面图
|
||||||
|
- images/17-template-library.png:模板库模板清单界面图
|
||||||
|
- images/18-template-edit-dialog.png:模板分类树编辑界面图
|
||||||
|
- images/19-template-batch-import.png:模板批量导入分类界面图
|
||||||
|
- images/20-user-admin.png:管理员用户管理后台界面图
|
||||||
|
- images/21-user-create-dialog.png:新增标注员账号界面图
|
||||||
|
- images/22-audit-reset-dialog.png:审计日志和恢复演示出厂设置确认界面图
|
||||||
|
- images/23-logout.png:退出登录按钮和返回登录界面图
|
||||||
|
|
||||||
|
## 分段视频
|
||||||
|
- 系统使用视频/01-登录与总体概况演示.mp4
|
||||||
|
- 系统使用视频/02-项目库与分割工作区演示.mp4
|
||||||
|
- 系统使用视频/03-AI推理与结果导出演示.mp4
|
||||||
|
- 系统使用视频/04-模板库与用户管理演示.mp4
|
||||||
|
- 系统使用视频/01-登录与总体概况演示.webm
|
||||||
|
- 系统使用视频/02-项目库与分割工作区演示.webm
|
||||||
|
- 系统使用视频/03-AI推理与结果导出演示.webm
|
||||||
|
- 系统使用视频/04-模板库与用户管理演示.webm
|
||||||
|
|
||||||
|
## 验证说明
|
||||||
|
本次验证以管理员账号进入线上系统,逐项检查登录、总体概况、项目库、分割工作区、AI 智能分割、AI 自动推理入口、GT Mask 导入预览、分割结果导出、模板库、用户管理、审计日志和退出登录等说明书涉及功能。删除项目、恢复演示出厂设置、生成帧确认、导出下载确认等可能改变演示环境或产生下载文件的危险提交动作仅验证入口与确认界面,不执行最终提交。
|
||||||