From 37a4c1379960c36e098cb57b3b96f308a01afc74 Mon Sep 17 00:00:00 2001 From: ila Date: Sun, 24 May 2026 17:21:17 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E5=88=9D=E5=A7=8B=E5=8C=96=E5=9B=9B?= =?UTF-8?q?=E4=B8=AA=E5=AD=90=E9=A1=B9=E7=9B=AE=E9=AA=A8=E6=9E=B6=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 mingxi-capture(PyQt5桌面程序)目录骨架 - 新增 mingxi-vision(FastAPI推理服务)目录骨架 - 新增 mingxi-backend(Django业务后端)目录骨架 - 新增 mingxi-frontend(Vue3管理后台)目录骨架 - 迁入 docs/(技术设计文档和PCB调研资料) - 补充 .gitignore(模型文件、Node.js依赖、运行时数据库) Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 376 ++++----- README.md | 4 +- docs/PCB 与 HRIPCB 数据集差异分析.md | 143 ++++ docs/mingxi-vision-架构设计.md | 826 ++++++++++++++++++++ docs/pcb缺陷检测初步方案.md | 218 ++++++ docs/pcb缺陷检测简介.md | 41 + docs/pcb缺陷识别开源项目.md | 131 ++++ docs/pcb调研问题.md | 38 + docs/pcb调研问题.pdf | Bin 0 -> 202750 bytes docs/明析平台-软件重构设计文档.md | 757 ++++++++++++++++++ mingxi-backend/apps/__init__.py | 0 mingxi-backend/apps/auth/__init__.py | 0 mingxi-backend/apps/auth/models.py | 0 mingxi-backend/apps/auth/views.py | 0 mingxi-backend/apps/detection/__init__.py | 0 mingxi-backend/apps/detection/models.py | 0 mingxi-backend/apps/detection/views.py | 0 mingxi-backend/apps/stats/__init__.py | 0 mingxi-backend/apps/stats/models.py | 0 mingxi-backend/apps/stats/views.py | 0 mingxi-backend/apps/system/__init__.py | 0 mingxi-backend/apps/system/models.py | 0 mingxi-backend/apps/system/views.py | 0 mingxi-backend/config/__init__.py | 0 mingxi-backend/config/settings.py | 0 mingxi-backend/config/urls.py | 0 mingxi-backend/config/wsgi.py | 0 mingxi-backend/manage.py | 0 mingxi-backend/requirements.txt | 7 + mingxi-capture/camera/__init__.py | 0 mingxi-capture/camera/hik_camera.py | 0 mingxi-capture/camera/mock_camera.py | 0 mingxi-capture/core/__init__.py | 0 mingxi-capture/core/capture_worker.py | 0 mingxi-capture/core/settings.py | 0 mingxi-capture/core/upload_queue.py | 0 mingxi-capture/main.py | 0 mingxi-capture/requirements.txt | 5 + mingxi-capture/ui/__init__.py | 0 mingxi-capture/ui/config_dialog.py | 0 mingxi-capture/ui/main_window.py | 0 mingxi-capture/ui/tray_icon.py | 0 mingxi-frontend/public/.gitkeep | 0 mingxi-frontend/src/api/.gitkeep | 0 mingxi-frontend/src/components/.gitkeep | 0 mingxi-frontend/src/router/.gitkeep | 0 mingxi-frontend/src/stores/.gitkeep | 0 mingxi-frontend/src/views/.gitkeep | 0 mingxi-vision/api/__init__.py | 0 mingxi-vision/api/detect.py | 0 mingxi-vision/api/health.py | 0 mingxi-vision/api/model.py | 0 mingxi-vision/config.py | 0 mingxi-vision/engine/__init__.py | 0 mingxi-vision/engine/annotator.py | 0 mingxi-vision/engine/base.py | 0 mingxi-vision/engine/defect_classes.py | 0 mingxi-vision/engine/loader.py | 0 mingxi-vision/engine/onnx_adapter.py | 0 mingxi-vision/engine/ultralytics_adapter.py | 0 mingxi-vision/main.py | 0 mingxi-vision/requirements.txt | 9 + mingxi-vision/schema.py | 0 mingxi-vision/scripts/benchmark.py | 0 mingxi-vision/scripts/export_onnx.py | 0 mingxi-vision/tests/.gitkeep | 0 66 files changed, 2377 insertions(+), 178 deletions(-) create mode 100644 docs/PCB 与 HRIPCB 数据集差异分析.md create mode 100644 docs/mingxi-vision-架构设计.md create mode 100644 docs/pcb缺陷检测初步方案.md create mode 100644 docs/pcb缺陷检测简介.md create mode 100644 docs/pcb缺陷识别开源项目.md create mode 100644 docs/pcb调研问题.md create mode 100644 docs/pcb调研问题.pdf create mode 100644 docs/明析平台-软件重构设计文档.md create mode 100644 mingxi-backend/apps/__init__.py create mode 100644 mingxi-backend/apps/auth/__init__.py create mode 100644 mingxi-backend/apps/auth/models.py create mode 100644 mingxi-backend/apps/auth/views.py create mode 100644 mingxi-backend/apps/detection/__init__.py create mode 100644 mingxi-backend/apps/detection/models.py create mode 100644 mingxi-backend/apps/detection/views.py create mode 100644 mingxi-backend/apps/stats/__init__.py create mode 100644 mingxi-backend/apps/stats/models.py create mode 100644 mingxi-backend/apps/stats/views.py create mode 100644 mingxi-backend/apps/system/__init__.py create mode 100644 mingxi-backend/apps/system/models.py create mode 100644 mingxi-backend/apps/system/views.py create mode 100644 mingxi-backend/config/__init__.py create mode 100644 mingxi-backend/config/settings.py create mode 100644 mingxi-backend/config/urls.py create mode 100644 mingxi-backend/config/wsgi.py create mode 100644 mingxi-backend/manage.py create mode 100644 mingxi-backend/requirements.txt create mode 100644 mingxi-capture/camera/__init__.py create mode 100644 mingxi-capture/camera/hik_camera.py create mode 100644 mingxi-capture/camera/mock_camera.py create mode 100644 mingxi-capture/core/__init__.py create mode 100644 mingxi-capture/core/capture_worker.py create mode 100644 mingxi-capture/core/settings.py create mode 100644 mingxi-capture/core/upload_queue.py create mode 100644 mingxi-capture/main.py create mode 100644 mingxi-capture/requirements.txt create mode 100644 mingxi-capture/ui/__init__.py create mode 100644 mingxi-capture/ui/config_dialog.py create mode 100644 mingxi-capture/ui/main_window.py create mode 100644 mingxi-capture/ui/tray_icon.py create mode 100644 mingxi-frontend/public/.gitkeep create mode 100644 mingxi-frontend/src/api/.gitkeep create mode 100644 mingxi-frontend/src/components/.gitkeep create mode 100644 mingxi-frontend/src/router/.gitkeep create mode 100644 mingxi-frontend/src/stores/.gitkeep create mode 100644 mingxi-frontend/src/views/.gitkeep create mode 100644 mingxi-vision/api/__init__.py create mode 100644 mingxi-vision/api/detect.py create mode 100644 mingxi-vision/api/health.py create mode 100644 mingxi-vision/api/model.py create mode 100644 mingxi-vision/config.py create mode 100644 mingxi-vision/engine/__init__.py create mode 100644 mingxi-vision/engine/annotator.py create mode 100644 mingxi-vision/engine/base.py create mode 100644 mingxi-vision/engine/defect_classes.py create mode 100644 mingxi-vision/engine/loader.py create mode 100644 mingxi-vision/engine/onnx_adapter.py create mode 100644 mingxi-vision/engine/ultralytics_adapter.py create mode 100644 mingxi-vision/main.py create mode 100644 mingxi-vision/requirements.txt create mode 100644 mingxi-vision/schema.py create mode 100644 mingxi-vision/scripts/benchmark.py create mode 100644 mingxi-vision/scripts/export_onnx.py create mode 100644 mingxi-vision/tests/.gitkeep diff --git a/.gitignore b/.gitignore index 36b13f1..e4de9c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,176 +1,200 @@ -# ---> Python -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] -*$py.class - -# C extensions -*.so - -# Distribution / packaging -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -*.py,cover -.hypothesis/ -.pytest_cache/ -cover/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -.pybuilder/ -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# UV -# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -#uv.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# pdm -# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. -#pdm.lock -# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it -# in version control. -# https://pdm.fming.dev/latest/usage/project/#working-with-version-control -.pdm.toml -.pdm-python -.pdm-build/ - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintained in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ - -# Ruff stuff: -.ruff_cache/ - -# PyPI configuration file -.pypirc - +# ---> 明析平台专用 + +# 模型文件(体积大,不进版本库) +*.pt +*.onnx +mingxi-vision/models/ + +# 前置机本地数据 +mingxi-capture/queue.db +mingxi-capture/config.ini + +# 大文件 +references/*.mkv +references/*.mp4 + +# IDE +.vscode/ +.idea/ + +# ---> Node.js (mingxi-frontend) +node_modules/ +mingxi-frontend/dist/ +mingxi-frontend/.env.local + +# ---> Python +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +#uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc + diff --git a/README.md b/README.md index 2a18642..7cfe333 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# mingxi_platform - +# mingxi_platform + 明晰平台 \ No newline at end of file diff --git a/docs/PCB 与 HRIPCB 数据集差异分析.md b/docs/PCB 与 HRIPCB 数据集差异分析.md new file mode 100644 index 0000000..2f2560f --- /dev/null +++ b/docs/PCB 与 HRIPCB 数据集差异分析.md @@ -0,0 +1,143 @@ +# PCB 与 HRIPCB 数据集差异分析 + +> 分析时间:2026-05-07 +> 分析对象:`pcb/`(TCC PCB Dataset)与 `HRIPCB/`(HRIPCB Dataset) + +--- + +## 1. 核心差异一览 + +| 维度 | PCB (TCC) | HRIPCB | +|------|-----------|--------| +| **来源** | Roboflow `tcc-r4j2r/pcb-la0tj` | Roboflow `ma007/hripcb` | +| **发布时间** | 2025-12-11 | 2023-04-16 | +| **规模** | 7,971 张 | 1,386 张 | +| **导出预处理** | **Resize to 240×240 (Fit within)** | **Resize to 640×640 (Stretch)** | +| **缺陷密度** | **~2.0 框/张图** | **~4.2 框/张图** | +| **同图变体数** | 每张原始图 **3~6 个变体** | 每张原始图 **2 个变体** | +| **License** | CC BY 4.0 | CC BY 4.0 | + +--- + +## 2. 关键差异详解 + +### 2.1 图像分辨率与预处理策略不同 + +这是两个数据集最本质的区别。 + +- **PCB**:被 Roboflow 预处理为 **240×240(Fit within,保持比例 + 填充)**。文件名中虽带有 `_600` 字样(暗示原始采集分辨率为 600×600),但实际导出图已缩放至 240×240。 +- **HRIPCB**:被预处理为 **640×640(Stretch,直接拉伸)**。原始图被强制拉成 640×640,可能存在轻微形变。 + +**训练影响**:YOLOv8 训练时会统一 `imgsz=640`,两者标签均为归一化坐标(0~1),可直接混用。但 PCB 从 240 放大到 640 时细节损失会比 HRIPCB 更明显,小目标特征可能更模糊。 + +### 2.2 缺陷密度不同 + +| 数据集 | Split | 图片数 | 缺陷框数 | 平均框/图 | +|--------|-------|--------|----------|-----------| +| PCB | train | 6,346 | 12,964 | **2.04** | +| PCB | valid | 798 | 1,588 | **1.99** | +| PCB | test | 827 | 1,660 | **2.01** | +| HRIPCB | train | 1,108 | 4,667 | **4.21** | +| HRIPCB | valid | 139 | 583 | **4.19** | +| HRIPCB | test | 139 | 576 | **4.14** | + +- **PCB**:平均每张图约 **2.0 个缺陷框**,整体相对稀疏。 +- **HRIPCB**:平均每张图约 **4.2 个缺陷框**,缺陷更密集,有些图可能包含同一类型的多个缺陷实例。 + +**结论**:HRIPCB 的缺陷密度约为 PCB 的 **2 倍**。这在训练时意味着 HRIPCB 样本对模型学习"密集小目标共存"场景的贡献更大。 + +### 2.3 数据构成方式不同 + +**PCB 文件名特征**: + +``` +l_light_01_missing_hole_01_1_600_jpg.rf.xxx.jpg +l_light_01_missing_hole_01_2_600_jpg.rf.xxx.jpg +l_light_01_missing_hole_01_3_600_jpg.rf.xxx.jpg +``` + +- 前缀 `l_light_` 表明采集时控制了光照条件(left light / 左侧光源)。 +- `_1_`、`_2_`、`_3_` 后缀表明**同一张缺陷样本有多个变体**(可能是不同光照、角度或采集参数)。 +- 数据冗余度更高,同类缺陷的重复样本多。 + +**HRIPCB 文件名特征**: + +``` +01_missing_hole_01_jpg.rf.xxx.jpg +01_missing_hole_01_jpg.rf.yyy.jpg +``` + +- 命名更简洁,每张原始图仅有 **2 个 Roboflow 自动变体**(后缀 hash 不同)。 +- 样本独立性更强,重复度低。 + +### 2.4 总标注实例数 + +| 数据集 | 图片数 | 总缺陷实例数 | +|--------|--------|-------------| +| PCB | 7,971 | ~16,212 | +| HRIPCB | 1,386 | ~4,826 | +| **合并后** | **9,357** | **~21,038** | + +--- + +## 3. 对模型训练的影响 + +| 影响项 | 说明 | +|--------|------| +| **分辨率差距** | PCB 从 240 上采样到 640 会丢失细节,小目标检测可能受一定影响;HRIPCB 原生 640,细节保留更完整 | +| **密度差异** | HRIPCB 更密集的标注有助于模型学习"多缺陷共存"场景,对实际产线更有价值 | +| **重复样本** | PCB 中同一缺陷的多个变体相当于轻度数据增强,有助于提升光照/角度鲁棒性 | +| **来源互补** | PCB 偏"受控光照实验"风格,HRIPCB 偏"标准工业样本"风格,合并后泛化能力更强 | +| **类别分布** | 两者类别定义完全一致(6 类缺陷),标签格式均为标准 YOLOv8 归一化坐标,可直接合并 | + +--- + +## 4. 使用建议 + +### 4.1 基础用法 + +直接使用 `dataset.py` 合并后训练: + +```bash +python dataset.py merge --src pcb HRIPCB --dst merged +``` + +合并后共 **9,357 张图、约 21,038 个缺陷实例**,数据量足够支撑 YOLOv8n/s 的训练。 + +### 4.2 进阶用法:重新划分 + +如果担心 PCB 占比过高(85%)导致模型过度偏向 PCB 的数据风格,可以打乱后重新按 8:1:1 划分: + +```bash +python dataset.py merge --src pcb HRIPCB --dst merged --rebalance --train 0.8 --val 0.1 --test 0.1 +``` + +### 4.3 训练参数建议 + +针对两个数据集的分辨率差异,建议: + +```yaml +# train.yaml +model: yolov8n.pt +data: D:/github2026/pcb-defect-detection/merged/data.yaml +imgsz: 640 # 统一统一到 640,补偿 PCB 的 240 上采样损失 +batch: 16 # RTX 4060 8GB 安全值 +epochs: 100 +amp: True # 混合精度必开 +patience: 20 # 早停 +``` + +### 4.4 如果精度不够 + +可考虑以下策略: + +1. **分阶段训练**:先用 PCB 预训练,再用 HRIPCB fine-tune(HRIPCB 密度高、标注更"干净")。 +2. **调整样本权重**:在 Ultralytics 中通过 `sample_weights` 或自定义 dataloader 提升 HRIPCB 样本的采样概率。 +3. **数据清洗**:检查 PCB 中 240×240 上采样后是否出现模糊/不可辨认的样本,必要时剔除低质量数据。 + +--- + +## 5. 附:数据来源链接 + +- **PCB (TCC)**:`https://universe.roboflow.com/tcc-r4j2r/pcb-la0tj/dataset/1` +- **HRIPCB**:`https://universe.roboflow.com/ma007/hripcb/dataset/1` diff --git a/docs/mingxi-vision-架构设计.md b/docs/mingxi-vision-架构设计.md new file mode 100644 index 0000000..0ef880c --- /dev/null +++ b/docs/mingxi-vision-架构设计.md @@ -0,0 +1,826 @@ +# mingxi-vision 技术架构与设计分析 + +> 版本:v1.0 · 日期:2026-05-24 +> 硬件约束:联想 Y7000P · RTX 4060 Laptop 8GB · Python 3.8 · Windows 11 +> 上游依赖:`yolo_classification_system/yolo8/inference.py`(迁移基础) + +--- + +## 1. 定位与职责边界 + +`mingxi-vision` 是整个明析平台的**推理微服务**,职责单一: + +``` +接收图像 → 前处理 → 模型推理 → 后处理 → 返回结构化缺陷JSON +``` + +它**不**做的事: +- 不持久化数据(无数据库依赖) +- 不做鉴权(内网服务,由 backend 代理) +- 不管理产线/批次业务(backend 的职责) +- 不直接控制相机(capture 的职责) + +--- + +## 2. 框架选型:FastAPI + +### 为什么不用 Django + +现有系统用 Django,但推理服务有不同的特征: + +| 维度 | Django(现有) | FastAPI(选用) | +|------|--------------|----------------| +| 定位 | 全功能Web框架 | 轻量API框架 | +| 启动时间 | ~3-5s | ~0.5s | +| ORM/DB | 必须配置 | 无需数据库 | +| 异步支持 | 有限(Django 4+ 部分支持) | 原生 async/await | +| 自动文档 | 需要额外配置 | 内置 /docs (Swagger) | +| 推理场景适配 | 过重 | 刚好合适 | + +### Python 3.8 的约束 + +FastAPI 在 Python 3.8 下完全可用,需注意: +- 类型注解用 `Optional[X]` 而非 `X | None`(3.10+ 语法) +- `from __future__ import annotations` 可缓解部分问题 +- Pydantic v1(随 FastAPI 早期版本)在 3.8 稳定 + +``` +# requirements.txt 核心版本锁定 +fastapi==0.104.1 # 3.8 兼容的最后稳定版系列 +uvicorn[standard]==0.24.0 +pydantic==1.10.13 # v1,Python 3.8 最稳定 +ultralytics==8.0.235 # 训练阶段用 +onnxruntime-gpu==1.16.3 # 推理部署阶段用 +opencv-python-headless==4.8.1.78 +numpy==1.24.4 # 3.8 + torch 2.0 兼容版本 +python-multipart==0.0.6 # FastAPI 文件上传必须 +``` + +--- + +## 3. 双运行时策略 + +这是 mingxi-vision 最核心的设计决策。 + +### 问题 + +- **训练阶段**:用 `ultralytics` 的 `.pt` 格式,便于迭代和验证 +- **部署阶段**:用 `.onnx` 格式,跨平台、无需安装 PyTorch、性能更稳定 +- 两套格式的推理 API 有差异,需要统一抽象 + +### 解决方案:运行时适配器(Adapter 模式) + +``` + ┌─────────────────────────────┐ + │ InferenceEngine │ ← 统一接口 + │ detect(image) → [Defect] │ + └──────────┬──────────────────┘ + │ 根据配置选择 + ┌───────────────┴────────────────┐ + ▼ ▼ + UltralyticsAdapter OnnxRuntimeAdapter + (.pt 文件,训练验证用) (.onnx 文件,生产部署用) + ultralytics.YOLO onnxruntime.InferenceSession +``` + +### 代码设计 + +```python +# engine/base.py +from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import List +import numpy as np + +@dataclass +class DefectBox: + class_id: int + class_name: str + class_name_zh: str + confidence: float + severity: str # fatal / major / minor / rework / none + box_xyxy: List[float] # [x1, y1, x2, y2],像素坐标 + + +@dataclass +class DetectResult: + defects: List[DefectBox] + duration_ms: float + image_width: int + image_height: int + model_version: str + + @property + def defect_count(self) -> int: + return len(self.defects) + + @property + def max_severity(self) -> str: + order = ["fatal", "major", "minor", "rework", "none"] + found = {d.severity for d in self.defects} + for s in order: + if s in found: + return s + return "none" + + @property + def avg_confidence(self): + if not self.defects: + return None + return round(sum(d.confidence for d in self.defects) / len(self.defects), 4) + + +class BaseInferenceEngine(ABC): + @abstractmethod + def detect(self, image: np.ndarray, conf: float) -> DetectResult: + ... + + @abstractmethod + def warmup(self) -> None: + """启动时预热,避免第一次推理延迟""" + ... +``` + +```python +# engine/ultralytics_adapter.py +import time +import numpy as np +from .base import BaseInferenceEngine, DefectBox, DetectResult +from .defect_classes import DEFECT_CLASSES + +class UltralyticsAdapter(BaseInferenceEngine): + """开发/训练验证阶段使用""" + + def __init__(self, weights_path: str): + from ultralytics import YOLO + self._model = YOLO(weights_path) + self._weights_path = weights_path + + def warmup(self): + dummy = np.zeros((640, 640, 3), dtype=np.uint8) + self._model.predict(source=dummy, verbose=False, conf=0.01) + + def detect(self, image: np.ndarray, conf: float = 0.45) -> DetectResult: + h, w = image.shape[:2] + t0 = time.perf_counter() + results = self._model.predict(source=image, verbose=False, conf=conf) + duration_ms = (time.perf_counter() - t0) * 1000 + + defects = [] + result = results[0] + if result.boxes is not None and len(result.boxes): + xyxy = result.boxes.xyxy.cpu().numpy() + confs = result.boxes.conf.cpu().numpy() + clsids = result.boxes.cls.cpu().numpy() + for i in range(len(xyxy)): + cid = int(clsids[i]) + meta = DEFECT_CLASSES.get(cid, { + "name": str(cid), "zh": str(cid), "severity": "minor" + }) + defects.append(DefectBox( + class_id=cid, + class_name=meta["name"], + class_name_zh=meta["zh"], + confidence=round(float(confs[i]), 4), + severity=meta["severity"], + box_xyxy=[round(float(x), 1) for x in xyxy[i]], + )) + + return DetectResult( + defects=defects, + duration_ms=round(duration_ms, 1), + image_width=w, + image_height=h, + model_version=str(self._weights_path), + ) +``` + +```python +# engine/onnx_adapter.py +import time +import cv2 +import numpy as np +import onnxruntime as ort +from .base import BaseInferenceEngine, DefectBox, DetectResult +from .defect_classes import DEFECT_CLASSES + +class OnnxRuntimeAdapter(BaseInferenceEngine): + """生产部署阶段使用,无 PyTorch 依赖""" + + def __init__(self, model_path: str, device: str = "cuda"): + providers = ( + ["CUDAExecutionProvider", "CPUExecutionProvider"] + if device == "cuda" + else ["CPUExecutionProvider"] + ) + self._session = ort.InferenceSession(model_path, providers=providers) + self._input_name = self._session.get_inputs()[0].name + self._input_shape = self._session.get_inputs()[0].shape # [1,3,640,640] + self._imgsz = self._input_shape[2] # 通常 640 + self._model_path = model_path + + def warmup(self): + dummy = np.zeros( + (1, 3, self._imgsz, self._imgsz), dtype=np.float32 + ) + self._session.run(None, {self._input_name: dummy}) + + def _preprocess(self, image: np.ndarray): + """BGR → RGB → letterbox → NCHW float32 [0,1]""" + img = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + img, ratio, (dw, dh) = self._letterbox(img, self._imgsz) + img = img.astype(np.float32) / 255.0 + img = np.transpose(img, (2, 0, 1)) # HWC → CHW + img = np.expand_dims(img, 0) # CHW → NCHW + return img, ratio, dw, dh + + @staticmethod + def _letterbox(img, new_size=640): + h, w = img.shape[:2] + ratio = min(new_size / h, new_size / w) + nh, nw = int(h * ratio), int(w * ratio) + img = cv2.resize(img, (nw, nh), interpolation=cv2.INTER_LINEAR) + dw = (new_size - nw) / 2 + dh = (new_size - nh) / 2 + top, bottom = int(round(dh - 0.1)), int(round(dh + 0.1)) + left, right = int(round(dw - 0.1)), int(round(dw + 0.1)) + img = cv2.copyMakeBorder(img, top, bottom, left, right, + cv2.BORDER_CONSTANT, value=(114, 114, 114)) + return img, ratio, dw, dh + + def _postprocess(self, outputs, orig_h, orig_w, ratio, dw, dh, conf_thres): + """YOLOv8 ONNX 输出解码:[1, 84, 8400] → DefectBox列表""" + pred = outputs[0][0] # [84, 8400] + pred = pred.T # [8400, 84] + boxes = pred[:, :4] # cx,cy,w,h + scores = pred[:, 4:] # [8400, num_classes] + + class_ids = np.argmax(scores, axis=1) + confidences = scores[np.arange(len(scores)), class_ids] + + mask = confidences > conf_thres + boxes, class_ids, confidences = ( + boxes[mask], class_ids[mask], confidences[mask] + ) + if len(boxes) == 0: + return [] + + # cx,cy,w,h → x1,y1,x2,y2 + x1 = boxes[:, 0] - boxes[:, 2] / 2 + y1 = boxes[:, 1] - boxes[:, 3] / 2 + x2 = boxes[:, 0] + boxes[:, 2] / 2 + y2 = boxes[:, 1] + boxes[:, 3] / 2 + + # 去除 letterbox padding,还原到原始坐标 + x1 = np.clip((x1 - dw) / ratio, 0, orig_w) + y1 = np.clip((y1 - dh) / ratio, 0, orig_h) + x2 = np.clip((x2 - dw) / ratio, 0, orig_w) + y2 = np.clip((y2 - dh) / ratio, 0, orig_h) + + # NMS + nms_ids = cv2.dnn.NMSBoxes( + np.stack([x1, y1, x2 - x1, y2 - y1], axis=1).tolist(), + confidences.tolist(), conf_thres, iou_threshold=0.45 + ) + if len(nms_ids) == 0: + return [] + + defects = [] + for idx in nms_ids.flatten(): + cid = int(class_ids[idx]) + meta = DEFECT_CLASSES.get(cid, { + "name": str(cid), "zh": str(cid), "severity": "minor" + }) + defects.append(DefectBox( + class_id=cid, + class_name=meta["name"], + class_name_zh=meta["zh"], + confidence=round(float(confidences[idx]), 4), + severity=meta["severity"], + box_xyxy=[ + round(float(x1[idx]), 1), round(float(y1[idx]), 1), + round(float(x2[idx]), 1), round(float(y2[idx]), 1), + ], + )) + return defects + + def detect(self, image: np.ndarray, conf: float = 0.45) -> DetectResult: + orig_h, orig_w = image.shape[:2] + inp, ratio, dw, dh = self._preprocess(image) + + t0 = time.perf_counter() + outputs = self._session.run(None, {self._input_name: inp}) + duration_ms = (time.perf_counter() - t0) * 1000 + + defects = self._postprocess(outputs, orig_h, orig_w, ratio, dw, dh, conf) + + return DetectResult( + defects=defects, + duration_ms=round(duration_ms, 1), + image_width=orig_w, + image_height=orig_h, + model_version=str(self._model_path), + ) +``` + +--- + +## 4. 模型管理:单例 + 启动加载 + +### 问题根源 + +现有 `inference.py` 的 `_MODEL_CACHE` 是进程级字典,首次请求时才加载模型(懒加载)。对推理服务来说,这会导致第一个请求有数秒延迟,在演示现场是灾难性的。 + +### 解决方案:FastAPI 生命周期钩子 + +```python +# engine/loader.py +from typing import Optional +from .base import BaseInferenceEngine +from config import settings + +_engine: Optional[BaseInferenceEngine] = None + + +def get_engine() -> BaseInferenceEngine: + if _engine is None: + raise RuntimeError("推理引擎未初始化,请检查启动日志") + return _engine + + +def init_engine() -> BaseInferenceEngine: + global _engine + if settings.runtime == "onnx": + from .onnx_adapter import OnnxRuntimeAdapter + _engine = OnnxRuntimeAdapter( + model_path=settings.model_path, + device=settings.device, + ) + else: + from .ultralytics_adapter import UltralyticsAdapter + _engine = UltralyticsAdapter(weights_path=settings.model_path) + + _engine.warmup() # 预热,消除第一次推理的延迟 + return _engine +``` + +```python +# main.py +from contextlib import asynccontextmanager +from fastapi import FastAPI +from engine.loader import init_engine +from api.detect import router as detect_router +from api.health import router as health_router + + +@asynccontextmanager +async def lifespan(app: FastAPI): + # 启动时加载模型 + engine = init_engine() + print(f"[mingxi-vision] 引擎就绪: {engine.__class__.__name__}") + yield + # 关闭时释放资源(ONNX session会自动GC) + + +app = FastAPI( + title="明析推理服务", + description="PCB缺陷检测推理接口", + version="1.0.0", + lifespan=lifespan, +) + +app.include_router(detect_router, prefix="/api") +app.include_router(health_router, prefix="/api") +``` + +--- + +## 5. 图像接收与前处理 + +### 接收来源 + +mingxi-vision 接受两种图像来源,用同一个端点处理: + +```python +# api/detect.py +import cv2 +import numpy as np +from fastapi import APIRouter, File, Form, UploadFile, HTTPException +from fastapi.responses import JSONResponse +from engine.loader import get_engine +from engine.annotator import draw_boxes +from schema import DetectResponse +import base64, uuid + +router = APIRouter() + + +@router.post("/detect", response_model=DetectResponse) +async def detect( + image: UploadFile = File(...), + conf: float = Form(default=0.45, ge=0.01, le=0.99), + line_id: str = Form(default=""), + batch_id: str = Form(default=""), + return_annotated: bool = Form(default=False), +): + # 1. 读取图像字节 + raw = await image.read() + if len(raw) > 20 * 1024 * 1024: # 20MB 上限 + raise HTTPException(status_code=413, detail="图像文件过大(上限20MB)") + + # 2. 解码为 numpy BGR + arr = np.frombuffer(raw, dtype=np.uint8) + img = cv2.imdecode(arr, cv2.IMREAD_COLOR) + if img is None: + raise HTTPException(status_code=422, detail="无法解码图像,请检查文件格式") + + # 3. 推理 + engine = get_engine() + result = engine.detect(img, conf=conf) + + # 4. 可选:返回标注图 + annotated_b64 = None + if return_annotated: + annotated = draw_boxes(img.copy(), result.defects) + _, buf = cv2.imencode(".jpg", annotated, [cv2.IMWRITE_JPEG_QUALITY, 85]) + annotated_b64 = base64.b64encode(buf.tobytes()).decode() + + return DetectResponse( + task_id=str(uuid.uuid4()), + line_id=line_id, + batch_id=batch_id, + duration_ms=result.duration_ms, + image_width=result.image_width, + image_height=result.image_height, + defect_count=result.defect_count, + max_severity=result.max_severity, + avg_confidence=result.avg_confidence, + defects=[d.__dict__ for d in result.defects], + annotated_image_b64=annotated_b64, + model_version=result.model_version, + ) +``` + +### 中文路径问题(继承自现有代码) + +现有 `inference.py` 已有 `_copy_to_ascii_temp_input()` 解决中文路径导致 OpenCV 无法读图的问题。`mingxi-vision` 改用 **内存读取**(`np.frombuffer` + `cv2.imdecode`),从源头消除路径问题,不再需要这个 workaround。 + +--- + +## 6. 后处理:标注图生成 + +```python +# engine/annotator.py +import cv2 +import numpy as np +from typing import List +from .base import DefectBox + +SEVERITY_COLORS = { + "fatal": (0, 0, 220), # 红(BGR) + "major": (0, 128, 255), # 橙 + "minor": (0, 215, 255), # 黄 + "rework": (255, 165, 0 ), # 蓝 + "none": (180, 180, 180), # 灰 +} + + +def draw_boxes(image: np.ndarray, defects: List[DefectBox]) -> np.ndarray: + for d in defects: + x1, y1, x2, y2 = [int(v) for v in d.box_xyxy] + color = SEVERITY_COLORS.get(d.severity, (180, 180, 180)) + cv2.rectangle(image, (x1, y1), (x2, y2), color, 2) + + label = f"{d.class_name_zh} {d.confidence:.2f}" + (tw, th), _ = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.55, 1) + cv2.rectangle(image, (x1, y1 - th - 6), (x1 + tw + 4, y1), color, -1) + cv2.putText( + image, label, (x1 + 2, y1 - 4), + cv2.FONT_HERSHEY_SIMPLEX, 0.55, (255, 255, 255), 1, cv2.LINE_AA + ) + return image +``` + +--- + +## 7. 缺陷类别定义 + +```python +# engine/defect_classes.py +# 与 HRIPCB 数据集的 6 类对齐,扩展至 10 类(含真实产线样本迁移学习后) + +DEFECT_CLASSES = { + # ── HRIPCB 基础 6 类(公开数据集,开箱即用)── + 0: {"name": "missing_hole", "zh": "缺孔", "severity": "fatal"}, + 1: {"name": "mouse_bite", "zh": "鼠咬", "severity": "major"}, + 2: {"name": "open_circuit", "zh": "断路", "severity": "fatal"}, + 3: {"name": "short_circuit", "zh": "短路", "severity": "fatal"}, + 4: {"name": "spur", "zh": "毛刺", "severity": "minor"}, + 5: {"name": "spurious_copper", "zh": "余铜", "severity": "major"}, + # ── 扩展类(真实产线样本微调后启用)── + 6: {"name": "oxidation", "zh": "氧化", "severity": "minor"}, + 7: {"name": "solder_ball", "zh": "锡珠", "severity": "rework"}, + 8: {"name": "scratch", "zh": "划痕", "severity": "minor"}, + 9: {"name": "label_error", "zh": "标签错贴","severity": "rework"}, +} + +SEVERITY_ORDER = ["fatal", "major", "minor", "rework", "none"] +``` + +--- + +## 8. 配置管理 + +```python +# config.py +import os +from typing import Literal +from pydantic import BaseSettings # pydantic v1 + + +class Settings(BaseSettings): + # 运行时选择 + runtime: Literal["ultralytics", "onnx"] = "ultralytics" + model_path: str = "./models/pcb_defect_v1.pt" + device: Literal["cuda", "cpu"] = "cuda" + + # 推理默认参数 + default_conf: float = 0.45 + max_image_size_mb: int = 20 + + # 服务配置 + host: str = "0.0.0.0" + port: int = 8001 + workers: int = 1 # 推理服务单 worker,GPU 不支持多进程共享 + + class Config: + env_file = ".env" + env_file_encoding = "utf-8" + + +settings = Settings() +``` + +`.env` 文件示例: + +```bash +# 开发阶段(ultralytics .pt) +RUNTIME=ultralytics +MODEL_PATH=./models/pcb_defect_v1.pt +DEVICE=cuda + +# 生产阶段(ONNX Runtime) +# RUNTIME=onnx +# MODEL_PATH=./models/pcb_defect_v1.onnx +# DEVICE=cuda +``` + +--- + +## 9. 健康检查与诊断接口 + +```python +# api/health.py +import platform +from fastapi import APIRouter +from engine.loader import get_engine + +router = APIRouter() + + +@router.get("/health") +def health(): + try: + engine = get_engine() + return { + "status": "ok", + "runtime": engine.__class__.__name__, + "platform": platform.system(), + } + except RuntimeError as e: + return {"status": "error", "detail": str(e)} + + +@router.get("/health/gpu") +def gpu_info(): + """开发调试用,确认 GPU 是否被正确使用""" + info = {"cuda_available": False, "onnx_providers": []} + try: + import torch + info["cuda_available"] = torch.cuda.is_available() + if torch.cuda.is_available(): + info["gpu_name"] = torch.cuda.get_device_name(0) + info["vram_total_gb"] = round( + torch.cuda.get_device_properties(0).total_memory / 1e9, 1 + ) + except ImportError: + pass + try: + import onnxruntime as ort + info["onnx_providers"] = ort.get_available_providers() + except ImportError: + pass + return info +``` + +--- + +## 10. 完整目录结构 + +``` +mingxi-vision/ +├── api/ +│ ├── __init__.py +│ ├── detect.py # POST /api/detect(核心推理接口) +│ └── health.py # GET /api/health, /api/health/gpu +├── engine/ +│ ├── __init__.py +│ ├── base.py # DefectBox, DetectResult, BaseInferenceEngine +│ ├── loader.py # 单例管理 + init_engine() +│ ├── ultralytics_adapter.py # .pt 推理(开发阶段) +│ ├── onnx_adapter.py # .onnx 推理(生产阶段) +│ ├── annotator.py # 在图像上绘制标注框 +│ └── defect_classes.py # 缺陷类别 + 等级映射表 +├── models/ +│ ├── pcb_defect_v1.pt # ultralytics 训练产物(gitignore) +│ └── pcb_defect_v1.onnx # 导出的 ONNX 模型(gitignore) +├── scripts/ +│ ├── export_onnx.py # pt → onnx 导出脚本 +│ └── benchmark.py # 本地推理性能测试 +├── tests/ +│ ├── test_detect_api.py +│ └── fixtures/ # 测试用 PCB 图片 +├── schema.py # Pydantic 响应模型 +├── config.py # Settings(pydantic BaseSettings) +├── main.py # FastAPI app + lifespan +├── requirements.txt +├── .env.example +└── README.md +``` + +--- + +## 11. 响应 Schema + +```python +# schema.py +from typing import List, Optional +from pydantic import BaseModel + + +class DefectItem(BaseModel): + class_id: int + class_name: str + class_name_zh: str + confidence: float + severity: str # fatal / major / minor / rework / none + box_xyxy: List[float] # [x1, y1, x2, y2] + + +class DetectResponse(BaseModel): + task_id: str + line_id: str + batch_id: str + duration_ms: float + image_width: int + image_height: int + defect_count: int + max_severity: str # 本次检测中最高等级缺陷 + avg_confidence: Optional[float] + defects: List[DefectItem] + annotated_image_b64: Optional[str] # 仅 return_annotated=true 时有值 + model_version: str +``` + +实际响应示例: + +```json +{ + "task_id": "a3f1c2d4-...", + "line_id": "LINE-01", + "batch_id": "BAT-20260524-001", + "duration_ms": 41.3, + "image_width": 3072, + "image_height": 2048, + "defect_count": 2, + "max_severity": "fatal", + "avg_confidence": 0.8762, + "defects": [ + { + "class_id": 2, + "class_name": "open_circuit", + "class_name_zh": "断路", + "confidence": 0.9134, + "severity": "fatal", + "box_xyxy": [234.5, 891.2, 312.8, 943.7] + }, + { + "class_id": 4, + "class_name": "spur", + "class_name_zh": "毛刺", + "confidence": 0.8390, + "severity": "minor", + "box_xyxy": [1204.1, 456.3, 1251.9, 489.0] + } + ], + "annotated_image_b64": null, + "model_version": "./models/pcb_defect_v1.pt" +} +``` + +--- + +## 12. 性能分析(Y7000P RTX 4060) + +### 推理延迟预估 + +| 运行时 | 模型 | 分辨率 | 单次推理 | 含预处理+后处理 | +|--------|------|--------|---------|--------------| +| ultralytics | YOLOv8n | 640×640 | ~12ms | ~20ms | +| ultralytics | YOLOv8s | 640×640 | ~20ms | ~30ms | +| ONNX Runtime GPU | YOLOv8n | 640×640 | ~8ms | ~15ms | +| ONNX Runtime CPU | YOLOv8n | 640×640 | ~80ms | ~100ms | + +> 数据来源:`pcb缺陷检测初步方案.md` 引用的 Y7000P 实测基准 + +**PCB 后道复判场景需求**:触发模式,每块板约 1-3 秒间隔,15ms 的推理延迟完全满足。 + +### 显存占用 + +| 模型 | 显存占用 | +|------|---------| +| YOLOv8n(ultralytics) | ~1.2GB | +| YOLOv8s(ultralytics) | ~2.4GB | +| YOLOv8n(ONNX CUDA EP) | ~0.8GB | + +RTX 4060 8GB 剩余 6GB+ 可用,不构成瓶颈。 + +### 并发限制 + +```python +# main.py 启动参数 +# workers=1:GPU 不支持多进程共享同一 CUDA Context +# 推理天然串行,配合 FastAPI 的 async 处理并发等待队列 +uvicorn main:app --host 0.0.0.0 --port 8001 --workers 1 +``` + +PCB 产线触发模式下,单工位请求天然串行,`workers=1` 完全够用。若需多产线并发,在 `mingxi-backend` 侧做请求队列即可。 + +--- + +## 13. 模型导出(pt → onnx) + +```python +# scripts/export_onnx.py +from ultralytics import YOLO + +model = YOLO("./models/pcb_defect_v1.pt") +model.export( + format="onnx", + imgsz=640, + opset=12, # onnxruntime 1.16 兼容 + simplify=True, # onnx-simplifier 优化计算图 + dynamic=False, # 固定 batch=1,推理服务不需要动态 batch +) +# 产物:pcb_defect_v1.onnx +``` + +切换到 ONNX 的时机: + +``` +1. YOLOv8n 在验证集 mAP@0.5 > 0.90 → 导出 ONNX +2. 运行 scripts/benchmark.py 对比两个运行时延迟 +3. 确认输出一致后,修改 .env 的 RUNTIME=onnx +4. 重启服务,观察 /api/health 确认切换成功 +``` + +--- + +## 14. 与现有代码的对应关系 + +| 现有 `inference.py` 函数 | mingxi-vision 对应位置 | 变化 | +|------------------------|----------------------|------| +| `_MODEL_CACHE` | `engine/loader.py` 单例 | 从懒加载改为启动时加载 | +| `_get_model()` | `loader.init_engine()` | 新增 ONNX 分支 | +| `_copy_to_ascii_temp_input()` | **已删除** | 改用内存读图,无需文件路径 | +| `_parse_result()` | `ultralytics_adapter.detect()` | 增加 severity 映射 | +| `run_image_inference()` | `engine/ultralytics_adapter.py` + `engine/onnx_adapter.py` | 拆成两个运行时 | +| `run_camera_inference()` | **不迁移** | 由 `mingxi-capture` 负责 | +| `run_video_inference()` | **暂不迁移** | 此版本不需要 | +| Django `MEDIA_ROOT` 文件落盘 | **已删除** | 推理服务无状态,不落盘 | + +--- + +## 15. 关键设计决策汇总 + +| 决策 | 选择 | 理由 | +|------|------|------| +| Web 框架 | FastAPI | 轻量、无需 DB、原生 async、自动文档 | +| 模型运行时 | 双运行时(适配器模式) | 开发用 .pt 方便迭代,生产用 .onnx 稳定 | +| 模型加载时机 | 启动时加载 + warmup | 消除首次推理延迟,路演不卡顿 | +| 图像读取 | 内存读取(np.frombuffer) | 彻底消除中文路径问题 | +| 标注图返回 | 按需(return_annotated=true) | 默认不返回,减少响应体积和编码开销 | +| 并发模型 | workers=1,单进程 | GPU CUDA Context 不支持多进程共享 | +| 鉴权 | 无 | 内网服务,由 backend 代理调用 | +| 数据持久化 | 无 | 无状态推理服务,落库交给 backend | +| NMS 后处理 | ONNX 适配器自实现,ultralytics 自带 | 两路输出语义一致 | diff --git a/docs/pcb缺陷检测初步方案.md b/docs/pcb缺陷检测初步方案.md new file mode 100644 index 0000000..57e87bd --- /dev/null +++ b/docs/pcb缺陷检测初步方案.md @@ -0,0 +1,218 @@ +# PCB缺陷检测初步方案(单机开发版) + +> 硬件约束修正:仅有一台联想 Y7000P 笔记本(Intel i7-14650HX 16核 @2.20GHz,16GB RAM,预计 RTX 4060 Laptop 8GB 独显)。 +> 本方案在 v1.1 和"pcb缺陷识别开源项目.md"基础上,针对"无 Jetson、无独立服务器、仅一台笔记本"做完整重构。 +> 对齐 CLAUDE.md:Python3.8 + YOLOv8 + Vue3.0 + Django4.0。 +> 起始日期:2026-05-07 + +--- + +## 1. 硬件盘点与能力边界 + +| 组件 | 规格 | 训练能力 | 推理能力 | +|---|---|---|---| +| CPU | i7-14650HX 16C/24T @2.20GHz,睿频5.2GHz | 数据预处理 / 标注 / 辅助 | OpenVINO CPU推理可行 | +| GPU | RTX 4060 Laptop 8GB GDDR6(Y7000P 2024标配,需核实) | **YOLOv8n/s 可训练,batch≤16** | FP16 实时推理 60+ FPS | +| RAM | 16GB DDR5 | **瓶颈**,大数据集需分批加载 | 推理无压力 | +| 存储 | 1TB NVMe(标配) | 够用,注意清理缓存 | — | +| 散热 | 笔记本主动散热 | **持续满载训练时需外接散热器** | 推理负载低 | + +**结论**:这台笔记本可以**完成训练 + Demo推理 + Web开发全流程**,但 Jetson / TensorRT / DeepStream 路线需要**降级替代**。 + +### 首要动作:确认 GPU 型号 + +开机执行 `nvidia-smi`(或设备管理器)确认: +- 若为 **RTX 4060 8GB**:方案按本文执行 +- 若为 **RTX 4050 6GB**:把 `imgsz` 从 640 降到 416,`batch` 从 16 降到 8 +- 若为**核显/无独显**:只能用 CPU 训练,YOLOv8n 一轮要数小时,建议立即借/租算力 + +--- + +## 2. 方案修正总览(对比原方案) + +| 环节 | 原方案 | 修正后(单笔记本) | 修正理由 | +|---|---|---|---| +| 训练硬件 | Jetson Orin Nano | **Y7000P RTX 4060** | 无 Jetson | +| 训练模型 | YOLOv8n/s 随意 | **固定 YOLOv8n**(s 作备选) | 8GB 显存 + 16GB 内存限制 | +| 边缘部署演示 | Jetson + DeepStream + TensorRT | **笔记本 + USB工业相机 + ONNX Runtime GPU** | 节省硬件预算,聚焦算法 | +| Demo 形态 | 边缘盒子现场演示 | **笔记本直接演示 + 预录视频兜底** | 现场网络/电源风险可控 | +| 实时推理 | TensorRT FP16 | **ONNX Runtime DirectML 或 CUDA EP** | Windows 原生支持,无需交叉编译 | +| 数据标注 | 标注团队 | **本机 Label Studio / labelme** | 5人团队自标注即可 | +| 产品部署 | 云服务器 | **本机 Docker + ngrok 内网穿透** 临时演示 | 省服务器钱 | +| 生产边缘盒 | Jetson 自购 | **MVP 阶段客户采购 / 租用** | 获奖后再投硬件 | + +--- + +## 3. GitHub 项目选型(按硬件修正) + +### 主选:aaravomega/pcb-defect-detection + +https://github.com/aaravomega/pcb-defect-detection + +- YOLOv8 + Ultralytics 标准流程,与 Python3.8 技术栈一致 +- Windows 原生支持,不需 Linux / Docker +- fork 后直接改 `data.yaml` 和 `train.py` + +### 数据:HRIPCB(主)+ DeepPCB(备) + +- **HRIPCB**(Roboflow 一键导出 YOLO 格式):https://universe.roboflow.com/ma007/hripcb/dataset/3 +- **DeepPCB**(含模板图,后期差分增强用):https://github.com/tangsanli5201/DeepPCB + +### 演示方案:放弃 Deepstream,改用 ONNX Runtime + OpenCV + +- 原因:NVIDIA DeepStream 主要面向 Jetson 和 Tesla 服务器卡,笔记本 4060 用起来收益小、坑多 +- 替代:训练后的 `best.pt` → 导出 ONNX → **ONNX Runtime GPU (CUDA Execution Provider)** → OpenCV 读 USB 相机 → Vue 看板展示 +- 备选:**OpenVINO**(Intel CPU 推理,i7-14650HX 上 YOLOv8n 可跑 20-30 FPS,作为 GPU 挂掉时的兜底) + +### 挠性板扩展:Flexible-PCB-Defect-Detection + +https://github.com/Pranshuk29/Flexible-PCB-Defect-Detection + +- 仅在 MVP 阶段、成功对接梅州智科后启用 +- 不在 Demo 阶段占用训练资源 + +--- + +## 4. 训练配置(针对 8GB 显存 + 16GB 内存) + +### 4.1 环境清单(Windows 11 + WSL2 可选) + +``` +Python 3.8.x +PyTorch 2.0.1 + CUDA 11.8(Y7000P 驱动原生支持) +Ultralytics 8.x +onnxruntime-gpu 1.16+ +opencv-python 4.8+ +label-studio 或 labelme +``` + +> 不建议用 WSL2 训练:Windows 下 PyTorch CUDA 性能已够,WSL 多一层开销且调试麻烦。 + +### 4.2 训练超参数(起步版) + +```yaml +# train.yaml(Y7000P 实测可行) +model: yolov8n.pt +data: hripcb.yaml +imgsz: 640 +batch: 16 # 8GB 显存极限,若 OOM 降到 8 +epochs: 100 +device: 0 # 单 GPU +workers: 4 # 16GB 内存下别超 4,否则卡死 +amp: True # 混合精度必开,省显存 +cache: ram # 数据集 <2GB 时开 RAM 缓存加速 +patience: 20 # 早停,省电省时间 +``` + +### 4.3 训练时间预估(HRIPCB 1386 张) + +| 模型 | 单轮时间 | 100轮总时 | 显存占用 | +|---|---|---|---| +| YOLOv8n | ~45s | **约 1.5 小时** | ~4GB | +| YOLOv8s | ~80s | 约 2.5 小时 | ~6GB | +| YOLOv8m | OOM 风险 | 不推荐 | >8GB | + +**建议**:先 n 后 s,n 版本达到 mAP@0.5 > 0.9 即可上路演,s 作为备选。 + +### 4.4 散热与稳定性 + +- 训练时**外接散热底座**,温度控制在 85℃ 以内 +- 关闭 Windows 自动更新,避免训练中断 +- 每晚跑训练、白天做产品开发,错峰使用笔记本资源 + +--- + +## 5. Demo 现场展示方案(替代 Jetson) + +### 5.1 硬件清单(总预算 ≤ 2000 元) + +| 设备 | 型号建议 | 价格 | 用途 | +|---|---|---|---| +| USB 工业相机 | 海康威视 MV-CU013-A0UC 或 海康 USB 摄像头 | ~800-1500 | 实拍 PCB 样品 | +| LED 环形光源 | 工业白光环形灯 | ~200 | 保证光照一致 | +| 简易光箱 / 黑色背景板 | 自制 | ~100 | 降低杂光干扰 | +| PCB 样品 | 向本地厂讨要废板 | 0 | 演示素材 | +| 外接散热底座 | 联想/酷冷至尊 | ~200 | 训练稳定性 | + +### 5.2 演示流程 + +``` +笔记本(Y7000P) + ├─ USB 相机 → OpenCV 取流 + ├─ ONNX Runtime GPU 推理 + ├─ Django 后端写入事件 + ├─ Vue 看板实时展示(localhost) + └─ 投屏到决赛现场大屏 +``` + +### 5.3 三重兜底 + +- **A 计划**:现场实时相机 + PCB 样品演示(最理想) +- **B 计划**:预录 90 秒场景视频 + Vue 看板重放(现场网络/相机故障时启用) +- **C 计划**:纯截图 PPT(极端情况,笔记本挂掉时) + +**每个计划必须提前演练 3 次以上**。 + +--- + +## 6. 开发环境(单机全栈) + +``` +Y7000P 上同时跑: +├─ 终端1:Django runserver (8000) +├─ 终端2:Vue dev server (5173) +├─ 终端3:YOLOv8 推理服务(FastAPI 独立进程,8001) +├─ 终端4:Label Studio(8080,标注用) +└─ 后台:PostgreSQL 或 SQLite(MVP 阶段 SQLite 足够) +``` + +**资源分配**: +- 训练时段:关掉 Django/Vue/Label Studio,独占 GPU 和内存 +- 开发时段:关掉训练,16GB 内存跑全栈无压力 +- **不要同时训练和开发**,16GB 必 OOM + +--- + +## 7. 三个月执行计划(对齐 Y7000P 节奏) + +| 周 | 工作内容 | 是否占用 GPU | +|---|---|---| +| W1 | 确认 GPU 型号;装环境;fork aaravomega;下载 HRIPCB | 轻度(跑通推理) | +| W2 | YOLOv8n 在 HRIPCB 上训练完成;拿到 mAP 基准 | **整夜占用** | +| W3 | Django 后端框架 + Vue 看板骨架;接 SQLite | 否 | +| W4 | YOLOv8 导出 ONNX;FastAPI 推理服务;OpenCV 取相机流 | 轻度 | +| W5 | 买 USB 工业相机 + 环形光;搭建演示光箱;拍测试素材 | 否 | +| W6 | Demo 版 v1:相机 → 推理 → 看板 全链路打通 | 轻度 | +| W7 | 联系丰顺威达 / 梅州超捷 / 智科,签 NDA 收样本 | 否 | +| W8 | 真实样本标注(Label Studio)+ 迁移学习微调 | **整夜占用** | +| W9 | 规则引擎(批次缺陷率/追溯)+ 事件管理 + 告警 | 否 | +| W10 | 挠性板扩展(若智科签约)+ 录 90s 场景视频 | 轻度 | +| W11 | 软著申请;客户 MOU 签署;BP 定稿 | 否 | +| W12 | 决赛 Demo 联调;三重兜底演练;路演彩排 | 否 | + +--- + +## 8. 风险清单(硬件层) + +| 风险 | 概率 | 影响 | 对策 | +|---|---|---|---| +| 笔记本训练过热降频 | 高 | 训练慢 | 外接散热底座 + 限制房间温度 | +| 8GB 显存 OOM | 中 | 训练中断 | batch 降到 8;imgsz 降到 416 | +| 16GB 内存爆满 | 中 | 系统卡死 | workers 降到 2;关闭浏览器等 | +| 决赛现场笔记本故障 | 低 | **灾难** | 二号机备份(团队另一人的笔记本同步工程)+ B/C 计划 | +| GPU 驱动更新导致 CUDA 挂掉 | 低 | 训练中断 | 关闭 NVIDIA 自动更新;锁定驱动版本 | +| 真实 PCB 样本获取失败 | 中 | 只能用公开数据集 | 提前 2 周对接 2 家以上厂商分散风险 | + +--- + +## 9. 后续升级路径(晋级后) + +- **初赛通过后**:考虑租云 GPU(AutoDL / 腾讯云 GN7 一周 ~300 元)加速 YOLOv8s / m 训练 +- **获奖后**:用奖金采购 1 台 **Jetson Orin Nano 8GB**(约 3500 元)做客户演示边缘盒子,切回原方案的 DeepStream 部署路线 +- **MVP 阶段**:客户侧硬件由客户采购或租用,我方只交付**软件 + 配置服务** + +--- + +## 10. 一句话结论 + +**用好 Y7000P 这一台机器,完全够支撑 Demo 版晋级**——关键是**把训练和开发错峰安排,显存内存资源专用**。Jetson / 云服务器留到 MVP 阶段和获奖后再投入,Demo 阶段聚焦"算法精度 + 产品闭环 + 本地客户意向"三板斧即可。 diff --git a/docs/pcb缺陷检测简介.md b/docs/pcb缺陷检测简介.md new file mode 100644 index 0000000..172e09f --- /dev/null +++ b/docs/pcb缺陷检测简介.md @@ -0,0 +1,41 @@ +# PCB线路板缺陷检测项目简介 + +## 一、项目介绍 + +PCB(印刷电路板)被称为"电子产品之母",手机、电脑、汽车里都有它的身影。一块线路板上布满了细如发丝的铜线路和密密麻麻的焊点,任何一处瑕疵都可能导致整台设备故障。 + +传统的人工检测方式依赖质检员用放大镜逐片检查,效率低、眼睛疲劳后漏检率高,而且培养一名熟练质检员需要数月时间。我们的项目利用AI视觉技术——就像给机器装上一双"火眼金睛",通过工业相机自动拍摄线路板图像,再由AI算法实时识别短路、断路、缺焊、异物等各类缺陷,检测速度比人工快数十倍,且24小时不知疲倦,漏检率大幅降低。 + +本项目旨在帮助中小线路板工厂以较低成本实现智能化质检升级,提升产品良率,降低返工成本。 + +## 二、工厂调研问题清单 + +### 生产流程类 +1. 工厂目前各生产环节(曝光、蚀刻、钻孔、电镀、丝印等)的工艺流程是怎样的? +2. 质检环节安排在哪些工序之后?目前有哪些检测站点? +3. 日产量/月产量大概是多少?产线运行几班制? + +### 缺陷情况类 +4. 目前最常见的缺陷类型有哪些?各占多大比例? +5. 各类缺陷的成因是什么?主要在哪些工序产生? +6. 是否有缺陷分类的标准或规范?是否有缺陷样本图片存档? +7. 最严重、最亟待解决的缺陷类型是哪一种? + +### 现有检测方式类 +8. 目前采用人工目检还是已有AOI(自动光学检测)设备? +9. 如有AOI设备,是什么品牌型号?检测效果和痛点是什么? +10. 人工检测的漏检率和误检率大约是多少? +11. 一名质检员一天能检测多少片板? + +### 数据与合作类 +12. 是否愿意提供历史缺陷图片用于AI模型训练?能否签署数据保密协议? +13. 对AI检测的准确率期望值是多少?(如漏检率<0.5%、误检率<2%) +14. 产线上是否已有工业相机或是否方便加装? +15. 如果部署AI检测系统,希望以什么形式合作?(一次性采购、按月租赁、按检测量计费?) + +### 环境与部署类 +16. 产线环境的光照条件如何?是否有稳定的照明? +17. 检测工位是否有网络环境?内网还是外网? +18. 线路板来料的尺寸范围是多少?最小线宽/线距是多少? +19. 对检测速度的要求是什么?(如每秒检测几片) +20. 工厂目前的IT基础设施如何?是否有专人维护自动化设备? diff --git a/docs/pcb缺陷识别开源项目.md b/docs/pcb缺陷识别开源项目.md new file mode 100644 index 0000000..0a9f8b8 --- /dev/null +++ b/docs/pcb缺陷识别开源项目.md @@ -0,0 +1,131 @@ +# PCB缺陷识别开源项目调研 + +> 服务于梅州市新一代电子信息暨人工智能产业创新创业大赛"PCB/电路板AI视觉缺陷检测平台"选题。 +> 结合2025年决赛PCB获奖企业产品形态(刚性板、挠性板、铝基板、Mini LED板、PTFE高频板、OSP涂层等),筛选出覆盖"基础6缺陷 / 挠性板 / 边缘部署 / 高质量基准"四个互补切面的5个GitHub项目,均有公开数据集可直接复用。 +> 调研日期:2026-05-07 + +--- + +## 选型总览 + +| # | 项目 | 框架 | 数据集 | 覆盖切面 | 对应梅州PCB厂 | +|---|---|---|---|---|---| +| 1 | tangsanli5201/DeepPCB | 基础baseline | DeepPCB(1500对) | 6类标准缺陷 + 模板对齐 | 超捷、华达、智科(AOI后复判) | +| 2 | Ixiaohuihuihui/Tiny-Defect-Detection-for-PCB | 小目标优化 | HRIPCB(北大,1386张) | 微小缺陷 + 高分辨率 | 丰顺威达(PTFE高频板)、兴宁精进(高效散热) | +| 3 | aaravomega/pcb-defect-detection | YOLOv8 | 7971张(HRIPCB扩增) | 即插即用算法底座 | 作为MVP版核心底座 | +| 4 | clintonoduor/PCB-Defect-Detection-using-Deepstream | YOLOv5 + Jetson + TensorRT | HRIPCB | 边缘实时部署 | 所有中小PCB厂(不接受云端) | +| 5 | Pranshuk29/Flexible-PCB-Defect-Detection | YOLOv5 + FlexSim | 自建FPC挠性板数据集 | 挠性板专项 | 梅州智科(挠性印制电路板,2025三等奖) | + +--- + +## 1. tangsanli5201/DeepPCB — 基准数据集 + baseline + +- **仓库**:https://github.com/tangsanli5201/DeepPCB +- **数据集特性**: + - **1,500组图像对**:每组包含"无缺陷模板图 + 带缺陷测试图",**像素级对齐** + - 6类缺陷:open(断路)、short(短路)、mousebite(鼠咬)、spur(毛刺)、pinhole(针孔)、spurious copper(余铜) + - 标注格式:PASCAL VOC(bounding box),开箱即用 +- **适配梅州场景**:对应**梅州超捷、华达、智科**等走"AOI后复判"路线的PCB厂——有模板图可用**差分增强**,检测精度更高 +- **建议用法**:作为**初赛资料**的算法精度证据(mAP数字有行业共识),先跑通baseline再迁移到真实样本 + +## 2. Ixiaohuihuihui/Tiny-Defect-Detection-for-PCB — 微小缺陷 + 高分辨率 + +- **仓库**:https://github.com/Ixiaohuihuihui/Tiny-Defect-Detection-for-PCB +- **数据集**:**HRIPCB**(北京大学人机交互开放实验室发布) + - 1,386张合成PCB图,6类缺陷(同DeepPCB) + - **分辨率更高,缺陷尺度更小**,更接近真实AOI拍摄环境 +- **镜像下载**: + - Roboflow:https://universe.roboflow.com/ma007/hripcb/dataset/3 (一键导出YOLO/COCO格式) + - Kaggle:https://www.kaggle.com/datasets/akhatova/pcb-defects +- **适配梅州场景**:对应**丰顺威达(PTFE高频板孔工艺)、兴宁精进(高效散热板)**这类**线宽细、缺陷尺度小**的场景 +- **建议用法**:作为训练主力,HRIPCB的小目标特性能弥补DeepPCB分辨率不足的问题 + +## 3. aaravomega/pcb-defect-detection — YOLOv8 即插即用 + +- **仓库**:https://github.com/aaravomega/pcb-defect-detection +- **数据集**:**7,971张**PCB标注图,6类缺陷(HRIPCB + 数据扩增) +- **框架**:YOLOv8 + Ultralytics transfer learning +- **技术栈匹配**:与 CLAUDE.md 约定的 Python3.8 + YOLOv8 完全一致 +- **适配梅州场景**:作为**MVP版的算法底座**,YOLOv8n/s 在 Jetson Nano/Orin 上可跑实时推理 +- **建议用法**:直接 fork,把 Django4.0 后端和 Vue3.0 看板接上就是完整产品 + +## 4. clintonoduor/PCB-Defect-Detection-using-Deepstream — 边缘部署样板 + +- **仓库**:https://github.com/clintonoduor/PCB-Defect-Detection-using-Deepstream +- **数据集**:HRIPCB + YOLOv5 训练权重 +- **亮点**:**NVIDIA DeepStream + Jetson AGX** 端到端 pipeline + - 含 TensorRT 量化 + - 视频流实时推理 + - 实时可视化 +- **适配梅州场景**:**路演现场演示神器** + - 评委偏好"边缘盒子 + 摄像头 + 实时告警"三件套 + - 中小 PCB 厂不接受云端部署,边缘盒子是刚需 +- **建议用法**:作为 **Demo 版的硬件展示方案**,现场摆一台 Jetson Orin Nano + 工业相机 + PCB 样品 + +## 5. Pranshuk29/Flexible-PCB-Defect-Detection — 挠性板专项差异化 + +- **仓库**:https://github.com/Pranshuk29/Flexible-PCB-Defect-Detection +- **数据集**:自建 **FPC 挠性板**数据集 + YOLOv5 + **FlexSim 数据增强**(模拟弯折形变) +- **适配梅州场景**: + - **直接对应 2025 三等奖企业"梅州智科电路板"的挠性印制电路板产品线** + - FPC 因弯折产生的形变缺陷(折痕、铜箔裂纹、层间分离)是**通用 PCB 数据集覆盖不到**的差异化能力 +- **建议用法**:作为**本次参赛的差异化亮点** + - 在标准 6 类缺陷之外加一个"挠性板专用"能力模块 + - 与梅州智科对接签 MOU(客户意向书) + +--- + +## 备选项目(路演备选 / 答辩应对) + +| 项目 | URL | 适用场景 | +|---|---|---| +| AyaAshraf76/PCB-defect-detection | https://github.com/AyaAshraf76/PCB-defect-detection | YOLOv8 + Roboflow 数据,教学级 | +| Hazrat-Ali9/Deep-Learning-AOI-for-PCBs | https://github.com/Hazrat-Ali9/Deep-Learning-AOI-for-PCBs-Real-Time-YOLO-Detection-of-Missing-Holes-Mouse-Bites-Shorts-and-Spurs | 实时 AOI 场景,补充参考 | +| EzekiasOkuPevi/PCB-Defect-Detection-Using-Deep-Learning | https://github.com/EzekiasOkuPevi/PCB-Defect-Detection-Using-Deep-Learning | YOLOv8 vs YOLOv10 对比,答辩用 | +| SiemonCha/pcb-defect-detection | https://github.com/SiemonCha/pcb-defect-detection | 生产级 pipeline,工程参考 | +| utkarsh-ankit/Defect-Detection-of-PCB | https://github.com/utkarsh-ankit/Defect-Detection-of-PCB | MobileNets 轻量化方案 | + +--- + +## 整合推进建议(对齐 v1.1 的 Demo 版→MVP 版分档) + +### Demo 版(1.5 个月,路演可用) + +1. 拉取 **项目1 DeepPCB** + **项目2 HRIPCB** 数据集合并训练 +2. 用 **项目3 aaravomega/pcb-defect-detection** 的 YOLOv8 底座做迁移学习 +3. 用 **项目4 Deepstream** 方案在 Jetson 上做实时演示 +4. 产出:现场可演示的边缘盒子 + 标准 mAP 基准数字 + +### MVP 版(3 个月,客户可交付) + +1. 接入 **1 家梅州本地 PCB 厂**真实产线样本,微调项目3的模型 +2. 用 **项目5 Flexible-PCB** 的 FPC 方案扩展挠性板能力,对接梅州智科 +3. Django4.0 + Vue3.0 产品化:用户系统 / 规则引擎 / 告警回放 / 追溯看板 +4. 产出:客户 MOU、软著证书、真实产线验证数据 + +### 路演包装话术 + +> "基于北大 HRIPCB 学术数据集 + 真实梅州产线样本双源训练,面向梅州本地 PCB 产业集群的 AI 视觉质检平台。" + +**学术可信度**(北大数据集)**+ 本地化落地**(真实产线)**双背书**,契合 2025 公告"项目展示完成度"与"自主知识产权"考察点。 + +--- + +## 版权与合规提示 + +- **DeepPCB、HRIPCB** 均以学术用途发布 +- 商业化部署前需在对应论文 / README 中确认授权条款 +- 路演阶段使用无碍,但要提前准备自有数据集方案用于答辩应对 +- 建议:**尽早启动真实样本采集**,降低对学术数据集的依赖 + +--- + +## 参考资料 + +- [pcb-defect-detection · GitHub Topics](https://github.com/topics/pcb-defect-detection) +- [HRIPCB on Roboflow Universe](https://universe.roboflow.com/ma007/hripcb/dataset/3) +- [PCB Defects dataset on Kaggle](https://www.kaggle.com/datasets/akhatova/pcb-defects) +- [PCB-YOLOV8X: a network for detecting micro-sized defects on PCB surfaces (Nature, 2026)](https://www.nature.com/articles/s41598-026-46089-6) +- [An Open Source Enhancement Algorithm for PCB Defect Detection Based on YOLOv8 (arXiv 2025)](https://arxiv.org/html/2507.02963v1) +- [Defect detection of printed circuit board assembly based on YOLOv5 (Nature, 2024)](https://www.nature.com/articles/s41598-024-70176-1) +- [PCB Electronic Component Soldering Defect Detection Using YOLO11 (PMC, 2025)](https://pmc.ncbi.nlm.nih.gov/articles/PMC12158347/) diff --git a/docs/pcb调研问题.md b/docs/pcb调研问题.md new file mode 100644 index 0000000..f987bfd --- /dev/null +++ b/docs/pcb调研问题.md @@ -0,0 +1,38 @@ +# 简介 +* 手机、电脑、汽车里都有PCB印刷电路板。 +* 一块线路板上布满了细如发丝的铜线路和密密麻麻的焊点,任何一处瑕疵都可能导致整台设备故障。 +* 传统的人工检测方式依赖质检员用放大镜逐片检查,效率低、眼睛疲劳后漏检率高,而且培养一名熟练质检员需要数月时间。 +* 我们的项目利用AI视觉技术,通过工业相机自动拍摄线路板图像,再由AI算法实时识别短路、断路、缺焊、异物等各类缺陷,检测速度比人工快数十倍,且24小时不知疲倦,漏检率大幅降低。 +* 搭配管理平台,随时查看记录和统计缺陷,生成数据报告. +* 本项目帮助中小线路板工厂以较低成本实现智能化质检升级,提升产品良率,降低返工成本。 + +#调研问题: + +##生产流程类 + +1. 工厂质检环节安排在哪些工序之后? +2. 日产量/月产量大概是多少?产线运行几班制? + +## 缺陷情况类 +1. 目前最常见的缺陷类型有哪些?各占多大比例? +2. 各类缺陷的成因是什么?主要在哪些工序产生? +3. 是否有缺陷分类的标准或规范?是否有缺陷样本图片存档? +4. 最严重、最亟待解决的缺陷类型是哪一种? + +## 现有检测方式类 +1. 目前采用人工目检还是已有AOI(自动光学检测)设备? +2. 如有AOI设备,是什么品牌型号?检测效果和痛点是什么? +3. 人工检测的漏检率和误检率大约是多少? +4. 一名质检员一天能检测多少片板? + +## 数据与合作类 +1. 对AI检测的准确率期望值是多少?(如漏检率<0.5%、误检率<2%) +2. 如果部署AI检测系统,希望以什么形式合作?(一次性采购、按月租赁、按检测量计费?) + + +## 环境与部署类 +1. 产线环境的光照条件如何?是否有稳定的照明? +2. 检测工位是否有网络环境?内网还是外网? +3. 线路板来料的尺寸范围是多少?最小线宽/线距是多少? +4. 对检测速度的要求是什么?(如每秒检测几片) +5. 工厂目前的IT基础设施如何?是否有专人维护自动化设备? \ No newline at end of file diff --git a/docs/pcb调研问题.pdf b/docs/pcb调研问题.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7d85ec0891006dadff4c66b32abb73d58a38d84e GIT binary patch literal 202750 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 版本:v2.0 · 日期:2026-05-24 +> 项目:基于机器视觉的图像识别技术应用平台——明析 +> 参赛:梅州市2026年新一代电子信息暨人工智能产业创新创业大赛 · 初创企业(创客)组 + +--- + +## 1. 重构背景 + +### 1.1 现有代码概况 + +当前仓库 `yolo_classification_system` 是一套**通用YOLO推理系统**,实现了: + +| 模块 | 现状 | +|------|------| +| 后端 | Django 4 + DRF,JWT鉴权,支持图片/视频/摄像头三种推理模式 | +| 推理 | `inference.py` 封装 ultralytics YOLO,模型缓存,结果落库 | +| 数据模型 | `UserProfile`、`YoloResult`、`SceneNews`、`SystemLog`、`YoloStatsDaily` | +| 前端 | Vue 3 + Vite,开发/生产环境分离,API代理配置完整 | +| 演示模型 | 驾驶员疲劳检测(`driver-drowsiness-detection/best.pt`) | + +### 1.2 重构目标 + +将通用系统改造为**PCB线路板缺陷检测专用平台(明析)**,在不改动客户现有硬件的前提下,通过算法叠加实现AI视觉质检能力升级。 + +--- + +## 2. 系统物理架构 + +### 2.1 两台机器部署 + +``` +┌─────────────────────────────────┐ 局域网 ┌──────────────────────────────────────┐ +│ 前置机(工业PC) │ ─────────────→ │ 推理服务器(Linux+GPU) │ +│ │ │ │ +│ 相机 ──USB3──→ mingxi-capture │ │ mingxi-vision :8001 (FastAPI) │ +│ (PyQt5桌面程序) │ │ mingxi-backend :8000 (Django) │ +│ Win7 SP1+ 工业机 │ │ mingxi-frontend :80 (Vue3) │ +└─────────────────────────────────┘ └──────────────────────────────────────┘ +``` + +| 角色 | 机器 | 操作系统 | 运行软件 | +|------|------|---------|---------| +| 前置机 | 工厂现有工业PC(USB3.0) | Windows 7 SP1 及以上 | mingxi-capture.exe | +| 推理服务器 | 团队配置(RTX 4060 或以上) | Linux | mingxi-vision + mingxi-backend + mingxi-frontend | + +### 2.2 数据流 + +``` +操作工(点击按钮)或 PLC触发信号 + │ + ▼ + mingxi-capture(前置机) + │ + ├─① 同步 POST 图像 ──────────────→ mingxi-vision(推理服务器:8001) + │ │ 推理完成 + │ ←── 返回标注图+缺陷列表+结论 ──────┘ + │ + ├─ 立即在桌面程序展示结果(操作工可见) + │ · 合格 / 不合格 结论 + │ · 标注了缺陷位置的图像 + │ · 每个缺陷的类型、等级、置信度 + │ + └─② 异步队列 POST 结果 ──────────→ mingxi-backend(:8000) + │ 存入 SQLite + 若失败 → 本地SQLite重试队列 │ + ▼ + 管理员/组长/厂长 + 通过浏览器查看 + (短轮询,1-2秒延迟) +``` + +### 2.3 端口分配 + +| 服务 | 端口 | 调用方 | +|------|------|-------| +| mingxi-vision | 8001 | mingxi-capture(同步推理) | +| mingxi-backend | 8000 | mingxi-capture(存档)、浏览器前端 | +| mingxi-frontend | 80 | 浏览器 | + +--- + +## 3. 子项目拆分方案 + +### 3.1 项目总览 + +``` +mingxi-capture/ Python 3.8 · PyQt5 · Windows桌面程序(前置机运行) +mingxi-vision/ Python 3.8 · FastAPI · PCB缺陷推理服务(推理服务器运行) +mingxi-backend/ Python 3.8 · Django 4 · 业务后端(推理服务器运行) +mingxi-frontend/ Vue 3.0 · 管理后台(推理服务器运行,浏览器访问) +``` + +### 3.2 代码迁移决策 + +| 现有文件/模块 | 处置方式 | 说明 | +|-------------|---------|------| +| `yolo8/models.py` → `UserProfile` | **直接复用** | JWT鉴权体系完整,扩展 role 字段 | +| `yolo8/models.py` → `SystemLog` | **直接复用** | 日志结构通用 | +| `yolo8/jwt_utils.py` | **直接复用** | token版本机制保留 | +| `yolo8/models.py` → `YoloResult` | **重构为** `DefectResult` | 增加PCB专用字段:缺陷等级、产线 | +| `yolo8/models.py` → `SceneNews` | **删除** | 与PCB业务无关 | +| `yolo8/models.py` → `YoloStatsDaily` | **重构为** `ProductionStat` | 改为产线维度统计 | +| `yolo8/inference.py` → `run_image_inference` | **迁移至** `mingxi-vision` | 推理服务核心,增加ONNX支持 | +| `yolo8/inference.py` → `run_camera_inference` | **删除** | 由 `mingxi-capture` 海康SDK替代 | +| `yolo8/inference.py` → `_copy_to_ascii_temp_input` | **删除** | 改为内存读图,彻底消除中文路径问题 | +| `yolo8/views.py` → 鉴权相关视图 | **直接复用** | `auth_*`、`user_*` 无需改动 | +| `yolo8/views.py` → `yolo_task_image` | **重构为** `detect_pcb` | 简化,接收capture推送 | +| `frontend/` | **重构** | 删除通用YOLO页面,改为管理后台 | + +--- + +## 4. mingxi-capture(前置采集程序) + +### 4.1 定位 + +运行在**前置机**(工厂工业PC)上的 Windows 原生桌面程序。操作工唯一的交互界面,负责连接相机、触发检测、展示结果,并将结果异步上报至后台。 + +### 4.2 技术栈 + +``` +语言:Python 3.8 +GUI:PyQt5(支持 Windows 7 SP1 及以上,系统托盘、对话框完整支持) +相机:MvImport(海康威视MVS Python SDK,随MVS安装包提供) +本地存储:SQLite(通过 Python 内置 sqlite3) +网络:requests(同步调用vision)+ threading(异步队列推送backend) +打包:PyInstaller → 单文件 .exe 或目录,客户解压即用 +最低系统:Windows 7 SP1 x64 +``` + +### 4.3 目录结构 + +``` +mingxi-capture/ +├── camera/ +│ ├── hik_camera.py # 海康相机封装(MvImport,Phase 2接入) +│ └── mock_camera.py # 模拟模式(读本地图片文件夹,Demo/开发用) +├── ui/ +│ ├── main_window.py # 主窗口:触发按钮 + 图像展示 + 缺陷列表 +│ ├── config_dialog.py # 配置弹窗:服务器地址、端口、相机参数 +│ └── tray_icon.py # 系统托盘图标:显示/隐藏主窗口、退出 +├── core/ +│ ├── capture_worker.py # 拍图+调推理(在QThread中执行,不阻塞UI) +│ ├── upload_queue.py # 异步上报队列(本地SQLite缓存+重试) +│ └── settings.py # 读写 config.ini 配置文件 +├── assets/ +│ └── tray_icon.png # 托盘图标 +├── config.ini # 默认配置(首次运行生成) +├── queue.db # 本地重试队列(SQLite,运行时生成) +├── main.py # 程序入口 +├── requirements.txt +└── mingxi-capture.spec # PyInstaller打包配置 +``` + +### 4.4 主窗口功能 + +``` +┌─────────────────────────────────────────┐ +│ 明析采集程序 [最小化到托盘] [×] │ +├─────────────┬───────────────────────────┤ +│ │ ┌───────────────────────┐│ +│ [手动检测] │ │ ││ +│ │ │ 标注图显示区域 ││ +│ 状态: 就绪 │ │ (检测后显示) ││ +│ │ │ ││ +│ 结论: │ └───────────────────────┘│ +│ ██ 不合格 │ │ +│ │ 缺陷列表: │ +│ 共 3 处 │ 类型 等级 置信度 │ +│ 最高: 致命 │ 断路 致命 0.94 │ +│ │ 短路 致命 0.88 │ +│ │ 毛刺 轻微 0.72 │ +└─────────────┴───────────────────────────┘ +``` + +### 4.5 配置弹窗(系统托盘右键→设置) + +``` +推理服务地址: [192.168.1.100] 端口: [8001] +后台服务地址: [192.168.1.100] 端口: [8000] +相机序列号: [自动检测 ▼] +模拟模式: [✓] 启用 图片目录: [C:\test_images\ 浏览] +置信度阈值: [0.45] +[保存] [取消] +``` + +配置持久化至 `config.ini`,程序启动时自动读取。 + +### 4.6 异步上报队列 + +```python +# core/upload_queue.py 逻辑 + +# 1. capture_worker 推理成功后,将结果插入本地 SQLite queue.db +# 2. 后台线程每 5 秒扫描一次 queue.db 中状态为 pending 的记录 +# 3. 尝试 POST 到 mingxi-backend +# 成功 → 标记为 sent +# 失败 → retry_count + 1,超过 10 次标记为 failed(不再重试) +# 4. 队列表结构: +# id, image_base64, result_json, created_at, status, retry_count, last_error +``` + +### 4.7 mock_camera 模拟模式 + +Phase 1(路演)无真实相机时,从配置目录中按序读取 `.jpg`/`.png` 文件,接口与 `hik_camera.py` 完全一致,上层代码无感知切换。 + +### 4.8 打包部署 + +```bash +pyinstaller mingxi-capture.spec +# 输出:dist/mingxi-capture/(目录模式)或 dist/mingxi-capture.exe(单文件) +# 客户端:解压后双击 mingxi-capture.exe 即可运行 +# 随安装包附带:海康 MVS Runtime DLL(如需相机功能) +``` + +### 4.9 触发模式(阶段支持) + +| 触发方式 | Phase 1 | Phase 2 | +|---------|---------|---------| +| 手动点击按钮 | ✅ | ✅ | +| PLC/传感器信号(串口/数字IO) | — | ✅ | +| 定时自动(固定频率) | — | ✅ | + +--- + +## 5. mingxi-vision(推理服务) + +### 5.1 职责 + +- 接收图像(来自 `mingxi-capture`) +- 调用明析平台(YOLOv8/ONNX)执行PCB缺陷检测 +- 返回缺陷列表(位置、类别、置信度、等级)+ 标注图(可选) +- 支持模型热重载(管理员通过后台切换模型时调用) + +### 5.2 技术栈 + +``` +语言:Python 3.8 +框架:FastAPI + uvicorn(workers=1,单进程,GPU不跨进程共享) +推理:ultralytics YOLOv8(开发阶段)/ ONNX Runtime(生产部署) +并发:asyncio.Lock(推理串行化,防止GPU冲突) +GPU:CUDA 11.x + cuDNN +``` + +### 5.3 并发处理:推理锁 + +```python +# engine/loader.py +import asyncio + +_inference_lock = asyncio.Lock() +_engine: Optional[BaseInferenceEngine] = None + +def get_inference_lock() -> asyncio.Lock: + return _inference_lock + +# api/detect.py +async def detect(image: UploadFile, conf: float = 0.45, ...): + raw = await image.read() + img = cv2.imdecode(np.frombuffer(raw, np.uint8), cv2.IMREAD_COLOR) + + async with get_inference_lock(): # 请求自动排队,GPU串行执行 + result = engine.detect(img, conf) + + return build_response(result) +``` + +- 并发请求不会崩溃,自动排队等待 +- RTX 4060,YOLOv8s,PCB图:约 20~40ms/张 → 25~50 fps +- Windows / Linux 行为完全一致(asyncio 事件循环原语,无OS依赖) + +### 5.4 模型热重载接口 + +``` +POST /api/model/reload +Body: { "model_path": "/opt/mingxi/models/pcb_v2.onnx" } +Response: { "status": "ok", "model_version": "pcb_v2", "warmup_ms": 312 } +``` + +热重载流程: +1. 管理员在浏览器上传新模型并点击"切换" +2. `mingxi-backend` 保存文件、更新数据库,调用此接口 +3. `mingxi-vision` 获取推理锁(等待当前推理完成),卸载旧模型,加载新模型,执行 warmup +4. 释放锁,返回成功 + +### 5.5 目录结构 + +``` +mingxi-vision/ +├── api/ +│ ├── detect.py # POST /api/detect +│ ├── model.py # POST /api/model/reload +│ └── health.py # GET /api/health, /api/health/gpu +├── engine/ +│ ├── base.py # DefectBox, DetectResult, BaseInferenceEngine +│ ├── loader.py # 单例 + asyncio.Lock + init_engine() +│ ├── ultralytics_adapter.py +│ ├── onnx_adapter.py +│ ├── annotator.py # 标注图生成(按severity着色) +│ └── defect_classes.py # HRIPCB 6类 + 扩展4类 +├── models/ # .pt 和 .onnx 文件(gitignored) +├── scripts/ +│ ├── export_onnx.py # pt → onnx 导出脚本 +│ └── benchmark.py +├── tests/ +├── schema.py # Pydantic 响应模型 +├── config.py # BaseSettings(读 .env) +├── main.py # FastAPI lifespan + app +└── requirements.txt +``` + +### 5.6 推理接口 + +``` +POST /api/detect +Content-Type: multipart/form-data +Fields: + image: <图像文件> + conf: float (default: 0.45) + return_annotated: bool (default: false) + +Response 200: +{ + "task_id": "uuid", + "duration_ms": 38, + "verdict": "fail", // pass / fail + "defect_count": 2, + "max_severity": "fatal", + "avg_confidence": 0.89, + "defects": [ + { + "class_id": 2, + "class_name": "open_circuit", + "class_name_zh": "断路", + "confidence": 0.94, + "severity": "fatal", + "box_xyxy": [120, 45, 198, 123] + } + ], + "annotated_image_base64": "..." // 仅 return_annotated=true 时返回 +} +``` + +### 5.7 缺陷类别与等级映射 + +```python +DEFECT_CLASSES = { + # HRIPCB 数据集原始6类 + 0: {"name": "missing_hole", "zh": "缺孔", "severity": "fatal"}, + 1: {"name": "mouse_bite", "zh": "鼠咬", "severity": "major"}, + 2: {"name": "open_circuit", "zh": "断路", "severity": "fatal"}, + 3: {"name": "short_circuit", "zh": "短路", "severity": "fatal"}, + 4: {"name": "spur", "zh": "毛刺", "severity": "minor"}, + 5: {"name": "spurious_copper", "zh": "余铜", "severity": "major"}, + # 扩展类(Phase 2 标注后训练) + 6: {"name": "oxidation", "zh": "氧化", "severity": "minor"}, + 7: {"name": "solder_ball", "zh": "锡珠", "severity": "rework"}, + 8: {"name": "scratch", "zh": "划痕", "severity": "minor"}, + 9: {"name": "label_error", "zh": "标签错贴","severity": "rework"}, +} +``` + +--- + +## 6. mingxi-backend(业务后端) + +### 6.1 职责 + +- 接收 `mingxi-capture` 推送的检测结果,持久化至 SQLite +- 提供 REST API 给浏览器管理后台 +- 用户管理、三级权限控制 +- 模型文件管理(上传、备份、切换、触发vision热重载) +- 系统参数配置 + +### 6.2 技术栈 + +``` +语言:Python 3.8 +框架:Django 4.0 + django-rest-framework +数据库:SQLite(内网单服务器部署,无高并发写入,SQLite足够) +认证:JWT(从现有系统直接复用) +``` + +> 初期不引入 Celery/Redis,保持部署简单。告警推送(Phase 2)再评估是否引入。 + +### 6.3 用户权限设计 + +| 角色 | 检测记录可见范围 | 其他权限 | +|------|---------------|---------| +| 操作工 | 仅自己触发的记录 | 无 | +| 组长 | 本组所有成员的记录 | 查看本组统计 | +| 管理员 | 全部记录 | 用户管理、系统配置、模型管理、查看所有统计 | + +```python +# UserProfile 扩展 +class UserProfile(models.Model): + user = models.OneToOneField(User) + role = models.CharField(choices=[ + ("operator", "操作工"), + ("leader", "组长"), + ("admin", "管理员"), + ], default="operator") + group = models.ForeignKey("WorkGroup", null=True) # 操作工和组长属于某个工组 + +class WorkGroup(models.Model): + name = models.CharField(max_length=100) + leader = models.ForeignKey(UserProfile, null=True, related_name="led_group") +``` + +### 6.4 模型管理设计 + +```python +class ModelRegistry(models.Model): + """模型版本注册表""" + name = models.CharField(max_length=100) # 文件名(含扩展名) + runtime = models.CharField(choices=["pt", "onnx"]) + file_path = models.CharField(max_length=500) # 服务器本地路径 + file_size = models.IntegerField() # 字节数 + is_active = models.BooleanField(default=False) # 当前生效模型 + uploaded_by = models.ForeignKey(UserProfile) + uploaded_at = models.DateTimeField(auto_now_add=True) + notes = models.TextField(blank=True) +``` + +**模型管理规则:** +- 同时只有一个 `is_active=True` +- 最多保留 10 个版本,超出时自动删除最早上传的非活跃版本及其文件 +- 切换模型时:更新 `is_active` → 调用 `POST http://localhost:8001/api/model/reload` + +### 6.5 管理员可配置参数 + +| 参数类别 | 具体参数 | +|---------|---------| +| 推理参数 | 置信度阈值、IOU阈值、图像输入尺寸 | +| 模型管理 | 上传模型、切换活跃模型、查看备份列表 | +| 产线配置 | 产线名称、前置机IP(仅记录,不主动通信) | +| 用户管理 | 新增/停用账号、分配角色、分配工组 | +| 告警规则 | Phase 2,预留接口 | + +### 6.6 数据模型设计 + +```python +class DefectResult(models.Model): + """单次检测记录""" + operator = models.ForeignKey(UserProfile, null=True) + line_id = models.CharField(max_length=50, blank=True) + source_image = models.ImageField(upload_to="originals/") + annotated_image = models.ImageField(upload_to="annotated/", null=True) + verdict = models.CharField(choices=["pass", "fail"]) + defect_count = models.IntegerField(default=0) + max_severity = models.CharField(choices=["none","rework","minor","major","fatal"]) + detections_json = models.TextField() # 完整缺陷列表JSON + avg_confidence = models.FloatField() + duration_ms = models.IntegerField() + model_version = models.CharField(max_length=100) + created_at = models.DateTimeField(auto_now_add=True) + + +class ProductionStat(models.Model): + """每日产线统计(聚合)""" + stat_date = models.DateField() + line_id = models.CharField(max_length=50) + total_count = models.IntegerField(default=0) + pass_count = models.IntegerField(default=0) + fail_count = models.IntegerField(default=0) + defect_dist = models.TextField() # 各缺陷类型数量JSON + + +class SysConfig(models.Model): + """系统参数键值存储""" + key = models.CharField(max_length=100, unique=True) + value = models.TextField() + updated_at = models.DateTimeField(auto_now=True) +``` + +### 6.7 API 接口设计 + +``` +# 认证(直接复用现有代码) +POST /api/auth/login +POST /api/auth/refresh +POST /api/auth/logout +GET /api/user/me + +# 检测结果(capture推送入口) +POST /api/detect/result/ # capture 上报推理结果 +GET /api/detect/results/ # 列表(按角色自动过滤) +GET /api/detect/results/{id}/ + +# 统计 +GET /api/stats/overview/ # 今日合格率、缺陷总数 +GET /api/stats/trend/ # 近N天趋势 +GET /api/stats/defect-dist/ # 缺陷类型分布 + +# 模型管理(管理员) +GET /api/admin/models/ # 模型列表(最多10条) +POST /api/admin/models/upload/ # 上传新模型 +POST /api/admin/models/{id}/activate/ # 切换活跃模型(触发vision热重载) +DELETE /api/admin/models/{id}/ # 手动删除某个备份 + +# 系统配置(管理员) +GET /api/admin/config/ +PATCH /api/admin/config/ + +# 用户管理(管理员) +GET /api/admin/users/ +POST /api/admin/users/ +PATCH /api/admin/users/{id}/ +GET /api/admin/groups/ +POST /api/admin/groups/ + +# 系统日志(直接复用) +GET /api/admin/logs/ +``` + +--- + +## 7. mingxi-frontend(管理后台) + +### 7.1 定位 + +**纯管理后台**,供组长、厂长、管理员通过浏览器使用。操作工不通过浏览器操作(操作工使用前置机桌面程序)。 + +### 7.2 技术栈 + +``` +框架:Vue 3 + Vite + TypeScript(保持现有配置不变) +UI:Element Plus(复用现有) +图表:ECharts(统计报表) +实时:短轮询(每1秒请求一次最新记录,满足1-2秒延迟要求,无需WebSocket) +``` + +> 短轮询而非 WebSocket:部署简单,Django 无需 Channels,延迟满足要求。 + +### 7.3 页面规划 + +| 路由 | 页面 | 可见角色 | 现有/新增 | +|------|------|---------|---------| +| `/login` | 登录 | 全部 | 复用 | +| `/dashboard` | 实时监控看板 | 组长、管理员 | **新增** | +| `/history` | 检测历史记录 | 全部(按权限过滤) | **新增** | +| `/stats` | 统计报表 | 组长、管理员 | **新增** | +| `/admin/models` | 模型管理 | 管理员 | **新增** | +| `/admin/config` | 系统配置 | 管理员 | **新增** | +| `/admin/users` | 用户管理 | 管理员 | 复用改造 | + +### 7.4 实时监控看板(/dashboard) + +- 最新检测结果卡片(标注图缩略图 + 结论) +- 今日合格率仪表盘 +- 缺陷类型分布饼图 +- 近10条记录时间线 +- 每1秒轮询 `/api/detect/results/?limit=1&ordering=-created_at` + +### 7.5 需删除的现有页面 + +``` +SceneNews 相关页面 +通用YOLO视频/摄像头检测页面 +驾驶员疲劳检测相关组件 +``` + +--- + +## 8. 系统间通信 + +### 8.1 完整通信图 + +``` +前置机(Windows) 推理服务器(Linux) +┌──────────────────────┐ ┌──────────────────────┐ +│ mingxi-capture │ │ mingxi-vision │ +│ │──① POST─────→│ /api/detect │ +│ QThread推理线程 │←─ 结果返回──│ asyncio.Lock串行 │ +│ │ └──────────────────────┘ +│ 主线程展示结果 │ +│ │ ┌──────────────────────┐ +│ upload_queue线程 │──② 异步────→│ mingxi-backend │ +│ (失败则重试) │ │ /api/detect/result │ +└──────────────────────┘ │ │ + │ SQLite存档 │ + └──────────┬───────────┘ + │ REST API + ┌──────────▼───────────┐ + │ mingxi-frontend │ + │ 浏览器短轮询 │ + └──────────────────────┘ + 管理员/组长/厂长 浏览器访问 +``` + +### 8.2 关键通信约定 + +| 通信路径 | 协议 | 格式 | 备注 | +|---------|------|------|------| +| capture → vision | HTTP POST | multipart/form-data(图像二进制) | 同步,等待结果 | +| vision → capture | HTTP Response | JSON(含 base64 标注图) | 一次请求一次响应 | +| capture → backend | HTTP POST | JSON(推理结果) | 异步,本地队列保障 | +| browser → backend | HTTP REST | JSON | 短轮询 + 增删改查 | +| backend → vision(热重载) | HTTP POST | JSON | 仅管理员切换模型时触发 | + +### 8.3 前置机配置两个地址 + +前置机桌面程序配置界面中填写: +- **推理服务地址**:`http://192.168.x.x:8001`(vision) +- **后台服务地址**:`http://192.168.x.x:8000`(backend) + +两个服务通常在同一台服务器上,填写相同IP、不同端口。 + +--- + +## 9. 硬件集成(相机配置) + +### 9.1 推荐型号 + +| 阶段 | 型号 | 分辨率 | 接口 | 用途 | +|------|------|--------|------|------| +| Demo/POC | MV-CS060-10GM | 600万像素 | USB3.0 | 算法验证,接工业PC | +| 产线部署 | MV-CA060-10GM | 600万像素 | GigE | 稳定产线,线长100m | +| 大板检测 | MV-CA120-10GM | 1200万像素 | GigE | 视野≥200mm的PCB | + +### 9.2 分辨率选型计算 + +``` +视野:100mm × 75mm(单次拍摄区域) +最小缺陷:0.1mm(针孔、断路) +像素尺寸 ≤ 0.1mm ÷ 3 = 0.033mm/pixel +所需分辨率:100 ÷ 0.033 ≈ 3030 pixels(水平) +结论:600万像素(3072×2048)满足需求 ✓ +``` + +### 9.3 配套清单(单工位 Demo 版) + +| 器材 | 型号/规格 | 估价 | +|------|----------|------| +| 工业相机 | MV-CS060-10GM | 1800-2500元 | +| 镜头 | 16mm C口定焦(1/1.8"靶面) | 500-800元 | +| LED环形光源 | 同轴/低角度,直径120mm | 400-600元 | +| USB3.0线缆 | ≤3m,锁扣式 | 80-150元 | +| 简易支架光箱 | 铝型材,可调高度 | 200-400元 | +| **合计** | | **约 3000-4450元** | + +--- + +## 10. 开发阶段划分 + +### Phase 1:Demo版(目标:2026年6月中旬决赛前) + +**路演方式:** 预先准备好的PCB图片,模拟模式演示完整流程,约5分钟。 + +**核心展示:** 操作工点击→检测→标注图展示→管理后台历史记录。 + +``` +P0(必须完成,路演核心): + [ ] mingxi-vision:图片推理API + asyncio.Lock + 启动warmup + [ ] mingxi-capture:PyQt5桌面程序,Mock模式,结果展示界面 + [ ] mingxi-backend:接收capture推送,DefectResult落库,基础REST API + [ ] mingxi-frontend:登录 + 检测历史列表 + 详情页 + [ ] mingxi-backend:三级权限(操作工/组长/管理员) + +P1(有时间做,加分项): + [ ] mingxi-frontend:实时监控看板(短轮询) + [ ] mingxi-backend:模型管理(上传/备份/切换) + [ ] mingxi-frontend:统计报表页 + [ ] mingxi-capture:系统托盘图标 +``` + +### Phase 2:POC版(目标:2026年Q3,接入真实相机) + +``` + [ ] mingxi-capture:接入海康MVS SDK,对接 MV-CS060-10GM + [ ] mingxi-capture:PLC触发接口(串口/数字IO) + [ ] mingxi-vision:ONNX Runtime部署(export_onnx.py导出) + [ ] mingxi-vision:模型热重载接口完善 + [ ] mingxi-backend:告警规则引擎(连续不良数、缺陷率阈值) + [ ] 完成1家PCB厂POC试用 +``` + +### Phase 3:产线版(目标:2026年Q4,首单签约) + +``` + [ ] 多相机支持(多条产线并发采集) + [ ] 模型迁移学习(基于客户真实样本微调) + [ ] 告警推送(企业微信/短信) + [ ] MES/ERP对接接口 + [ ] 边缘部署探索(Jetson Orin,脱离大型服务器) + [ ] 软件著作权申请 +``` + +--- + +## 11. 开发环境搭建 + +### 11.1 各项目启动命令 + +```bash +# mingxi-vision(推理服务器,Linux) +cd mingxi-vision +pip install -r requirements.txt +uvicorn main:app --host 0.0.0.0 --port 8001 --workers 1 + +# mingxi-backend(推理服务器,Linux) +cd mingxi-backend +pip install -r requirements.txt +python manage.py migrate +python manage.py runserver 0.0.0.0:8000 + +# mingxi-frontend(推理服务器,Linux) +cd mingxi-frontend +npm install +npm run build # 生产:dist/ 由 nginx 托管 +npm run dev # 开发:localhost:5173 + +# mingxi-capture(前置机,Windows,开发阶段) +cd mingxi-capture +pip install -r requirements.txt +python main.py # 启动桌面程序,自动进入Mock模式(若配置了图片目录) +``` + +### 11.2 环境变量 + +```bash +# mingxi-vision/.env +MODEL_PATH=./models/pcb_defect_v1.pt +RUNTIME=ultralytics # 或 onnx +DEVICE=cuda # 或 cpu +CONF_THRESHOLD=0.45 + +# mingxi-backend/.env +SECRET_KEY=... +DATABASE_PATH=./db.sqlite3 +VISION_SERVICE_URL=http://127.0.0.1:8001 +CORS_ALLOWED_ORIGINS=http://localhost:5173 +MODEL_STORAGE_DIR=/opt/mingxi/models +MODEL_MAX_BACKUPS=10 +``` + +### 11.3 开发联调注意事项 + +- `mingxi-capture` 在 Windows 开发机上运行,配置 vision/backend 为开发机局域网IP +- `mingxi-vision` 和 `mingxi-backend` 建议在同一台机器(或WSL2)上启动 +- SQLite 文件在 `mingxi-backend/` 目录下,无需额外数据库服务 + +--- + +## 12. 参考资料 + +| 资料 | 路径/来源 | +|------|---------| +| 创业技术书 | `梅州创新创业大赛/创业技术书v1.3.docx` | +| 明析vision架构详细设计 | `梅州创新创业大赛/mingxi-vision-架构设计.md` | +| 现有后端代码 | `yolo_classification_system/` | +| PCB缺陷检测调研 | `梅州创新创业大赛/pcb缺陷检测初步方案.md` | +| 海康MVS SDK | 随MVS安装包提供,路径:`C:\Program Files (x86)\MVS\Development\` | +| HRIPCB数据集 | 公开学术数据集,CC BY 4.0,6类缺陷,10,000+样本 | +| PyQt5文档 | https://doc.qt.io/qtforpython-5/ | +| PyInstaller文档 | https://pyinstaller.org/en/stable/ | diff --git a/mingxi-backend/apps/__init__.py b/mingxi-backend/apps/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/auth/__init__.py b/mingxi-backend/apps/auth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/auth/models.py b/mingxi-backend/apps/auth/models.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/auth/views.py b/mingxi-backend/apps/auth/views.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/detection/__init__.py b/mingxi-backend/apps/detection/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/detection/models.py b/mingxi-backend/apps/detection/models.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/detection/views.py b/mingxi-backend/apps/detection/views.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/stats/__init__.py b/mingxi-backend/apps/stats/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/stats/models.py b/mingxi-backend/apps/stats/models.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/stats/views.py b/mingxi-backend/apps/stats/views.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/system/__init__.py b/mingxi-backend/apps/system/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/system/models.py b/mingxi-backend/apps/system/models.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/apps/system/views.py b/mingxi-backend/apps/system/views.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/config/__init__.py b/mingxi-backend/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/config/settings.py b/mingxi-backend/config/settings.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/config/urls.py b/mingxi-backend/config/urls.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/config/wsgi.py b/mingxi-backend/config/wsgi.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/manage.py b/mingxi-backend/manage.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-backend/requirements.txt b/mingxi-backend/requirements.txt new file mode 100644 index 0000000..4efc725 --- /dev/null +++ b/mingxi-backend/requirements.txt @@ -0,0 +1,7 @@ +Django==4.1.13 +djangorestframework==3.14.0 +django-cors-headers==4.3.1 +PyJWT==2.8.0 +python-dotenv==1.0.0 +Pillow==10.2.0 +requests==2.31.0 diff --git a/mingxi-capture/camera/__init__.py b/mingxi-capture/camera/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/camera/hik_camera.py b/mingxi-capture/camera/hik_camera.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/camera/mock_camera.py b/mingxi-capture/camera/mock_camera.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/core/__init__.py b/mingxi-capture/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/core/capture_worker.py b/mingxi-capture/core/capture_worker.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/core/settings.py b/mingxi-capture/core/settings.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/core/upload_queue.py b/mingxi-capture/core/upload_queue.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/main.py b/mingxi-capture/main.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/requirements.txt b/mingxi-capture/requirements.txt new file mode 100644 index 0000000..4fdf990 --- /dev/null +++ b/mingxi-capture/requirements.txt @@ -0,0 +1,5 @@ +PyQt5==5.15.10 +requests==2.31.0 +opencv-python==4.8.1.78 +numpy==1.24.4 +pyinstaller==6.3.0 diff --git a/mingxi-capture/ui/__init__.py b/mingxi-capture/ui/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/ui/config_dialog.py b/mingxi-capture/ui/config_dialog.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/ui/main_window.py b/mingxi-capture/ui/main_window.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-capture/ui/tray_icon.py b/mingxi-capture/ui/tray_icon.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-frontend/public/.gitkeep b/mingxi-frontend/public/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-frontend/src/api/.gitkeep b/mingxi-frontend/src/api/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-frontend/src/components/.gitkeep b/mingxi-frontend/src/components/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-frontend/src/router/.gitkeep b/mingxi-frontend/src/router/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-frontend/src/stores/.gitkeep b/mingxi-frontend/src/stores/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-frontend/src/views/.gitkeep b/mingxi-frontend/src/views/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/api/__init__.py b/mingxi-vision/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/api/detect.py b/mingxi-vision/api/detect.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/api/health.py b/mingxi-vision/api/health.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/api/model.py b/mingxi-vision/api/model.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/config.py b/mingxi-vision/config.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/engine/__init__.py b/mingxi-vision/engine/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/engine/annotator.py b/mingxi-vision/engine/annotator.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/engine/base.py b/mingxi-vision/engine/base.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/engine/defect_classes.py b/mingxi-vision/engine/defect_classes.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/engine/loader.py b/mingxi-vision/engine/loader.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/engine/onnx_adapter.py b/mingxi-vision/engine/onnx_adapter.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/engine/ultralytics_adapter.py b/mingxi-vision/engine/ultralytics_adapter.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/main.py b/mingxi-vision/main.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/requirements.txt b/mingxi-vision/requirements.txt new file mode 100644 index 0000000..6fc356b --- /dev/null +++ b/mingxi-vision/requirements.txt @@ -0,0 +1,9 @@ +fastapi==0.104.1 +uvicorn[standard]==0.24.0 +pydantic==1.10.13 +ultralytics==8.0.235 +onnxruntime-gpu==1.16.3 +opencv-python-headless==4.8.1.78 +numpy==1.24.4 +python-multipart==0.0.6 +python-dotenv==1.0.0 diff --git a/mingxi-vision/schema.py b/mingxi-vision/schema.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/scripts/benchmark.py b/mingxi-vision/scripts/benchmark.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/scripts/export_onnx.py b/mingxi-vision/scripts/export_onnx.py new file mode 100644 index 0000000..e69de29 diff --git a/mingxi-vision/tests/.gitkeep b/mingxi-vision/tests/.gitkeep new file mode 100644 index 0000000..e69de29