
启视QVis V0.2 把机器视觉选型中最常用的三件事放到了同一套工具里镜头计算器负责把光学参数算准离线知识库负责在没有外网时快速查到可用的镜头、相机和光源型号本地方案则保证数据留在本地、产线现场也能稳定运行。对于编写视觉方案、评估设备可行性、跑现场调试的工程师来说这套“视觉选型三件套”真正解决的不是某个高深的算法问题而是选型查找、参数核对和方案整理这类每天都会重复的工作。V0.2 的目标不是让工具功能更多而是让从需求到参数、从参数到型号、从型号到方案的路径更短。1. 视觉选型为什么需要一套本地工具1.1 选型工作真正的耗时点一个视觉项目从需求到设备清单最难的部分常常不是算法而是前期选型。工程师需要同时面对镜头、相机、光源三类物料每一种都涉及型号、品牌、参数、接口、交期和价格信息。传统方式是把产品手册、Excel 表、浏览器搜索结果混在一起使用参数散落在不同 PDF 中单位不统一型号命名规则也不一致。实际项目中选型工作通常集中在几个固定动作根据视场和工作距离估算焦距根据精度反推相机分辨率再拿着参数去筛选可用的镜头和相机。这些动作看起来简单但每次都要重新查找公式、翻手册、核对靶面和卡口容易出错也容易浪费时间。QVis V0.2 正是把这三个动作固化成了工具模块。镜头计算器解决“参数怎么算”离线知识库解决“型号怎么查”本地方案解决“工具在哪里跑”。三者组合之后选型工作才从临时计算变成可复用的工程流程。1.2 QVis V0.2 的三个模块分别解决什么模块主要输入主要输出典型场景镜头计算器工作距离、传感器尺寸、视场宽度、检测精度焦距、分辨率、放大倍率、选型建议新项目初期的粗选和参数论证离线知识库品牌、卡口、靶面、分辨率、接口等筛选条件匹配型号列表、数据手册路径、关键参数对比无外网环境下的方案对比本地方案本地安装包、数据库文件、离线资源包可独立运行的选型环境产线现场、办公内网、客户演示三个模块的分工是清晰的。镜头计算器解决的是“物理约束”告诉工程师光学上需要什么参数离线知识库解决的是“市场约束”告诉工程师当前可获得的型号有哪些本地方案解决的是“环境约束”保证这套流程在产线无网、内网隔离或数据敏感的场景下仍然可用。1.3 V0.2 在版本定位上的变化V0.2 的单点功能并不是全新的概念。镜头计算、参数查询、本地部署每一项单独拿出来都可以找到替代方案。这个版本的价值在于把三者串成一条闭环计算器输出光学参数知识库把光学参数翻译成具体型号本地方案让整个过程不依赖外网和公有云。“三件套”而不是“三个工具”核心区别就在这里。一个只会算焦距的计算器价值有限一个能算焦距、能筛型号、能脱机使用并且把过程记录下来的工具才真正适合作为视觉选型的日常基础设施。2. 镜头计算器的参数模型和实现方式2.1 镜头选型先要算清哪些量镜头选型的起点是明确成像约束。最基本的一组参数包括视场FOV、工作距离WD、传感器靶面尺寸、焦距、放大倍率、系统分辨率、像元尺寸、景深、卡口和畸变要求。其中视场、工作距离、传感器尺寸和检测精度通常是需求方给定的输入焦距和相机分辨率是计算器要输出的结果景深和畸变属于后续校核项会在选型完成后用来验证方案是否成立。在项目初期最常用的计算有两个一是根据工作距离、视场和传感器尺寸求焦距二是根据视场和精度求相机需要多少像素。把这两个计算做准确镜头选型的第一步就完成了大半。2.2 计算公式、单位和基准方向薄透镜近似下焦距、工作距离、传感器尺寸和视场之间存在如下关系焦距 f 工作距离 WD * 传感器尺寸 s / 视场 FOV这里的单位要保持一致。如果 WD 用毫米s 用毫米FOV 也用毫米得到的焦距单位就是毫米。例如传感器宽度 6.4mm工作距离 200mm视场宽度 40mm那么焦距为f 200 * 6.4 / 40 32mm这是一个非常典型的工业镜头选型结果。相机分辨率估算可以按特征点最少像素数来推算。假设检测精度要求为 0.05mm视场宽度为 40mm一条边上的有效特征至少需要 2 到 3 个像素来稳定判定那么该方向的像素数至少为像素数 视场 / 精度 * 每特征像素数 40 / 0.05 * 3 2400如果两个方向要求接近则总像素数约为 2400 * 2400 576 万像素实际选型建议 600 万像素以上工程上常直接按 6MP 或 9MP 选择。放大倍率定义为传感器尺寸与视场的比值放大倍率 β 传感器尺寸 / 视场景深可参考近似公式景深 DOF ≈ 2 * 光圈 F * 允许弥散圆直径 δ * (1 β) / β²这个公式只用于初算因为实际镜头的光学设计、畸变和光圈位置都会影响景深。最终必须通过实际装机和测试确认。2.3 计算模块的最小实现在 QVis V0.2 中镜头计算器可以按以下方式做一个最小实现from dataclasses import dataclass dataclass class LensCalcParam: working_distance_mm: float sensor_width_mm: float fov_width_mm: float dataclass class SystemCalcParam: fov_mm: float accuracy_mm: float pixels_per_feature: int 3 def calc_focal_length(param: LensCalcParam) - float: if param.fov_width_mm 0 or param.sensor_width_mm 0: raise ValueError(视场和传感器尺寸必须大于 0) return round( param.working_distance_mm * param.sensor_width_mm / param.fov_width_mm, 2, ) def calc_magnification(param: LensCalcParam) - float: return round(param.sensor_width_mm / param.fov_width_mm, 4) def calc_min_pixels(param: SystemCalcParam) - int: return int(param.fov_mm / param.accuracy_mm * param.pixels_per_feature)这段代码把三个核心计算拆成独立函数方便单测和回归。需要说明的是这里的实现只覆盖了初选场景实际项目中还需要加入像素尺寸、接口类型、卡口、畸变等约束。2.4 命令行方式运行为了让计算器可以在没有界面的环境下使用可以提供一个命令行入口python -m app.core.calc --wd 200 --sensor 6.4 --fov 40 --accuracy 0.05预期输出焦距建议: 32.0 mm 放大倍率: 0.16 最小像素数(单边): 2400 分辨率建议: 6MP 或更高命令行方式的好处是便于集成进脚本和自动化流程。比如批量评估多个工件的选型参数时可以循环调用这个命令并汇总输出。2.5 参数表中容易算错的地方参数含义常见取值错误影响工作距离 WD镜头前端到被测物的距离50mm 到 1000mmWD 偏差会导致焦距明显偏移传感器宽度相机靶面宽度不是对角线6.4mm 表示 1/1.8 英寸靶面用对角线计算会得到偏大的焦距视场宽度与被测物短边或长边对应的实际尺寸由检测区域决定方向选错会得到错误的焦距精度单像素对应的物理尺寸0.02mm 到 0.1mm精度定义错误会放大像素需求每特征像素数边缘稳定判定需要的像素量2 到 4设为 1 会低估分辨率这里特别容易犯的错误有三个。第一传感器尺寸的方向。传感器有长边和短边计算焦距时必须明确用的是哪条边。16:9 靶面和 4:3 靶面即使对角线相同长边方向的焦距也不一样。第二分辨率估算中的“精度”含义。精度通常指单个像素对应的物理尺寸但实际检测中一个特征至少需要多个像素才能稳定判定。只按“精度等于像素尺寸”计算经常导致相机分辨率不足。第三把近似公式当成精确值。薄透镜公式在近距离、大视场、低畸变镜头下误差较小但在远心镜头、广角镜头和变焦镜头上并不适用。计算器给出的结果只能作为初选最终必须通过实际镜头测试确认。3. 离线知识库的数据建模和检索3.1 为什么离线不是降级而是需求很多选型工具默认联网但在真实场景里视觉工程师经常处在没有外网的环境中产线车间网络隔离客户现场只允许内网访问办公环境对数据传输有安全要求。这时候一个必须联网才能查型号的计算器就是不可用的。离线知识库的价值正在于此。它把镜头、相机、光源等物料数据提前下载到本地查询过程不依赖公网数据也不会离开本机。对工厂来说“数据不出厂”往往比“功能多”更重要。因此离线不是功能的降级而是面向真实产线的默认形态。3.2 数据模型先把选型字段固定下来知识库的核心是数据结构。镜头、相机和光源是三类独立对象需要单独建模。项目中使用 SQLite 作为本地数据库结构简洁适合单机部署。CREATE TABLE lens ( id INTEGER PRIMARY KEY, brand TEXT NOT NULL, model TEXT NOT NULL UNIQUE, focal_length_mm REAL, max_sensor_size_mm REAL, mount TEXT, aperture_min REAL, aperture_max REAL, working_distance_range TEXT, distortion TEXT, price_estimate TEXT, datasheet_path TEXT, source_version TEXT, created_at TEXT ); CREATE TABLE camera ( id INTEGER PRIMARY KEY, brand TEXT NOT NULL, model TEXT NOT NULL UNIQUE, sensor_width_mm REAL, sensor_height_mm REAL, sensor_type TEXT, resolution_mp REAL, pixel_size_um REAL, interface TEXT, frame_rate_fps REAL, datasheet_path TEXT, source_version TEXT, created_at TEXT ); CREATE TABLE light_source ( id INTEGER PRIMARY KEY, brand TEXT NOT NULL, model TEXT NOT NULL UNIQUE, color TEXT, wavelength_nm INTEGER, power_w REAL, type TEXT, datasheet_path TEXT, source_version TEXT, created_at TEXT );这张表结构的要点是型号字段唯一选型关键参数都占用独立列数据来源用 source_version 标记数据手册用 datasheet_path 指向本地文件。这样后续新增供应商数据时不会破坏已有查询逻辑。3.3 检索和筛选逻辑离线知识库的查询主要通过结构化筛选完成。比如要找一个支持 6.4mm 靶面、焦距在 25mm 到 40mm 之间、卡口为 C 口的镜头查询可以这样写SELECT model, focal_length_mm, mount, max_sensor_size_mm FROM lens WHERE mount C AND max_sensor_size_mm 6.4 AND focal_length_mm BETWEEN 25 AND 40 ORDER BY focal_length_mm;相机侧的筛选逻辑类似重点关注接口、靶面尺寸和分辨率SELECT model, resolution_mp, sensor_width_mm, interface FROM camera WHERE interface GigE AND sensor_width_mm 6.4 AND resolution_mp 6 ORDER BY resolution_mp;对于中文检索需要注意 SQLite 的 FTS5 全文检索默认分词对中文并不友好。V0.2 的查询优先采用结构化字段筛选加关键词标签列的方式避免在离线包中引入复杂的中文分词依赖。每个物料可以维护品牌别名、型号别名和应用场景标签用 LIKE 匹配多个字段即可。3.4 数据导入和维护知识库的数据来源通常是供应商提供的数据表或自建的 CSV 文件。批量导入时最容易出现编码和字段错位问题。下面是一个带校验的导入片段import csv import sqlite3 import sys def import_lens_csv(db_path: str, csv_path: str, encoding: str utf-8): required [brand, model, focal_length_mm] conn sqlite3.connect(db_path) cursor conn.cursor() with open(csv_path, r, encodingencoding, newline) as fp: reader csv.DictReader(fp) headers reader.fieldnames or [] for field in required: if field not in headers: raise ValueError(f缺少必需列: {field}) for row in reader: cursor.execute( INSERT OR REPLACE INTO lens (brand, model, focal_length_mm, max_sensor_size_mm, mount, aperture_min, aperture_max, datasheet_path, source_version) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) , ( row.get(brand, ).strip(), row.get(model, ).strip(), float(row.get(focal_length_mm) or 0), float(row.get(max_sensor_size_mm) or 0), row.get(mount, ).strip(), float(row.get(aperture_min) or 0), float(row.get(aperture_max) or 0), row.get(datasheet_path, ).strip(), row.get(source_version, v0.2).strip(), ), ) conn.commit() conn.close()导入前做列名校验导入中使用 INSERT OR REPLACE 保证型号唯一导入后可以输出影响行数用于核对。生产环境建议先备份数据库再执行导入。3.5 数据版本和来源标记离线知识库最大的风险是数据过期。如果没有版本和来源标记工程师很难判断一个型号参数是否已经更新。因此每条记录都要带上 source_version、created_at 等字段同时本地资源包要保留数据手册文件方便随时核对原始资料。升级知识库时推荐做法是保留旧版本数据表用版本号区分。上线新数据包前先做一次完整导入演练对比新旧版本中关键型号的数量和参数差异。4. 本地方案的架构、部署和数据安全4.1 本地方案的两种落地形态本地方案有两种常见形态。一种是桌面 GUI 应用打包成单个 exe 或 AppImage双击即可运行另一种是本地 Web 服务程序监听本机端口浏览器访问页面完成操作。QVis V0.2 采用本地 Web 服务加浏览器访问的方式。原因是界面迭代快不依赖特定桌面框架跨平台表现一致数据层统一走本地 SQLite不引入独立数据库服务未来如果要加多人协作只需要把端口开放给局域网并增加权限控制。这种形态的取舍是启动时需要运行一个本地进程依赖 Python 环境。生产环境可以用 PyInstaller 打包成可执行文件降低现场部署难度。4.2 目录结构和配置推荐目录结构如下qvis/ ├─ app/ │ ├─ main.py │ ├─ server.py │ ├─ core/ │ │ ├─ calc.py │ │ └─ searcher.py │ └─ web/ │ ├─ index.html │ └─ static/ │ ├─ app.js │ └─ style.css ├─ data/ │ ├─ optics.db │ ├─ resources/ │ │ ├─ lens_datasheet/ │ │ ├─ camera_datasheet/ │ │ └─ light_datasheet/ │ └─ backup/ ├─ config/ │ └─ app.yaml ├─ scripts/ │ ├─ import_csv.py │ └─ backup.py ├─ tests/ │ └─ test_calc.py └─ requirements.txt配置文件示例app: name: QVis version: 0.2.0 database: path: ./data/optics.db backup_dir: ./data/backup local_server: host: 127.0.0.1 port: 9080 knowledge: resource_root: ./data/resources enable_auto_index: true配置文件把数据库路径、端口和资源根目录外置方便不同环境切换。生产环境不要把所有参数都写死在代码里。4.3 部署步骤以源码方式部署时按以下步骤执行python -m venv venv source venv/bin/activate # Windows 下使用: venv\Scripts\activate pip install -r requirements.txt python app/main.py --config config/app.yaml启动成功后浏览器访问http://127.0.0.1:9080判断部署成功的标准不只是页面能打开还要验证三件事计算器能正常计算知识库能查到本地数据断网环境下功能仍然完整。如果某一步依赖公网资源说明本地方案还没有完全闭环。4.4 本地方案与在线方案的取舍维度本地方案在线方案网络依赖不依赖公网适合产线内网必须保持网络连接数据安全数据不出本机容易控制数据经过第三方服务需要信任模型多人协作默认单机扩展靠局域网共享天然支持多端同步更新维护需要手动升级数据包和程序服务端统一发布初始部署成本需要安装运行环境或打包只需要注册访问适用场景工厂、现场、保密环境办公室、跨团队协作如果团队有集中维护物料数据的需求可以在本地方案基础上增加“局域网共享数据库”能力把 SQLite 文件放到共享目录并用文件锁控制并发写入。4.5 备份、迁移和升级本地方案的数据全部集中在 data 目录因此备份策略可以非常直接定期复制整个 data 目录。python scripts/backup.py --source ./data --dest ./data/backup/2025-01-15恢复时把备份目录中的 optics.db 和 resources 复制回 data 目录即可。升级程序前必须做一次备份同时记录当前数据库版本。如果数据库结构发生变更需要提供迁移脚本而不是直接替换数据库文件。5. 一个完整的选型流程示例5.1 需求描述假设一个视觉检测项目需要测量工件宽度是否超差检测区域宽度为 40mm精度要求 0.05mm工作距离大约 200mm相机和镜头需要搭配使用现场运行在无外网环境。这个需求实际上包含三层约束光学上需要合适的焦距和分辨率市场上需要能买到的型号部署上需要离线可用。QVis V0.2 的三件套正好覆盖这三层。5.2 计算器输出使用前面的公式输入 WD200mm、传感器宽度 6.4mm、FOV 宽度 40mm、精度 0.05mm得到参数计算结果焦距32.0mm放大倍率0.16最小像素数单边2400分辨率建议6MP 或更高卡口建议C 口或 CS 口焦距 32mm 在实际镜头产品中不算标准值通常需要向 25mm 或 35mm 靠拢。选择 35mm 时视场会缩小需要确认仍能覆盖 40mm 检测区域选择 25mm 时视场变大会损失一点分辨率。这种取舍要在知识库中对比多个型号后决定。5.3 在知识库中筛选匹配型号根据计算结果筛选镜头条件为C 口、支持 6.4mm 靶面、焦距 25mm 到 35mm。筛选相机条件为GigE 接口、靶面不小于 6.4mm、分辨率不低于 6MP。SELECT model, focal_length_mm, max_sensor_size_mm FROM lens WHERE mount C AND max_sensor_size_mm 6.4 AND focal_length_mm BETWEEN 25 AND 35 ORDER BY focal_length_mm;SELECT model, resolution_mp, sensor_width_mm FROM camera WHERE interface GigE AND sensor_width_mm 6.4 AND resolution_mp 6 ORDER BY resolution_mp;查询结果通常会有多个候选型号。此时需要结合数据手册中的畸变、工作距离范围、价格和交期做二次筛选。5.4 生成选型建议单筛选完成后工具可以把结果导出成选型建议单方便后续与他人确认。JSON 是一个合适的中立格式{ requirement: { fov_width_mm: 40, working_distance_mm: 200, accuracy_mm: 0.05 }, optical_result: { focal_length_mm: 32.0, magnification: 0.16, min_pixels_along_axis: 2400 }, candidate_lens: [ { model: LM35HC, focal_length_mm: 35, mount: C, max_sensor_size_mm: 6.4 } ], candidate_camera: [ { model: MV-CA060-10GM, resolution_mp: 6.2, sensor_width_mm: 6.4, interface: GigE } ] }建议单的价值在于可追溯。任何参数都可以回推到计算过程和数据手册而不是只给出一个“推荐型号”。5.5 结果验证公式过只是第一关计算器输出和知识库筛选都通过后还需要做实物验证。把镜头和相机装到支架上测量实际视场是否接近 40mm使用分辨率测试卡检查画面清晰度确认畸变是否符合要求再调整光圈检查景深是否覆盖工件波动范围。验证完成后把实测数据记录回知识库作为该型号在类似项目中的应用案例。这也是离线知识库后续最有价值的内容来源。6. 常见问题与排查链路6.1 计算值与镜头标称焦距对不上现象计算器输出焦距 32mm但镜头标称值为 35mm实际安装后视场比预期小。可能原因传感器尺寸用错方向工作距离测量不准确镜头存在畸变薄透镜近似公式本身有误差。检查方式确认传感器宽度和视场宽度使用的是同一条边用卷尺重新测量镜头前端到被测物的距离查看镜头数据手册中的畸变参数。处理建议把目标焦距放宽为一个范围在知识库中筛选临近档位再用实际安装结果校正。6.2 知识库搜不到已录入的型号现象数据库里明明有某型号但界面搜索时查不到。可能原因筛选条件过严比如同时限制了焦距、卡口和靶面型号输入带空格或大小写不一致导入时字段错位导致参数为空。检查方式先去掉所有筛选条件只搜索型号关键字检查数据库中的模型是否包含多余空格用 SQL 单独查询该型号的所有字段。处理建议在搜索界面提供“重置筛选”按钮导入时对字符串统一 strip 和大小写归一增加型号别名字段。6.3 CSV 导入乱码或字段错位现象导入 CSV 后镜头型号和焦距列错位中文乱码。可能原因文件编码不是 UTF-8可能是 GBKCSV 表头与代码要求的字段名不一致某行缺少列值导致解析错位。检查方式用文本编辑器查看文件编码输出表头列表并与 required 字段对比在导入脚本中增加 row 字段数量校验。处理建议优先统一为 UTF-8 编码导入前输出表头预览导入后统计成功行数和失败原因。6.4 本地方案启动失败和数据丢失现象程序启动时报端口占用、数据库路径错误或数据目录权限不足。可能原因9080 端口被其他程序占用配置文件中的数据库路径不对data 目录没有写入权限数据库文件被其他进程锁定。检查方式查看启动日志中的异常栈检查端口和进程确认工作目录与配置文件中的相对路径一致。处理建议端口冲突时修改配置文件中的 port路径使用绝对路径便于排查数据库锁定时关闭其他访问进程升级前先备份 data 目录。6.5 排查顺序总表问题现象优先检查常用操作处理建议计算值偏离标称输入参数方向和单位重新确认 WD、传感器边、FOV 方向把焦距放宽为选型范围搜索无结果筛选条件和字段值清空筛选条件再搜索增加重置筛选和别名匹配导入乱码错位编码和表头输出表头预览统一 UTF-8校验必填列启动失败日志、端口、路径查看启动日志和端口占用修改端口或路径确认权限数据丢失备份文件和时间点检查 backup 目录定期执行备份脚本排查时按“输入是否正确、数据是否完整、配置是否生效、环境是否满足”的顺序推进不要一上来就怀疑工具本身。7. 最佳实践和下一步扩展7.1 参数维护规范离线知识库要持续可用必须配套参数维护规范。每条记录都要能追溯到数据手册单位统一使用毫米和微米型号字段全局唯一版本号和时间戳必须填写来源注明供应商和更新时间数据手册本地化存储避免链接失效。对于价格和交期这类易变信息不要混入选型参数表单独维护并在界面上标注“参考值”字样。7.2 用回归用例守住计算器镜头计算器是选型流程的入口参数一旦算错后续所有结果都会偏离。建议为计算模块维护一组回归用例覆盖常见靶面、不同工作距离和精度边界。def test_focal_length_32mm(): param LensCalcParam( working_distance_mm200, sensor_width_mm6.4, fov_width_mm40, ) assert calc_focal_length(param) 32.0 def test_focal_length_invalid_fov(): param LensCalcParam( working_distance_mm200, sensor_width_mm6.4, fov_width_mm0, ) try: calc_focal_length(param) except ValueError: pass else: raise AssertionError(视场为 0 时应抛出异常)每次修改计算逻辑后运行测试能避免旧功能被新特性破坏。7.3 发布前检查清单V0.2 以及后续版本发布前可以按下面的清单逐项检查计算器回归用例全部通过。知识库能正确导入和导出导入后有行数和字段校验。断网环境下运行完整流程确认不依赖公网资源。数据库备份和恢复流程演练通过。数据目录权限和路径在不同机器上验证通过。版本号、数据库版本和配置文件版本三者一致。新增型号都带有数据来源和版本标记。异常场景有明确提示而不是静默失败。这份清单严格来说不复杂但对工具类项目非常重要。很多本地方案失效都是因为缺少这类发布检查。7.4 下一步扩展方向QVis V0.2 之后可以沿着几个方向扩展。第一增加打光方案库把光源颜色、类型、照射角度与检测特征关联起来。第二增加选型评分和对比功能从分辨率余量、价格、交期、畸变等维度量化对比候选方案。第三把选型建议单导出成标准方案文档或 BOM直接衔接采购流程。第四在局域网范围内增加多人共享数据库让团队统一维护物料数据。第五逐步覆盖 3D 视觉选型把点云精度、工作距离和测量范围纳入计算模型。对这些扩展要有一个基本判断工具的核心价值始终是计算有依据、数据可追溯、环境能落地。功能可以增加但这三条不能丢。对视觉工程师来说最有价值的练习不是把界面做得更漂亮而是把自己的选型流程沉淀成一套可复用的参数模型和数据结构。先用好计算器再维护好知识库最后让工具在真实产线环境里跑通这才是“视觉选型三件套”真正发挥作用的方式。