手眼标定之摄像机内参和外参

1.图像坐标系,摄像机坐标系,世界坐标系

勇哥说明一下:

图像坐标系就是相机感觉芯片上的坐标系。

摄像机坐标系就是镜头表面上的坐标系。

世界坐标系就是摄像机看到内容的坐标系。

图片1.png

2. 摄像机内部参数:[Focus,Kappa,SxSy,CxCy,WhithHeight]

面阵相机(division模式)

Focus(焦距):远焦镜头镜头焦距的长度

Kappa:扭曲系数(畸变)

SxSy:像素大小

CxCy图像中心点坐标

WhithHeight:图像的宽高

面阵相机(polynomia模式):

Focus(焦距):远焦镜头镜头焦距的长度

K1, K2, K3, P1,P2:扭曲系数

SxSy:像素大小

CxCy图像中心点坐标

WhithHeight:图像的宽高

Baler相机资料介绍

https://www.baslerweb.com/cn/products/cameras/area-scan-cameras/ace/aca640-90gc/

image.png

image.png

2. 摄像机外部参数:世界坐标系下摄像机的位姿,描述摄像机坐标系转换为世界坐标系的转换关系,这个转换关系包括了旋转和平移信息,又成为位姿,位姿可以表示为:[X轴平移,Y轴平移,Z轴平移,X轴旋转,Y轴旋转,Z轴旋转],摄像机外部参数通过摄像机拍摄标定板获取的;


注意:外部参数跟摄像机的位姿说的是同一个东西。


(1)获取外参的例子

image.png

dev_close_window ()
dev_update_off ()
dev_set_draw ('margin')
read_image (Image, 'scratch/scratch_perspective')
get_image_pointer1 (Image, Pointer, Type, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle1)
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
dev_display (Image)
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
* 
* step: calibrate the camera
* 
CaltabName := 'caltab_30mm.descr'
* make sure that the file 'CaltabDescrName' is in the current directory,
* the HALCONROOT/calib directory, or use an absolut path
*StartCamPar := [0.012,0,0.0000055,0.0000055,Width/2,Height/2,Width,Height]
StartCamPar := [0.0184898,-548.002,8.33409e-006,8.3e-006,275.291,255.374,640,480]
create_calib_data ('calibration_object', 1, 1, CalibDataID)
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
NumImages := 12
for i := 1 to NumImages by 1
    read_image (Image, 'scratch/scratch_calib_'+i$'02d')
    dev_display (Image)
    find_caltab (Image, Caltab, CaltabName, 3, 112, 5)
    dev_set_color ('green')
    dev_display (Caltab)
    find_marks_and_pose (Image, Caltab, CaltabName, StartCamPar, 128, 10, 18, 0.9, 15, 100, RCoord, CCoord, StartPose)
    dev_set_color ('red')
    disp_circle (WindowHandle1, RCoord, CCoord, gen_tuple_const(|RCoord|,2.5))
    dev_set_part (0, 0, Height-1, Width-1)
    set_calib_data_observ_points (CalibDataID, 0, 0, i, RCoord, CCoord, 'all', StartPose)
endfor
dev_update_time ('on')
disp_continue_message (WindowHandle1, 'black', 'true')
stop ()
calibrate_cameras (CalibDataID, Error)
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
get_calib_data (CalibDataID, 'calib_obj_pose', [0,1], 'pose', PoseCalib)

write_pose (PoseCalib, 'Externalcamera_parameters.dat')


(2)获取内参例子一

* This example compares the calibration results obtained
* for the camera models 'division' and 'polynomial'.
* A sequence of calibration images was acquired with a camera
* that has a lens with strong radial distortions. Multiple
* calibrations of the camera are performed by appending a new
* image from the sequence to the calibration data for each
* successive calibration turn.
* 
* 
dev_update_off ()
dev_close_window ()
* 
read_image (Image, 'calib/calib_distorted_01')
get_image_size (Image, Width, Height)
dev_open_window_fit_image (Image, 0, 0, 400, 400, WindowHandle)
get_window_extents (WindowHandle, MainR, MainC, MainWidth, MainHeight)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
dev_set_line_width (1)
dev_set_draw ('margin')
* 
StartCamParPoly := [0.005,0,0,0,0,0,9.3e-6,9.3e-6,Width * 0.5,Height * 0.5,Width,Height]
StartCamParDiv := [0.005,0,9.3e-6,9.3e-6,Width * 0.5,Height * 0.5,Width,Height]
* 
dev_set_window (WindowHandle)
dev_display (Image)
disp_message (WindowHandle, 'Determine the marks and pose of\nthe calibration plate for the camera\nmodels \'division\' and \'polynomial\'', 'window', 12, 12, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
create_calib_data ('calibration_object', 1, 1, DivCalibDataID)
set_calib_data_cam_param (DivCalibDataID, 0, 'area_scan_division', StartCamParDiv)
set_calib_data_calib_object (DivCalibDataID, 0, 'caltab_100mm.descr')
* 
create_calib_data ('calibration_object', 1, 1, PolyCalibDataID)
set_calib_data_cam_param (PolyCalibDataID, 0, 'area_scan_polynomial', StartCamParPoly)
set_calib_data_calib_object (PolyCalibDataID, 0, 'caltab_100mm.descr')
* 
* Determine marks and pose of the calibration plate to perform the calibration
* set_calib_model_params_specific (DivCalibDataID, 'camera', 0, 'excluded_params', 'pose')
* set_calib_model_params_specific (PolyCalibDataID, 'camera', 0, 'excluded_params', 'pose')
StatFDiv := []
StatKappaDiv := []
StatSxDiv := []
StatCyDiv := []
StatFPoly := []
StatK1Poly := []
StatSxPoly := []
StatCyPoly := []
NumImgs := 69
NumImgsSkip := 13
ImgsBaseFN := 'calib/calib_distorted_'
* Choose, in which order the calibration images
* shall be used. You can select between an ascending
* order:
Indices := [1:NumImgs]
* and a random order, which is selected by
* uncommenting the following line:
* Indices := [34,16,52,29,63,65,45,14,10,3,38,18,49,36,59,6,21,43,50,47,1,11,26,44,13,28,66,68,48,54,40,67,2,55,30,17,69,64,56,60,23,5,58,27,20,57,9,31,25,46,4,53,61,39,37,32,7,15,22,41,19,51,12,42,62,33,8,35,24]
* 
* If you use the images in ascending order, the calibration
* first uses the images with calibration plates that are not
* tilted and then the images with the tilted calibration plates.
* Within the graphs you see that the standard deviation
* is significantly improved after adding the tilted
* calibration plates.
* If you use the images in random order, the standard deviation
* is also improved, but at an earlier stage of the calibration.
* Note that the random sequence has been created with the
* following line and has been hard coded to get repeatable
* results:
* Indices := sort_index(rand(NumImgs)) + 1
* 
MaxDF := 0
MaxDSx := 0
MaxDSy := 0
for K := 1 to NumImgs by 1
    I := Indices[K - 1]
    read_image (Image, ImgsBaseFN + I$'02')
    find_calib_object (Image, DivCalibDataID, 0, 0, K, [], [])
    find_calib_object (Image, PolyCalibDataID, 0, 0, K, [], [])
    * 
    * 
    * 
    dev_display (Image)
    dev_set_color ('green')
    get_calib_data_observ_points (DivCalibDataID, 0, 0, K, Row, Column, Index, StartPose)
    disp_caltab (WindowHandle, 'caltab_100mm.descr', StartCamParDiv, StartPose, 1)
    * 
    dev_set_color ('magenta')
    get_calib_data_observ_points (PolyCalibDataID, 0, 0, K, Row, Column, Index, StartPose)
    disp_caltab (WindowHandle, 'caltab_100mm.descr', StartCamParPoly, StartPose, 1)
    disp_message (WindowHandle, 'Extracting calibration features', 'window', -1, -1, 'black', 'true')
    * 
    * Perform calibration
    * (if a minimum number of images has been processed)
    if (K > NumImgsSkip)
        calibrate_cameras (DivCalibDataID, ErrorsDiv)
        calibrate_cameras (PolyCalibDataID, ErrorsPoly)
        get_calib_data (DivCalibDataID, 'camera', 0, 'params', CamParamDiv)
        get_calib_data (PolyCalibDataID, 'camera', 0, 'params', CamParamPoly)
        get_calib_data (DivCalibDataID, 'camera', 0, 'params_deviations', DeviationsDiv)
        get_calib_data (PolyCalibDataID, 'camera', 0, 'params_deviations', DeviationsPoly)
        * 
        StatFDiv := [StatFDiv,CamParamDiv[0],DeviationsDiv[0]]
        StatKappaDiv := [StatKappaDiv,CamParamDiv[1],DeviationsDiv[1]]
        StatSxDiv := [StatSxDiv,CamParamDiv[2],DeviationsDiv[2]]
        StatCyDiv := [StatCyDiv,CamParamDiv[5],DeviationsDiv[5]]
        StatFPoly := [StatFPoly,CamParamPoly[0],DeviationsPoly[0]]
        StatK1Poly := [StatK1Poly,CamParamPoly[1],DeviationsPoly[1]]
        StatSxPoly := [StatSxPoly,CamParamPoly[6],DeviationsPoly[6]]
        StatCyPoly := [StatCyPoly,CamParamPoly[9],DeviationsPoly[9]]
        * 
        MaxDF := max([MaxDF,DeviationsDiv[0],DeviationsPoly[0]])
        MaxDSx := max([MaxDSx,DeviationsDiv[2],DeviationsPoly[6]])
        MaxDSy := max([MaxDSy,DeviationsDiv[3],DeviationsPoly[7]])
    endif
endfor
disp_message (WindowHandle, ['Extraction completed!','Proceed to the inspection of the','standard deviations'], 'window', -1, -1, 'black', 'true')
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
* 
clear_calib_data (PolyCalibDataID)
clear_calib_data (DivCalibDataID)
* 
WinWidth := 600
WinHeight := 300
dev_open_window (0, MainWidth + 13, WinWidth, WinHeight, 'black', WindowHandleDiv)
dev_open_window (MainHeight + 62, 0, MainWidth, 2 * WinHeight - MainHeight, 'black', WindowlHandleCmp)
dev_open_window (WinHeight + 62, MainWidth + 13, WinWidth, WinHeight, 'black', WindowHandlePoly)
* 
* Inspect focal length
ImgNumRange := [NumImgsSkip + 1,NumImgs]
plot_stats_graph (StatFDiv, WindowHandleDiv, 'Focal length - Division', [], true, ['Focal length','Std. deviation'], ImgNumRange, PlotStartC, PlotEndC)
plot_stats_graph (StatFPoly, WindowHandlePoly, 'Focal length - Polynomial', [], true, ['Focal length','Std. deviation'], ImgNumRange, PlotStartC, PlotEndC)
plot_compare_graph (StatFPoly, StatFDiv, WindowlHandleCmp, ['Standard deviation - Focal length','(comparison)'], ['polynomial','divisional'], ImgNumRange)
inspect_images (WindowHandle, WindowHandleDiv, NumImgs, NumImgsSkip, PlotStartC, PlotEndC, Indices, ImgsBaseFN, 'Focal length - Division')
wait_seconds (.5)
* Inspect radial distortion parameters (Kappa and K1)
plot_stats_graph (StatKappaDiv, WindowHandleDiv, 'Kappa - Division', [], false, ['kappa','std. deviation'], ImgNumRange, PlotStartC, PlotEndC)
plot_stats_graph (StatK1Poly, WindowHandlePoly, 'K1 - Polynomial', [], false, ['K1','std. deviation'], ImgNumRange, PlotStartC, PlotEndC)
dev_set_window (WindowlHandleCmp)
dev_clear_window ()
disp_message (WindowlHandleCmp, '[comparison not available]', 'window', 130, 120, 'white', 'false')
inspect_images (WindowHandle, WindowHandleDiv, NumImgs, NumImgsSkip, PlotStartC, PlotEndC, Indices, ImgsBaseFN, 'Kappa - Division')
wait_seconds (.5)
* Inspect Sx
plot_stats_graph (StatSxDiv, WindowHandleDiv, 'Sx - Division', [], true, ['sx','std. deviation'], ImgNumRange, PlotStartC, PlotEndC)
plot_stats_graph (StatSxPoly, WindowHandlePoly, 'Sx - Polynomial', [], true, ['sx','std. deviation'], ImgNumRange, PlotStartC, PlotEndC)
plot_compare_graph (StatSxPoly, StatSxDiv, WindowlHandleCmp, ['Standard deviation - Sx','(comparison)'], ['polynomial','divisional'], ImgNumRange)
inspect_images (WindowHandle, WindowHandleDiv, NumImgs, NumImgsSkip, PlotStartC, PlotEndC, Indices, ImgsBaseFN, 'Sx - Division')
wait_seconds (.5)
* Inspect Cy
plot_stats_graph (StatCyDiv, WindowHandleDiv, 'Cy - Division', [], true, ['sy','std. deviation'], ImgNumRange, PlotStartC, PlotEndC)
plot_stats_graph (StatCyPoly, WindowHandlePoly, 'Cy - Polynomial', [], true, ['sy','std. deviation'], ImgNumRange, PlotStartC, PlotEndC)
plot_compare_graph (StatCyPoly, StatCyDiv, WindowlHandleCmp, ['Standard deviation - Cy','(comparison)'], ['polynomial','divisional'], ImgNumRange)
inspect_images (WindowHandle, WindowHandleDiv, NumImgs, NumImgsSkip, PlotStartC, PlotEndC, Indices, ImgsBaseFN, 'Cy - Division')
disp_message (WindowHandle, 'End of program', 'window', 12, 12, 'black', 'true')
gray_window (WindowHandleDiv)
gray_window (WindowHandlePoly)
gray_window (WindowlHandleCmp)


(3)获取内参二

image.png

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)
OpSystem := environment('OS')
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')
* 
* Calibrate the camera.
* 
StartCamPar := [0.016,0,0.0000074,0.0000074,326,247,652,494]
create_calib_data ('calibration_object', 1, 1, CalibDataID)
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', StartCamPar)
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
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
calibrate_cameras (CalibDataID, Error)
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
* 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)


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2025年4月    »
123456
78910111213
14151617181920
21222324252627
282930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864