多个相机内外参标定详解[halcon]

本次讲述一个halcon实例,如何对多个相机参数进行标定。
相机的标定流程一般由以下几个部分:
相机参数的初始化->读取标定文件->读取标定板图像->进行标定->标定结果。
1. 相机参数的初始化
在开始标定前,要把相机与镜头的基础参数告知系统,主要包括8个参数:
Focus:镜头的焦距, 单位是m
Kappa:径向畸变系数。
Sx:两个相邻像元工方向的距离。
Sy:两个相邻像元y方向的距离。
Cx:图像上主点的x坐标。
Cy,:图像上主点的y坐标„
ImageWidth:图像的宽度。
ImageHeight:图像的高度。
在halcon中,用gen_cam_par_area_scan_polynomial 算子对相机参数进行初始化设置。
2. 读取标定文件
读取的标定文件必须要和实际使用的标定板规格一致,否则标定结果不准确。
3. 读取标定板图像
在拍照获取标定板图像时,一定要注意下列情况,获取高质量的标定板图像时计算获得准确标定结果的基础。
->标定板不宜过小,至少要覆盖图像总面积的1/4;
->内部圆点的直径应该大于20个像素;
->标定板背景要暗,最好是黑色或接近黑色;
->打光时,标定板白色部分亮度要大于100,黑色与白色亮度差值大于100;
->光照亮度均匀,不能过曝光或欠曝光,即最高亮度低于255,最低亮度大于3;
->拍摄标定图像时,需要不同的旋转角度和倾斜角度,最好每个象限2张以上,标定图像至少10张,最好15~20张;
->标定板要涉及图像的各个区域(四个角以及中间)。
4.进行标定
标定板图像拍完以后,就可以进行标定了。标定之前要挑选一张图像作为参考图像, 参考图像中标定板的位置, 即为后续的世界坐标系和测量平面。 调用HALCON的算子对图像中的标定板进行识别, 识别前系统会先对图像进行高斯平滑, 然后将圆点中心和标定板的剪切角提取到图像上。 标定图像没有质量问题, 就可以根据获取到的标定点的数据进行标定计算。

实例如下:
1)参数设置:
dev_update_off ()
*标定板图像存储路径
ImgPath := ‘3d_machine_vision/multi_view/’
*标定板图像名称前缀
ImgPrefix := ‘multi_view_calib_’
*其中一张标定板图像所在路径+前缀+后缀(即路径+名称)
FileName := ImgPath + ImgPrefix + ‘cam_0_00’
*读取图像,获取图像大小
read_image (Image, FileName)
get_image_size (Image, Width, Height)
*比例因子设置
Scale := .5

2)标定信息
标定板信息,100100mm的标定板
CaltabDescr := ‘caltab_100mm.descr’
*标定板厚度,单位为m
CaltabThickness := 0.0064
*相机数量为4
NumCameras := 4
*标定任务数量位1
NumCalibObjects := 1
*标定板图像数量为20
NumPoses := 20
*光学系统/相机参数初始化
gen_cam_par_area_scan_polynomial (0.0085, 0.0, 0.0, 0.0, 0.0, 0.0, 6e-6, 6e-6, Width * .5, Height * .5, Width, Height, StartCamPar)

3)创建标定模型
*创建标定模型
create_calib_data (‘calibration_object’, NumCameras, NumCalibObjects, CalibDataID)
*设置初始化相机系统参数
set_calib_data_cam_param (CalibDataID, ‘all’, [], StartCamPar)
*设置标定板信息
set_calib_data_calib_object (CalibDataID, 0, CaltabDescr)

4)进行标定
*打开四个窗口,以显示由四个摄像头组成的多视图立体设置的图像
open_windows_multi_view_setup (Height, Width, Scale, WindowHandles)
*忽略的图像
NumIgnoredImg := 0
for PoseIndex := 0 to NumPoses - 1 by 1
for CameraIndex := 0 to NumCameras - 1 by 1
*第一张图像的路径+名称
FileName := ImgPath + ImgPrefix + ‘cam_’ + CameraIndex + ‘_’ + PoseIndex$‘02’
*读取图像
read_image (Image, FileName)
* 设置系统信息, 不强制刷新变动图像
set_system (‘flush_graphic’, ‘false’)
*激活窗口
dev_set_window (WindowHandles[CameraIndex])
*显示图像
dev_display (Image)
*错误信息提示
Message := ['Camera ’ + CameraIndex,'Pose # ’ + PoseIndex]
*信息颜色
Color := [‘black’,‘black’]
* 是否显示错误信息变量
ShowErrorMsg := false
try
* 在图像中找到标定板,提取其中的圆点,并将其信息存入标定数据模型中
find_calib_object (Image, CalibDataID, CameraIndex, 0, PoseIndex, [], [])
* 获取标定板外框的轮廓, 方便查看
get_calib_data_observ_contours (Caltab, CalibDataID, ‘caltab’, CameraIndex, 0, PoseIndex)
*获取标定板内圆点的轮廓, 方便查看
get_calib_data_observ_contours (Marks, CalibDataID, ‘marks’, CameraIndex, 0, PoseIndex)
*显示标定板外框轮廓、圆点轮廓
dev_display (Caltab)
dev_display (Marks)
catch (Exception)
* 设置显示错误信息变量为true
ShowErrorMsg := true
*忽略的图像数量+1
NumIgnoredImg := NumIgnoredImg + 1
if (Exception[0] == 8402)
* 算子find_calib_object 没有找到标定板
Message := [Message,‘No calibration tab found!’]
*颜色设置为红色
Color := [Color,‘red’]
elseif (Exception[0] == 8404)
* find_calib_object could not extract the marks
*算子 find_calib_object 找不到圆点
Message := [Message,‘Marks were not identified!’]
*颜色设置为红色
Color := [Color,‘red’]
else
* 如果出现未知错误则添加以下信息到message
Message := [Message,‘Unknown Exception!.’]
*颜色设置为红色
Color := [Color,‘red’]
endif
*添加忽略图像信息到Message
Message := [Message,‘This image will be ignored.’]
*颜色设置为红色
Color := [Color,‘red’]
endtry
*在对应相机的窗口显示Message信息
disp_message (WindowHandles[CameraIndex], Message, ‘window’, 12, 12, Color, ‘true’)
if (ShowErrorMsg)
* 显示错误状态
enforce_visualization (WindowHandles)
disp_continue_message (WindowHandles[3], ‘black’, ‘true’)
stop ()
endif
endfor
enforce_visualization (WindowHandles)
endfor

*如果每个相机可用于标定的图像数量大于10
if ((NumPoses * NumCameras) - NumIgnoredImg >= NumCameras * 10)
*标定图像
calibrate_cameras (CalibDataID, Error)
else
*否则,添加错误信息到message
Message := ‘Too few marks were provided!’
Message[1] := ‘Please adapt the parameters for’
Message[2] := ‘extraction of the marks or provide’
Message[3] := ‘more images with better quality.’
*颜色设置为红色、黑色
Color := [‘red’,‘black’,‘black’,‘black’]
*显示错误信息,提醒添加图像数量
disp_message (WindowHandles[0], Message, ‘window’, 12, 12, Color, ‘true’)
return ()
endif

*创建一个相机设置模型, 并确定合适的世界坐标系
get_calib_data (CalibDataID, ‘model’, ‘general’, ‘camera_setup_model’, CameraSetupModelID)
*世界坐标系将由指数为0的相机标定板图像中标定板图像进行确定
RefPoseIndex := 0
*获取参考相机ID
get_calib_data (CalibDataID, ‘model’, ‘general’, ‘reference_camera’, RefCameraID)
*获取参考相机世界坐标
get_calib_data (CalibDataID, ‘calib_obj_pose’, [0,RefPoseIndex], ‘pose’, PoseCam0Indx0)
*设置原点位置
set_origin_pose (PoseCam0Indx0, 0, 0, CaltabThickness, ReferencePose)
*设置相机坐标系位置
set_camera_setup_param (CameraSetupModelID, ‘general’, ‘coord_transf_pose’, ReferencePose)

*判断文件是否再在, 方便写入,如果没有,生成文件
file_exists (‘four_camera_setup_model.csm’, FileExists)
if (not FileExists)
write_camera_setup_model (CameraSetupModelID, ‘four_camera_setup_model.csm’)
endif

5)标定结果显示
*相机参数
*获取相机标定的内参数项目名列表
get_calib_data (CalibDataID, ‘camera’, 0, ‘params_labels’, ParLabels)
*第一个相机内参数的数值
get_camera_setup_param (CameraSetupModelID, 0, ‘params’, CamPar0)
*第二个相机内参数的数值
get_camera_setup_param (CameraSetupModelID, 1, ‘params’, CamPar1)
*第三个相机内参数的数值
get_camera_setup_param (CameraSetupModelID, 2, ‘params’, CamPar2)
*第四个相机内参数的数值
get_camera_setup_param (CameraSetupModelID, 3, ‘params’, CamPar3)

  • 相机外参数
  • 获取相机标定的外参数项目名列表
    get_calib_data (CalibDataID, ‘camera’, 0, ‘pose_labels’, PoseLabels)
    *第一个相机外参数的数值
    get_camera_setup_param (CameraSetupModelID, 0, ‘pose’, CamPose0)
    *第二个相机外参数的数值
    get_camera_setup_param (CameraSetupModelID, 1, ‘pose’, CamPose1)
    *第三个相机外参数的数值
    get_camera_setup_param (CameraSetupModelID, 2, ‘pose’, CamPose2)
    *第四个相机外参数的数值
    get_camera_setup_param (CameraSetupModelID, 3, ‘pose’, CamPose3)
    *标定结果
    *显示相机内参
    disp_camera_parameters_multi_view_4 (WindowHandles, ParLabels, CamPar0, CamPar1, CamPar2, CamPar3)
    disp_continue_message (WindowHandles[3], ‘black’, ‘true’)
    stop ()
  • 显示相机外参
    disp_camera_poses_multi_view_4 (WindowHandles, PoseLabels, CamPose0, CamPose1, CamPose2, CamPose3)

你可能感兴趣的:(计算机视觉,图像处理,人工智能)