深入理解halcon相機標定

目錄

  • 相機標定簡介
  • 深度說明
      • 1、相機標定參數介紹
      • 2、標定板詳細介紹
          • 問題1:halcon是否只能使用halcon專用的標定板?
          • 問題2:halcon標定板如何生成?
          • 問題3:halcon標定板如何擺放,拍照數量有無限制?
  • 標定步驟
      • 1、設置相機內部初始值
          • 使用set_calib_data_cam_param 算子設置相機內部初始值
          • 畸變類型選擇與參數確定技巧
      • 2、標定板初始化
      • 3、創建標定數據模型
      • 4、獲取標定圖片
      • 5、使用圖像進行相機內參標定,得到結果
      • 6、使用圖像進行相機外參標定,得到結果
  • Halcon相機標定代碼與解析

  • 博主寫作不容易,還是需要您鼓勵
  • 萬水千山總是情 , 先點個贊行不行

最近有的人私信我,說看了我的《HALCON相機標定相機內參相機外參》https://blog.csdn.net/cashmood/article/details/100089295一文后,還是有不懂的地方,這里給大家做一個深入的教程。

相機標定簡介

首先鏡頭有畸變,也就是說照出的圖像與實際不符產生了形變。即使工業鏡頭也是有千分之幾的畸變率的。
上個圖告訴大家畸變
在這里插入圖片描述
這個圖里,第一個圖就是我們相機下的真實的形狀,后邊兩個就是照出來有畸變的圖片。

其次鏡頭與相機無論你的機械結構精度多高,也不容易或者說沒辦法將相機安裝的特別正,那相機安裝不正也是會導致誤差的。大家想知道具體數學模型的話可以搜一下相機標定的理論方面的知識,我側重怎么做。
標定就是把上述兩個東西轉化成正常的。
無論是在圖像測量或者機器視覺應用中,相機參數的標定都是非常關鍵的環節,其標定結果的精度及算法的穩定性直接影響相機工作產生結果的準確性。

深度說明

1、相機標定參數介紹

在這里插入圖片描述
內參:確定攝像機從三維空間到二維空間的投影關系。
針孔相機(FA鏡頭相機)模型為6個參數(f,kSx,Sy,Cx,Cy);遠心鏡頭相機模型為5個參數(f,Sx,Sy,Cx,Cy);線陣相機為11個參數(f,k,Sx,Sy,Cx,Cy,Width,Highth,Vx,Vy,Vz)。
其中:
f為焦距;
k表示徑向畸變量級。如果k為負值,畸變為桶形畸變,如果為正值,那么畸變為枕形畸變。
Sx,Sy是縮放比例因子。對于針孔攝像機(FA鏡頭)表示圖像傳感器水平和垂直方向上相鄰像素之間的距離,初始值與真實值越接近計算速度越快。對于遠心攝像機模型,表示像素在世界坐標系中的尺寸。
Cx,Cy是圖像的主點,對于針孔相機,這個點是投影中心在成像平面上的垂直投影,同時也是徑向畸變的中心。對于遠心攝像機模型,只表示畸變的中心。
Vx,Vy,Vz:線陣相機必須與被拍攝物體之間有相對移動才能拍攝到一幅有用的圖像。這是運動向量。Sx,Sy對于線陣相機是相鄰像元的水平和垂直距離。

2、標定板詳細介紹

問題1:halcon是否只能使用halcon專用的標定板?

halcon提供了簡便、精準的標定算子與標定助手,這在實際使用中極大地方便了使用者
在halcon中有兩種標定方式:
halcon自帶例程中出現的,用halcon定義的標定板,如下圖:
在這里插入圖片描述
用戶自定義標定板,用戶可以制作任何形狀、形式的標定板,如下圖:
在這里插入圖片描述
所以,halcon并非只能使用專用標定板,也可以使用自定義標定板就可以進行標定。

問題2:halcon標定板如何生成?

使用gen_caltab算子來制作一個標定板
gen_caltab( : : XNum, YNum, MarkDist, DiameterRatio, CalPlateDescr, CalPlatePSFile : )
XNum:每行黑色標志圓點的數量
YNum:每列黑色標志圓點的數量
MarkDist:兩個就近黑色圓點中心之間的距離,單位是m
DiameterRatio:黑色圓點直徑與兩圓點中心距離的比值
CalPlateDescr:標定板描述文件的文件路徑
CalPlatePSFile :標定板圖像文件路徑,可以用ps打開
示例:
gen_caltab( 7, 7, 0.1, 0.5, ‘caltab.descr’, ‘caltab.ps’)
大家可以自己思考一下每個參數的含義
行數:7
列數:7
黑色圓點半徑:0.05m
圓點中心間距:0.1m

問題3:halcon標定板如何擺放,拍照數量有無限制?

并非拍照標定數量越多,越能取得高的精度,halcon建議拍攝數量在9-16張,并且對擺放位置做了建議。標定板占標定視野的1/3-1/4,對于標定板成像灰度值應大于128,以便順利提取。如下圖所示:
在這里插入圖片描述

標定步驟

注意只介紹面陣相機,其他的相機和面陣道理想同。

1、設置相機內部初始值

使用set_calib_data_cam_param 算子設置相機內部初始值

set_calib_data_cam_param( : : CalibDataID, CameraIdx, CameraType, CameraParam : )
CalibDataID:標定句柄
CameraIdx:相機序號
CameraType:相機模型種類;面陣相機Division畸變模型’area_scan_division’;polynomial畸變模型’area_scan_polynomial’。。。。。。
CameraParam :與相機模型種類相對應的參數;面陣相機Division畸變模型’area_scan_division’([Focus, Kappa, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight]);polynomial畸變模型’area_scan_polynomial’([Focus, K1, K2, K3, P1, P2, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight])。。。。。。

相機模型種類與相機參數對應表:
在這里插入圖片描述

畸變類型選擇與參數確定技巧

畸變模型選擇
division畸變模型只適用于精度不高的,標定圖片數量較少的情況:
polynomial畸變模型對徑向畸變、切向畸變都進行矯正,精度較高,花費時間較長。
參數確定技巧
Focus代表焦距,按照我們鏡頭參數進行填寫,遠心鏡頭填寫0

Kappa為畸變大小,因為在標定之前,所以默認填寫0

Sx, Sy像元的寬高填寫相機的像元尺寸。可以查相機手冊,或者咨詢相機廠家。
Cx, Cy填寫圖像的中心坐標
ImageWidth, ImageHeight填寫圖像的寬高

2、標定板初始化

使用算子 set_calib_data_calib_object
例如:
CaltabDescr := ‘caltab_100mm.descr’
set_calib_data_calib_object (CalibDataID, 0, CaltabDescr)
這個比較簡單,大家看幫助就可以懂,就不進行介紹了

3、創建標定數據模型

使用算子 create_calib_data( : : CalibSetup, NumCameras, NumCalibObjects : CalibDataID)
CalibSetup:創建的內容
NumCameras:相機個數
NumCalibObjects :標定項目數
CalibDataID:標定句柄
例如:
create_calib_data (‘calibration_object’, 1, 1, CalibDataID)

4、獲取標定圖片

標定板為正方形,尺寸大小為要照射區域寬度的1/3,相機拍攝或者讀入9-16張圖片,拍攝圖片時標定板盡量覆蓋整個視場;標定板圓點的直徑不能小于10個像素。

5、使用圖像進行相機內參標定,得到結果

方式一:
使用標定圖像,直接用halcon全自動,進行標定
find_calib_object (Image, CalibDataID, CameraIndex, 0, PoseIndex, [], [])
得到標定數據
get_calib_data (CalibDataID, ‘camera’, 0, ‘type’, CameraType)

方式二:
1、尋找標定板區域,確定圓心,將結果加載到組元中
find_caltab(Image : CalPlate : CalPlateDescr, SizeGauss, MarkThresh, MinDiamMarks : )
find_marks_and_pose(Image, CalPlateRegion : : CalPlateDescr, StartCamParam, StartThresh, DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks : RCoord, CCoord, StartPose)
set_calib_data_observ_points( : : CalibDataID, CameraIdx, CalibObjIdx, CalibObjPoseIdx, Row, Column, Index, Pose : )
原理:首先find_caltab算子對圖像高斯濾波(核大小為SizeGauss),接著閾值分割(閾值大小為MarkThresh)將標定板的區域找出來;find_marks_and_pose算子對區域中的圓進行分割,找到圓的個數,周長,坐標等應該和標定板描述文件中的一致,否則會自動調整StartThresh,使得StartThresh按照DeltaThresh步長減小到MinDiamMarks ,直到找到準確的圓心。
2、進行標定
calibrate_cameras( : : CalibDataID : Error)
返回平均投影誤差Error

6、使用圖像進行相機外參標定,得到結果

攝像機外參:決定攝像機坐標系與世界坐標系之間相對位置關系
其中Pw為世界坐標,Pc為攝像機坐標,T=(Tx,Ty,Tz)是平移向量,R=(a,b,r)是旋轉矩陣,分別是繞攝像機坐標系Z軸旋轉角度為r;繞攝像機坐標系Y軸旋轉角度為b;繞攝像機坐標系X軸旋轉角度為a。6個參數組成攝像機外參(a,b,r,Tx,Ty,Tz)
并且滿足下式:
Pc=R*Pw+T

具體步驟:
set_calib_data_cam_param( : : CalibDataID, CameraIdx, CameraType, CameraParam : )
set_calib_data_calib_object( : : CalibDataID, CalibObjIdx, CalibObjDescr : )
find_calib_object(Image : : CalibDataID, CameraIdx, CalibObjIdx, CalibObjPoseIdx, GenParamName, GenParamValue : )
get_calib_data_observ_contours( : Contours : CalibDataID, ContourName, CameraIdx, CalibObjIdx, CalibObjPoseIdx : )
get_calib_data_observ_points( : : CalibDataID, CameraIdx, CalibObjIdx, CalibObjPoseIdx : Row, Column, Index, Pose)
set_origin_pose( : : PoseIn, DX, DY, DZ : PoseNewOrigin)
在這里插入圖片描述

Halcon相機標定代碼與解析

**創建標定板
gen_caltab(7,7,0.008,0.5,'48_48mm.descr','48_48mm.ps')*=======標定內參
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')*標定相機
StartCamPar := [0.0,0.0,0.0000299,0.0000299,4896/2,3264/2,4896,3264]
create_calib_data ('calibration_object', 1, 1, CalibDataID)
set_calib_data_cam_param (CalibDataID, 0, 'area_scan_telecentric_division', StartCamPar)
set_calib_data_calib_object (CalibDataID, 0, '48_48mm.descr')for index := 1 to 13 by 1read_image (Image, '標定20/' + index + '.png')get_image_size(Image, Width, Height)dev_display (Image)find_calib_object (Image, CalibDataID, 0, 0, index, [], [])get_calib_data_observ_contours (Caltab, CalibDataID, 'caltab', 0, 0, index)dev_set_color ('green')dev_display (Caltab)
endforcalibrate_cameras (CalibDataID, Error)
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
get_calib_data (CalibDataID, 'calib_obj_pose', [0,1], 'pose', PoseCalib)*輸出計算的相機內參
write_cam_par (CamParam, 'camera_parameters.dat')Message:= '相機內參已經寫入文件中'
disp_message (WindowHandle, Message, 'window', 12, 12, 'red', 'false')
clear_calib_data (CalibDataID)
stop()*=====標定外參
dev_set_draw ('margin')
dev_set_line_width (1)
set_display_font (WindowHandle, 14, 'mono', 'true', 'false')*從文件中讀取內參 存儲文件:camera_parameters.dat
tryread_cam_par ('camera_parameters.dat', CamParam)
catch (Exception)stop ()
endtry*開始計算
open_file('data.csv','output', FileHandle)
fwrite_string(FileHandle,'Dis_pix*0.0299204,Dis_m*1000,Distance')
fnew_line (FileHandle)
close_file(FileHandle)*選擇一張作為標定作為最終標定位姿(任意一張都可以)
index:=1
read_image (Image,'標定20/'+index+'.png')
dev_display (Image)
CaltabName := '48_48mm.descr'
create_calib_data ('calibration_object', 1, 1, CalibDataID)set_calib_data_cam_param (CalibDataID, 0, 'area_scan_telecentric_division', CamParam)
set_calib_data_calib_object (CalibDataID, 0, CaltabName)
find_calib_object (Image, CalibDataID, 0, 0, 1, [], [])
get_calib_data_observ_contours (Caltab, CalibDataID, 'caltab', 0, 0, 1)
get_calib_data_observ_points (CalibDataID, 0, 0, 1, RCoord, CCoord, Index, PoseForCalibrationPlate)
dev_set_color ('green')
dev_display (Caltab)
dev_set_color ('red')
disp_caltab (WindowHandle, CaltabName, CamParam, PoseForCalibrationPlate, 1)
dev_set_line_width (1)
disp_circle (WindowHandle, RCoord, CCoord, gen_tuple_const(|RCoord|,1.5))
* caltab_points (CaltabName, X, Y, Z)
* calibrate_cameras (CalibDataID, Error)
* To take the thickness of the calibration plate into account, the z-value
* of the origin given by the camera pose has to be translated by the
* thickness of the calibration plate.
* Deactivate the following line if you do not want to add the correction.
set_origin_pose (PoseForCalibrationPlate, 0, 0, 0, PoseCalib)
* disp_continue_message (WindowHandle, 'black', 'true')
* stop ()*像素距離
distance_pp(RCoord[0],CCoord[0],RCoord[48],CCoord[48], Dis_pix)
*像素直接轉換mm然后計算
pix2mm(RCoord, CCoord,CamParam[2],CamParam[3],newCol,newRow)
distance_pp(newRow[0],newCol[0],newRow[48],newCol[48], Dis_m)
*用同一個世界坐標系來計算
image_points_to_world_plane(CamParam, PoseCalib,[RCoord[0],RCoord[48]], [CCoord[0],CCoord[48]], 'mm', X1, Y1)
distance_pp(Y1[0],X1[0],Y1[1],X1[1],Distance)*輸出計算結果比較
open_file('data.csv','append', FileHandle)
fwrite_string(FileHandle, Dis_pix*0.0299+','+Dis_m*1000+','+Distance+'\n')
close_file(FileHandle)    Message:= '計算完畢'
disp_message (WindowHandle, Message, 'window', 12, 12, 'red', 'false')
stop()

此文檔由http://www.ihalcon.com/read-7598.html分享整理得到。

  • 博主簡介:
  • 工業自動化上位機軟件工程師、機器視覺算法工程師、運動控制算法工程師。目前從業于智能制造自動化行業。 博主郵箱:2296776525@qq.com
  • 幫忙點個贊吧。哈哈。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/254405.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/254405.shtml
英文地址,請注明出處:http://en.pswp.cn/news/254405.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

halcon模板匹配干擾邊緣消除辦法(最硬核方式)

目錄halcon手繪形狀匹配模板手繪形狀匹配模板主要算子解析draw_nurbs 繪制平滑曲線參數解釋create_shape_model_xld 使用XLD輪廓創建模板參數解釋實例演示與解析實例代碼展示與解析運行過程與處理展示讀入圖像繪制模板使用繪制的XLD創建模板查找模板博主寫作不容易,…

往文件中寫數據--增量

有的功能需要打印日志文件,但是日志文件太多不方便查看,我就把信息輸出到一個TXT文件中了。 下面就是我將要說的,往文件中寫數據(增量),代碼很簡單,也可以放在你的代碼中運行一下: /…

SQL Server 數據庫查找重復記錄的幾種方法

http://www.hanyu123.cn/html/c61/6790.html 一、查某一列(或多列)的重復值。(只可以查出重復記錄的值,不能查出整個記錄的信息) 例如:查找stuid,stuname重復的記錄: select stuid,s…

xvid 數據編碼和解碼

由于視頻開發的需求,封裝xvid c調用接口,使之優雅易用 我已經對pc camera視頻流(RGB)進行嘗試,編碼之后傳輸到遠程主機進行解碼回放,效果不錯 具體的xvid的參數可以進一步優化,這里只是提供簡單的范例 1. xvid 解碼 …

第一個PowerShell腳本——PowerShell三分鐘(九)

前面把基礎知識講了一遍,現在我們開始寫一個最初級的腳本寫腳本的工具有很多,有文本文檔,有PowerShell ISE,PowerShell Studio等,這里選用系統自帶的PowerShell ISE這里大家依然要記得以管理員身份運行,否則…

C#精準定時

文章目錄簡介StopWatch類例子1,用作延時例子2,用作算法耗時評估博主寫作不容易,孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 簡介 我們在自動化上位機編寫過程中,上位機的定時應用在很多地方。對于工業上位機程序設計起…

聯合體(union)和結構體(struct)的區別

1. 聯合說明和聯合變量定義 聯合也是一種新的數據類型, 它是一種特殊形式的變量。 聯合說明和聯合變量定義與結構十分相似。其形式為: union 聯合名{ 數據類型 成員名; 數據類型 成員名; ... } 聯合變量名; 聯合表示幾個變量公用一個內存位置, 在不同的時間保存不同…

MVC架構簡介及其測試策略

最近在WEB端測試工作中陷入了瓶頸,單純的手動功能測試在沒有成熟的代碼規范之前還是很容易坑的,WEB自動化測試一時半會還沒有什么進展,所以決定先學習一下網站用的MVC架構,跟著教程寫了一個小網站,大概也找到了WEB測試…

prototype與_proto_

1、prototype與_proto_ ①prototype:是函數才有的屬性,這個屬性是一個指針。當一個構造函數被創建時,該構造函數會自動生成一個prototype指針,該指針指向構造函數的原型。這個原型會有其他實例共享的一些屬性和方法。 ②_proto_&a…

Halcon求取矩形頂點坐標

文章目錄簡介Halcon源碼博主寫作不容易,孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 簡介 我們在使用Halcon畫矩形時,并不能得到矩形四角頂點坐標。但是我們可以通過數學計算得到矩形定點坐標的位置。 我們在計算過程中需要知道矩形的長軸與短…

kafka常用的shell命令

kafka常用shell命令: ------------------------------------ 1、創建topic bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test 2、查看創建的topic bin/kafka-topics.sh --list --zookeeper localhost:…

python+pycharm+Django報錯

報錯&#xff1a; Unhandled exception in thread started by <function wrapper at 0x2d7e410>Traceback (most recent call last):File "/root/virtual_dir/wxwebapp_court_nositepkg/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, i…

C++多線程實例(_beginThreadex創建多線程)

C多線程&#xff08;二&#xff09;(_beginThreadex創建多線程) C/C Runtime 多線程函數一 簡單實例&#xff08;來自codeprojct&#xff1a;http://www.codeproject.com/useritems/MultithreadingTutorial.asp&#xff09; 主線程創建2個線程t1和t2&#xff0c;創建時2個線程…

halcon求取區域頂點

文章目錄簡介Halcon源代碼處理效果博主寫作不容易&#xff0c;孩子需要您鼓勵 萬水千山總是情 , 先點個贊行不行 簡介 使用halcon求取頂點的方法。 Halcon源代碼 read_image (Image1, 1.png)points_foerstner (Image1, 1, 2, 3, 200, 0.3, gauss, false, RowJunctions, …

從excel表中生成批量SQL,將數據錄入到數據庫中

excel表格中有許多數據&#xff0c;需要將數據導入數據庫中&#xff0c;又不能一個一個手工錄入&#xff0c;可以生成SQL&#xff0c;來批量操作。1.首先在第二行的H列&#xff0c;插入函數&#xff1a;CONCATENATE("INSERT INTO book (bookid, title, volume, author, u…

HDU-5895 Mathematician QSC

題目大意&#xff1a; 已知f[0] 0, f[1] 1, f[i] f[i-1] * 2 f[i-2]&#xff0c;且g[n] g[n-1] f[n] * f[n]&#xff0c;現在給出n&#xff0c;y&#xff0c;x&#xff0c;s&#xff0c;問你x^(g[n*y]) mod (s 1)的值為多少。 解題思路&#xff1a; 首先可以得到的是g[n…

C#的兩種類據類型:值類型和引用類型

目錄什么是值類型&#xff0c;什么是引用類型概念&#xff1a;值類型和引用類型區別什么是值類型&#xff0c;什么是引用類型 概念&#xff1a; 值類型直接存儲其值&#xff0c;而引用類型存儲對其值的引用。部署&#xff1a;托管堆上部署了所有引用類型。 引用類型&#xf…

ring0 ring3 kernel driver

intel cpu的權限訪問控制&#xff1a;ring0 ~ ring5. window、linux操作系統都只用了ring0&#xff0c;ring3&#xff0c;對應內核態和用戶態. 驅動程序工作在內核態&#xff0c;沒有main函數入口&#xff0c;而應用程序工作在用戶態。轉載于:https://www.cnblogs.com/yiii/p/6…

Linux 的多線程編程的高效開發經驗

轉自&#xff1a;http://www.chineselinuxuniversity.net/articles/22615.shtml 本文中我們針對 Linux 上多線程編程的主要特性總結出 5 條經驗&#xff0c;用以改善 Linux 多線程編程的習慣和避免其中的開發陷阱。在本文中&#xff0c;我們穿插一些 Windows 的編程用例用以對…

Visual C++中error spawning cl.exe解決辦法

| 版權聲明&#xff1a;本文為博主原創文章&#xff0c;未經博主允許不得轉載。 今天安裝Vc6.0的時候出現了一個error spawning cl.exe的錯誤&#xff0c;在網上找了一些資料&#xff0c;才知道這是因為路徑設置的問題引起的&#xff0c; “cl.exe”是VC真正的程序編譯器&…