3、相机成像模型:针孔相机模型、透镜畸变
做视觉检测这些年,我越来越觉得一个道理:不懂相机模型,标定就是瞎蒙。你想想看,相机是怎么把三维世界变成二维图像的?这里面藏着什么数学关系?畸变又是怎么来的?今天咱们就把这事彻底聊透。
3.1 针孔相机模型——最朴素的成像原理
说白了,针孔相机模型就是最原始的「小孔成像」。光线通过一个小孔,在后面的感光面上形成倒立的像。这个模型虽然简单,但它是所有相机模型的基石。
我个人习惯把针孔模型拆成三步来理解:
- 世界坐标系:物体在真实世界中的位置,单位是米或毫米
- 相机坐标系:以相机光心为原点,Z轴指向镜头前方
- 图像坐标系:最终落在传感器上的像素位置
这三步之间的转换,说白了就是几个矩阵乘法的事。我给大家画个图,一看就明白:
这个图里最关键的是啥?是相似三角形。物体高度 H,成像高度 h,物距 Z,焦距 f,它们的关系就是:
h / H = f / Z
嗯,就这么简单。但实际相机不是小孔,是透镜。这就引出了下一个问题。
3.2 透镜畸变——理想很丰满,现实很骨感
实际镜头不是完美的小孔,光线穿过透镜会发生折射。这就导致了一个问题:图像变形了。我在项目中遇到过好几次,标定板拍出来直线是弯的,一开始还以为是标定板没放平,后来才发现是镜头畸变在作怪。
畸变主要分两类:径向畸变和切向畸变。
3.2.1 径向畸变
径向畸变,说白了就是图像从中心到边缘被「拉伸」或「压缩」了。它沿着镜头半径方向发生,离中心越远,畸变越明显。
径向畸变有两种:
- 桶形畸变:图像向外凸出,像桶一样。广角镜头常见。
- 枕形畸变:图像向内凹陷,像枕头一样。长焦镜头常见。
数学上怎么描述?用泰勒级数展开:
x_corrected = x * (1 + k1*r² + k2*r⁴ + k3*r⁶)
y_corrected = y * (1 + k1*r² + k2*r⁴ + k3*r⁶)
其中 r 是像素到图像中心的距离,k1、k2、k3 是径向畸变系数。一般 k1 就够用了,k2 用于高精度场景,k3 通常用在鱼眼镜头里。
3.2.2 切向畸变
切向畸变是啥?它是因为镜头和成像平面不平行造成的。说白了,就是镜头装歪了,或者传感器贴歪了。
数学表达式:
x_corrected = x + [2*p1*x*y + p2*(r² + 2*x²)]
y_corrected = y + [p1*(r² + 2*y²) + 2*p2*x*y]
p1、p2 是切向畸变系数。这个畸变在工业相机里一般很小,但如果你用的是手机摄像头模组,那切向畸变可能就比较明显了。
3.3 畸变对视觉检测的影响
畸变不校正,后果很严重。我给大家列几个真实场景:
| 检测任务 | 畸变影响 | 后果 |
|---|---|---|
| 尺寸测量 | 边缘位置偏移 | 测量误差可达几个像素 |
| 定位抓取 | 中心点偏移 | 机器人抓偏,撞坏工件 |
| 二维码识别 | 图案扭曲 | 解码失败率飙升 |
| 缺陷检测 | 特征变形 | 误检、漏检 |
你想想看,如果畸变不校正,你测出来的尺寸能准吗?我见过一个案例,某工厂用未标定的相机测零件长度,结果每天测出来的数据都不一样,最后发现是镜头畸变加上温度变化导致的。
3.4 畸变校正的工程实践
畸变校正说白了就两步:
- 标定:用标定板算出畸变系数 k1、k2、p1、p2 等
- 校正:用这些系数把畸变图像映射回无畸变图像
OpenCV 里实现起来很简单:
import cv2
import numpy as np
# 假设你已经标定得到了相机矩阵和畸变系数
camera_matrix = np.array([[fx, 0, cx],
[0, fy, cy],
[0, 0, 1]], dtype=np.float32)
dist_coeffs = np.array([k1, k2, p1, p2, k3], dtype=np.float32)
# 读取畸变图像
img = cv2.imread('distorted.jpg')
h, w = img.shape[:2]
# 计算新的相机矩阵(可选,用于调整视野)
new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(
camera_matrix, dist_coeffs, (w, h), 1, (w, h))
# 畸变校正
undistorted = cv2.undistort(img, camera_matrix, dist_coeffs, None, new_camera_matrix)
# 裁剪掉黑边
x, y, w, h = roi
undistorted = undistorted[y:y+h, x:x+w]
cv2.imwrite('undistorted.jpg', undistorted)
3.5 避坑指南
做畸变校正这些年,我踩过不少坑。分享几个最典型的:
- 标定板要拍够:至少 15-20 张不同角度、不同位置的图像。我曾经偷懒只拍了 8 张,结果标定出来的参数在边缘区域误差很大。
- 标定板要占满视野:别只拍中间,边缘也要覆盖到。畸变在边缘最明显,不拍边缘等于没标定。
- 注意标定板的平整度:如果标定板本身是弯的,标定出来的畸变系数会把板的弯曲也算进去。我见过有人用打印纸当标定板,结果标定出来全是错的。
- 温度变化要小心:镜头和相机在温度变化时,内参和畸变系数会漂移。如果产线温度变化大,建议定期重新标定。
好了,相机模型和畸变这块就聊到这。记住一句话:标定是视觉检测的基石,畸变校正是标定的核心。搞懂了这些,后面的手眼标定、对位算法才能跑得稳。
公众号:蓝海资料掘金营,微信deep3321