使用OpenCV校准鱼眼镜头-第2部分
重磅干货,第一时间送达
在昨天的文章中我们介绍了有关如何使用OpenCV校准鱼眼镜头的一些基础知识,并我们在最后留下了一个问题。那么今天我们就来看看这个问题该如何解决。
但是,如果大家遇到以下任何一种情况,那就得了解一些细节的问题了。
失真图像的尺寸与校准所用的尺寸不同;
默认不失真设置裁剪掉的像素数量太大,无法接受。
我们需要首先了解什么是“平衡”(在经典cv2模块中也称为“ alpha” ),以及它如何影响未失真图像的尺寸和形状。先来看一个比较极端的图像矫正的例子。
矫正前
矫正后
注意:如您所知,OpenCVfisheye模块通过将角拉伸得过大而过度补偿了角。但这对于大多数图像来说效果都是挺好的。
这里涉及3个不同的维度:
dim1。原始图像的尺寸。
dim2。这是在使图像不失真之后要保留的尺寸。dim2很难理解,因为它受的影响balance,它基本上告诉OpenCV要保留多少图像。当时balance = 0,OpenCV将保留图像的最佳部分。而balance = 1,OpenCV保留原始图像的每个像素,这意味着很多黑色填充区域和过度拉伸的角。dim2其长宽比必须与相同dim1。
dim3。OpenCV将放置未失真图像的最终包装盒的尺寸。它可以是任何大小和任何纵横比。但是大多数情况下,除非想对未失真的图像进行裁剪,否则我们希望使其与原图像相同。
希望下面的程序比正式的OpenCV文档更容易理解。将dim2,dim3和balance(dim1可以从输入图像派生)传递到undistort下面的方法。
# You should replace these 3 lines with the output in calibration step
DIM=XXX
K=np.array(YYY)
D=np.array(ZZZ)
def undistort(img_path, balance=0.0, dim2=None, dim3=None):
img = cv2.imread(img_path)
dim1 = img.shape[:2][::-1] #dim1 is the dimension of input image to un-distort
assert dim1[0]/dim1[1] == DIM[0]/DIM[1], "Image to undistort needs to have same aspect ratio as the ones used in calibration"
if not dim2:
dim2 = dim1
if not dim3:
dim3 = dim1
scaled_K = K * dim1[0] / DIM[0] # The values of K is to scale with image dimension.
scaled_K[2][2] = 1.0 # Except that K[2][2] is always 1.0
# This is how scaled_K, dim2 and balance are used to determine the final K used to un-distort image. OpenCV document failed to make this clear!
new_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(scaled_K, D, dim2, np.eye(3), balance=balance)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(scaled_K, D, np.eye(3), new_K, dim3, cv2.CV_16SC2)
undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
cv2.imshow("undistorted", undistorted_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
for p in sys.argv[1:]:
undistort(p)
当然,大家应该尝试不同的值,以了解它们如何改变最终图像,达到一个平衡状态!
交流群
赞 (0)