Haf*_*ian 6 opencv image camera-calibration
我正在按照教程校准我的相机。我了解了使用棋盘求相机内参和畸变系数的整个过程。我不明白的是,为什么在那之后,我们称之为getOptimalNewCameraMatrix?尤其是alpha参数。已经阅读了文档,但可能因为缺乏相机校准的知识,我真的无法理解它。
以下是上述图像的未失真图像示例(使用 OpenCV 的undistort)。
对于这个,我只是使用获得的内在相机和失真系数直接对图像进行失真处理。

至于这个,在我解开它之前,我getOptimalNewCameraMatrix用alpha=0(左)和alpha=1(右)来称呼它。
从我所见,getOptimalNewCameraMatrix是在不丢失信息的情况下保留原始图像?我希望有人能解释这个函数的真正作用。
如果我想用来自运动的结构 (SfM) 和来自这台相机的图片构建一个 3D 模型,我应该首先调用getOptimalNewCameraMatrix?
谢谢。
小智 22
我使用了openCV 校准教程中提到的相同图像(您可以在这里找到名为 left01.jpg 到 left14.jpg 的图像(实际上 left10.jpg 似乎丢失了,但这没关系))在校准步骤之后 - 假设正方形尺寸为30毫米-在教程中我得到了这个相机矩阵:
mtx = [[534.07088364 0. 341.53407554]
[ 0. 534.11914595 232.94565259]
[ 0. 0. 1. ]]
Run Code Online (Sandbox Code Playgroud)
另一方面,使用命令获得的新相机矩阵newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))为
newcameramtx = [[457.92434692 0. 342.55548195]
[ 0. 456.2421875 233.34661351]
[ 0. 0. 1. ]]
Run Code Online (Sandbox Code Playgroud)
请注意,这里alpha=1,但它可能是 [0,1] 之间的另一个值。使用另一个值会产生不同的newcameramtx.
到目前为止,没有什么新鲜事。然后,我在校准过程中对所有使用的图像进行了“不失真”处理,并将它们保存到两个新文件夹中。
其中一个文件夹(我们称其为第一个文件夹),填充了直接使用获得的本征相机(即mtx)和畸变系数(dist)获得的未畸变图像。
另一个(我们称之为第二个文件夹)充满了使用newcameramtx和相同的失真系数 ( dist) 的未失真图像。
明确地说,我使用了以下命令:
cv2.undistort(img, mtx, dist, None, mtx)
Run Code Online (Sandbox Code Playgroud)
和:
cv2.undistort(img, mtx, dist, None, newcameramtx)
Run Code Online (Sandbox Code Playgroud)
分别将结果图像保存到上述两个文件夹中。我没有roi在保存之前使用裁剪未扭曲的图像。结果图像就像您在问题中找到并给出的一样。
然后,使用第一个文件夹中的未失真图像,我重新执行校准过程,发现以下相机矩阵:
cv2.undistort(img, mtx, dist, None, mtx)
Run Code Online (Sandbox Code Playgroud)
cv2.undistort(img, mtx, dist, None, newcameramtx)
Run Code Online (Sandbox Code Playgroud)
对第二个文件夹执行相同操作,得到以下相机矩阵:
mtx_1stFolder = [[533.72669262 0. 341.96641109]
[ 0. 533.73880924 232.9742336 ]
[ 0. 0. 1. ]]
Run Code Online (Sandbox Code Playgroud)
newcameramtx_1stFolder = [[533.41644287 0. 341.35446736]
[ 0. 532.47808838 232.56343633]
[ 0. 0. 1. ]]
Run Code Online (Sandbox Code Playgroud)
mtx现在,请注意这里、mtx_1stFolder、 和newcameramtx_1stFolder彼此之间的距离有多近。同样,请注意newcameramtx、mtx_2ndFolder、 和newcameramtx_2ndFolder彼此之间的距离有多近。
基于这些观察,我的想法是直接使用获得的固有相机和畸变系数对图像进行去畸变,不会影响相机矩阵。它相应地返回相同大小的图像,但这些生成的图像会丢失一些像素。
如果您可以接受这种损失,那么您完全可以不使用cv2.getOptimalNewCameraMatrix。但是,如果您需要丢失像素中给出的信息,您还可以选择相应地使图像不失真,将alpha[0,1] 之间的参数设置为相同的图像尺寸或您想要的任何尺寸。
然而,此操作肯定会破坏您的相机矩阵,并且您需要对新的未失真图像进行新的校准。cv2.getOptimalNewCameraMatrix函数可以估计新的相机矩阵,而无需您进行新的校准。这就解释了为什么newcameramtx和mtx_2ndFolder彼此非常接近。
这似乎也解释了为什么mtx_2ndFolder和newcameramtx_2ndFolder彼此接近,因为没有太多可以扭曲的东西(对于 和 也是如此mtx_1stFolder)newcameramtx_1stFolder。
到目前为止我还没有提到的一件事是dist每个校准过程的失真系数( )。这实际上让我无法说我的想法是肯定的,所以我愿意接受对我的想法的更正。
直观上,我预计第一次校准会出现一些失真系数,因为图像明显失真。正如预期的那样,失真系数向量为:
mtx_2ndFolder = [[458.04299944 0. 342.94915275]
[ 0. 456.31672142 233.39481945]
[ 0. 0. 1. ]]
Run Code Online (Sandbox Code Playgroud)
另一方面,我预计对未失真图像的校准会给出更少的系数,理想情况下为 0,因为理想情况下所有失真都被消除了。
然而,第一个文件夹的校准给出:
newcameramtx_2ndFolder = [[458.24960327 0. 342.20507346]
[ 0. 455.25088501 232.99452259]
[ 0. 0. 1. ]]
Run Code Online (Sandbox Code Playgroud)
对第二个文件夹的校准给出:
dist = [[-0.29297164 0.10770696 0.00131038 -0.0000311 0.0434798 ]]
Run Code Online (Sandbox Code Playgroud)
对于前三项,结果如预期的那样,幅度逐渐减小到零,但它们并没有急剧接近 0。
另外,对于最后两项,系数增加了,这与我的预期相反。
小智 8
如果您想获得与原始图像形状相同的图像,则必须丢失一些像素。
opencv 文档中的“alpha”参数描述指出......
自由缩放参数介于 0(当未失真图像中的所有像素均有效时)和 1(当所有源图像像素保留在未失真图像中时)之间
对我来说,这意味着值为 0 时,所有像素都将进行几何变换以包含在内。径向和切向畸变将被消除,但图像的几何形状将不正确。
getOptimalNewCameraMatrix用于使用具有相同校准的同一相机的不同分辨率。
getOptimalNewCameraMatrix当我使用然后对返回的感兴趣区域应用裁剪时,我会得到最好的结果。
这是我用于此目的的 python 代码片段。
newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h))
mapx, mapy = cv2.initUndistortRectifyMap(mtx, dist, None, newcameramtx, dim, 5)
image = cv2.remap(image, mapx, mapy, cv2.INTER_LINEAR)
x, y, w, h = roi
image = image[y:y + h, x:x + w]
Run Code Online (Sandbox Code Playgroud)
这应该会获取您的最后一张图像(右侧的针垫图像)并为您提供最有用的图像。
我还将该undistort 方法分为两部分,因为您可以继续调用remap从相机接收到的新图像,前提是它们具有相同的分辨率
| 归档时间: |
|
| 查看次数: |
10824 次 |
| 最近记录: |