CommonLibraries/README.md

11 KiB
Raw Blame History

目标测光曝光控制模块

独立 C++17 静态库,依赖 OpenCV core、imgproc。可独立计算原始图像的全局/ROI 亮度;也可通过控制实例接收采集时间及实际曝光,返回下一帧曝光建议。支持源码子目录引用和安装后的 CMake 包引用。

模块负责测光、时间窗口历史、3/5 点预测、比例/PI/死区控制及 CAPTURE/TRACK/LOST 状态管理。识别、采图、相机 SDK、机器人、三维处理、自动增益和业务节拍均由调用方负责。

接入方式

源码引用:

add_subdirectory(path/to/TargetExposureControl)
target_link_libraries(your_app PRIVATE TargetExposureControl::Control)

安装包引用:

find_package(TargetExposureControl 1 CONFIG REQUIRED)
target_link_libraries(your_app PRIVATE TargetExposureControl::Control)

配置 CMake 时设置 OpenCV_DIR,安装方式还需将安装前缀加入 CMAKE_PREFIX_PATH。安装包要求使用构建时相同版本的 OpenCV;使用其他版本时重新构建本库。编译器、架构、运行库和 Debug/Release 也应与调用工程一致。OpenCV 的运行时 DLL 由使用方部署。本库没有相机 SDK 或 Qt 依赖。

每路相机/图像流使用一个 target_exposure::ExposureControl 实例。不同实例状态隔离,同一实例由调用方串行调用。所有曝光单位为 微秒 us,所有时间戳也使用同一时钟域下的非负微秒;两者语义不同,不可相互替代。

独立离线测光(1.1.0)

只计算保存图像时,直接调用 measureImage,不创建控制实例、不设置曝光或时间,也不调用 preCapture。以下变量由调用方提供:

target_exposure::Roi roi;
roi.rectangles = final_metering_rects; // 可换成旋转框或实际分割掩膜
const auto measurement = target_exposure::measureImage(original_image, roi, roi_is_usable);
// measurement.global.arithmetic_gray:全局普通平均灰度。
// measurement.target.arithmetic_gray:ROI 普通平均灰度。
// measurement.target.gray:ROI 截尾均值,保留既有控制算法的统计口径。

第四个参数为可选的 MeteringConfig,默认整图测光、目标区域两端各截尾 5%、至少 16 个原始像素和 8 个保留像素。只计算全局时传空 Roi 和 false。roi_is_usable 只表示存在可测光的区域;手绘 ROI 有效不代表工件已到位或已识别。

每个区域使用一次像素直方图,同时输出普通均值、截尾均值、原始/保留像素数和截尾前的近黑/饱和比例。目标样本不足时两个均值均为空,不能用零替代;全局不受目标区域无效影响。配置非法时两个区域均返回 MeterStatus::InvalidConfiguration;图像、ROI 错误由对应状态报告。无有效区域时不检查闲置 ROI 内容,全局照常计算。

这是无状态函数,同一输入可重复计算,结果不受曝光控制实例的历史影响;调用期间原图和 mask 均不被修改或保留。允许在输入数据不被并发修改的前提下并发测光。采集时间、处理耗时、模型来源及 CSV/JSON 存档由应用程序关联,不由测光函数生成。

processFrame() 使用同一测光实现,控制仍使用原 gray 字段。新增字段追加在原有数据字段之后,保留原源码的聚合初始化顺序;新增数据字段不保证旧二进制 ABI,应用和静态库应一起重新编译。

曝光控制调用顺序

  1. 准备本工况的 Config。必须提供最小、最大和经验曝光;静止采图上限由业务节拍确定。
  2. 拍照前调用 preCapture(now_us, config)。检查 accepted;若 initialization_required,由调用方先成功设置 suggested_exposure_us,再采集。
  3. 调用方采集原始图像并识别,读取这一帧真正使用的曝光值,构造 FrameInput。
  4. 调用 processFrame(input),检查输入接收状态、测光有效性及原因。仅当 adjustment_suggested=true 时,由调用方将建议应用于下一帧。
  5. 每一帧都重新执行拍照前检查。建议未成功应用时,不把建议值当实际曝光。初始化设置失败时由业务重试设置或显式复位,不继续假装初始化成功。

可编译运行的完整示例见 examples/minimal.cpp,配置见 examples/static_station_config.hpp。示例由外部循环模拟图像和曝光应用,模块本身不采图、不等待、不循环试曝光。

target_exposure::ExposureControl exposure;
target_exposure::Config config;
config.min_exposure_us = 100;
config.max_exposure_us = 20000;       // 仅作示例,替换为本工况上限
config.empirical_exposure_us = 1000;  // 替换为本工况经验值

// 拍照前:
auto prepare = exposure.preCapture(now_us, config);
// accepted=false 时处理错误;initialization_required=true 时先由业务设置曝光。
// 业务完成采图、识别后:
target_exposure::FrameInput input;
input.image = original_image;                 // CV_8UC1 或 CV_8UC3(BGR)
input.roi.rectangles = final_metering_rects;   // 也可叠加旋转矩形或 masks
input.has_usable_target = detector_has_target;
input.timestamp_us = captured_at_us;
input.actual_exposure_us = actual_frame_exposure_us;
auto result = exposure.processFrame(input);
// result.adjustment_suggested 为 true 时,由业务设置 result.suggested_exposure_us。

上面的变量来自调用工程,片段用于说明接口顺序;独立运行使用完整示例。

输入和测光契约

  • 支持 Gray8 和 BGR8。BGR 使用 OpenCV 固定 COLOR_BGR2GRAY 转换;不做归一化、gamma 调整或自动增强。不接受画框图、增强图和未经解释的 Bayer/12/16 bit 数据。
  • Roi 中矩形、旋转矩形及 mask 可以混用,按像素取并集,重叠只统计一次。mask 必须为与图像同尺寸的 CV_8UC1,非零即选中。
  • 普通矩形使用 OpenCV 的左闭右开范围,先裁剪到图像;旋转矩形按像素中心是否位于旋转后的半开矩形内判断,不使用其包围框直接测光。
  • 输入 ROI 被视为最终结果,不隐式内缩。inset(rect, fraction_per_side) 是独立、显式辅助函数;比例指每一侧内缩量,整数矩形向内取整。
  • arithmetic_gray 为截尾前的普通平均;全局 gray 与其相同,global_center_fraction<1 时统计固定比例的居中矩形。目标 gray 在并集内上下各删除 floor(N × trim_fraction_each_side) 个样本后求平均。
  • 无目标、ROI 空/格式错误、像素不足均有明确状态,gray、arithmetic_gray 为 std::nullopt。真实黑图的灰度 0 可以是有效测量。
  • 非有限、非正或超出当前配置范围的实际曝光属于输入契约错误,返回 InvalidActualExposure,保留错误实参用于诊断,不伪造实际曝光或产生调整建议。调用方应修正配置/曝光状态后重走拍照前流程。
  • 同一实例内帧时间必须严格递增。重复、乱序及缺少拍照前检查的帧不更新控制状态。相机时间重置时显式 reset(ResetReason::ClockChanged)。
  • 图像只在调用期间读取,不改原图、不保存图像副本;调用期间调用方须保证数据有效且不被其他线程修改。

关键配置

所有控制参数都在公共头文件的强类型结构体中配置,无额外配置文件解析依赖。

配置 默认/示例 含义
min/max/empirical_exposure_us 默认未设置,必须由调用方填写 曝光范围及初始化曝光
profile_id、revision default、0 工况身份;任何参数或版本变化也会在拍照前初始化
history_window_us、idle_timeout_us 各 300000000 us 历史窗口与停机阈值分别判断
history_capacity 512 帧诊断和有效目标各自保留最多此数量;不得小于预测点数
detect_confirm_frames/lost_confirm_frames/freeze_frames 3/3/2 三态连续计数和冻结拍数
metering.trim_fraction_each_side 0.05 每侧截尾比例
metering.min_target_pixels/min_retained_pixels 16/8 截尾前、后最少像素
metering.global_center_fraction 1.0 全图;可配置为 0~1 之间的中央区域比例
controller.target_gray 118 8 bit 标度下的目标灰度示例
controller.deadband_ratio/hysteresis_ratio/large_error_ratio 0.10/0.02/0.40 相对误差阈值,0.10 表示 10%
controller.proportional_gain/kp/ki 0.70/0.40/0.10 附件比例分支及离散 PI 系数示例
controller.integral_abs_limit/max_step_ratio 1.0/0.25 积分幅度上限、大小误差统一步长上限
controller.same_direction_frames 2 小误差连续同方向确认;大误差按已确认规则立即动作
prediction.points 3,可选 5 只使用最近指定数量的有效目标记录
prediction.enabled/photometric_model_confirmed true/false 必须确认光度模型前提后才采用预测;未确认仍正常反馈控制
prediction.black_level 0.0 已知黑电平偏置,不从场景中猜测
prediction.nominal_interval_us/max_horizon_us 0/60000000 us 未传下一拍时刻时的备用间隔;0 表示缺失,无时距则降级
prediction.max_relative_fit_rmse 0.10 归一化响应拟合的相对残差上限
prediction.max_near_black_fraction/max_saturated_fraction 0.10/0.05 排除失去线性响应的记录;截尾前统计
prediction.min_predicted_gray/max_predicted_gray 1/254 预测适用范围
recovery.global_reference_gray 未设置 独立全局参考,不自动等于目标灰度
recovery.deadband_ratio/gain/max_step_ratio 0.30/0.30/0.10 单次恢复判据与保守比例修正

所有示例值只用于演示配置和逻辑,不能代表所有工件。调用方选择黑件/白件或不同工况配置。参数错误由 validate(config) 或 preCapture().errors 报告。

详细预测公式、三态和恢复预算语义见 控制与状态说明。

构建与验证

Windows x64、VS 2022/MSVC 下,原控制版本使用 OpenCV 4.7 验证;当前独立测光版本使用与 MatchVerify 相同的 OpenCV 4.10 重新构建验证。源码构建不硬编码本机路径;以下命令使用本机实际依赖位置。

pwsh -NoProfile -File tools/verify.ps1 `
  -BuildRoot E:/05_Temp/TargetExposureControl/capture-metering `
  -OpenCVDir E:/06_EnvConfig/opencv/build/x64/vc16/lib `
  -OpenCVRuntimeDir E:/06_EnvConfig/opencv/build/x64/vc16/bin

脚本依次配置、构建 Release、运行全部分组 CTest 和最小示例、安装库,再构建并运行只引用安装包的独立消费工程。完整日志位于构建根目录的 verification.log。所有测试使用模拟时间和内存图像,不连接相机。

OpenCV 4.7 Windows 包的顶层配置不识别某些新 MSVC 版本。脚本发现已存在的 x64/vc16/lib/OpenCVConfig.cmake 时直接使用该包配置;没有修改 OpenCV。手动配置时可将 OpenCV_DIR 设到该目录。其他 OpenCV 布局可传具体包目录和 -OpenCVRuntimeDir。

源码作为子目录接入时默认不构建示例与测试;可通过 TEC_BUILD_TESTS、TEC_BUILD_EXAMPLES 控制。安装包内还包含中文说明与完整示例。

实际命令、结果及剩余验证边界见 实施记录。构建、模拟控制测试和安装接入验证不能证明真实相机参数生效、实际成像改善或现场验收。