1.标定相关的任务-->>解决畸变和坐标系的转换

  1.1 描述和查找标定对象

  1.2 补偿透视和径向变形,径向畸变包括枕形畸变和桶形畸变

  1.3 相机参数(内外参)

  1.4 图像坐标到世界坐标的转换

  1.5 自标定:不用标定板用图像四周包含直线特征进行标定

  1.6 其他标定:一台相机标定、多台相机标定、手眼标定

2.分割模型(Division)

  分割模型使用一个参数(k)对径向变形进行建模,光学中心就在图像中心

  【k>0枕形畸变】  【k=0没有畸变】  【k<0桶形畸变】

['area_scan_division',Focus,Kappa,Sx,Sy*,Cx,Cy,ImageWidth,ImageHeight]

Focus:焦距

Kappa:k值,初始值为0

Sx,Sy*:中心缩放比例

Cx,Cy:图像中心

ImageWidth,ImageHeight:图像大小

3.多项式模型(polynomial):光学中心可能不在图像中心

  多项式模型使用三个参数(K1,K2,K3)对径向变形进行建模,并使用两个参数(P1,P2)对偏心变形进行建模

['area_scan_polynomial',Focus,K1 ,K2,K3,P1,P2,Sx,Sy*,Cx,Cy,ImageWidth,ImageHeight]

Focus:焦距

K1 ,K2,K3,P1,P2:多项式模型参数,初始值为0

Sx,Sy*:中心缩放比例

Cx,Cy:图像中心

ImageWidth,ImageHeight:图像大小

4.透视畸变

  被摄物越远,显得越小;镜头离被摄体越远,被摄体外观上的大小变化越小

  透视畸变术语三维畸变的范畴,同意姿态可以看作为透视变化的特殊形式。单相机无法解决透视畸变

  单相机和四轴机器人标定的主要误差也是透视畸变

5.倾斜镜头:旋转描述旋转轴的方向,倾斜度描述了镜头的实际倾斜度

area_scan_tilt_ * 普通FA镜头倾斜

area_scan_tilt_image_side_telecentric_* 像方倾斜

area_scan_tilt_object_side_telecentric_* 物方倾斜

area_scan_tilt_bilateral_telecentric_* 双远心倾斜  

【tilt 倾斜】【bilateral 双边】【telecentric 远心】

6.相机标定内参

CameraType:摄像机类型

Focus:镜头焦距(仅适用于在镜头物侧执行透视投影的镜头,远心镜头设置0)初始值为所用镜头的标称焦距,例如0.008mm

Magnification:镜头的放大倍率(仅用于物侧远心镜头)

Kappa(K):变形系数,用于建模镜头的径向和偏心变形(仅用于多项式模型),将0.0用作所有五个系数的初始值

ImagePlaneDist:镜头出瞳(小孔)到像平面(Sensor)的距离

Tilt,Rot:旋转轴是广州相对于传感器平面法线倾斜的角度。旋转角度是围绕光轴(z轴)的旋转。这些角度通常基于导致使用倾斜透镜的考虑因素而大致已知,或者可以从倾斜透镜的机构中读取

Sx,Sy:比例因子

Cx,Cy:径向畸变的中心,使用图像的半宽和半高作为初始值

ImageWidth,ImageHeight:采样图像的宽度和高度

Vx,Vy,Vz:运行矢量的X,Y和Z分量(先扫模型)

Halcon深度学习标注工具 halcon高精度标定怎么标定的_多项式

7.六边形标定板

  7.1 至少看到一种取景器图案才能找到校准板。为了确保印版没有倒转,至少需要看到二个。
z轴指向校准板, x轴指向右侧, y轴指向下方,沿z轴方向观察。
  7.3 优点:标定板不必在图像中完全可见

  对应算子:create_caltab

Halcon深度学习标注工具 halcon高精度标定怎么标定的_多项式_02

Halcon深度学习标注工具 halcon高精度标定怎么标定的_建模_03

Halcon深度学习标注工具 halcon高精度标定怎么标定的_建模_04

Halcon深度学习标注工具 halcon高精度标定怎么标定的_Image_05

*create_caltab生成六边形标定板
*标定的Marks点,13行每行15个Mark,相邻Mark相距0.0015m
*五组六边形坐标,其行列坐标是[6,2,2,10,10], [7,2,12,2,12]
*.cpd为描述文件,.ps是可以直接打印的文件
create_caltab (13, 15, 0.0015, [6,2,2,10,10], [7,2,12,2,12], 'dark_on_light', 'calplate.cpd', 'calplate.ps')

* Calibration 01: Code generated by Calibration 01
ImageFiles := []
ImageFiles[0] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161013501.bmp'
ImageFiles[1] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161023237.bmp'
ImageFiles[2] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161038073.bmp'
ImageFiles[3] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161105778.bmp'
ImageFiles[4] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161126403.bmp'
ImageFiles[5] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161137323.bmp'
ImageFiles[6] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161143684.bmp'
ImageFiles[7] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161149840.bmp'
ImageFiles[8] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161157518.bmp'
ImageFiles[9] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161201848.bmp'
ImageFiles[10] := 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161229559.bmp'
TmpCtrl_ReferenceIndex := 0
TmpCtrl_PlateDescription := 'D:/标定/calplate.cpd'
*选择分割模型 0.458是放大倍率(投影模型选择圆心) 单个像元的宽高是4.5μm  图像大小是5120*5120
StartParameters := ['area_scan_telecentric_division',0.458,0,0.0000045,0.0000045,2560,2560,5120,5120]
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 |ImageFiles|-1 by 1
    read_image (Image, ImageFiles[Index])
    find_calib_object (Image, CalibHandle, 0, 0, Index, TmpCtrl_FindCalObjParNames, TmpCtrl_FindCalObjParValues)
endfor
* Calibration 01: Perform the actual calibration
set_calib_data (CalibHandle, 'camera', 0, 'excluded_settings', [])
calibrate_cameras (CalibHandle, TmpCtrl_Errors)
*CameraParameters内参
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
*CameraPose外参
set_origin_pose (CameraPose, 0.0, 0.0, 0.003, CameraPose)
stop ()
* 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, we load the reference image
read_image (Image, 'D:/001-Projects/0003-H21直径测量/4-15/标定/DownLeft/Image_20210415161013501.bmp')
* Calibration 01: Extract plate data from the image
TmpCtrl_PlateDescription := 'D:/标定/calplate.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.
*0.003是标定板的厚度
set_origin_pose (CameraPose, 0.0, 0.0, 0.003, CameraPose)

* Calibration 01: **********************************************************
* Calibration 01: Sample Task: Transform measurements into world coordinates
* Calibration 01: **********************************************************
* Calibration 01: First, obtain the image coordinates of some points of interest
* Calibration 01: lying in the reference plane. Here, we simply take the first
* Calibration 01: two mark center points of the plate
TmpCtrl_ImageRows := [TmpCtrl_MarkRows[0], TmpCtrl_MarkRows[12]]
TmpCtrl_ImageColumns := [TmpCtrl_MarkColumns[0], TmpCtrl_MarkColumns[12]]
* Calibration 01: A line between the two points, just for visualization
gen_contour_polygon_xld (TmpObj_ImageContour, TmpCtrl_ImageRows, TmpCtrl_ImageColumns)
* Calibration 01: Convert image coordinate to world coordinates (using [mm])
* Calibration 01: The Z coordinates will be 0 by definition (on reference plane)
image_points_to_world_plane (CameraParameters, CameraPose, TmpCtrl_ImageRows, TmpCtrl_ImageColumns, 'mm', TmpCtrl_WorldX, TmpCtrl_WorldY)
* Calibration 01: Determine the distance in world coordinate [mm]
distance_pp (TmpCtrl_WorldY[0], TmpCtrl_WorldX[0], TmpCtrl_WorldY[1], TmpCtrl_WorldX[1], TmpCtrl_Distance)
*pixel距离
distance_pp (TmpCtrl_MarkRows[0], TmpCtrl_MarkColumns[0], TmpCtrl_MarkRows[12], TmpCtrl_MarkColumns[12], Distance)
*一个像素多少毫米
cali:=TmpCtrl_Distance/Distance
stop ()

Halcon标定程序,使用标定助手会更简单

8.三角形标定板

z轴指向校准板, x轴指向右侧, y轴指向下方,沿z轴方向观察。

  对应算子:gen_caltab

 

Halcon深度学习标注工具 halcon高精度标定怎么标定的_多项式_06

 9.Halcon的标定步骤

准备校准输入数据 StartCamParam
执行与实际校准 calibrate_cameras
RMSE)
CamParam(内参)
  9.5 校准过程的其他信息:
获得合适的校准板
    拍摄一组合适的图像
    使用哪种失真模型
3D相机模型以及3D点如何转换为图像坐标系

标定过程
1.准备标定板 标定板参数
2.相机内参初始化、标定模型
3.准备标定图像
4.标定内参、外参(外参是用其中一张标定板标定出基于此标定板的位姿)
5.评估标定结果(Error=RMSE)

Halcon深度学习标注工具 halcon高精度标定怎么标定的_建模_04

Halcon深度学习标注工具 halcon高精度标定怎么标定的_Image_05

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.
* 
*初始化标定板参数
*0.016 焦距
*0 Kappa初始值
*0.0000074, 0.0000074  X和Y像素当量
*326, 247 图像中心
*652, 494 图像大小
gen_cam_par_area_scan_division (0.016, 0, 0.0000074, 0.0000074, 326, 247, 652, 494, StartCamPar)
create_calib_data ('calibration_object', 1, 1, CalibDataID)
set_calib_data_cam_param (CalibDataID, 0, [], StartCamPar)
*设置描述信息
set_calib_data_calib_object (CalibDataID, 0, 'caltab_30mm.descr')
*描述一个X和Y方向黑点个数为7、间距为0.0125、标定比例0.5、caltab.descr:生成的标定板文件
* gen_caltab (7, 7, 0.0125, 0.5, 'caltab.descr', 'caltab.ps')
NumImages := 10
* Note, we do not use the image from which the pose of the measurement plane can be derived
for I := 1 to NumImages by 1
    read_image (Image, ImgPath + 'calib_' + I$'02d')
    dev_display (Image)
    *寻找标定板
    find_calib_object (Image, CalibDataID, 0, 0, I, [], [])
    get_calib_data_observ_contours (Caltab, CalibDataID, 'caltab', 0, 0, I)
    dev_set_color ('green')
    dev_display (Caltab)
endfor
*执行标定
*Error:成功校准后,以像素为单位返回优化的反投影的均方根误差(RMSE),如果与0.1相差较大,则校准效果不佳
calibrate_cameras (CalibDataID, Error)
curIndex:=10
*获取内参
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
*获取外参:位姿
*先读取一个标定板,读取基于此标定板下的相机的位姿
*所以只需要一张标定板图像就可以获取相机的外参(基于此标定板的外参),Index是索引为10的标定板图像
get_calib_data (CalibDataID, 'calib_obj_pose', [0,curIndex], 'pose', CameraPose)
disp_3d_coord_system (WindowHandle, CamParam, CameraPose, 0.01)
CalTabThickness:=0.5
*重新设置原点,Z方向偏移0.5
set_origin_pose (CameraPose, 0, 0, CalTabThickness, PoseNewOrigin)
disp_3d_coord_system (WindowHandle, CamParam, PoseNewOrigin, 0.01)
* Write the internal camera parameters to a file
write_cam_par (CamParam, 'camera_parameters.dat')
Message := 'Interior camera parameters have'
Message[1] := 'been written to file'
disp_message (WindowHandle, Message, 'window', 12, 12, 'red', 'false')
* clear_calib_data (CalibDataID)

Halcon示例

10.标定过程中注意事项 

  10.1 标定过程中请勿更改相机设置     位置、光圈、焦距

  10.2 标定板的放置
    标定板的每个部分均应至少被图像覆盖一次。校准板也可以填充整个图像
    倾斜角度, 校准图像集还应包含带有倾斜校准板的图像。大约30-45°的角度沿不同方向倾斜,如果景深而无法实现推荐的角度,则应至少在设置时使板倾斜得尽可能陡。
    图像数量/校准板姿势,六边形的最少6张,至少4张带有倾斜,三角形最少15张。
  10.3 不允许倒置
  10.4 标记直径应至少为20个像素,建议40个像素左右,即一个黑点的直径为40
  10.5 校准板的明暗区域之间的对比度应至少为100灰度值,亮区域不要设置为255,不要过曝(不要超过240)
  10.6 避免过曝,浅色部分的灰度值不超过240
  10.7 校准板应均匀照明,并应避免反射,相同颜色区域灰度值范围不应超过45

11.两种标定模型对比 

  11.1 分割模型使用一个参数来建模径向变形,而多项式模型使用五个参数来建模径向变形和偏心变形

  11.2 校准图像少,或者没有充分覆盖视野, 则分割模型通常会比多项式模型产生更稳定的结果。

  11.3 项式模型的主要优点是它可以更精确地对变形进行建模,并且还对偏心变形进行了建模,缺点是计算慢
  11.4 通常,应使用分割模型进行校准。如果校准的准确性不够高,则可以使用多项式模型

12. 获取相机姿态

  TransX:相机沿坐标系的x轴平移。
:相机沿坐标系的y轴平移。
:相机沿坐标系的z轴平移。
:相机绕坐标系的x轴旋转。
:相机绕坐标系的y轴旋转。
:相机绕坐标系的z轴旋转
:旋转链 ,先旋转那个后旋转那个,其结果不一样

13. image_points_to_world_plane

 

Halcon深度学习标注工具 halcon高精度标定怎么标定的_建模_09

 gen_image_to_world_plane_map

 

Halcon深度学习标注工具 halcon高精度标定怎么标定的_Image_10

14.通用标定模型在精密检测中缺点 

要求多张图片拟合,实际项目中不好操作,特别是现场需要重新标定的时候很麻烦
  14.2 视野中标定板区域不能有遮挡,但是很多项目视野中有夹具遮挡的

主要受标定条件影响是精度不高

     思考:能否用一张图标定畸变、标定大小区域不变的无畸变图?   答案:可以

15.面补:每一个mark点的坐标是真实无畸变的坐标,二次元坐标去找最近的Mark点坐标

  在标定过程中对所有的mark点都走一遍,记录下真实无畸变的Mark坐标,只有Offset才有畸变,前提是Mark点足够密

Halcon深度学习标注工具 halcon高精度标定怎么标定的_Image_11

16.面补的计算步骤

得到标定板点间距pix,计算初始像素当量scale
[row,col][x,y]
  16.3 优化像素当量
  16.4 计算标定板偏移位置和角度
0点对齐
[row,col][x,y]

17. 网格矫正 gen_grid_rectification_map

网格整流的基本原理是,从畸变的图像到对齐图像的映射是根据对齐网格的畸变图像确定的

18.自定义网格

要使用自定义网格,则网格点必须由您自己定义gen_arbitrary_distortion_map、 可用于确定映射

问题: 1、遮挡的网格重新的Map会有黑洞——虚拟填充孔洞数据
、网格点位置不同,裁剪出来的图像大小和起点不同——左上角对其,裁剪图像
19. EasyVision的思路:GenArbitraryDistortionMap  精密测量的自定义网格标定

计算像素当量(参考上面)
0点虚拟构造所有标准点
  19.3 提取角点和标准点坐标对齐
  19.4 使用构建点补充空白对齐提取点
Map
Map图,得到1: 1图像

Halcon深度学习标注工具 halcon高精度标定怎么标定的_Halcon深度学习标注工具_12

 20.至此径向畸变都已解决,唯有透视畸变还未解决。透视畸变是硬件的问题,使用远新镜头可很好消除透视畸变。

  远心镜头,远心度越小越好

Halcon深度学习标注工具 halcon高精度标定怎么标定的_Halcon深度学习标注工具_13