Halcon学习笔记:Halcon标定步骤-3d_coordinates.hdev示例
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)
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 (640480) Subsampling (320240)
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 (640480) Subsampling (320240)
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 (640480) Subsampling (320240)
Cx 320.0 160.0
Cy 240.0 120.0 -
ImageWidth,ImageHeight:有實際圖片大小來初始化該值
for example:
Full image (640480) Subsampling (320240)
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)// 從標定數據模型中獲取基于點的觀測數據(49個點的坐標,索引,粗略估計被測校準物體相對于被測相機的姿態) 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.有了所有圖像中的圓心就可以標定了
* 返回平均投影誤差Errorscalibrate_cameras (CalibDataID, Errors)7.示例:3d_coordinates 測量世界坐標中的傾斜物體
本地函數: get_measure_positions
(Image : PlateRegion : CalibDataID, PoseIndex : Distance, Phi, RowCenter, ColumnCenter)
主函數 main
* * 1.初始化程序 dev_close_window () dev_open_window (0, 0, 768, 576, 'black', WindowHandle) dev_update_off () dev_set_draw ('margin') dev_set_line_width (3) set_display_font (WindowHandle, 14, 'mono', 'true', 'false') * * 2.標定相機 * 為一個區域掃描相機生成一個相機參數數組,該參數數組設置為面陣相機的Division畸變模型模板: * CameraParam:[Focus, Kappa, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight] CalTabDescrFile := 'caltab_big.descr' gen_cam_par_area_scan_division (0.008, 0, 0.0000086, 0.0000086, 384, 288, 768, 576, StartCamPar) * 創建haclon 標定數據模型('calibration_object'為標定設置類型,CalibDataID 數據模型的句柄 ) * 在標定數據模型中設置相機的類型和初始參數(StartCamPar 為初始參數) * 定義在標定模型中的標定對象(CalTabDescrFile 描述文件名) create_calib_data ('calibration_object', 1, 1, CalibDataID) set_calib_data_cam_param (CalibDataID, 0, [], StartCamPar) set_calib_data_calib_object (CalibDataID, 0, CalTabDescrFile) * * 3.采圖 NumImages := 10 for I := 1 to NumImages by 1read_image (Image, 'calib/calib-3d-coord-' + I$'02d')dev_display (Image)Message := 'Find calibration plate in\nall calibration images (' + I + '/' + NumImages + ')'disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true') ***** 找到halcon 標定板,并在標定數據模型中設置提取的點和輪廓 ******find_calib_object (Image, CalibDataID, 0, 0, I - 1, [], [])* 從標定數據模型中查詢存儲或計算的數據(O號相機數據,項目類型-'init_params'表示初始相機內部參數,StartCamPar 初始化數據)* 從標定數據模型中獲取基于點的觀測數據(49個點的坐標,索引,粗略估計“被測校準物體(標定板)”相對于被測相機的姿態)* 從校準數據模型中獲取基于輪廓的觀測數據(標定板輪廓,所觀察到的校準對象位姿的索引)get_calib_data (CalibDataID, 'camera', 0, 'init_params', StartCamPar)get_calib_data_observ_points (CalibDataID, 0, 0, I - 1, Row, Column, Index, Pose)get_calib_data_observ_contours (Contours, CalibDataID, 'caltab', 0, 0, I - 1)* 標出圓形坐標點-畫叉gen_cross_contour_xld (Cross, Row, Column, 6, 0.785398)dev_set_color ('green')dev_display (Contours)dev_set_color ('yellow')dev_display (Cross) endfor disp_continue_message (WindowHandle, 'black', 'true') stop () * *** 通過同時最小化處理 確定所有相機參數(Error:優化的反投影均方根誤差(RMSE))*** calibrate_cameras (CalibDataID, Error) * 從標定數據模型中查詢存儲或計算的數據(0號相機的數據,項目類型-'params'表示優化后的相機內部參數,CamParam 輸出數據) get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam) * ******** 4.Perform measurements 驗證(1D 尺寸測量) ******** * for I := 1 to NumImages by 1read_image (Image, 'calib/calib-3d-coord-' + I$'02d')* ** 一、現在,測量標定板的黑邊的長度:* I-索引號; PlateRegion-標定板區域;Distance-垂直邊框的距離;* Phi-公垂線的方向;RowCenter/ColumnCenter-table中心點坐標;* 生成一個矩形的XLD輪廓。get_measure_positions (Image, PlateRegion, CalibDataID, I, Distance, Phi, RowCenter, ColumnCenter)gen_rectangle2_contour_xld (Rectangle, RowCenter, ColumnCenter, Phi, Distance * 0.52, 8)*** 二、一維尺寸測量:* 1.設置測量區域:準備提取垂直于矩形的直邊(MeasureHandle——測量矩形對象句柄)* 2.找尋你設定檢測區域內的邊緣:提取垂直于矩形或環形弧的直邊* (Amplitude-指定的是一個縮放,通過邊界的坐標加上縮放的計算,可以計算出確切的距離就存在Distance里)* 3.刪除一個測量對象gen_measure_rectangle2 (RowCenter, ColumnCenter, Phi, Distance * 0.52, 8, 768, 576, 'nearest_neighbor', MeasureHandle) measure_pos (Image, MeasureHandle, 1, 40, 'all', 'all', RowEdge, ColumnEdge, Amplitude, Distance1)close_measure (MeasureHandle)Rows := [RowEdge[0],RowEdge[|RowEdge| - 1]]Columns := [ColumnEdge[0],ColumnEdge[|RowEdge| - 1]]gen_cross_contour_xld (Cross, Rows, Columns, 16, Phi)*** 三、轉換坐標:(相機坐標系->世界坐標系的轉化)* 查詢標定數據(所有標定對象的總體姿態或特定的標定對象姿態的數據 * 通過選擇DataName中的以下參數,您可以查詢在由calibrate_cameras執行標定期間,* 哪些標定對象位姿參數得到了(或已經得到了)優化)* 'pose'——優化標定對象位姿,相對于當前參考相機get_calib_data (CalibDataID, 'calib_obj_pose', [0,I - 1], 'pose', Pose)* 將兩個邊界點轉換為世界坐標系* 計算兩點的距離image_points_to_world_plane (CamParam, Pose, Rows, Columns, 'm', SX, SY)distance_pp (SY[0], SX[0], SY[1], SX[1], Width)* ** 四、顯示寬度測量結果dev_display (Image)dev_set_color ('white')dev_set_line_width (3)dev_display (Rectangle)dev_set_color ('green')dev_set_draw ('fill')dev_set_line_width (2)dev_display (Cross)dev_set_draw ('margin')* 寬度顯示disp_message (WindowHandle, 'Width = ' + (Width * 100)$'8.3f' + 'cm', 'window', 12, 12, 'black', 'true')disp_continue_message (WindowHandle, 'black', 'true')stop ()* ** 五、現在,測量標定標記(標定板上的標定點)的大小 * 提取圖像中的橢圓erosion_circle (PlateRegion, ROI, 17.5)reduce_domain (Image, ROI, ImageReduced)*使用Deriche, Lanser, Shen或Canny過濾器提取亞像素精確的邊緣edges_sub_pix (ImageReduced, Edges, 'canny', 1, 20, 60)select_contours_xld (Edges, SelectedEdges, 'contour_length', 20, 99999999, -0.5, 0.5)* Fit ellipses to extracted edges 將橢圓匹配到提取的邊緣* 由橢圓或橢圓弧構成的近似的XLD輪廓(輸出橢圓參數)fit_ellipse_contour_xld (SelectedEdges, 'fitzgibbon', -1, 2, 0, 200, 3, 2, Row, Column, Phi, Radius1, Radius2, StartPhi, EndPhi, PointOrder)MeanRadius1 := mean(Radius1)MeanRadius2 := mean(Radius2)DevRadius1 := deviation(Radius1)DevRadius2 := deviation(Radius2)** 將橢圓轉換為世界坐標,它們應該是圓,并將圓從米轉換為毫米,這樣我們就可以看到它們。contour_to_world_plane_xld (SelectedEdges, WorldCircles, CamParam, Pose, 'mm')* Fit ellipses to the circles in world coordinates 在世界坐標中將橢圓與圓匹配fit_ellipse_contour_xld (WorldCircles, 'fitzgibbon', -1, 2, 0, 200, 3, 2, Row, Column, Phi, RadiusW1, RadiusW2, StartPhi, EndPhi, PointOrder)MeanRadiusW1 := mean(RadiusW1)MeanRadiusW2 := mean(RadiusW2)DevRadiusW1 := deviation(RadiusW1)DevRadiusW2 := deviation(RadiusW2)* * 顯示橢圓測量結果dev_display (Image)dev_set_color ('yellow')dev_set_line_width (3)dev_display (SelectedEdges)Message := 'Measured dimensions of the ellipses'Message[0] := ' Mean Radius1; Mean Radius2; (Standard deviations [%])'Message[1] := 'Image coordinates: ' + MeanRadius1$'5.2f' + 'px; ' + MeanRadius2$'5.2f' + 'px (' + (DevRadius1 / MeanRadius1 * 100)$'4.2f' + ', ' + (DevRadius2 / MeanRadius2 * 100)$'4.2f' + ')'Message[2] := 'World coordinates: ' + (MeanRadiusW1 / 10)$'5.2f' + 'cm; ' + (MeanRadiusW2 / 10)$'5.2f' + 'cm (' + (DevRadiusW1 / MeanRadiusW1 * 100)$'4.2f' + ', ' + (DevRadiusW2 / MeanRadiusW2 * 100)$'4.2f' + ')'disp_message (WindowHandle, Message, 'window', 12, 12, 'black', 'true')if (I < 10)disp_continue_message (WindowHandle, 'black', 'true')stop ()endif endfor clear_calib_data (CalibDataID)結果:
1.read_image
2.find_calib_object 填充標定數據模型
3.calibrate_cameras (CalibDataID, Error) 矯正所有相機參數
4.驗證相機標定結果:通過 1D mesuring
- 1)get_measure_positions 找到需要測量區域的位姿(位置和方向)
- 2)gen_measure_rectangle2 設置測量區域
- 3)measure_pos 找尋你設定檢測區域內的邊緣:提取垂直于矩形的所有直邊
- 4)image_points_to_world_plane 轉換坐標:(相機坐標系->世界坐標系的轉化)
5)測量標記點的大小: - Radius1 ,Radius2 橢圓長短 半徑
8.參考算子介紹
- HALCON 1D Measure 算子初識
- 一維測量中measure_pos和measure_pairs算子
總結
以上是生活随笔為你收集整理的Halcon学习笔记:Halcon标定步骤-3d_coordinates.hdev示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QT学习笔记(四):Qt5+MSVC编译
- 下一篇: Halcon算子学习:surface_n