红外-可见光双目相机标定Matlab
红外-可见光双目相机标定Matlab
在计算机视觉领域,双目相机标定是实现图像配准和深度估计的基础。本文以大疆H20T红外镜头为例,详细介绍了红外-可见光双目相机的标定过程,包括标定板拍摄、图像预处理、参数计算和重投影等关键步骤。通过实际操作和实验结果,探讨了双目相机标定在实际应用中可能遇到的问题和解决方案。
博主使用的是大疆H20T红外镜头,采集双模态数据,对H20T的红外图像和可见光图像进行配准。对于这个镜头,红外内核与可见光内核的相对位置是固定的,那我们可以假设它是一个共轴光学系统,所以尝试一下使用双目相机的标定方法。
1. 拍摄标定板
这里用的是红外图像加广角相机的图像,用加热的红外标定板进行拍摄。拍摄各个角度的图像。
2. 图像预处理
opencv和matlabApp都要求输入图像尺寸是一样的,所以这里需要对RGB图像进行处理,先裁剪与IR图像画幅大致匹配的尺寸,在resize到640*512。
3. 输入matlab的双目标定APP中
出现了一个问题:IR角点和RGB角点的原点不一样,原因是标定板的白色方格在IR中是黑色的,在RGB中是银色的。
4. 解决方法
我们对IR图像像素值进行反转,让黑色变白色,白色变黑色。这样原点不一样的问题可以解决,但是在拍摄标定板过程中也遇到一个问题。标定板的图层是银色的,对于RGB图像会反射背景环境,导致无法识别到所有的像角点。这里我们想了一个办法,对RGB图像像素值大于27的点放大了3-4倍,至于为什么是27,这是plot了无法识别角点区域的点,发现该增强亮度的区域值最小大概是27。(还试了拉伸对比度和Gamma 校正的方法,效果不如这个方法简单粗暴)
5. 计算标定参数
我们将处理后的图像输入matlab的双目标定APP中,计算标定参数。
6. 重投影
将得到的参数扔进opencv中对图像进行重投影,代码如下:这里需要注意的是,矩阵需要转置。
import numpy as np
import cv2
left_camera_matrix = np.array([[1112.02339500555,0,331.640270609595], [0,1110.44876980388,251.009012663238], [0, 0, 1]])
left_distortion = np.array([[0.0422714758036742, -1.81400594451195, -0.000663821801309170, 0.000167344495667083, 0]])
right_camera_matrix = np.array([[1075.25372134604,0,375.180071190304], [0,1074.03911789164,214.299738568775], [0, 0, 1]])
right_distortion = np.array([[-0.0816146850309497, 0.460490686070165, -0.000704960780593024, 0.000753298004712835, 0]])
R = np.array([[0.999941932740515, -0.00448882320225720, -0.00979702064007809],
[0.00449576363363795, 0.999989658350134, 0.000686514481516287],
[0.00979383768058758, -0.000730519706613411, 0.999951772379271]])
T = np.array([-50, 0.01, -0.0047326802636])
size = (640, 512)
R1, R2, P1, P2, Q, validPixROI1, validPixROI2 = cv2.stereoRectify(left_camera_matrix, left_distortion, right_camera_matrix, right_distortion, size, R, T)
left_map1, left_map2 = cv2.initUndistortRectifyMap(left_camera_matrix, left_distortion, R1, P1, size, cv2.CV_16SC2)
right_map1, right_map2 = cv2.initUndistortRectifyMap(right_camera_matrix, right_distortion, R2, P2, size, cv2.CV_16SC2)
print(Q)
img_left = cv2.imread('testimagepath')
img_right = cv2.imread('testimagepath')
cv2.imshow('ori_left', img_left)
cv2.imshow('ori_right', img_right)
img_left_rectified = cv2.remap(img_left, left_map1, left_map2, cv2.INTER_LINEAR)
img_right_rectified = cv2.remap(img_right, right_map1, right_map2, cv2.INTER_LINEAR)
img = cv2.hconcat([img_left, img_right])
concat = cv2.hconcat([img_left_rectified, img_right_rectified])
cv2.imshow('left', img_left_rectified)
cv2.imshow('right', img_right_rectified)
i = 0
while (i < 512):
cv2.line(img, (0,i), (1279,i), (0,255,0), )
cv2.line(concat, (0, i), (1279, i), (0, 255, 0), )
i = i + 36
cv2.imshow('original', img)
cv2.imshow('rectified', concat)
cv2.waitKey(0)
7. 结果分析
然而得到的投影图像结果并不准确,一开始还以为是标定板拍摄图像不准确,于是又拍了几组,还是得到一样的结果。然后又觉得可能是处理步骤出了问题,又用opencv给的图像重新跑了一遍,结果是准确的。看来这种方法行不通,此后又试了两种方法,这里直接放链接:可见光相机畸变矫正-CSDN博客
https://blog.csdn.net/OrigamiSun/article/details/121403939?ops_request_misc=&request_id=&biz_id=102&utm_term=%E7%BA%A2%E5%A4%96%E7%9B%B8%E6%9C%BA%E7%9A%84%E7%95%B8%E5%8F%98%E6%A0%A1%E6%AD%A3&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-121403939.nonecase&spm=1018.2226.3001.4187
热红外/可见光图像融合 - lwc3258 - 博客园
这两种方法都尝试了之后,发现这两种对于目标和标定板与相机距离一样的图像的匹配结果是准确的,但是对于距离不一样的图像对,结果并不准确。这里简单放一下这两个方法的结果,目标距离大约都是20m。
8. 最终结论
最后博主觉得应该是透视投影与正交投影的原因,导致两个镜头的物体成像并不是线性变化换的,总的来说,就是广角相机会出现近大远小的现象。可能无法通过双目标定的方法进行匹配,如果一定要用双目标定的话,需要对每个距离都进行标定。
H20T的镜头因为焦段不一样,很难通过双目标定的方法进行匹配,如果需要对图像进行配准的话,应该用图像匹配算法。对于匹配算法,我们也进行了一定的尝试,有需要的话后期整理。
本文原文来自CSDN