halcon单相机标定和畸变矫正程序

原文链接:https://blog.csdn.net/weixin_43197380/article/details/90438976
一、理论

为什么要进行单相机标定?

广义:畸变矫正和一维和二维测量

畸变矫正:
在几何光学和阴极射线管(CRT)显示中。畸变是对直线投影的一种偏移。简单来说直线投影是场景内的一条直线投影到图片上也保持为一条直线。那畸变简单来说就是一条直线投影到图片上不能保持为一条直线了。这是一种光学畸变(optical aberration)。畸变是一种相差,可能由于摄像机镜头导致,会对拍摄的物体的形状产生变化,影响测量。
我自己对畸变矫正的理解就是,当相机进行标定时,虽然标定板也产生了畸变,但是标定板(圆形)的准确数据我们已经告诉了halcon,比如,圆的排列方式、直径、中心距等。通过加载多张标定板图片,halcon可以通过函数求出镜头里发生畸变的标定板与未发生畸变的标定板之间的映射关系,也就是相机本身的内参(拍摄有畸变)和矫正之后无畸变内参之间的映射关系,将这种映射关系作用到拍摄时发生畸变的物体当中,就完成了畸变校正.。
步骤:
1)通过标定求出相机内参。
2)通过有畸变的内参求出无畸变的内参。用chage_radial_distortion_cam_par()函数完成。
3)求出有畸变的内参和无畸变的内参之间的映射关系。用
gen_radial_distortion_map()函数
4)将上边的映射关系作用到产生畸变的物体当中,完成畸变校正
一维和二维的测量
图片上的尺寸是像素距离,标定后,可以求出像素距离与物理空间距离的换算关系,从而计算出实际的物理尺寸。
狭义:求解相机的内参和外参以及畸变参数,得到二维平面像素坐标和三维世界坐标的关系,从而进行三维重建。

相机内参:相机的固有属性,在进行畸变校正时需要用到相机的内参。
相机外参:物体在经过透镜成像之后,实际上是经过了旋转和平移,而外参就是告诉我们物体成像后经过了那种旋转和平移,相机的外参包括平移矢量和旋转矩阵。
畸变参数:采用理想针孔模型,由于通过针孔的光线少,摄像机曝光太慢,在实际使用中均采用透镜,可以使图像生成迅速,但代价是引入了畸变。有两种畸变对投影图像影响较大: 径向畸变和切向畸变。
相机的畸变和内参是相机本身的固有特性,标定一次即可一直使用。但由于相机本身并非理想的小孔成像模型以及计算误差,采用不同的图片进行标定时得到的结果都有差异。一般重投影误差很小的话,标定结果均可用。

二、标定流程
实现的原理是根据相机的像元尺寸、焦距和标定板的描述文件(.descr)来找到显示的标定板图像上面的标志点,从而确定标定板实际输入的参数(Distance、Diameter等)和这些参数对应的图像像素大小的关系,完成标定。

这里我用的标定板是7*7圆点标定板,型号:HC070—3.75

在这里插入图片描述
标定板数据可参考:
在这里插入图片描述
标定步骤:

1)使用gen_caltab算子生成一个标定文件

标定前需要生成一个.descr的描述文件,也就是世界坐标系与像素坐标系的关系,当我们下一次做别的项目时,只需要调用描述文件,即可完成标定过程。
生成标记文件的算子:gen_caltab (7, x方向的标记数;
7, y方向的标记数;
0.0075, 标记点圆心之间的距离,单位:米;
0.5, 标记点直径与标记点圆心之间距离的比值;
‘C:/Users/Administrator/Desktop/caltab.descr’,标定板的描述文件的保 存路径;
‘caltab.ps’,描述标定板的一些信息,打印标定板时会用到)

2)打开标定助手,加载标定文件,设置相机参数(单个像元宽高(问相机厂商或看手册),相机焦距)
在这里插入图片描述
3)实时获取各个角度、位置的标定板图片(9-16张左右),并选择其中一种图片设置参考位姿,然后标定。
在这里插入图片描述
可以看到相机的参数:
在这里插入图片描述
4)保存相机内、外参,下次使用测量助手直接调用内外参文件。
在这里插入图片描述
在这里插入图片描述
单独说一下如何进行畸变校正,可以接上面的第三步之后:生成标定数据(相机内、外参)代码,从而进行畸变校正
在这里插入图片描述
*相机内参
CameraParameters := [0.0375147,-270.806,8.30152e-006,8.3e-006,647.48,520.914,1280,960]
*相机位姿,即外参(旋转矩阵+平移矢量)
CameraPose := [-0.0091626,-0.00625214,0.700967,2.46926,358.933,179.443,0]
*1、校正径向畸变,得到新的相机内参
change_radial_distortion_cam_par (‘adaptive’, CameraParameters, 0, CamParamOut)
stop ()

  • Image Acquisition 02: Code generated by Image Acquisition 02
    open_framegrabber (‘GigEVision’, 0, 0, 0, 0, 0, 0, ‘default’, -1, ‘default’, -1, ‘false’, ‘default’, ‘CAMERA_QBY_DM’, 0, -1, AcqHandle)
    grab_image_start (AcqHandle, -1)
    while (true)
    grab_image_async (Image, AcqHandle, -1)
    *2、对发生径向畸变的图像生成投影映射,图像的映射数据存在第一个参数中
    gen_radial_distortion_map (Map, CameraParameters, CamParamOut, ‘bilinear’)
    *3、对图像进行畸变校正
    map_image (Image, Map, ImageMapped)
    endwhile
    close_framegrabber (AcqHandle)

注意:相机标定之后,相机焦距、上下位置不能再动,否则需要重新标定。

三、实战:以一元硬币为例

1、 打开测量助手,加载上面得到的相机内、外参
在这里插入图片描述
2、.进行快速测量,可以看到最后测量结果24.1232mm
在这里插入图片描述
3、生成代码后,加入上面的畸变校正,即可完成完整的标定过程
3. Measure 01: Code generated by Measure 01
4. Measure 01: Initialize acquisition
open_framegrabber (‘GigEVision’, 0, 0, 0, 0, 0, 0, ‘default’, -1, ‘default’, -1, ‘false’, ‘default’, ‘CAMERA_QBY_DM’, 0, -1, AcqHandle)
5. Measure 01: Initialize calibration
CameraParameters := [0.0220788,-613.469,6.00309e-006,6e-006,613.491,509.255,1280,960]
CameraPose := [-0.00464111,-0.00298404,0.341764,2.05327,359.502,89.9295,0]
1、校正径向畸变,得到新的相机内参
change_radial_distortion_cam_par (‘adaptive’, CameraParameters, 0, CamParamOut)
stop ()
6. Measure 01: Prepare measurement
AmplitudeThreshold := 40
RoiWidthLen2 := 25
set_system (‘int_zooming’, ‘true’)
7. Measure 01: Coordinates for line Measure 01 [0]
LineRowStart_Measure_01_0 := 495.5
LineColumnStart_Measure_01_0 := 385.5
LineRowEnd_Measure_01_0 := 498.167
LineColumnEnd_Measure_01_0 := 745.5
8. Measure 01: Convert coordinates to rectangle2 type
TmpCtrl_Row := 0.5
(LineRowStart_Measure_01_0+LineRowEnd_Measure_01_0)
TmpCtrl_Column := 0.5*(LineColumnStart_Measure_01_0+LineColumnEnd_Measure_01_0)
TmpCtrl_Dr := LineRowStart_Measure_01_0-LineRowEnd_Measure_01_0
TmpCtrl_Dc := LineColumnEnd_Measure_01_0-LineColumnStart_Measure_01_0
TmpCtrl_Phi := atan2(TmpCtrl_Dr, TmpCtrl_Dc)
TmpCtrl_Len1 := 0.5sqrt(TmpCtrl_DrTmpCtrl_Dr + TmpCtrl_Dc*TmpCtrl_Dc)
TmpCtrl_Len2 := RoiWidthLen2
9. Measure 01: Create measure for line Measure 01 [0]
10. Measure 01: Attention: This assumes all images have the same size!
gen_measure_rectangle2 (TmpCtrl_Row, TmpCtrl_Column, TmpCtrl_Phi, TmpCtrl_Len1, TmpCtrl_Len2, 1280, 960, ‘nearest_neighbor’, MsrHandle_Measure_01_0)
while (true)
* Measure 01: Acquire image
grab_image (Image, AcqHandle)
* Measure 01: Execute measurements
*2、对发生径向畸变的图像生成投影映射,图像的映射数据存在第一个参数中
gen_radial_distortion_map (Map, CameraParameters, CamParamOut, ‘bilinear’)
*3、对图像进行畸变校正
map_image (Image, Map, ImageMapped)
measure_pos (ImageMapped, MsrHandle_Measure_01_0, 19.5, 40, ‘all’, ‘all’, Row_Measure_01_0, Column_Measure_01_0, Amplitude_Measure_01_0, Distance_Measure_01_0)
* Measure 01: Transform to world coordinates
* Measure 01: Calibrate positions for Measure 01 [0]
image_points_to_world_plane (CameraParameters, CameraPose, Row_Measure_01_0, Column_Measure_01_0, 0.001, Column_World_Measure_01_0, Row_World_Measure_01_0)
* Measure 01: Calibrate distances
TmpCtrl_Length := |Row_World_Measure_01_0|
if (TmpCtrl_Length > 0)
tuple_select_range (Row_World_Measure_01_0, 0, TmpCtrl_Length - 2, TmpCtrl_RowFrom)
tuple_select_range (Column_World_Measure_01_0, 0, TmpCtrl_Length - 2, TmpCtrl_ColumnFrom)
tuple_select_range (Row_World_Measure_01_0, 1, TmpCtrl_Length - 1, TmpCtrl_RowTo)
tuple_select_range (Column_World_Measure_01_0, 1, TmpCtrl_Length - 1, TmpCtrl_ColumnTo)
distance_pp (TmpCtrl_RowFrom, TmpCtrl_ColumnFrom, TmpCtrl_RowTo, TmpCtrl_ColumnTo, Distance_World_Measure_01_0)
endif
* Measure 01: Do something with the results
endwhile
11. Measure 01: Clear measure when done
close_measure (MsrHandle_Measure_01_0)

  • 9
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值