我也曾有同样的问题。我在网上搜索时找不到清晰明确的答案,但是经过一些测试后,我对
cv2.getOptimalNewCameraMatrix
函数实际为用户做了什么有了一个想法。
我使用了
openCV校准教程中提到的相同图像(你可以在
这里找到它们,它们被命名为left01.jpg到left14.jpg(实际上,left10.jpg似乎丢失了,但没关系)。)在校准步骤之后-假设正方形尺寸为30毫米-我得到了这个相机矩阵:
mtx = [[534.07088364 0. 341.53407554]
[ 0. 534.11914595 232.94565259]
[ 0. 0. 1. ]]
使用命令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. ]]
注意这里的alpha=1
,但它可以是[0,1]之间的其他值。使用另一个值将给出不同的newcameramtx
。
到目前为止还没有什么新东西。然后,我对校准过程中使用的所有图像进行了“去畸变”处理,并将它们保存到两个新文件夹中。其中一个文件夹(我们称其为第1个文件夹)直接使用获取的内部相机(即mtx
)和畸变系数(dist
)填充了未失真的图像,另一个文件夹(我们称其为第2个文件夹)使用newcameramtx
和相同的畸变系数(dist
)填充了未失真的图像。明确地说,我分别使用命令 cv2.undistort(img, mtx, dist, None, mtx)
和 cv2.undistort(img, mtx, dist, None, newcameramtx)
并将结果图像保存到上述两个文件夹中。在保存之前,我没有使用roi
裁剪未失真的图像。结果图像就像您在问题中发现并给出的那样。
然后,使用第1个文件夹中的未失真图像,我重新执行了校准过程,并找到了以下相机矩阵:
mtx_1stFolder = [[533.72669262 0. 341.96641109]
[ 0. 533.73880924 232.9742336 ]
[ 0. 0. 1. ]]
newcameramtx_1stFolder = [[533.41644287 0. 341.35446736]
[ 0. 532.47808838 232.56343633]
[ 0. 0. 1. ]]
对第二个文件夹执行相同操作后,得到以下相机矩阵:
mtx_2ndFolder = [[458.04299944 0. 342.94915275]
[ 0. 456.31672142 233.39481945]
[ 0. 0. 1. ]]
newcameramtx_2ndFolder = [[458.24960327 0. 342.20507346]
[ 0. 455.25088501 232.99452259]
[ 0. 0. 1. ]]
现在,请注意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
)。这实际上让我无法确定我的想法是否正确,因此我对我的想法持开放态度。直观地说,我希望在第一次校准中找到一些失真系数,因为图像显然已失真。如预期所述,失真系数向量如下:
dist = [[-0.29297164 0.10770696 0.00131038 -0.0000311 0.0434798 ]]
另一方面,我本以为对未畸变图像进行校准会得到更少的系数,理想情况下应该是0,因为所有畸变都被完美地去除了。然而,对第一个文件夹进行校准所得到的结果是:
dist = [[ 0.00760897 -0.07313015 0.0002162 0.0003522 0.1605208 ]]
第二个文件夹的校准结果为:
dist = [[ 0.00135068 -0.02390678 0.0001996 0.0003413 0.0580141 ]]
对于前三项,结果如预期般朝着0逐渐变小,但并不会急剧接近0。 对于后两项,系数增加了,这与我的预期相反。 如果有人知道为什么会出现这种情况,我将不胜感激。
centerPrincipalPoint
标志。如果你从undistort
函数返回的图像和 alpha=0 的无畸变图像进行比较,它们会显示不同的结果(alpha=0 图像中的正方形看起来不是正方形)。这是因为默认情况下,当不使用新矩阵时,使用图像中心而不是通过getOptimalNewCameraMatrix
重新计算主点。将此标志设置为 true 可以获得与不使用最优矩阵时 alpha=0 相同的结果。 - IndefiniteBen