一些视觉项目中会用到双目视觉,双目视觉可以判别出物体所在的空间位置,有很多应用场景。
双目视觉,即两个相机在两边看同一个视野,然后获取目标物的空间位置X,Y,Z。
架设图就不画了,差不多就那样。下面介绍下标定方法。
提下:双目视觉标定:就是获取左右两个相机的内参和右相机相对与左相机的Pose。
这边使用的是一块30mm的标定板来坐双目标定,长这样。
放在相机下面,两个相机都能看到这板子。左相机和右相机分别取图。然后,分别获取这49个黑点的图像坐标,以及计算他们此时的Pose。得到了2组49点坐标,2组pose。因为两个相机啊。
重复上面这步,就是把移动板子,放歪点,放斜点,可以不再同一平面。取图,获取点和Pose。 15次。
类似这样
这样得到左相机735个坐标(RowL,CoordL) 和 15个Pose :StartPoseL。右相机一样。分别将他们写到一个一维数组里去。
这些数据就可以用来做双目标定啦。
以上步骤的halcon代码
ImgPath := 'stereo/board/'
Index := 1
read_image (ImageL, ImgPath + 'calib_l_' + Index$'02d')
read_image (ImageR, ImgPath + 'calib_r_' + Index$'02d')
CaltabFile := 'caltab_30mm.descr'
caltab_points (CaltabFile, X, Y, Z)
get_image_size (ImageL, WidthL, HeightL)
get_image_size (ImageR, WidthR, HeightR)
StartCamParL := [0.0125,0,1.48e-5,1.48e-5,WidthL / 2.0,HeightL / 2.0,WidthL,HeightL]
StartCamParR := StartCamParL
SizeGauss := 3
MarkThresh := 120
MinDiamMarks := 5
StartThresh := 128
DeltaThresh := 10
MinThresh := 18
Alpha := 0.9
MinContLength := 15
MaxDiamMarks := 100
RowsL := []
ColsL := []
StartPosesL := []
RowsR := []
ColsR := []
StartPosesR := []
for Index := 1 to 15 by 1
* Read the calibration images
read_image (ImageL, ImgPath + 'calib_l_' + Index$'02d')
read_image (ImageR, ImgPath + 'calib_r_' + Index$'02d')
* Search for the calibration plate
find_caltab (ImageL, CaltabL, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)
find_caltab (ImageR, CaltabR, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)
* Display calibration plate regions
* Extraction of marks and pose as well as visualization of the
* results for the second image.
find_marks_and_pose (ImageL, CaltabL, CaltabFile, StartCamParL, StartThresh, DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks, RCoordL, CCoordL, StartPoseL)
* Extraction of marks and pose as well as visualization of the
* results for the second image.
find_marks_and_pose (ImageR, CaltabR, CaltabFile, StartCamParR, StartThresh, DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks, RCoordR, CCoordR, StartPoseR)
* Accumulate the image coordinates of the calibration marks
* as well as the estimated initial poses for all stereo pairs,
* where the poses has been estimated consistently.
RowsL := [RowsL,RCoordL]
ColsL := [ColsL,CCoordL]
StartPosesL := [StartPosesL,StartPoseL]
RowsR := [RowsR,RCoordR]
ColsR := [ColsR,CCoordR]
StartPosesR := [StartPosesR,StartPoseR]
endfor
最后用一个算子标定 binocular_calibration
binocular_calibration (X, Y, Z, RowsL, ColsL, RowsR, ColsR, StartCamParL, StartCamParR, StartPosesL, StartPosesR, 'all', CamParamL, CamParamR, NFinalPoseL, NFinalPoseR, cLPcR, Errors)
双目标定即:获取左右两个相机的内参和右相机相对与做相机的Pose。
我们上面那个算子获得的CamParamL、CamParamR、cLPcR就是它们。
下面介绍一个应用:
上面是双目相机拍的两张图,我们要获取那个黑的立方体的高度:立方体上表面到地下那个平面的高度差。
思路很简单,左右两张图分别有4个关键点,就是那个两对着的小三角的交点。知道底下三个关键点的空间坐标即能拟合一个平面,然后立方体上的关键点也有空间位置,计算点到平面的高度差。当然,用向量很容易算出高度。
第一步:我们从标定知道了两相机内参和相对Pose
CamParamLeft := [0.0128583,-533.075,7.40044e-006,7.4e-006,310.243,243.807,640,480]
CamParamRight := [0.0130659,-512.699,7.41508e-006,7.4e-006,333.347,237.374,640,480]
RelPose := [0.154132,-0.00585068,0.0429294,359.932,336.422,359.901,0]
第二步:分别找到两张图关键点的图像坐标
critical_points_sub_pix (ImageLeft, 'facet', 2.0, 5, RowMin, ColMin, RowMax, ColMax, RowPointLeft, ColumnPointLeft)
gen_cross_contour_xld (CrossLeft, RowPointLeft, ColumnPointLeft, 20, rad(45))
critical_points_sub_pix (ImageRight, 'facet', 2.0, 5, RowMin, ColMin, RowMax, ColMax, RowPointRight, ColumnPointRight)
gen_cross_contour_xld (CrossRight, RowPointRight, ColumnPointRight, 20, rad(45))
第三步:通过调用intersect_lines_of_sight算子,得到关键点在左边相机下的空间位置。这个算子需要两相机内参和相对Pose。和两图像中关键点的图像坐标。
intersect_lines_of_sight (CamParamLeft, CamParamRight, RelPose, RowPointLeft, ColumnPointLeft, RowPointRight, ColumnPointRight, X, Y, Z, Dist)
好了,得到的X,Y,Z单位都是米,乘以1000,单位变成毫米。
求高度容易了哇,通过向量P2P0和P2P3算出Z方向单位法向量,点乘向量P2P1,就是高度了啊!
OK!