学习Halcon(4)-Halcon标定步骤

转自:http://blog.sina.com.cn/s/blog_c45109570102wsbw.html


Halcon标定步骤

1.设置相机内部参数的初始值

StartCamPar := [0.016,0,0.0000074,0.0000074,326,247,652,494]
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)

   *set_calib_data_cam_param:初始化相机内部参数

*参数1.CalibDataID:输入要获取的校正数据模型句柄

*参数2.CameraIdx:输入对应的相机索引

*参数3.CameraType:输入相机类型

*参数4.CameraParam:输入初始化的相机参数

     1.1 相机型号

      (1)面阵

      (2)线阵

     1.2 参数设置(这里只讲面阵相机)

      (1)Division畸变模型

          CameraParam:[Focus, Kappa, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight]

      (2)Polynomial 畸变模型

          CameraParam:[Focus, K1, K2, K3, P1, P2, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight]

          注:当镜头为远心镜头时,Focus=0;

     1.3 畸变类型的选择

         Division畸变模型只适用于进度要求不是很高,标定图片数量较少的情况;Polynomial 畸变模型对镜像

      畸变和切向畸变都校正,精度较高,花费时间长。

     1.4 标定时个参数值的确定技巧

        Focus f:镜头的标称焦距, e.g., 0.016 m.; 对于远心镜头为0.
       κ: 一般去0.0
        Or:
      K1, K2, K3,P1, P2:可全部初始化为0
      Sx: 由CCD\CMOS确定建议取值如下:
           Full image (640*480) Subsampling (320*240)
           1/3"-Chip 0.0000055 m 0.0000110 m
           1/2"-Chip 0.0000086 m 0.0000172 m
           2/3"-Chip 0.0000110 m 0.0000220 m
      Sy: 由CCD\CMOS确定建议取值如下:

          for example:
           Full image (640*480) Subsampling (320*240)
           1/3"-Chip 0.0000055 m 0.0000110 m
           1/2"-Chip 0.0000086 m 0.0000172 m
           2/3"-Chip 0.0000110 m 0.0000220 m

      Cx and Cy: 光心坐标初始值,建议取值如下:
         for example:
          Full image (640*480) Subsampling (320*240)
          Cx 320.0 160.0
          Cy 240.0 120.0
      ImageWidth,ImageHeight:有实际图片大小来初始化该值
       for example:
      Full image (640*480) Subsampling (320*240)
      ImageWidth 640 320
      ImageHeight 480 240

2.标定板初始化

    CaltabName := 'caltab_30mm.descr'//标定板描述文件
    set_calib_data_calib_object (CalibDataID, 0, CaltabName)

3.创建数据模型

create_calib_data ('calibration_object', 1, 1, CalibDataID)

4.获取标定图片

    相机拍摄不同位姿下图片8-15张,拍摄图片时标定板尽量覆盖整个视场(标定板要根据工作距离、视场大小定制);拍摄图片上的圆直径不得小于10个像素

5.加载所有图像,寻找标定板区域,确定圆心,将结果加载到组元中

for I := 1 to NumImages by 1
... acquire image ...
  find_caltab (Image, Caltab, CaltabName, SizeGauss, MarkThresh, MinDiamMarks)/分割和标准化图像中的校准板区域
  find_marks_and_pose (Image, Caltab, CaltabName, StartCamPar, StartThresh, \
      DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks, RCoord, CCoord, StartPose)
  set_calib_data_observ_points (CalibDataID, 0, 0, I, RCoord, CCoord, 'all', StartPose)
endfor

下面将Halcon中提取目标点的大致原理说一下:

首先find_caltab 算子对图像高斯滤波(核大小为SizeGauss),接着阈值分割(与之大小为MarkThresh)将标定板的区域找出来, find_marks_and_pose 算子对区域中的圆进行分割,找到圆的个数,周长,坐标位置等应该和标定板描述文件中的一致,否则会自动调整StartThresh,使得StartThresh按照DeltaThresh步长减小到MinThresh,知道找到准确的圆心。

 

6.有了所有图像中的圆心就可以标定了

    calibrate_cameras (CalibDataID, Errors)

    返回平均投影误差Errors

以下是一个伪代码段.......(明天再续)
* Calibration parameters
CaltabDescr := 'caltab_100mm.descr'
CaltabThickness := 0.0064
NumCameras := 4
NumCalibObjects := 1
NumPoses := 20
CameraType := 'area_scan_polynomial'
StartCamPar := [0.0085, 0.0, 0.0, 0.0, 0.0, 0.0, 6e-6, 6e-6, Width*.5, Height*.5, Width, Height]
* Create camera calibration model and set parameters
create_calib_data ('calibration_object', NumCameras, NumCalibObjects, CalibDataID)
* Set used camara type
set_calib_data_cam_param (CalibDataID, 'all', CameraType, StartCamPar)
* Set used calibration object
set_calib_data_calib_object (CalibDataID, 0, CaltabDescr)

摄像机标定程序:

注意:E:/calibration_image :为标定图像文件路径

      'E:/calibration_description/caltab_123mm.descr:为标定描述文件路径


*程序开始

list_files ('E:/calibration_image', 'files', ImageFiles)

TmpCtrl_AllMarkRows := []

TmpCtrl_AllMarkColumns := []

TmpCtrl_StartPoses := []

TmpCtrl_ReferenceIndex := 0

StartParameters := [0.008,0,5.2e-006,5.2e-006,640,512,1280,1024]

for Index := 0 to |ImageFiles|-1 by 1

    read_image (Image, ImageFiles[Index])

    find_caltab (Image, TmpObj_PlateRegion, 'E:/calibration_description/caltab_123mm.descr', 3, 112, 5)

    find_marks_and_pose (Image, TmpObj_PlateRegion, 'E:/calibration_description/caltab_123mm.descr', StartParameters, 128, 10, 18, 0.9, 15, 100, TmpCtrl_MarkRows, TmpCtrl_MarkColumns, TmpCtrl_EstimatedPose)

    TmpCtrl_AllMarkRows := [TmpCtrl_AllMarkRows, TmpCtrl_MarkRows]

    TmpCtrl_AllMarkColumns := [TmpCtrl_AllMarkColumns, TmpCtrl_MarkColumns]

    TmpCtrl_StartPoses := [TmpCtrl_StartPoses, TmpCtrl_EstimatedPose]

endfor

caltab_points ('E:/calibration_description/caltab_123mm.descr', TmpCtrl_X, TmpCtrl_Y, TmpCtrl_Z)

camera_calibration (TmpCtrl_X, TmpCtrl_Y, TmpCtrl_Z, TmpCtrl_AllMarkRows, TmpCtrl_AllMarkColumns, StartParameters, TmpCtrl_StartPoses, 'all', CameraParameters, TmpCtrl_FinalPoses, TmpCtrl_Errors)

tuple_select_range (TmpCtrl_FinalPoses, 7*TmpCtrl_ReferenceIndex, 7*TmpCtrl_ReferenceIndex + 6, CameraPose)

set_origin_pose (CameraPose, 0.0, 0.0, 0.001, CameraPose)

stop ()

 

一、读入图像,函数如下

list_files ('E:/calibration_image', 'files', ImageFiles)

for Index := 0 to |ImageFiles|-1 by 1

    read_image(Image, ImageFiles[Index])

endfor

注释:'E:/calibration_image':为图像路径,图像文件索引是从0开始的,所以|ImageFiles|(文件数量)减去1

算子:read_image(:Image :FileName):读取名称为FileName的图像Image

二、提取图像Images中标定板上的圆形标志来确定标定板的有效区域,算子如下:

find_caltabImage:Caltab:CalTabDescrFileSizeGaussMarkThreshMinDiamMarks:

    

确定标定板上圆形标志点的二维坐标,并得到摄像机外部参数的初始值,算子如下:

find_marks_and_pose ImageCalTabRegion: :CalTabDescrFile StartCamParamStartThreshDeltaThreshMinThreshAlphaMinContLengthMaxDiamMarks:RcoordCcoordStartPose

   

注释:函数find_caltab在图像中寻找标定板是基于标定板的特征——在一个亮的区域中存在黑色标定点。首先使用高斯滤波器进行图像平滑。参数SizeGauss确定高斯滤波器的尺寸。SizeGauss值越大进行图像平滑的幅度就越大,这在图像噪声比较大时是必要的。在进行图像平滑操作后,为了寻找标定板的位置,我们进行一个阈值分割,可以参考灰度直方图,灰度值范围由最小值MarkThresh到最大值255,因此,MarkThresh必须小于标定板上白色区域的灰度值,并且最好大于图像中其他大范围较亮的区域的灰度值。在阈值分割得到的多个区域中,其中包含孔的数量最符合标定板上标定点数量的凸状区域被选中。为了减少噪声影响,直径小于MinDiamMarks的孔将被除去。标志点的数量可以从标定板描述文件(CalTabDescrFile)中读出。

    函数find_marks_and_pose提取标定板上各个标志点,并精确得到它们在图像坐标系中的坐标。上面我们已经通过函数find_caltab找到了标定板的区域,这时我们首先在输入图像Image的这个区域(CalTabRegion)中应用边缘检测。这个边缘检测通过参数Alpha进行控制。Alpha的值越大 ,边缘检测的灵敏度也就越高,这将使边缘检测时找到更多的细节,但同时对噪声的抑制能力下降。在边缘图像中,提取出封闭的轮廓线。为了更准确的寻找轮廓线,对边缘的振幅进行一个阀值操作。所有振幅高的点(标定点的边界)都被选中。首先,这个阀值设置为StartTh

resh。如果寻找封闭轮廓线或估计位姿失败,这个阀值接连地减DeltaThresh 直到阀值降低到最小值MinThresh

    闭合的轮廓线的数量必须与标定板描述文件(CalTabDescrFile)中描述的标志点的数量一致,并且这些闭合轮廓线的形状必须是椭圆状的。长度比MinContLength 短的轮廓线或者轮廓线形成区域的直径大MaxDiamMarks(如标定板的外框),这些轮廓线将被忽略抛弃。

 

三、保存坐标值

 

TmpCtrl_AllMarkRows := []

TmpCtrl_AllMarkColumns := []

TmpCtrl_StartPoses := []

 

TmpCtrl_AllMarkRows := [TmpCtrl_AllMarkRows, TmpCtrl_MarkRows]

TmpCtrl_AllMarkColumns := [TmpCtrl_AllMarkColumns, TmpCtrl_MarkColumns]

TmpCtrl_StartPoses := [TmpCtrl_StartPoses, TmpCtrl_EstimatedPose]


注释:标定点的在图像坐标系中的坐标存储 在两个数组中,第一个数组存储所有点的行坐标,第二个数组存储所有点的列坐标,且要保证两个数组的值一一对应。这些数组长度取决于标定板上标定点的个数以及拍摄的标定图像的数量。它们的存储顺序是 按照图像顺序排列的,也就是说刚开始的m个值存储的是第一幅图像中m个标定点的坐标值,这个顺序和函数caltab_points的数组X,Y,Z中的存储顺序是一致的。

 

四、摄像机标定输入参数

StartParameters := [0.008,0,5.2e-006,5.2e-006,640,512,1280,1024]

    初始值摄像机标定是一个非常复杂的非线性优化的问题,因此就需要为摄像机的参数提供尽量精确的初始值。摄像机内部参数的初始值主要由CCD传感器和镜头的说明书确定。面阵摄像机的内参初始值可以输入一个

数 组 [f,k,Sx,Sy,Cx,Cy,NumColumns,NumRows]也就是说 ,不仅要提供摄像机的初始内参,还要提供图像的宽(NumColumns)和高(NumRows)

  

五、确定摄像机的内参,误差分析,算子如下

camera_calibration: :NXNYNZNrowNcolStartCamParamNstartPoseEstimateParams:CamParamNfinalPoseErrors

函数如下:

caltab_points ('E:/calibration_description/caltab_123mm.descr', TmpCtrl_X, TmpCtrl_Y, TmpCtrl_Z)

camera_calibration(TmpCtrl_X,TmpCtrl_Y,TmpCtrl_Z,TmpCtrl_AllMarkRows,TmpCtrl_AllMarkColumns,StartParameters,TmpCtrl_StartPoses, 'all',CameraParameters, TmpCtrl_FinalPoses, TmpCtrl_Errors)

    

    在给定了摄像机的内外参数的初始值之后,已知三维位置的标定点可以转换到摄像机坐标系中。然后,寻求一组摄像机的参数可以使通过计算投影到图像上的标定点坐标和直接从图像中提取出的标定点的坐标的距离最小。这个最小化的过程将返回相当精确的摄像机参数。然而,为了获得最高精度的摄像机参数,需要拍摄标定板的多幅图像,在拍摄时,标定板被放置在图像的不同位置并且旋转的角度也不同,以致于使用外部方位的所有自由度。如果拍摄一幅包含标定板的图像,最优化的参数包括摄像机的内参和一组外参。此时,最优化的目标是确定所有这些参数能够满足每幅图中通过投影计算得到的点坐标和图像中直接提取的坐标值距离最小。在HALCON ,使用camera_calibration 函数就是实现这个功能。

 

六、选择某幅图像作为参考位姿,确定摄像机外参

TmpCtrl_ReferenceIndex := 0

注释:TmpCtrl_ReferenceIndex:为将要设置为参考位姿势的图像。0代表第一张。1代表第二张。以此类推。

tuple_select_range (TmpCtrl_FinalPoses, 7*TmpCtrl_ReferenceIndex, 7*TmpCtrl_ReferenceIndex + 6, CameraPose)

set_origin_pose (CameraPose, 0.0, 0.0, 0.001, CameraPose)

注释:tuple_select_range:进行数组选择。

      set_origin_pose:计算摄像机外部参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值