halcon的标定助手完成标定后,是可以自动生成一些代码。它是很好的参考。
////////////////////标定数据Tuple////////////////
CameraParameters := ['area_scan_division',0.00928003,-1009.07,2.50105e-06,2.5e-06,1236.62,1005.87,2592,1944] CameraPose := [0.00527608,-0.016633,0.174111,10.3202,3.44142,208.299,0]
///////////////////标定函数////////////////////////
* Calibration 01: Code generated by Calibration 01 open_framegrabber ('GigEVision2', 0, 0, 0, 0, 0, 0, 'progressive', -1, 'default', -1, 'false', 'default', '94aab8005ad8_Microvision_MVEM500M', 0, -1, AcqHandle) TmpCtrl_ReferenceIndex := 0 TmpCtrl_PlateDescription := 'C:/Program Files/MVTec/HALCON-19.11-Progress/calib/calplateHG30.cpd' StartParameters := ['area_scan_division',0.008,0,2.5e-06,2.5e-06,1296,972,2592,1944] TmpCtrl_FindCalObjParNames := 'sigma' TmpCtrl_FindCalObjParValues := 1 * Calibration 01: Create calibration model for managing calibration data create_calib_data ('calibration_object', 1, 1, CalibHandle) set_calib_data_cam_param (CalibHandle, 0, [], StartParameters) set_calib_data_calib_object (CalibHandle, 0, TmpCtrl_PlateDescription) * Calibration 01: Collect mark positions and estimated poses for all plates for Index := 0 to 19 by 1 grab_image (Image, AcqHandle) find_calib_object (Image, CalibHandle, 0, 0, Index, TmpCtrl_FindCalObjParNames, TmpCtrl_FindCalObjParValues) stop () endfor * Calibration 01: Perform the actual calibration calibrate_cameras (CalibHandle, TmpCtrl_Errors) get_calib_data (CalibHandle, 'camera', 0, 'params', CameraParameters) get_calib_data (CalibHandle, 'calib_obj_pose', [0, TmpCtrl_ReferenceIndex], 'pose', CameraPose) * Calibration 01: Adjust origin for plate thickness set_origin_pose (CameraPose, 0.0, 0.0, 0.001, CameraPose) stop () close_framegrabber (AcqHandle)
///////////////////由文件读取标定的内参与位姿////////////////////////
* Calibration 01: Code generated by Calibration 01 open_framegrabber ('GigEVision2', 0, 0, 0, 0, 0, 0, 'progressive', -1, 'default', -1, 'false', 'default', '94aab8005ad8_Microvision_MVEM500M', 0, -1, AcqHandle) read_cam_par ('C:/Users/Administrator/Desktop/左相机8005.cal', CameraParameters) read_pose ('C:/Users/Administrator/Desktop/左相机8005.dat', CameraPose) stop () close_framegrabber (AcqHandle)
///////////////////将测量结果转到世界坐标系////////////////////////
dev_close_window() dev_update_off() * Image Acquisition 01: Code generated by Image Acquisition 01 open_framegrabber ('GigEVision2', 0, 0, 0, 0, 0, 0, 'progressive', -1, 'default',\ 'force_ip=192.168.0.215/00:B0:9D:F5:DD:53/192.168.0.1/255.255.254.0', \ 'false', 'default', '00b09df5dd53_PointGreyResearch_970230000000', 0, -1, AcqHandle) read_cam_par ('C:/Users/Administrator.PC8-20191007LRY/Desktop/BFLY_LY_50M.cal', CameraParameters) read_pose ('C:/Users/Administrator.PC8-20191007LRY/Desktop/BFLY_LY_50M.dat', CameraPose) grab_image (Image, AcqHandle) get_image_size(Image, Width, Height) dev_open_window(0, 0, Width/3, Height/3, 'black', WindowHandle) dev_display(Image) TmpCtrl_PlateDescription := 'D:/Program Files/MVTec/HALCON-19.11-Progress/calib/calplateHG30.cpd' TmpCtrl_FindCalObjParNames := 'sigma' TmpCtrl_FindCalObjParValues := 1 create_calib_data ('calibration_object', 1, 1, CalibHandle) set_calib_data_cam_param (CalibHandle, 0, [], CameraParameters) set_calib_data_calib_object (CalibHandle, 0, TmpCtrl_PlateDescription) find_calib_object (Image, CalibHandle, 0, 0, 0, TmpCtrl_FindCalObjParNames, TmpCtrl_FindCalObjParValues) get_calib_data_observ_points (CalibHandle, 0, 0, 0, TmpCtrl_MarkRows, TmpCtrl_MarkColumns, TmpCtrl_Ind, CameraPose) set_origin_pose (CameraPose, 0.0, 0.0, 0.0032, CameraPose) *显示世界坐标系坐标轴 disp_3d_coord_system(WindowHandle, CameraParameters, CameraPose, 0.05) TmpCtrl_ImageRows := [TmpCtrl_MarkRows[0], TmpCtrl_MarkRows[1]] TmpCtrl_ImageColumns := [TmpCtrl_MarkColumns[0], TmpCtrl_MarkColumns[1]] gen_contour_polygon_xld (TmpObj_ImageContour, TmpCtrl_ImageRows, TmpCtrl_ImageColumns) image_points_to_world_plane (CameraParameters, CameraPose, TmpCtrl_ImageRows, TmpCtrl_ImageColumns,\ 'mm', TmpCtrl_WorldX, TmpCtrl_WorldY) distance_pp (TmpCtrl_WorldY[0], TmpCtrl_WorldX[0], TmpCtrl_WorldY[1], TmpCtrl_WorldX[1], TmpCtrl_Distance) close_framegrabber (AcqHandle)
测量的时候,有意把标定板倾斜放置,让它在3D坐标上有变化。
测量到的两个圆心距离是2.01356mm,标准距离是2.0mm。
换个方向
再换个方向
可以看到,世界坐标系的轴跟着在变化。
也就是说标定块是可以区分3D方向的。
在3D坐标下变化,我们的测量结果基本上是一致的。
另外算子set_origin_pose (CameraPose, 0.0, 0.0, 0.0032, CameraPose) 是平移世界坐标原点,其中0.0032就是标定的时候填写的标定板的厚度。
勇哥发现这个值如果填写为0,则测量结果要更准确一些。(这个有点奇怪)
///////////////////将XLD轮廓变换到世界坐标系中////////////////////////
* Calibration 01: Sample code generated by Calibration 01 * Calibration 01: For demonstration purposes, we use the calibration * Calibration 01: plate itself as sample object. * Calibration 01: Therefore, please take another calibration plate image stop () grab_image (Image, AcqHandle) * Calibration 01: Extract plate data from the image TmpCtrl_PlateDescription := 'C:/Program Files/MVTec/HALCON-19.11-Progress/calib/calplateHG30.cpd' TmpCtrl_FindCalObjParNames := 'sigma' TmpCtrl_FindCalObjParValues := 1 * Calibration 01: Create calibration model for managing calibration data create_calib_data ('calibration_object', 1, 1, CalibHandle) set_calib_data_cam_param (CalibHandle, 0, [], CameraParameters) set_calib_data_calib_object (CalibHandle, 0, TmpCtrl_PlateDescription) find_calib_object (Image, CalibHandle, 0, 0, 0, TmpCtrl_FindCalObjParNames, TmpCtrl_FindCalObjParValues) get_calib_data_observ_points (CalibHandle, 0, 0, 0, TmpCtrl_MarkRows, TmpCtrl_MarkColumns, TmpCtrl_Ind, CameraPose) * Calibration 01: Using the calibration plate as test object, the marks actually * Calibration 01: lie above the corrected measurement plane. Therefore, we 'uncorrect' * Calibration 01: the plane of measurement by the plate thickness here. set_origin_pose (CameraPose, 0.0, 0.0, 0.001, CameraPose) * Calibration 01: ********************************************************** * Calibration 01: Sample Task: Transform contours into world coordinates * Calibration 01: ********************************************************** * Calibration 01: First, obtain an XLD in image coordinates which relates to some * Calibration 01: interesting features in the image. Here, we simply generate a contour * Calibration 01: connecting the mark center points of the plate gen_contour_polygon_xld (TmpObj_ImageContour, TmpCtrl_MarkRows, TmpCtrl_MarkColumns) * Calibration 01: Then, we convert it to world coordinates (using [mm]) contour_to_world_plane_xld (TmpObj_ImageContour, TmpObj_WorldContour, CameraParameters, CameraPose, 'mm') * Calibration 01: Extract mark center points in world coordinates [mm] get_contour_xld (TmpObj_WorldContour, TmpCtrl_WorldX, TmpCtrl_WorldY) stop ()
注意XLD轮廓变换到世界坐标系后位于标块左上角那个红点处。
这个变换后的轮廓只是单位变了。
///////////////////从单副图像中评估位姿////////////////////////
* Calibration 01: Sample code generated by Calibration 01 * Calibration 01: For demonstration purposes, we use the calibration * Calibration 01: plate itself as sample object. * Calibration 01: Therefore, please take another calibration plate image stop () grab_image (Image, AcqHandle) * Calibration 01: Extract plate data from the image TmpCtrl_PlateDescription := 'C:/Program Files/MVTec/HALCON-19.11-Progress/calib/calplateHG30.cpd' TmpCtrl_FindCalObjParNames := 'sigma' TmpCtrl_FindCalObjParValues := 1 * Calibration 01: Create calibration model for managing calibration data create_calib_data ('calibration_object', 1, 1, CalibHandle) set_calib_data_cam_param (CalibHandle, 0, [], CameraParameters) set_calib_data_calib_object (CalibHandle, 0, TmpCtrl_PlateDescription) find_calib_object (Image, CalibHandle, 0, 0, 0, TmpCtrl_FindCalObjParNames, TmpCtrl_FindCalObjParValues) get_calib_data_observ_points (CalibHandle, 0, 0, 0, TmpCtrl_MarkRows, TmpCtrl_MarkColumns, TmpCtrl_Ind, CameraPose) * Calibration 01: Using the calibration plate as test object, the marks actually * Calibration 01: lie above the corrected measurement plane. Therefore, we 'uncorrect' * Calibration 01: the plane of measurement by the plate thickness here. set_origin_pose (CameraPose, 0.0, 0.0, 0.001, CameraPose) * Calibration 01: ********************************************************** * Calibration 01: Sample Task: Pose Estimation * Calibration 01: ********************************************************** * Calibration 01: With known camera parameters, one image is enough to * Calibration 01: determine the new pose stop ()
下面是标定时的位姿:
[0.00858819, 0.00535895, 0.53037, 358.13, 0.643493, 1.02991, 0]
下面是由一张图片求出的位姿:
[0.00453219, 0.00332088, 0.530478, 358.312, 0.724421, 179.253, 0]
从中可以看到Z轴转了180度。
///////////////////校正图像////////////////////////
* Calibration 01: Sample code generated by Calibration 01 * Calibration 01: For demonstration purposes, we use the calibration * Calibration 01: plate itself as sample object. * Calibration 01: Therefore, please take another calibration plate image stop () grab_image (Image, AcqHandle) * Calibration 01: Extract plate data from the image TmpCtrl_PlateDescription := 'C:/Program Files/MVTec/HALCON-19.11-Progress/calib/calplateHG30.cpd' TmpCtrl_FindCalObjParNames := 'sigma' TmpCtrl_FindCalObjParValues := 1 * Calibration 01: Create calibration model for managing calibration data create_calib_data ('calibration_object', 1, 1, CalibHandle) set_calib_data_cam_param (CalibHandle, 0, [], CameraParameters) set_calib_data_calib_object (CalibHandle, 0, TmpCtrl_PlateDescription) find_calib_object (Image, CalibHandle, 0, 0, 0, TmpCtrl_FindCalObjParNames, TmpCtrl_FindCalObjParValues) get_calib_data_observ_points (CalibHandle, 0, 0, 0, TmpCtrl_MarkRows, TmpCtrl_MarkColumns, TmpCtrl_Ind, CameraPose) * Calibration 01: Using the calibration plate as test object, the marks actually * Calibration 01: lie above the corrected measurement plane. Therefore, we 'uncorrect' * Calibration 01: the plane of measurement by the plate thickness here. set_origin_pose (CameraPose, 0.0, 0.0, 0.001, CameraPose) * Calibration 01: ********************************************************** * Calibration 01: Sample Task: Image Rectification * Calibration 01: ********************************************************** * Calibration 01: Choose the desired width of the visible area in world coordinates [mm] TmpCtrl_RectificationWidth := 40 * Calibration 01: Convert to [m] TmpCtrl_RectificationWidth := TmpCtrl_RectificationWidth / 1000.0 * Calibration 01: Adjust origin so the plate is roughly centered set_origin_pose (CameraPose, -0.5*TmpCtrl_RectificationWidth, -0.4*TmpCtrl_RectificationWidth, 0, TmpCtrl_RectificationPose) * Calibration 01: Generate the rectification map gen_image_to_world_plane_map (TmpObj_RectificationMap, CameraParameters, TmpCtrl_RectificationPose, 2592, 1944, 2592, 1944, TmpCtrl_RectificationWidth / 2592, 'bilinear') * Calibration 01: Now, images can be rectified using the rectification map map_image (Image, TmpObj_RectificationMap, TmpObj_RectifiedImage) stop ()
原图为某姿式下的标定板。
gen_image_to_world_plane_map算子生成修正图
map_image算子进行畸变修正后的效果
再次调整姿态,更斜一些。
生成的校正图如下:
校正之后的效果:

