1, Camera internal parameter calibration
Objective: the purpose of calibrating internal parameters is to eliminate lens distortion.
The internal parameters of the area array camera are composed of an 8-bit array, including:
Focus stands for focal length, which is filled in according to our lens parameters, and 0 for telecentric lens
Kappa is the distortion size, because it is filled in 0 by default before calibration
The width and height of SX and sy pixels fill in the pixel size of the camera. You can check the camera manual or consult the camera manufacturer.
Cx, Cy fill in the center coordinates of the image
ImageWidth, ImageHeight fill in the width and height of the image
By referring to the manual, we can know other parameters except Kappa, and fill in the known information, which is the uncalibrated initial camera internal parameters.
With the initial internal parameters, you can set them with the following operator:
set_calib_data_cam_param (CalibDataID, 0, , startCamPar)
After calibration, I will get the internal parameters of the camera after calibration. The difference from that before calibration is that the value of Kappa is calculated, which is no longer 0, and other parameters are roughly unchanged. Therefore, internal parameter calibration is the process of calculating distortion coefficient.
2, Camera external parameter calibration
Objective: to determine the relative position relationship between the camera coordinate system and the world coordinate system. With the position relationship Pose, the points of the pixel coordinate system and the world coordinate system can be transformed into each other, so as to achieve the application purpose of calibration. Therefore, external parameter calibration is to solve the Pose (position) of the product to be located relative to the camera.
Meaning represented by 7 parameters in 3D pose: [0,0,0,0,0,0,0]
The first six represent the amount of translation and rotation, and the last represents the combined types of orderoftransform, orderofrotform and viewoftransform.
Reference articles on pose: Create in HALCON_ Seven parameters in pose and pose_ m0_37833782 blog - CSDN blog
Understanding of camera pose - halcon calibration - a road few people take
3, Reference code
1, Get internal parameters, refer to routine camera_calibration_internal ImgPath := '3d_machine_vision/calib/' dev_close_window () dev_open_window (0, 0, 652, 494, 'black', WindowHandle) dev_update_off () dev_set_draw ('margin') dev_set_line_width (3) set_display_font (WindowHandle, 14, 'mono', 'true', 'false') * * Calibrate the camera. * *Create the initial internal parameter data array by referring to the manual and other materials gen_cam_par_area_scan_division (0.016, 0, 0.0000074, 0.0000074, 326, 247, 652, 494, StartCamPar) *Create a calibration handle on which all operations are performed create_calib_data ('calibration_object', 1, 1, CalibDataID) *Set the uncalibrated initial internal parameter data created above set_calib_data_cam_param (CalibDataID, 0, , StartCamPar) *Set the description file of the calibration board, which is used to find the calibration board from each picture later set_calib_data_calib_object (CalibDataID, 0, 'caltab_30mm.descr') NumImages := 10 * Note, we do not use the image from which the pose of the measurement plane can be derived *10 A picture of a calibration plate at different positions in the field of view for I := 1 to NumImages by 1 read_image (Image, ImgPath + 'calib_' + I$'02d') dev_display (Image) *Automatically check the position information of the calibration plate find_calib_object (Image, CalibDataID, 0, 0, I, , ) endfor *Yes find_calib_object After that, the calibration can be carried out. After 10 times, 10 positions are calibrated calibrate_cameras (CalibDataID, Error) *Start calibration *After calibration, you can use the following operator to obtain the internal parameters of the calibrated camera get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam) * Write the internal camera parameters to a file *Save the calibrated camera internal parameters as a file for use write_cam_par (CamParam, 'camera_parameters.dat') Message := 'Interior camera parameters have' Message := 'been written to file' disp_message (WindowHandle, Message, 'window', 12, 12, 'red', 'false') 2, Get external parameters, reference routine camera_calibration_external *Method 1. Calibrate the plate to determine the pose *The calibration process of the external parameter is the same as that of the internal parameter. After the calibration process, the internal parameter and external parameter data (i.e. pose) already exist *Same use get_calib_data Get external parameters pose get_calib_data (CalibHandle, 'calib_obj_pose', [0, 1], 'pose', CameraPose) *Third parameter ItemIdx It consists of tuples of two parameters.[0, 1]It represents the positioning attitude in the first picture of No. 0 calibration plate. *We calibrated 10 pictures of calibration plates at different positions, so we obtained 10 pose data, and selected one of them as the reference pose, *In the future, the position of the product we want to locate should also be the same as the position of the reference pose, so we can use the pose to realize pixel coordinates and world coordinates *Point conversion clear_calib_data (CalibDataID) *Method 2. Determine the pose at least 3 points *4 points in the world coordinate system X := [0,50,100,80] Y := [5,0,5,0] Z := [0,0,0,0] *Corresponding to 4 points in the pixel coordinate system RCoord := [414,227,85,128] CCoord := [119,318,550,448] *Load camera internal parameters read_cam_par ('camera_parameters.dat', CamParam) *The pose is directly calculated from the correspondence between image points and world coordinate system points vector_to_pose (X, Y, Z, RCoord, CCoord, CamParam, 'iterative', 'error', FinalPose, Errors) *((optional) set_origin_pose Parallel transformation of a pose is the same as affine transformation *The final pose obtained by all methods is on the plane by default, and the thickness of the calibration plate is not considered, so it can be used *This method is used to set the thickness of the calibration plate and optimize the pose parameters set_origin_pose (FinalPose, 0, 0, 0.00075, FinalPose) *Save pose data as a file write_pose (FinalPose, 'pose_from_three_points.dat') 3, Practical application (1)Point coordinate conversion dev_update_window ('on') dev_display (Image) while (1) *Get pixel coordinates of mouse point get_mbutton (WindowHandle, Row, Column, Button) if (Button == 4) break endif dev_display (Image) dev_set_color ('green') disp_cross (WindowHandle, Row, Column, 6, 0) *Use the following operators to convert the image coordinates to world coordinates using the specified internal and external parameters image_points_to_world_plane (CamParam, FinalPose, Row, Column, 1, X1, Y1) disp_message (WindowHandle, 'X = ' + X1, 'window', 320, 400, 'red', 'false') disp_message (WindowHandle, 'Y = ' + Y1, 'window', 340, 400, 'red', 'false') endwhile (2)Measure straight line distance * The routine draws a range in the world coordinate system and measures the distance of multiple lines contained therein *Idea: determine in the world coordinate system ROI Ranges, converting to in the image coordinate system ROI，Measure the distance between lines in the image *Pixel distance, convert the pixel points into points in the bit world coordinate system, and calculate the actual distance dev_set_color ('red') dev_display (Image) * Sets the in the world coordinate system ROI region ROI_X_WCS := [-2,-2,112,112] ROI_Y_WCS := [0,0.5,0.5,0] ROI_Z_WCS := [0,0,0,0] *Convert pose to 3 D Transformation matrix,hom_mat3d_to_pose:3D Transform matrix to pose pose_to_hom_mat3d (FinalPose, CCS_HomMat_WCS) *Convert points in the world coordinate system to the camera coordinate system affine_trans_point_3d (CCS_HomMat_WCS, ROI_X_WCS, ROI_Y_WCS, ROI_Z_WCS, CCS_RectangleX, CCS_RectangleY, CCS_RectangleZ) *Converts points in the camera coordinate system to the image coordinate system project_3d_point (CCS_RectangleX, CCS_RectangleY, CCS_RectangleZ, CamParam, RectangleRow, RectangleCol) *Here we put the absolute in the world coordinate system ROI The points of the range are converted to the image coordinate system *Generate images ROI gen_region_polygon_filled (ROI, RectangleRow, RectangleCol) *Find the minimum circumscribed rectangle smallest_rectangle2 (ROI, RowCenterROI, ColCenterROI, PhiROI, Length1ROI, Length2ROI) * Prepare the survey and create a survey tool gen_measure_rectangle2 (RowCenterROI, ColCenterROI, PhiROI, Length1ROI, Length2ROI, 652, 494, 'bilinear', MeasureHandle) *Start measurement measure_pairs (Image, MeasureHandle, 0.4, 5, 'all_strongest', 'all', RowEdgeFirst, ColumnEdgeFirst, AmplitudeFirst, RowEdgeSecond, ColumnEdgeSecond, AmplitudeSecond, IntraDistance, InterDistance) close_measure (MeasureHandle) dev_display (Image) disp_message (WindowHandle, 'Measuring the position of the pitch lines', 'window', 450, 25, 'red', 'false') dev_set_color ('green') *Find the midpoint of the line width of each line RowPitchLine := (RowEdgeFirst + RowEdgeSecond) / 2.0 ColPitchLine := (ColumnEdgeFirst + ColumnEdgeSecond) / 2.0 disp_cross (WindowHandle, RowPitchLine, ColPitchLine, 6, 0) *Convert points on a line in the image coordinate system to the world coordinate system image_points_to_world_plane (CamParam, FinalPose, RowPitchLine, ColPitchLine, 1, X1, Y1) for I := 1 to |X1| by 1 *Sets the output position of the text on the form set_tposition (WindowHandle, RowEdgeFirst[I - 1] + 5, ColumnEdgeFirst[I - 1] - 20) if (I == |X1|) set_tposition (WindowHandle, RowEdgeFirst[I - 1], ColumnEdgeFirst[I - 2]) endif *Display information write_string (WindowHandle, X1[I - 1]$'.3f' + 'mm') endfor disp_continue_message (WindowHandle, 'black', 'true') stop () (3)Take the specified point as the center to convert the image to the position of the specified pose dev_close_inspect_ctrl (YOfContour) dev_close_inspect_ctrl (XOfContour) * Now, transform the whole image WidthMappedImage := 652 HeightMappedImage := 494 dev_display (Image) * First, determine the scale for the mapping * (here, the scale is determined such that in the * surroundings of the points P0 and P1, the image scale of the * mapped image is similar to the image scale of the original image) *The distances between two points in the world coordinate system and the corresponding image coordinate system are calculated respectively distance_pp (X, Y, X, Y, DistP0P1WCS) distance_pp (RCoord, CCoord, RCoord, CCoord, DistP0P1PCS) *Find out the proportional relationship between world coordinates and image coordinates Scale := DistP0P1WCS / DistP0P1PCS * Then, determine the parameter settings for set_origin_pose such * that the point given via get_mbutton will be in the center of the * mapped image dev_display (Image) disp_message (WindowHandle, 'Define the center of the mapped image', 'window', 12, 12, 'red', 'false') *Extract a point in the screen, and later move the picture to the center of the screen according to the position of this pixel in the image get_mbutton (WindowHandle, CenterRow, CenterColumn, Button1) *Convert points to world coordinates image_points_to_world_plane (CamParam, FinalPose, CenterRow, CenterColumn, 1, CenterX, CenterY) *Set the pose of the picture to be converted, and translate the image according to the points selected above set_origin_pose (FinalPose, CenterX - Scale * WidthMappedImage / 2.0, CenterY - Scale * HeightMappedImage / 2.0, 0, PoseNewOrigin) *Generates a projection from the image to the world coordinate system gen_image_to_world_plane_map (Map, CamParam, PoseNewOrigin, 652, 494, WidthMappedImage, HeightMappedImage, Scale, 'bilinear') *Apply projection to image map_image (Image, Map, ImageMapped) dev_clear_window () dev_display (ImageMapped) * In the case that only one image has to be mapped, the operator * image_to_world_plane can be used instead of the operators * gen_image_to_world_plane_map and map_image. *(Optional) you can use the operator when you only need to map one image image_to_world_plane *To replace the operator gen_image_to_world_plane_map and map_image. image_to_world_plane (Image, ImageMapped, CamParam, PoseNewOrigin, WidthMappedImage, HeightMappedImage, Scale, 'bilinear')