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算子进行畸变修正后的效果

再次调整姿态,更斜一些。

生成的校正图如下:

校正之后的效果:



少有人走的路



















