Halcon例程(基于多個標定圖的單目相機標定)詳解—— Camera_calibration_multi_image.hdev

一、前言

在我的工業相機專欄里已經將相機標定涉及到的理論部分講解完畢,為什么要標定以及標定要求出什么參數呢,用一個Halcon 例程來幫助理解。
這個例程是比較經典的標定程序,基本將標定過程講的比較清楚,用的標定圖像是系統自帶的,如果想自己做可以在Halcon助手選項里拍照生成。

二、代碼

* 設置窗口和字體
ImgPath := '3d_machine_vision/calib/'
dev_close_window ()
dev_open_window (0, 0, 640, 480, 'black', WindowHandle)
dev_update_off ()
dev_set_draw ('margin')
dev_set_line_width (3)
set_display_font (WindowHandle, 22, 'mono', 'true', 'false')
* 
* 相機標定過程
* 
* 生成面陣相機初始參數,參數均為相機已知參數
* (: : 焦距, 畸變因子, Sx, Sy, Cx, Cy, 圖像寬度, 圖像高度 : CameraParam存儲元組)
* (Sx, Sy為傳感器芯片上兩個相鄰單元之間的水平豎直距離,也就是像素的大小,單位為m/像素;Cx, Cy為圖像原點的行列坐標,單位為像素;)
gen_cam_par_area_scan_division (0.012, 0, 0.00000375, 0.00000375, 640, 480, 1280, 960, StartCamPar)
*創建Halcon標定數據模型(標定類型,相機數量,標定物數量,模型句柄)
*其作用在于指定相機標定類型,設置標定過程,存儲標定數據和結果。
create_calib_data ('calibration_object', 1, 1, CalibDataID)
*設定相機初始參數(句柄,相機參數索引,相機類型,起始相機參數)
*此段程序跑完的句柄見下圖。
set_calib_data_cam_param (CalibDataID, 0, [], StartCamPar)
*設定標定板初始參數(句柄,標定板數量索引,標定板描述(文件名或者標定板所有點的三維坐標))此例生成三維坐標系坐標值(x,y,z),其中z為0;坐標原點在finder模式的中心Mark點中心,坐標系的z軸指向標定板,x軸指向右側,y軸指向下方,視角沿z軸。
set_calib_data_calib_object (CalibDataID, 0, 'calplate_80mm.cpd')//此文件可用記事本打開,里面記錄了標定板五個mark模式的點坐標和半徑。
calibration marks at y = -0.0290538 m
-0.0374193548387097 -0.0290537554818005 0.000645161290322581

在這里插入圖片描述

*讀圖,并生成落輪廓和點的特征參數值
NumImages := 7
for I := 1 to NumImages by 1
*讀圖,路徑在C盤用戶公共文檔里,% 2d是將數字按寬度為2,采用右對齊方式輸出,若數據位數不到2位,則左邊補空格,所以文件名為calib_0X。read_image (Image, ImgPath + 'calib_image_' + I$'02d')dev_display (Image)*尋找標定板并在模型中設定提取的點和輪廓信息*(圖像變量,句柄,相機的索引,標定板的索引,計數變量,參數名(使用六邊形標定板,設置額外的參數值,可以使圖像平滑等),參數值)*該算子將標定板每個點的輪廓和點坐標,索引和此圖像標定板相對于相機坐標系的位姿提取出來,保存在句柄中。*find_caltab在圖像中尋找標定板是基于標定板的特征——在一個亮的區域中存在黑色Mark點*算子對圖像高斯濾波(核大小為SizeGauss),接著閾值分割(與之大小為MarkThresh)將標定板的區域找出來.find_calib_object (Image, CalibDataID, 0, 0, I, [], [])*從標定數據模型中獲取基于輪廓的觀測數據*(輪廓變量,句柄,返回標定板查找模式的輪廓內含三個參數(marks(返回每一個輪廓,calib(返回查找模式的輪廓),last_caltab(會返回上次成功的查找結果,但會忽略索引信息)),相機索引,標定板索引,變量)* 標定板查找器:有兩種模式,一種是特殊標記六邊形(即一個標記及其六個相鄰標記),其中四個或六個標記包含一個孔;另外是帶有矩形排列標記的校準板:校準板的邊緣在一角有一個三角形。這里是第一種,結果如下圖所示。get_calib_data_observ_contours (Caltab, CalibDataID, 'caltab', 0, 0, I)*從標定數據模型中獲取基于點的觀測數據get_calib_data_observ_points (CalibDataID, 0, 0, I, Row, Column, Index, StartPose)dev_set_color ('green')dev_display (Caltab)dev_set_color ('red')*畫出坐標的輪廓,輪廓以中心點的方式顯示(窗口句柄,中心點行坐標,列坐標,半徑)tuple_gen_const(: : Length, Const : Newtuple)(元組長度,常量初始值)disp_circle (WindowHandle, Row, Column, gen_tuple_const(|Row|,1.5))
endfor

在這里插入圖片描述
關于find_calib的更多細節見鏈接:
Halcon相機標定

*最重要的算子:相機標定,通過同步的最小化過程確定所有相機參數;
*計算相機內外參矩陣,原理見鏈接(https://blog.csdn.net/baidu_35536188/article/details/109772056)
*(句柄,優化后的反投影的均方根誤差(RMSE),單位為像素,該誤差用來反映優化是否成功,越接近0表示效果越好)
calibrate_cameras (CalibDataID, Errors)
*獲取相機標定數據--內參值,將其存在CamParam上。
get_calib_data (CalibDataID, 'camera', 0, 'params', CamParam)
*獲取標定板數據,將其第一幅圖的位姿存在Pose里。
get_calib_data (CalibDataID, 'calib_obj_pose', [0,1], 'pose', Pose)* 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.
* *設置新的坐標原點。在Z軸坐標加0.02,主要是考慮標定板的厚度,該算子通過DX、DY和DZ給定的向量轉換3D poseIn的原點,并以poseNewOrigin形式返回結果。
set_origin_pose (Pose, 0, 0, 0.002, Pose)
* measure the distance between the pitch lines

在這里插入圖片描述
在這里插入圖片描述

read_image (Image, ImgPath + 'ruler')
dev_display (Image)
* 準備提取垂直于矩形長軸的直邊。 矩形的中心在(Row,Column),Phi為矩形主軸的角度,Lenth1和Lenth2為兩軸的長度,即矩形兩邊長度的一半。
* (矩形中心點的行坐標,列坐標,矩形的縱軸與水平的角度(弧度),矩形的半寬,矩形的半高,圖像的寬,高,要使用的插值類型,測量對象句柄)
gen_measure_rectangle2 (690, 680, rad(-0.25), 480, 8, 1280, 960, 'bilinear', MeasureHandle)
*提取垂直于矩形或環形弧的邊緣對
*(圖像,句柄,高斯平滑的西格瑪參數值,最小邊緣幅度,灰度值轉換的類型以確定邊緣如何成對,邊緣對第一條邊的中心的Row坐標,列坐標,
邊緣對第一條邊的邊緣幅度(帶符號),邊緣對第二條邊的中心的Row坐標,列坐標,邊緣幅度,邊緣對內部之間的距離,邊緣間距離)
measure_pairs (Image, MeasureHandle, 0.5, 5, 'all', 'all', RowEdgeFirst, ColumnEdgeFirst, AmplitudeFirst, RowEdgeSecond, ColumnEdgeSecond, AmplitudeSecond, IntraDistance, InterDistance)
Row := (RowEdgeFirst + RowEdgeSecond) / 2.0
Col := (ColumnEdgeFirst + ColumnEdgeSecond) / 2.0
*顯示X點,如下圖所示。
disp_cross (WindowHandle, Row, Col, 20, rad(45))
*將圖像點轉換為世界坐標系的z=0平面
*(相機內參,位姿,行,列,單位,世界坐標系的X坐標點,Y坐標點)
image_points_to_world_plane (CamParam, Pose, Row, Col, 'mm', X1, Y1)
*計算兩點間的距離
distance_pp (X1[0:11], Y1[0:11], X1[1:12], Y1[1:12], Distance)
*求平均距離和
tuple_mean (Distance, MeanDistance)
*計算距離的標準差
tuple_deviation (Distance, DeviationDistance)
disp_message (WindowHandle, 'Mean distance: ' + MeanDistance$'.3f' + 'mm +/- ' + DeviationDistance$'.3f' + 'mm', 'window', 30, 60, 'yellow', 'false')

在這里插入圖片描述

三、總結

Halcon 的標定步驟總結如下:

  1. gen_cam_par_area_scan_division:生成相機參數矩陣;
  2. create_calib_data,set_calib_data_cam_param, set_calib_data_calib_object:創建標定數據模型,并設定相機和標定板的參數值,包括相機起始內參和標定板的坐標系。
  3. find_calib_object,在多幅標定圖像中尋找標定板,并提取其輪廓和點特征,生成相對于相機坐標系的位姿矩陣(7維)。
  4. calibrate_cameras,計算內外參,并計算誤差值。
  5. 讀實際要測量的圖,設定感興趣矩形區域,并通過邊緣檢測計算邊緣點坐標并標記出來,并根據計算出的內外參將二維坐標轉為3維坐標,計算出偏差。
    綜合下來,感覺HALCON標定的過程還是比較清晰的,關鍵算子里面的程序還是需要理解一下。

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

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

相關文章

SkipList 跳表

為什么選擇跳表 目前經常使用的平衡數據結構有:B樹,紅黑樹,AVL樹,Splay Tree, Treep等。 想象一下,給你一張草稿紙,一只筆,一個編輯器,你能立即實現一顆紅黑樹,或者AVL樹…

Redis failover過程

在Leader觸發failover之前,首先wait數秒(隨即0~5),以便讓其他sentinel實例準備和調整。如果一切正常,那么leader就需要開始將一個salve提升為master,此slave必須為狀態良好(不能處于SDOWN/ODOWN狀態)且權重值最低(redis.conf中)的…

機器學習——深度學習之卷積神經網絡(CNN)——LeNet卷積神經網絡結構

目錄 一、卷積神經網絡 1、卷積神經的作用 2、LeNet 1)數據庫準備——minst 2)模型 二、關于卷積神經網絡結構的一些術語定義 1、特征圖(Feature map) 2、height(長度)、width(寬度&…

工業相機(3D)主要參數詳述

一、前言 準確的完成相機選型是一個視覺工程師必備的技能,而選型前必須對其內部參數了如指掌。工業相機是一種比較復雜的產品,其參數很多,每個參數可能會有不同的標準,下面對主要的參數會做比較詳細的闡述。 二、參數詳述 2.1 …

JAVA8永久代

在Java虛擬機(以下簡稱JVM)中,類包含其對應的元數據,比如類的層級信息,方法數據和方法信息(如字節碼,棧和變量大小),運行時常量池,已確定的符號引用和虛方法表…

Struts 2初體驗

Struts2簡介: Struts2是一個基于MVC設計模式的Web應用框架,它本質上相當于一個servlet,在MVC設計模式中,Struts2作為控制器(Controller)來建立模型與視圖的數據交互。 Struts 2 目錄結構:     apps目錄:Struts2示例…

機器學習——深度學習之數據庫和自編碼器

目錄 一、數據庫——數據獲取 1、Mnist 2、ImageNet 二、自編碼器(Auto-encoder)——參數初始化 1、功能 2、基本思想 1)訓練第一層 2)訓練第二層及以后的神經網絡 ? 3)利用BP對整個神經網絡的參數初始值進…

Halcon例程詳解 (深度圖轉換為3D圖像)—— xyz_attrib_to_object_model_3d

一、前言 深度圖向點云圖進行轉換是進行3D檢測項目時會遇到的問題,halcon里也有針對此問題的相關例程,下面對此例程進行分析。通過學習此例程,我們可以掌握如何將一張深度圖像和一張正常二維圖像轉換為3D點云。 二、分析 * 初始化界面 dev…

動態代理之Cglib淺析

什么是Cglib Cglib是一個強大的,高性能,高質量的代碼生成類庫。它可以在運行期擴展JAVA類與實現JAVA接口。其底層實現是通過ASM字節碼處理框架來轉換字節碼并生成新的類。大部分功能實際上是ASM所提供的,Cglib只是封裝了ASM,簡化了…

機器學習——深度學習之卷積神經網絡(CNN)——AlexNet卷積神經網絡結構

目錄 一、AlexNet卷積神經網絡結構模型 1、數據庫ImageNet 2、AlexNet第一層卷積層 二、AlexNet卷積神經網絡的改進 1、非線性變化函數的改變——ReLU 2、最大池化(Max Pooling)概念的提出——卷積神經網絡通用 1)池化層 2&#xff0…

POJ - 3470 Walls

小鳥往四個方向飛都枚舉一下,數據范圍沒給,離散以后按在其中一個軸線排序,在線段樹上更新墻的id,然后就是點查詢在在哪個墻上了。 這題有個trick,因為數據范圍沒給我老以為是inf設置小了,WA了很多發。&…

C# —— 深入理解委托類型

一. 委托定義 1. 委托與多播委托 委托類型表示對具有特定參數列表和返回類型的方法的引用,定義了委托實例可以調用的某類方法。 通過委托,我們可以動態的通過委托變量來調用委托方法。一般用delegate來命名委托類型,但Action和Func也可以達到同樣的效果…

【VS開發】【C++語言】reshuffle的容器實現算法random_shuffle()的使用

假設你需要指定范圍內的隨機數,傳統的方法是使用ANSI C的函數random(),然后格式化結果以便結果是落在指定的范圍內。但是,使用這個方法至少有兩個缺點。首先,做格式化時,結果常常是扭曲的,所以得不到正確的隨機數&…

C#委托——基礎2

在上一篇隨筆中,簡要說明了怎樣定義委托,定義事件,訂閱事件,最后也實現了效果,就是當員工類的某個對象,執行某個事件時,委托事件被觸發,后面也得到了結果,但是想象一下實…

機器學習——深度學習之編程工具、流行網絡結構、卷積神經網絡結構的應用

目錄 一、編程工具 caffe實現LENET-5 二、流行的網絡結構 1、VGGNET 2、Googlenet ? 3、ResNet? ? 三、卷積神經網絡的應用 1、人臉識別 ? 2、人臉驗證 3、人臉特征點檢測 4、卷積神經網絡壓縮 一、編程工具 caffe的優點:模型標準化,源代碼…

Halcon例程詳解(激光三角系統標定)—— calibrate_sheet_of_light_calplate.hdev

前言 1 激光三角測距 激光三角測距法原理很簡單,是通過一束激光以一定的入射角度照射被測目標,激光在目標表面會產生漫反射,在另一角度利用透鏡對反射激光匯聚成像,光斑成像在CCD(Charge-coupled Device,感光耦合組件)位置傳感器上。當被測物體沿激光方向發生移動時,…

【轉】如何實現一個文件系統

如何實現一個文件系統 摘要 本章目的是分析在Linux系統中如何實現新的文件系統。在介紹文件系統具體實現前先介紹文件系統的概念和作用,抽象出文件系統概念模型。熟悉文件系統的內涵后,我們再進一步討論Linux系統中文件系統的特殊風格和具體文件系統在Li…

【tenserflow】——數據類型以及常用屬性

目錄 一、什么是Tensor? 二、Tensorflow常見數據類型 三、Tensorflow常見屬性device\cpu\gpu\ndim\shape\rank等 1、創建一個tensor 1)tf.constant() 2)tf.Variable() 2、判斷一個變量是否為tensor張量 3、生成不同設備(cpu,gpu&#x…

C# 事件詳解附實例分析

一、定義 事件是兩個對象間發布消息和響應后處理消息的過程,通過委托類型來實現的。 事件的機制被稱為發布-訂閱機制,其算法過程為:首先定義一個委托類型,然后在發布者類中聲明一個event事件,同時此類中還有一個用來觸…

網頁開發瀏覽器兼容性問題

1、在ie6下的雙margin問題 在ie6下,設置了float的元素,以float:left為例,如圖所示。會出現第一個浮動元素,即相對于父級元素浮動的,會出現雙倍margin的問題。 注意僅僅是相對于父級元素浮動的,即第一個會出…