自瞄教程
02 识别

练习:运行第一个传统视觉识别器

使用 Daedalus 模拟器和 C++ SDK 取图,实时观察灯条候选与配对角点。

这一节提供一个可以直接运行的传统视觉参考程序。它从 Daedalus 模拟器读取图像,完成颜色差与亮度阈值、形态学处理、轮廓筛选、灯条拟合和灯条配对,并将每一步画到窗口中。程序只识别灯条及其几何关系,不识别数字。

运行它的目的不是直接得到比赛代码,而是让你能立刻看见:一个阈值改变后,二值图、候选灯条和最终四个角点分别发生了什么。

1. 实验使用的 Release 与接口

从 Daedalus Simulator Releases 仓库获取最新稳定的完整 Release,并使用同一个包随附的 C++ SDK、标定和文档。也可以从全部 Releases选择需要复现的历史版本:

  • Windows:windows-x86_64.zip;
  • Ubuntu 24.04:优先使用 linux-x86_64.tar.gz,也可以使用 ZIP。

本练习只依赖 Daedalus SDK v1 的稳定接口;实际模拟器和 SDK 版本以下载包的 release.json 为准,不要跨版本混用。

程序只通过公开 SDK 使用模拟器:

接口地址本实验中的作用
SceneControlClient127.0.0.1:5603/UDP创建实验会话、切换 Shooting Range、控制靶车运动
TcpImageClient127.0.0.1:5602/TCP读取带帧号和曝光时间戳的最新完整图像
camera-calibration.jsonRelease 根目录提供固定只读的相机内参、畸变与相机外参

图像流采用 latest-only 语义:识别处理较慢时,中间帧会被跳过,程序得到的是最新完整帧。source_sequence 是帧身份,capture_timestamp_ns 是曝光时间;两者都应跟随识别结果继续向下游传递。

2. 启动模拟器

完整解压 Release,不要只拿出 bin/。第一次练习使用可视模式,便于同时观察场景和算法窗口。

Windows

cd <Daedalus发布目录>
Set-ExecutionPolicy -Scope Process Bypass
./start-simulator.ps1 -Visible

Linux

cd <Daedalus发布目录>
chmod +x ./start-simulator.sh ./bin/daedalus
./start-simulator.sh --visible

模拟器启动后保持运行。练习程序会通过 SDK 自动切换到 ShootingRange。

3. 固定相机参数

本实验使用 Release 根目录的 camera-calibration.json,标定 ID 为 daedalus-camera-1440x1080-v2,修订号为 2。图像尺寸和像素格式:

width  = 1440
height = 1080
TCP 默认格式 = RGBA32

相机内参矩阵:

K = [1303.67532368147, 0,                720.0;
     0,                1303.67532368147, 540.0;
     0,                0,                1.0]

畸变系数采用 plumb_bob 顺序:

D = [k1, k2, p1, p2, k3] = [0, 0, 0, 0, 0]

这个练习输出灯条端点构成的二维角点,暂时不调用 PnP;后续模块直接沿用同一份标定进入位姿解算。

4. 获取参考程序

源码可从教程站直接打开:examples/first-traditional-detector。该页静态发布完整的 README.md、CMakeLists.txt 与 src/main.cpp,不依赖 GitHub 仓库权限。它已经完成:

  • 建立场景控制会话并切换 ShootingRange;
  • 使用 TcpImageClient::waitForLatest() 读取图像;
  • 根据帧头把 RGB24 / RGBA32 转换为 OpenCV BGR;
  • 构造颜色差与亮度二值图,查找和筛选灯条轮廓;
  • 将候选灯条两两配对,输出固定顺序的四个灯条端点;
  • 显示原图、二值图和参数滑条;
  • 按 1 使用静止目标,按 2 使用直线运动,按 3 使用直线并自转。

核心入口是:

// 颜色掩码 → 轮廓 → 灯条 → 配对角点。
DetectionResult runTraditionalDetector(const cv::Mat& bgr,
                                       const DetectorParameters& parameters);

5. 构建练习程序

需要 C++17、CMake 3.16、OpenCV 4,以及 Release 自带的预编译 SDK。

Linux

sudo apt update
sudo apt install -y build-essential cmake ninja-build libopencv-dev

cmake -S examples/first-traditional-detector \
  -B build/first-traditional-detector \
  -G Ninja \
  -DCMAKE_BUILD_TYPE=Release \
  -DCMAKE_PREFIX_PATH=<Daedalus发布目录>/sdk

cmake --build build/first-traditional-detector --parallel
./build/first-traditional-detector/first_traditional_detector

Windows

先通过 vcpkg 安装 OpenCV:

C:/dev/vcpkg/vcpkg install opencv4:x64-windows

在 Visual Studio Developer PowerShell 中配置和构建:

cmake -S examples/first-traditional-detector `
  -B build/first-traditional-detector `
  -DCMAKE_BUILD_TYPE=Release `
  -DCMAKE_PREFIX_PATH=<Daedalus发布目录>/sdk `
  -DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake

cmake --build build/first-traditional-detector --config Release --parallel
./build/first-traditional-detector/Release/first_traditional_detector.exe

6. 先观察可视化结果

程序启动后检查:

  1. 模拟器自动进入 Shooting Range;
  2. detector 窗口持续显示 1440×1080 图像;
  3. mask 窗口显示由颜色和亮度规则产生的二值图;
  4. 橙色矩形是灯条候选,黄色线是灯条长轴;
  5. 绿色四边形和圆点是两灯条配对得到的四个角点;
  6. 左上角的 seq 与 timestamp_ns 随新帧更新;
  7. 按 1、2、3 时目标运动状态发生变化。

这一步已经跑通“场景控制 → 图像接口 → OpenCV → 可视化”的最小链路。

7. 修改像素与灯条规则

程序默认通过下列规则提取红色灯条;enemy: red / blue 滑条可切换颜色差的方向:

color_score = R - B
bright_score = gray

mask = (color_score > color_difference_threshold)
       AND
       (bright_score > brightness_threshold)

拖动 brightness、color difference、morphology radius 和 minimum area 滑条。每次只改一个参数,观察:

  • 灯条是否保持完整,是否因为阈值或形态学操作断裂、粘连;
  • 背景是否产生新的白色区域和候选灯条;
  • 哪些候选灯条没有通过几何配对;
  • 绿色四点是否连续,还是发生跳变与错误配对。

接着阅读 runTraditionalDetector():它使用 cv::findContours() 和 cv::minAreaRect() 得到候选灯条,并比较两灯条的长度比、长轴角度差、中心高度差和间距。改变其中任意一个阈值后,重新运行相同场景,记录输出变化。

8. 主动制造失败

按以下顺序完成三组实验,每次保留滑条参数和一张截图:

实验操作观察重点
静止基线按 1,调整参数直到稳定识别哪些规则真正必要,哪些规则只是当前画面的巧合
直线运动按 2,保持参数不变轮廓、灯条角度和角点是否开始抖动
直线并自转按 3,保持参数不变哪个几何阈值最先导致漏检,放宽后又增加了什么误检

然后故意提高亮度阈值、降低颜色差阈值、扩大形态学核,分别观察漏检、误检和轮廓粘连。这个过程展示了传统视觉规则之间的取舍。

9. 验收标准

  • 程序能够通过 SDK 自动切换 Shooting Range 并持续读取图像;
  • 能解释 source_sequence、capture_timestamp_ns 和 latest-only 的含义;
  • 能说明橙色候选灯条、黄色长轴、绿色角点和二值图分别代表什么;
  • 能修改颜色、亮度、轮廓与灯条配对至少四类规则;
  • 输出固定顺序的四个二维灯条端点;
  • 完成静止、直线、直线并自转三组实验;
  • 保存至少两个失败案例,并指出是哪条规则造成漏检或误检。

完成后再进入神经网络章节。此时“为什么要从手写规则转向数据驱动模型”不再只是一个结论,而是你已经亲自遇到的问题。

On this page