4. 视觉基础

各位同学,欢迎来到视觉基础这一章。说实话,这部分内容看起来偏理论,但它是整个项目的基石。你想想看,机械臂要抓东西,首先得“看见”东西在哪儿。而“看见”这件事,背后就是相机模型和标定在起作用。

我刚开始做机器人抓取时,就吃过没搞懂相机模型的亏。当时相机拍出来的位置总偏几毫米,折腾了两天才发现是内参没标准。嗯,从那以后,我再也不敢跳过这一步了。

4.1 相机模型:小孔成像与针孔模型

相机成像,说白了就是小孔成像原理。光线从物体反射,穿过镜头中心(光心),投射到成像平面上。我们用的针孔模型,就是把这个过程数学化。

核心公式很简单:

X_image = f * (X_world / Z_world)
Y_image = f * (Y_world / Z_world)

其中 f 是焦距,单位是像素。这里有个坑:实际相机镜头不是理想针孔,所以我们需要引入内参来修正。

关键点:相机模型把三维世界点映射到二维像素点。这个映射关系,由内参和外参共同决定。

4.2 内参与外参:相机的“身份证”和“定位器”

内参是相机自己的属性,就像人的身份证。外参是相机在世界坐标系中的位姿,就像人的GPS定位。

内参矩阵 K:

K = [[fx,  0, cx],
     [ 0, fy, cy],
     [ 0,  0,  1]]
  • fx, fy:焦距在x、y方向的像素值
  • cx, cy:主点坐标(光心在像素平面的投影)

外参矩阵 [R|t]:

  • R:旋转矩阵(3x3),描述相机朝向
  • t:平移向量(3x1),描述相机位置

我习惯把外参理解为“相机在哪儿、朝哪儿看”。内参则是“相机怎么把光线变成像素”。

参数类型 含义 是否随相机移动变化
内参 焦距、主点、畸变系数 否(固定)
外参 旋转矩阵R、平移向量t 是(随位姿变化)

我的经验:标定内参时,棋盘格要拍20张以上,覆盖不同角度和距离。只拍几张的话,标定结果容易飘。

4.3 畸变校正:让直线变直

实际镜头都有畸变,尤其是广角镜头。径向畸变让直线变弯,切向畸变让图像倾斜。

畸变模型:

x_distorted = x * (1 + k1*r^2 + k2*r^4 + k3*r^6) + [2*p1*x*y + p2*(r^2 + 2*x^2)]
y_distorted = y * (1 + k1*r^2 + k2*r^4 + k3*r^6) + [p1*(r^2 + 2*y^2) + 2*p2*x*y]
  • k1, k2, k3:径向畸变系数
  • p1, p2:切向畸变系数
  • r:像素点到主点的距离

我曾经在一个项目中,因为没做畸变校正,机械臂抓取时边缘物体偏差达到5mm。校正后直接降到0.5mm以内。所以,这一步千万别省。

避坑指南:畸变校正后,图像边缘会被裁剪或拉伸。建议保留校正后的完整图像,不要直接裁剪,否则会丢失边缘信息。

4.4 手眼标定:让相机和机械臂“握手”

手眼标定,就是求相机坐标系和机械臂基坐标系之间的变换关系。说白了,就是让机械臂知道“相机看到的物体,在我自己的坐标系里在哪儿”。

两种主流方式:

  • Eye-in-Hand(眼在手上):相机装在机械臂末端,随臂移动
  • Eye-to-Hand(眼在手外):相机固定安装,不随臂移动
方式 优点 缺点 适用场景
Eye-in-Hand 视野灵活,可近距离观察目标 标定复杂,需考虑末端位姿变化 抓取、装配、检测
Eye-to-Hand 标定简单,视野固定 视野受限,可能被遮挡 分拣、码垛、定位

标定方程:

对于 Eye-in-Hand:

AX = XB

其中 A 是机械臂末端位姿变化,B 是相机看到的标定板位姿变化,X 是待求的手眼矩阵。

对于 Eye-to-Hand:

AX = XB

形式一样,但 A 和 B 的含义不同。A 是机械臂基座到末端的变换,B 是相机到标定板的变换。

核心思路:手眼标定本质是解 AX=XB 方程。常用方法有 Tsai 两步法、Park 法等。我习惯用 OpenCV 的 calibrateHandEye() 函数,直接出结果。

4.5 知识体系总览

下面这张图,把本章的核心逻辑串起来了。你一看就明白:

视觉基础与手眼标定知识体系 视觉基础与手眼标定知识体系 相机模型(针孔模型) 内参(焦距、主点) 外参(R、t) 畸变校正 手眼标定(AX=XB) Eye-in-Hand Eye-to-Hand 视觉定位 + 机械臂控制 💡 核心逻辑 相机模型 → 内参外参 → 畸变校正 → 手眼标定 → 视觉定位 + 机械臂控制

4.6 实战步骤:手眼标定流程

我直接给你一个标准流程,照着做就行:

  1. 准备标定板:棋盘格或圆点阵,打印出来贴平板上
  2. 固定相机:如果是 Eye-in-Hand,把相机装在机械臂末端;如果是 Eye-to-Hand,固定安装
  3. 采集数据:移动机械臂到不同位姿,同时记录:
    • 机械臂末端位姿(从控制器读取)
    • 相机拍摄的标定板图像
  4. 提取角点:用 OpenCV 的 findChessboardCorners() 提取标定板角点
  5. 求解手眼矩阵:调用 calibrateHandEye(),输入机械臂位姿和相机位姿
  6. 验证精度:用标定结果反算,看误差是否在可接受范围内

我的习惯:采集数据时,让机械臂走 15-20 个不同姿态。姿态差异越大,标定结果越稳定。别偷懒只拍 5 个点,那会后悔的。

4.7 常见问题与避坑

  • 标定结果不收敛:检查标定板是否平整,图像是否清晰
  • 误差偏大:增加采集姿态数量,覆盖更大工作空间
  • 手眼矩阵奇异:避免机械臂走直线或纯旋转,要混合运动

我曾经踩过的坑:有一次标定结果一直不对,折腾了两天。最后发现是标定板贴在了亚克力板上,反光导致角点提取不准。换成哑光纸打印,一次就过了。

好了,这一章的内容就这些。记住:相机模型是基础,内参外参是核心,畸变校正不能省,手眼标定是关键。把这些搞明白,后面的视觉定位和机械臂控制就顺了。