# 宝可梦上线包自检 (card_seg_v0904) # 用法: D:\顾工交接\wzj\宝可梦\上线\校验上线包.ps1 $ErrorActionPreference = 'Stop' $Root = Split-Path -Parent $MyInvocation.MyCommand.Path Set-Location $Root Write-Host "" Write-Host "=== 宝可梦上线包自检 · card_seg_v0904 ===" -ForegroundColor Cyan Write-Host "包路径: $Root" Write-Host "" # ---------- 1. MD5 校验 ---------- Write-Host "[1/3] MD5 校验 (对照 MD5SUMS.txt, 基准=249 生产端)" -ForegroundColor Yellow $sumFile = Join-Path $Root 'MD5SUMS.txt' if (-not (Test-Path $sumFile)) { Write-Host " X 找不到 MD5SUMS.txt" -ForegroundColor Red; exit 1 } $ok = 0; $bad = 0; $missing = 0 foreach ($line in (Get-Content -LiteralPath $sumFile -Encoding UTF8)) { if ($line -notmatch '\S') { continue } $parts = $line -split '\s+', 2 $want = $parts[0].Trim().ToLower() $rel = $parts[1].Trim() -replace '/', '\' $path = Join-Path $Root $rel if (-not (Test-Path $path)) { Write-Host (" X 缺失 {0}" -f $rel) -ForegroundColor Red $missing++; continue } $got = (Get-FileHash -Path $path -Algorithm MD5).Hash.ToLower() $mb = [math]::Round((Get-Item $path).Length / 1MB, 1) if ($got -eq $want) { Write-Host (" OK {0,8} MB {1}" -f $mb, $rel) -ForegroundColor Green $ok++ } else { Write-Host (" X 不一致 {0}" -f $rel) -ForegroundColor Red Write-Host (" 期望 {0}" -f $want) Write-Host (" 实际 {0}" -f $got) $bad++ } } Write-Host (" -> 一致 {0} / 不一致 {1} / 缺失 {2}" -f $ok, $bad, $missing) Write-Host "" # ---------- 2. 关键结构 ---------- Write-Host "[2/3] 关键文件与目录" -ForegroundColor Yellow $must = @( 'README_上线清单.md', 'README_操作方法.md', 'code\build_dual_gallery_v0904.py', 'code\serve_recognition_api.py', 'code\serve_card_match_v2.py', 'code\modules\attribute_detector.py', 'code\build_dual_gallery_v0904.py', 'data\gallery_v0904\gallery_dual_meta.json', 'data\train_meta_v0904.json', 'code\serve_card_match.py', 'code\serve_lang_judge.py', 'code\config.py', 'code\scripts\cascade_match.py', 'code\modules\feature_extractor_dual.py', 'docs\宝可梦卡牌识别服务文档接口.md', 'offline_cache\huggingface_hub\models--facebook--dinov2-large', 'offline_cache\paddlex_official_models\PP-OCRv6_medium_rec' ) $structBad = 0 foreach ($m in $must) { if (Test-Path (Join-Path $Root $m)) { Write-Host (" OK {0}" -f $m) -ForegroundColor Green } else { Write-Host (" X {0}" -f $m) -ForegroundColor Red $structBad++ } } Write-Host "" # ---------- 3. 图库形状 ---------- Write-Host "[3/3] 图库特征形状 (npy 头部, 应为 91116 x 1024)" -ForegroundColor Yellow foreach ($n in @('gallery_v0904/gallery_upper_features.npy', 'gallery_v0904/gallery_lower_features.npy')) { $p = Join-Path $Root "data\$n" if (-not (Test-Path $p)) { Write-Host (" X 缺失 {0}" -f $n) -ForegroundColor Red; continue } $fs = [System.IO.File]::OpenRead($p) $buf = New-Object byte[] 200 [void]$fs.Read($buf, 0, 200) $fs.Close() $head = [System.Text.Encoding]::ASCII.GetString($buf) if ($head -match "'shape':\s*\(([0-9]+),\s*([0-9]+)\)") { $rows = $Matches[1]; $cols = $Matches[2] if ($rows -eq '91116' -and $cols -eq '1024') { Write-Host (" OK {0} shape=({1}, {2})" -f $n, $rows, $cols) -ForegroundColor Green } else { Write-Host (" X {0} shape=({1}, {2}) <- 期望 (91116, 1024), 疑似混版!" -f $n, $rows, $cols) -ForegroundColor Red $structBad++ } } else { Write-Host (" ? {0} 解析不出 shape" -f $n) -ForegroundColor DarkYellow } } Write-Host "" # ---------- 汇总 ---------- if ($bad -eq 0 -and $missing -eq 0 -and $structBad -eq 0) { Write-Host "===== 全部通过, 上线包完好 =====" -ForegroundColor Green Write-Host "下一步: 按 README_上线清单.md 第六节落位, 第七节启动;" -ForegroundColor Gray Write-Host " /health 的 gallery_size 必须是 91116, 且要再打一个真实请求才算验过。" -ForegroundColor Gray } else { Write-Host "===== 有问题, 见上方红色行 =====" -ForegroundColor Red exit 1 }