card-recog-demo/docs/demo说明.md
a1518 ccf8eeb21d Initial commit: Flutter card recognition demo
Camera capture, corner detection/refinement, and preview crop pipeline for trading cards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-12 20:17:32 -07:00

8.5 KiB
Raw Blame History

Card Scan Demo 说明

对照《集换社_反编译分析报告》v3.23.15)与本仓库当前实现,说明 demo 定位、流水线与差异。


1. 背景:集换社里的「卡牌扫描」

集换社是 TCG 卡牌 C2C 交易平台(包名 com.jihuanshe),卡牌扫描只是完整业务中的一环,不是独立工具 App。

反编译报告里与扫描相关的关键结论:

集换社侧证据
入口 CardScanActivity / CardScanAlbumActivity / CaptureActivity / ScanActivity
相机 CameraXMetadataHolderService 等)
识别 Google ML Kitlibmlkitcommonpipeline.so ~8.4MB、GraphicOverlayMlKitInitProvider
裁剪 uCropMCropActivity)— 识别不佳时可手动纠偏后再跑
结果 匹配卡牌库 → CardDetailActivity(详情 / 价格)→ 购物车或上架

报告中的扫描流程可概括为:

相机 / 相册 → ML Kit 边框检测 →(可选)手动裁剪 → 匹配卡牌数据库 → 详情页

加固(爱加密)导致无法还原完整 Java/Kotlin 源码,上述链路主要来自 Manifest、Native 库与 Flutter 字符串等静态证据,不是可运行的源码级复刻。

本 demo 只复现「拍/选图 → 锁定卡边 → 裁剪纠偏」 这一段视觉能力,不包含交易、匹配库、登录、支付等平台能力。


2. Demo 是什么

纯 Flutter 小应用(carddex_demo v2.0.0),竖屏暗色 UI。

一句话:拍照或相册选图 → 按 TCG 引导框裁切 → ML Kit 目标检测得到外接框 → 经典 CV 细化倾斜四边形 → 透视 / 轴对齐裁剪 → 预览结果。

明确不做

  • 实时预览帧上的检测(拍摄页只有引导框)
  • 卡牌身份识别 / 图库检索 / 价格
  • 打包自研或从 APK 抽取的 TFLite 模型(早期方案已废弃)
  • 集换社业务订单、IM、拍卖、仓储等

3. 与集换社扫描链路的对照

维度 集换社(反编译推断) 本 Demo
形态 交易 App 内嵌模块Native Activity 独立 Flutter Demo
采集 CameraX + 相册 Activity camera + image_picker
检测时机 报告描述含实时预览标注(GraphicOverlay 仅静帧:进入预览页后跑一次
检测引擎 Google ML Kit 同为 Google ML Kit Object Detection
边框形态 报告侧重 AABB + Overlay细节不可见 AABB → 可选倾斜四边形细化
裁剪纠偏 uCrop 手动为主 自动透视 / 轴对齐裁剪(无手动 uCrop
下游 匹配卡库 → 详情 / 交易 :只展示锁定框与裁切图
架构上下文 Native + Flutter Hybrid + 大量 SDK 单应用、无后端、无加固

技术选型上demo 与集换社扫描模块最接近的一点是:都用 ML Kit 做卡牌区域定位,而不是卡牌分类识别。定位成功后集换社走业务匹配demo 停在图像几何处理。

早期仓库内的 carddex_flutter_demo_plan.md 曾计划复刻 CardDex 的本地 detect.tflite;当前实现已改为 ML Kit与集换社扫描栈更一致也避免依赖 APK 内模型资产。


4. 工程结构

lib/
├── main.dart                 # 入口、竖屏、暗色主题
├── screens/
│   ├── capture_screen.dart   # 相机预览 + 引导框(无 ML
│   └── preview_screen.dart   # 检测 / 细化 / 裁剪 / 展示
├── services/
│   ├── card_detector.dart    # ML Kit 静帧检测 + 选框 + 调用细化
│   ├── card_corner_refiner.dart  # Otsu / 连通域 / 最小外接四边形
│   └── card_cropper.dart     # 透视或轴对齐裁剪,贴合 63:88
└── widgets/
    ├── guide_overlay.dart    # 拍摄页暗角 + 白框
    └── guide_frame.dart      # 引导框几何(含 BoxFit.cover 映射)

依赖(与相机 / 图像相关):

作用
camera 后置预览与拍照
image_picker 相册
google_mlkit_object_detection 静帧目标检测
image 解码、模糊输入、透视 copyRectify、JPEG
path_provider 引导裁切临时文件

assets/ 为空:模型由 ML Kit 插件运行时提供,不随 App 打包自定义 .tflite


5. 用户流程

flowchart LR
  A["CaptureScreen<br/>相机 / 相册"] --> B["PreviewScreen"]
  B --> C["按引导框裁切全图"]
  C --> D["ML Kit 静帧检测"]
  D --> E["经典 CV 角点细化"]
  E --> F["透视 / AABB 裁剪"]
  F --> G["展示锁定框 + 结果图"]
  G --> H["重新拍摄 → pop"]
页面 职责
CaptureScreen 后置相机、ResolutionPreset.high、引导遮罩、快门 / 相册 / 翻转。生命周期:切后台释放、回前台重建。
PreviewScreen 全部视觉处理与结果 UI绿框锁定、置信度 / 标签、裁切图、重拍)。

导航为一次 Navigator.push,无路由库、无状态管理包。


6. 处理流水线(实现细节)

6.1 引导框

TCG 常见比例 63:88。框约占视口高度 62%、宽度 78%,垂直中心约在 46%。

  • 拍照:用预览视口 + BoxFit.cover 反算到照片像素(GuideFrame.inCoverImage)。
  • 相册:直接在图像坐标系算引导矩形(GuideFrame.inImage)。

进入检测前先按引导框裁掉框外区域,减小背景干扰(隐含前提:卡已大致落在框内)。

6.2 ML Kit 检测(CardDetector

  • DetectionMode.single,开启分类与多目标。
  • 输出 CardBoxAABB、置信度、标签通用 COCO 类名,不是卡牌 ID
  • pickBest:分数 = 0.4 * confidence + 0.6 * fillRatio,丢弃填充比 ∉ [0.04, 0.98] 的框。

这是通用物体检测,不是「宝可梦 / 游戏王」专用模型;能锁边框即可,标签仅作调试信息。

6.3 角点细化(CardCornerRefiner

在 AABB 邻域做经典视觉,把轴对齐框尽量收成倾斜四边形:

  1. 顶部略抬高、ROI 外扩
  2. 灰度 → 模糊 → Otsu保证 AABB 中心为前景
  3. 最大连通域(优先覆盖种子点)
  4. 凸包 → 最小面积矩形 → TL→TR→BR→BL
  5. 面积校验失败则退回 AABB成功则外扩并照顾卡头区域

6.4 裁剪(CardCropper

条件 行为
有倾斜四边形 copyRectify 透视变换 → 竖向校正 → 贴合 63:88
仅有 AABB 外扩约 6% 后轴对齐裁切并贴合比例
无检测框 按引导框中心区域裁切(usedDetection: false

大图最长边限制约 2560JPEG 质量约 98。


7. 能力边界(相对报告中的产品能力)

反编译报告中的集换社扫描落点是 「识别成功 → 匹配数据库 → 交易」。本 demo 停在几何裁切:

集换社:  采集 → ML Kit → (uCrop) → 匹配库 → 详情/交易
本 Demo: 采集 → 引导裁切 → ML Kit → 角点细化 → 自动裁切 → 预览
                ▲                              ▲
                多出的本地几何步骤               无业务下游

因此:

  • 能验证「静帧 + ML Kit 锁边 + 透视纠偏」是否够用做上架 / 鉴定前处理。
  • 不能验证卡牌检索准确率、价格、多卡桌面、强反光 / 极端角度等产品级指标。
  • 检测失败时仍可按引导框出图,便于继续调试 UI但不代表识别成功。

8. 运行

export PATH="$HOME/flutter/bin:$PATH"
cd /Users/a1518/Desktop/project/card-dex-demo
flutter pub get
flutter run

Android minSdk 为 26需相机与媒体读取权限。真机效果明显优于模拟器。


9. 相关文档

文档 说明
集换社_反编译分析报告.md APK 静态分析(扫描相关见 §4.8、§6.2、§9.1
carddex_flutter_demo_plan.md 早期 TFLite 方案(已与当前实现不一致,仅作历史参考)
README.md 最短运行说明

10. 小结

本 demo 是对照集换社扫描模块做的 视觉前处理实验床:同样依赖 Google ML Kit 做区域定位,但用 Flutter 实现「引导框 → 静帧检测 → 角点细化 → 透视裁切」闭环,刻意剥离交易与图库匹配。若后续要对齐集换社产品路径,需要在裁切结果之上另接卡牌检索 / 版本匹配 API而不是继续堆叠本仓库内的几何管线。