From 9a2a65345253cb92f2f32c5cb928a16bd7816d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E9=BB=98=E6=B6=B5?= <21739308@qq.com> Date: Fri, 18 Sep 2026 01:43:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8C=E6=AD=A5=20TinyPose=200.3.0=20?= =?UTF-8?q?=E5=AA=92=E4=BD=93=E8=83=BD=E5=8A=9B=E4=B8=8E=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reports/tinypose-media-portal-browser.json | 157 +++++++++++++++++++++ reports/tinypose-media-portal/README.md | 9 ++ src/content/models/pp-tinypose.yaml | 15 +- src/content/models/registry.test.ts | 8 +- src/pages/models/[slug].astro | 2 +- tests/portal.spec.ts | 10 +- 6 files changed, 186 insertions(+), 15 deletions(-) create mode 100644 reports/tinypose-media-portal-browser.json create mode 100644 reports/tinypose-media-portal/README.md diff --git a/reports/tinypose-media-portal-browser.json b/reports/tinypose-media-portal-browser.json new file mode 100644 index 0000000..d78efb1 --- /dev/null +++ b/reports/tinypose-media-portal-browser.json @@ -0,0 +1,157 @@ +{ + "config": { + "argv": [ + "C:\\nvm4w\\nodejs\\node.exe", + "F:\\git\\00_chenmohan\\github\\chenmohan123.github.io\\.worktrees\\tinypose-media-portal\\node_modules\\playwright\\cli.js", + "test", + "--grep", + "TinyPose 0.3.0", + "--reporter=json", + "--output=reports/tinypose-media-portal/screenshots" + ], + "configFile": "F:\\git\\00_chenmohan\\github\\chenmohan123.github.io\\.worktrees\\tinypose-media-portal\\playwright.config.ts", + "rootDir": "F:/git/00_chenmohan/github/chenmohan123.github.io/.worktrees/tinypose-media-portal/tests", + "failOnFlakyTests": false, + "forbidOnly": false, + "fullyParallel": false, + "globalSetup": null, + "globalTeardown": null, + "globalTimeout": 0, + "grep": {}, + "grepInvert": null, + "maxFailures": 0, + "metadata": { + "actualWorkers": 1 + }, + "preserveOutput": "always", + "projects": [ + { + "outputDir": "F:/git/00_chenmohan/github/chenmohan123.github.io/.worktrees/tinypose-media-portal/reports/tinypose-media-portal/screenshots", + "repeatEach": 1, + "retries": 0, + "metadata": { + "actualWorkers": 1 + }, + "id": "", + "name": "", + "testDir": "F:/git/00_chenmohan/github/chenmohan123.github.io/.worktrees/tinypose-media-portal/tests", + "testIgnore": [], + "testMatch": [ + "**/*.@(spec|test).?(c|m)[jt]s?(x)" + ], + "timeout": 30000 + } + ], + "quiet": false, + "reporter": [ + [ + "json" + ] + ], + "reportSlowTests": { + "max": 5, + "threshold": 300000 + }, + "shard": null, + "tags": [], + "updateSnapshots": "missing", + "updateSourceMethod": "patch", + "version": "1.62.1", + "workers": 6, + "webServer": { + "command": "node ./node_modules/astro/bin/astro.mjs dev --host 127.0.0.1", + "env": { + "ASTRO_DEV_BACKGROUND": "0" + }, + "port": 4321, + "reuseExistingServer": true + } + }, + "suites": [ + { + "title": "portal.spec.ts", + "file": "portal.spec.ts", + "column": 0, + "line": 0, + "specs": [ + { + "title": "TinyPose 0.3.0 在 1280px 展示三项资产、媒体边界和独立 SDK 链接", + "ok": true, + "tags": [], + "tests": [ + { + "timeout": 30000, + "annotations": [], + "expectedStatus": "passed", + "projectId": "", + "projectName": "", + "results": [ + { + "workerIndex": 0, + "parallelIndex": 0, + "status": "passed", + "duration": 1607, + "errors": [], + "stdout": [], + "stderr": [], + "retry": 0, + "startTime": "2026-09-17T17:34:03.177Z", + "annotations": [], + "attachments": [] + } + ], + "status": "expected" + } + ], + "id": "291f6c0e7fe47579f0c2-6a287430ab4380b9977c", + "file": "portal.spec.ts", + "line": 4, + "column": 3 + }, + { + "title": "TinyPose 0.3.0 在 390px 展示三项资产、媒体边界和独立 SDK 链接", + "ok": true, + "tags": [], + "tests": [ + { + "timeout": 30000, + "annotations": [], + "expectedStatus": "passed", + "projectId": "", + "projectName": "", + "results": [ + { + "workerIndex": 0, + "parallelIndex": 0, + "status": "passed", + "duration": 782, + "errors": [], + "stdout": [], + "stderr": [], + "retry": 0, + "startTime": "2026-09-17T17:34:05.736Z", + "annotations": [], + "attachments": [] + } + ], + "status": "expected" + } + ], + "id": "291f6c0e7fe47579f0c2-57ec3d4f5a422e9bb7e3", + "file": "portal.spec.ts", + "line": 4, + "column": 3 + } + ] + } + ], + "errors": [], + "stats": { + "startTime": "2026-09-17T17:33:58.688Z", + "duration": 8208.078, + "expected": 2, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } +} diff --git a/reports/tinypose-media-portal/README.md b/reports/tinypose-media-portal/README.md new file mode 100644 index 0000000..adc9143 --- /dev/null +++ b/reports/tinypose-media-portal/README.md @@ -0,0 +1,9 @@ +# TinyPose 0.3.0 门户同步 + +2026-09-18(北京时间),门户登记已经发布的 TinyPose 0.3.0,补充图片、本地视频及摄像头 Demo 能力。SDK 输入仍为单帧 Blob/RGBA/region,三项模型身份、默认来源与独立链接保持原契约。 + +- 本地65项单测通过;Astro检查0错误、0警告,保留7项既有提示;14页构建成功。 +- `../tinypose-media-portal-browser.json`:1280px与390px两项浏览器检查通过,覆盖目录筛选、详情、三项资产、版本、边界、独立链接及无横向溢出。 +- 发布后的线上截图、浏览器回读与GitHub部署提交归档于SDK的 `reports/2026-09-17-media/release/portal-*`。 + +媒体12组合385帧和图片24组合是桌面验证;摄像头使用Chromium fake-device,不声明物理摄像头、手机、微信或NPU兼容。门户不复制推理runtime。 diff --git a/src/content/models/pp-tinypose.yaml b/src/content/models/pp-tinypose.yaml index f87b00d..011cab5 100644 --- a/src/content/models/pp-tinypose.yaml +++ b/src/content/models/pp-tinypose.yaml @@ -3,12 +3,12 @@ name: PP-TinyPose brand: baidu task: pose-estimation status: available -summary: 在浏览器本地估计单人人体姿态,提供 256×192 与 128×96 两种输入规格;支持单人图片或调用者提供的人体框,输出原图坐标的 17 个 COCO 关键点,并支持 CPU/WASM、GPU/WebGPU 和主线程/Worker。 +summary: 在浏览器本地估计单人人体姿态,提供 256×192 与 128×96 两种输入规格和17个COCO关键点;SDK处理单帧或调用者人体框,独立Demo支持图片、本地视频与摄像头,提供CPU/WASM、GPU/WebGPU和主线程/Worker。 repository: https://github.com/chenmohan123/web-sdk-PP-TinyPose license: Apache-2.0 package: name: web-sdk-pp-tinypose - version: 0.2.0 + version: 0.3.0 demo: url: https://chenmohan123.github.io/web-sdk-PP-TinyPose/ localProcessing: true @@ -21,11 +21,11 @@ runtime: - browser: Chromium 153.0.8010.12 os: Windows 11 10.0.26200 device: Intel Core i5-10400F / WASM,ModelScope/Hugging Face × 主线程/Worker - testedAt: 2026-09-17 + testedAt: 2026-09-18 - browser: Chromium 153.0.8010.12 os: Windows 11 10.0.26200 device: NVIDIA Blackwell / WebGPU,ModelScope/Hugging Face × 主线程/Worker - testedAt: 2026-09-17 + testedAt: 2026-09-18 io: input: [Blob, RGBA, region(调用者提供的人体框)] output: [17 个 COCO 关键点(原图坐标与 score), crop, image, runtime, model, timings] @@ -46,10 +46,11 @@ assets: url: https://www.modelscope.cn/models/chenmohan/web-sdk-pp-tinypose/resolve/97c04100baef646f1b9c4d83295d8e2f14b4324d/tinypose-128x96/0.2.0/w16a32/tinypose-128x96-w16a32.onnx sha256: 8671c7b424d85d4f017b6410602de6095b1fbb9fffca38ad5489039dd2a0cfea limitations: - - 当前处理单人图片或调用者提供的人体框,没有内置人体检测器、自动多人检测、相机、视频或跟踪能力;score 为热力图响应,不是可见性概率。 + - SDK继续接收单帧Blob/RGBA或调用者人体框;视频解码、摄像头权限和帧调度属于独立Demo。固定人体框不跟踪运动,没有内置人体检测器、自动多人、跟踪或动作识别;score 为热力图响应,不是可见性概率。 - 默认 ModelScope,另可选择 Hugging Face;两个来源使用固定提交并提供相同 SHA-256 的模型,显式来源或后端失败不会静默切换。 - - 2026-09-17 三模型 × 双源 × WASM/WebGPU × 主线程/Worker 的最终 24 组合已通过真实图片推理,并核验已发布 npm、Pages 与 GitHub Release 的 0.2.0;证据见 SDK reports/2026-09-17-variants/online-browser.json 与同目录 release/ 回执。 + - 2026-09-18 三模型 × 双源 × WASM/WebGPU × 主线程/Worker 的24组合通过真实图片推理;连续帧12组合共385帧。已核验npm、Pages与GitHub Release的0.3.0,证据见SDK reports/2026-09-17-media/及release/回执。 + - 视频支持播放/暂停、单帧、暂停定位和固定选框;摄像头仅由用户开启、不采集音频,停止或隐藏页面释放资源。线上默认配置的视频及Chromium fake-device摄像头通过双语/390px验收;模拟摄像头不代表物理设备兼容。 - W16A32 仅用于 128×96,以 FP16 权重存储并转回 FP32 计算,不是普通 FP16 推理;普通 FP16 与 256×192 W16A32 未通过质量门槛,未发布。 - 2026-09-17 固定 64 图/110 人 GT 框子集平均 OKS 仅用于同批次比较,不是全量 COCO AP;不能据此宣称压缩模型或 GPU 普遍更快。 - - 手机、其他浏览器、微信 web-view 和 WebNN/NPU 尚未验证;390px 视口检查不代表实体手机验证。 + - 物理摄像头、手机、其他浏览器、微信 web-view 和 WebNN/NPU 尚未验证;390px 视口检查不代表实体手机验证,变化人物图片测试素材不证明真实动作质量。 - SDK 与模型遵循 Apache-2.0,模型再分发须保留 LICENSE、NOTICE 和 PaddleDetection 上游归属;npm 包不包含 ONNX 权重。 diff --git a/src/content/models/registry.test.ts b/src/content/models/registry.test.ts index f76005d..1652911 100644 --- a/src/content/models/registry.test.ts +++ b/src/content/models/registry.test.ts @@ -4,7 +4,7 @@ import { parse } from "yaml"; import { modelSchema } from "../../lib/registry/schema"; describe("model registry", () => { - it("登记 TinyPose 0.2.0 的三项稳定资产并保留桌面验证边界", () => { + it("登记 TinyPose 0.3.0 并保留单帧SDK与媒体Demo边界", () => { const models = readdirSync("src/content/models") .filter((file) => file.endsWith(".yaml")) .map((file) => modelSchema.parse(parse(readFileSync(`src/content/models/${file}`, "utf8")))); @@ -12,7 +12,7 @@ describe("model registry", () => { const model = models.find((entry) => entry.id === "pp-tinypose"); expect(model).toBeDefined(); expect(model?.task).toBe("pose-estimation"); - expect(model?.package).toEqual({ name: "web-sdk-pp-tinypose", version: "0.2.0" }); + expect(model?.package).toEqual({ name: "web-sdk-pp-tinypose", version: "0.3.0" }); expect(model?.runtime.backends).toEqual([ { name: "wasm", status: "stable" }, { name: "webgpu", status: "stable" }, @@ -42,7 +42,9 @@ describe("model registry", () => { }, ]); expect(model?.runtime.verifiedEnvironments).toHaveLength(2); - expect(model?.runtime.verifiedEnvironments.every((environment) => environment.testedAt === "2026-09-17")).toBe(true); + expect(model?.runtime.verifiedEnvironments.every((environment) => environment.testedAt === "2026-09-18")).toBe(true); + expect(model?.limitations.join(" ")).toContain("视频解码、摄像头权限和帧调度属于独立Demo"); + expect(model?.limitations.join(" ")).toContain("模拟摄像头不代表物理设备兼容"); expect(model?.io.input).toEqual(["Blob", "RGBA", "region(调用者提供的人体框)"]); expect(model?.io.output).toContain("17 个 COCO 关键点(原图坐标与 score)"); }); diff --git a/src/pages/models/[slug].astro b/src/pages/models/[slug].astro index 6ea62b7..d38b99e 100644 --- a/src/pages/models/[slug].astro +++ b/src/pages/models/[slug].astro @@ -18,6 +18,6 @@ const npmUrl = `https://www.npmjs.com/package/${data.package.name}`;

{data.brand} · {taskDisplayNames[data.task] ?? data.task}

{data.name}

{data.summary}

{model.id === 'pp-detection' &&

模型选型与对比 →

} - {model.id === 'pp-tinypose' &&

规格与精度对比 →

} + {model.id === 'pp-tinypose' &&

规格与精度对比 →

}

运行能力

模型资源

    {data.assets.map((asset) =>
  • {asset.id} · {mib(asset.bytes)} · SHA-256 已记录
  • )}

限制

    {data.limitations.map((item) =>
  • {item}
  • )}
diff --git a/tests/portal.spec.ts b/tests/portal.spec.ts index 8c29170..561022b 100644 --- a/tests/portal.spec.ts +++ b/tests/portal.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from "@playwright/test"; for (const width of [1280, 390]) { - test(`TinyPose 0.2.0 在 ${width}px 展示三项资产、发布边界和独立 SDK 链接`, async ({ page }) => { + test(`TinyPose 0.3.0 在 ${width}px 展示三项资产、媒体边界和独立 SDK 链接`, async ({ page }) => { await page.setViewportSize({ width, height: 844 }); await page.goto("/"); await expect(page.locator('astro-island[component-url*="ModelDirectory"]')).not.toHaveAttribute("ssr", ""); @@ -15,7 +15,7 @@ for (const width of [1280, 390]) { await page.getByRole("link", { name: "PP-TinyPose", exact: true }).click(); await expect(page.getByRole("heading", { level: 1 })).toHaveText("PP-TinyPose"); await expect(page.getByText("baidu · 人体姿态", { exact: true })).toBeVisible(); - await expect(page.getByText("web-sdk-pp-tinypose@0.2.0", { exact: true })).toBeVisible(); + await expect(page.getByText("web-sdk-pp-tinypose@0.3.0", { exact: true })).toBeVisible(); await expect(page.getByText(/256×192.*128×96/)).toBeVisible(); await expect(page.getByRole("listitem").filter({ hasText: "tinypose-256x192-fp32" })).toContainText("5.42 MiB"); await expect(page.getByRole("listitem").filter({ has: page.getByText("tinypose-enhance-128x96", { exact: true }) })).toContainText("5.42 MiB"); @@ -23,12 +23,14 @@ for (const width of [1280, 390]) { await expect(page.getByRole("link", { name: "GitHub 仓库", exact: true })).toHaveAttribute("href", "https://github.com/chenmohan123/web-sdk-PP-TinyPose"); await expect(page.getByRole("link", { name: "npm 包", exact: true })).toHaveAttribute("href", "https://www.npmjs.com/package/web-sdk-pp-tinypose"); await expect(page.getByRole("link", { name: "打开在线 Demo", exact: true })).toHaveAttribute("href", "https://chenmohan123.github.io/web-sdk-PP-TinyPose/"); - await expect(page.getByRole("link", { name: "规格与精度对比 →", exact: true })).toHaveAttribute("href", "https://github.com/chenmohan123/web-sdk-PP-TinyPose/blob/v0.2.0/README.md"); + await expect(page.getByRole("link", { name: "规格与精度对比 →", exact: true })).toHaveAttribute("href", "https://github.com/chenmohan123/web-sdk-PP-TinyPose/blob/v0.3.0/README.md"); await expect(page.getByText(/score 为热力图响应,不是可见性概率/)).toBeVisible(); await expect(page.getByText(/默认 ModelScope.*Hugging Face/)).toBeVisible(); await expect(page.getByText(/W16A32.*FP16 权重.*FP32 计算/)).toBeVisible(); await expect(page.getByText(/普通 FP16.*256×192 W16A32.*未发布/)).toBeVisible(); - await expect(page.getByText(/24 组合.*0\.2\.0/)).toBeVisible(); + await expect(page.getByText(/24组合.*0\.3\.0/)).toBeVisible(); + await expect(page.getByText(/视频解码、摄像头权限和帧调度属于独立Demo/)).toBeVisible(); + await expect(page.getByText(/模拟摄像头不代表物理设备兼容/)).toBeVisible(); await expect(page.getByText(/GT 框子集平均 OKS.*不是全量 COCO AP/)).toBeVisible(); await expect(page.getByText(/手机.*尚未验证/)).toBeVisible(); expect(await page.evaluate(() => document.documentElement.scrollWidth <= innerWidth)).toBe(true);