1. 程式人生 > >鐳射三角測量(sheet of light)halcon示例詳解 Reconstruct_Connection_Rod_Calib.hdev 三維重建

鐳射三角測量(sheet of light)halcon示例詳解 Reconstruct_Connection_Rod_Calib.hdev 三維重建

 

原文作者:aircraft

原文連結:https://www.cnblogs.com/DOMLX/p/11555100.html

 

 

前言:最近專案用到halcon的3d模板匹配,三維重建,相機標定,所以最近都在研究這些,現在分享一下對鐳射三角測量示例的個人理解。

 

1.Reconstruct_Connection_Rod_Calib.hdev

先看一下這個halcon示例做了些什麼:

通過一道鐳射照射過一個零件,留下了一個個片截圖,後面用於測量其深度資訊。

 

 

 

 

而示例就是用光片模型的重建,對所有的connection_rod系列圖片進行處理,重建出原模型的影象:

 

 

 

 

 

 

也可以看片光x,y,z的資訊:

 

 

 

 

 

 

 

最後我們可以呼叫halcon的運算元visualize_object_model_3d (WindowHandle, ObjectModel3DID, CameraParam1, PoseIn, 'color', 'blue', 'Reconstructed Connection Rod', '', Instructions, PoseOut) 將3d零件模型重建

 

 

 

 

 

 

模型可以通過滑鼠隨意移動,就跟我上篇部落格 opengl匯入3d模型並且顯示一樣OpenGl讀取匯入3D模型並且新增滑鼠移動旋轉顯示

 2.鐳射三角測量

鐳射三角測距法作為低成本的鐳射雷達設計方案,可獲得高精度、高性價比的應用效果,併成為室內服務機器人導航的首選方案,本文將對鐳射雷達核心元件進行介紹並重點闡述基於鐳射三角測距法的鐳射雷達原理。

鐳射雷達四大核心元件

鐳射雷達主要由鐳射器、接收器、訊號處理單元和旋轉機構這四大核心元件構成。

鐳射器:鐳射器是鐳射雷達中的鐳射發射機構。在工作過程中,它會以脈衝的方式點亮。以思嵐科技的RPLIDAR A3系列雷達為例,每秒鐘,它會點亮和熄滅16000次。

接收器:鐳射器發射的鐳射照射到障礙物以後,通過障礙物的反射,反射光線會經由鏡頭組匯聚到接收器上。

訊號處理單元:訊號處理單元負責控制鐳射器的發射,以及接收器收到的訊號的處理。根據這些資訊計算出目標物體的距離資訊。

旋轉機構:以上3個元件構成了測量的核心部件。旋轉機構負責將上述核心部件以穩定的轉速旋轉起來,從而實現對所在平面的掃描,併產生實時的平面圖資訊。

 

鐳射三角測距法原理

目前鐳射雷達的測量原理主要有脈衝法、相干法和三角法3種,脈衝法和相干光法對鐳射雷達的硬體要求高,但測量精度比鐳射三角法要高得多,故多用於軍事領域。而鐳射三角測距法因其成本低,精度滿足大部分商用及民用要求,故得到了廣泛關注。

鐳射三角測距法主要是通過一束鐳射以一定的入射角度照射被測目標,鐳射在目標表面發生反射和散射,在另一角度利用透鏡對反射鐳射匯聚成像,光斑成像在CCD(Charge-coupled Device,感光耦合元件)位置感測器上。當被測物體沿鐳射方向發生移動時,位置感測器上的光斑將產生移動,其位移大小對應被測物體的移動距離,因此可通過演算法設計,由光斑位移距離計算出被測物體與基線的距離值。由於入射光和反射光構成一個三角形,對光斑位移的計算運用了幾何三角定理,故該測量法被稱為鐳射三角測距法。

按入射光束與被測物體表面法線的角度關係,鐳射三角測距法可分為斜射式和直射式兩種。

1、直射式鐳射三角測距法

如圖1所示,當鐳射光束垂直入射被測物體表面,即入射光線與被測物體表面法線共線時,為直射式鐳射三角法。

 

2、斜射式鐳射三角測距法

當光路系統中,鐳射入射光束與被測物體表面法線夾角小於90°時,該入射方式即為斜射式。如圖2所示的光路圖為鐳射三角法斜射式光路圖。

由鐳射器發射的鐳射與物體表面法線成一定角度入射到被測物體表面,反(散)射光經B處的透鏡匯聚成像,最後被光敏單元採集。

由圖2可知入射光AO與基線AB的夾角為α,AB為鐳射器中心與CCD中心的距離,BF為透鏡的焦距f,D為被測物體距離基線無窮遠處時反射光線在光敏單元上成像的極限位置。DE為光斑在光敏單元上偏離極限位置的位移,記為x。當系統的光路確定後,α、AB與f均為已知引數。由光路圖中的幾何關係可知△ABO∽△DEB,則有邊長關係:

則易知

在確定系統的光路時,可將CCD位置感測器的一個軸與基線AB平行(假設為y軸),則由通過演算法得到的鐳射光點畫素座標為(Px,Py)可得到x的值為:

其中CellSize是光敏單元上單個畫素的尺寸,DeviationValue是通過畫素點計算的投影距離和實際投影距離x的偏差量。當被測物體與基線AB產生相對位移時,x改變為x,由以上條件可得被測物體運動距離y為:

 

 

3.程式碼註解

 

看註釋就好了,慢慢看,結合示例跑一下就能大概理解了,示例在halcon的鐳射三角測量

 

如果在看的過程中對某個運算元不理解,引數有疑問,可以直接雙擊那個運算元

 

,開啟幫助手冊,去看每個運算元的引數資訊,以及用法介紹:

 

 

 

 

 

* 首先,建立一個片光模型,並設定合適的引數,接下來連續採集一系列輪廓影象。

* 最後,從模型中檢索視覺差影象,分數影象,標定座標X,Y和Z以及測量得到的3D物件模型並顯示。

*

dev_update_off () //暫停熟悉

read_image (ProfileImage, 'sheet_of_light/connection_rod_001') //讀取影象

dev_close_window () //關閉窗體

dev_open_window_fit_image (ProfileImage, 0, 0, 1024, 768, WindowHandle1) //開啟一個新窗體

set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')//設定字型

dev_set_draw ('margin') //設定輪廓

dev_set_line_width (3) //設定線寬

dev_set_color ('green') //設定顏色為綠色

dev_set_lut ('default') //

*

* 設定計算校準測量所需的姿勢和相機引數

* 內部相機引數

CamParam := [0.0126514,640.275,-2.07143e+007,3.18867e+011,-0.0895689,0.0231197,6.00051e-006,6e-006,387.036,120.112,752,240]

CamPose := [-0.00164029,1.91372e-006,0.300135,0.575347,0.587877,180.026,0] //相機座標

LightplanePose := [0.00270989,-0.00548841,0.00843714,66.9928,359.72,0.659384,0] //片光平面座標

MovementPose := [7.86235e-008,0.000120112,1.9745e-006,0,0,0,0] //

*

* 建立模型以處理配置檔案影象並設定模型所需的引數

gen_rectangle1 (ProfileRegion, 120, 75, 195, 710) //建立矩形

* 建立一個基於 3D 測量的片光模型

create_sheet_of_light_model (ProfileRegion, ['min_gray','num_profiles','ambiguity_solving'], [70,290,'first'], SheetOfLightModelID)

set_sheet_of_light_param (SheetOfLightModelID, 'calibration', 'xyz') //將標定變形應用在不同的影象中

set_sheet_of_light_param (SheetOfLightModelID, 'scale', 'mm') //單位

set_sheet_of_light_param (SheetOfLightModelID, 'camera_parameter', CamParam) //相機內部引數

set_sheet_of_light_param (SheetOfLightModelID, 'camera_pose', CamPose) //相機座標系統

set_sheet_of_light_param (SheetOfLightModelID, 'lightplane_pose', LightplanePose) //相機姿態,如果與測的物體相同平面

set_sheet_of_light_param (SheetOfLightModelID, 'movement_pose', MovementPose) //移動姿態,移動過程中通常為大地座標

*

* 連續的影象測量輪廓

for Index := 1 to 290 by 1

read_image (ProfileImage, 'sheet_of_light/connection_rod_' + Index$'.3') //讀取影象

dev_display (ProfileImage) //顯示影象

dev_display (ProfileRegion) //顯示區域

measure_profile_sheet_of_light (ProfileImage, SheetOfLightModelID, []) //對輸入和儲存的輪廓影象進行片光技術處理

disp_message (WindowHandle1, '採集輪廓影象', 'window', -1, -1, 'black', 'true') //顯示資訊

endfor

* 獲取片光影象

get_sheet_of_light_result (Disparity, SheetOfLightModelID, 'disparity') //返回片光深度距離

get_sheet_of_light_result (X, SheetOfLightModelID, 'x') //返回片光x資料

get_sheet_of_light_result (Y, SheetOfLightModelID, 'y') //返回片光y資料

get_sheet_of_light_result (Z, SheetOfLightModelID, 'z') //返回片光z資料

get_sheet_of_light_result_object_model_3d (SheetOfLightModelID, ObjectModel3DID) //返回片光3D模型資料

clear_sheet_of_light_model (SheetOfLightModelID) //清除指定片光模型

*

* 顯示視差影象

get_image_size (Disparity, Width, Height) //獲取影象大小

dev_set_window_extents (0, 0, Width, Height) //調整大小

dev_set_lut ('temperature') //

set_display_font (WindowHandle1, 16, 'mono', 'true', 'false') //設定字型

dev_clear_window () //清除窗體

dev_display (Disparity)

disp_message (WindowHandle1, '重建片光生產的視差影象', 'window', -1, -1, 'black', 'true') //顯示資訊

disp_continue_message (WindowHandle1, 'black', 'true') //顯示暫停資訊

stop () //暫停

*

* 顯示Z座標

dev_close_window () //關閉窗體

dev_open_window (Height + 10, 0, Width * .5, Height * .5, 'black', WindowHandle3) //開啟窗體3

set_display_font (WindowHandle3, 16, 'mono', 'true', 'false')//設定字型

dev_display (Z) //顯示Z資訊

disp_message (WindowHandle3, '標定的 Z 座標', 'window', -1, -1, 'black', 'true') //顯示資訊

*

* 顯示Y座標

dev_open_window ((Height + 10) * .5, 0, Width * .5, Height * .5, 'black', WindowHandle2) //開啟窗體2

set_display_font (WindowHandle2, 16, 'mono', 'true', 'false')//設定字型

dev_display (Y)//顯示Z資訊

disp_message (WindowHandle2, '標定的 Y 座標', 'window', -1, -1, 'black', 'true')

*

* 顯示X座標

dev_open_window (0, 0, Width * .5, Height * .5, 'black', WindowHandle1) //開啟窗體1

dev_display (X)//顯示Z資訊

dev_set_lut ('default')

set_display_font (WindowHandle1, 16, 'mono', 'true', 'false')//設定字型

disp_message (WindowHandle1, '標定的 X 座標', 'window', -1, -1, 'black', 'true') //顯示資訊

disp_continue_message (WindowHandle3, 'black', 'true') //顯示暫停資訊

stop () //暫停

*

* Display the 3d object model

CameraParam1 := [0.012,0,6e-006,6e-006,376,240,752,480] //相機內部引數

Instructions[0] := '旋轉: Left 滑鼠左鍵'

Instructions[1] := '縮放: Shift + 滑鼠左鍵'

Instructions[2] := '移動Move: Ctrl + 滑鼠左鍵'

PoseIn := [0,-10,300,-30,0,-30,0]

dev_close_window () //關閉窗體2

dev_close_window () //關閉窗體3

dev_close_window () //關閉窗體12

dev_open_window (0, 0, CameraParam1[6], CameraParam1[7], 'black', WindowHandle) //開啟新窗體

set_display_font (WindowHandle, 16, 'mono', 'true', 'false')//設定字型

visualize_object_model_3d (WindowHandle, ObjectModel3DID, CameraParam1, PoseIn, 'color', \

'blue', '重建', '', Instructions, PoseOut)//顯示資訊

* 清除片光模型

clear_object_model_3d (ObjectModel3DID)

 

這上面有提到一個視差影象:

Disparity(視差)怎麼理解?
        在研究雙目深度圖估計時,經常會使用D=B×f/d(D:Depth,B:Baseline,f:focal,d:disparity)這個公式,從視差推理出深度,那麼這裡的d到底怎麼理解?
        現在,伸出你左右手的食指,放在離眼睛不同距離的位置上。先閉上左眼看兩隻手指,再閉上右眼觀察兩隻手指,可以發現,左右眼看到的東西是不一樣的,其次,**距離眼睛近的物體移動的距離(視差)更大,距離眼睛遠的物體移動的距離(視差)更小。**將同一空間物理點在不同影象中的映像點對應起來,這個差別,我們稱作視差(Disparity)影象。參考下圖:

 

 


        公式不難發現,視差與深度成反比,關係如下:

 

 



        有了視差disparity,就可以推斷出深度圖。深度影象也稱為距離影象,是指將相機到場景中各點的距離(深度)值作為畫素值的影象。深度圖獲取方法有很多,例如:鐳射雷達深度成像法、計算機立體視覺成像、座標測量機法、莫爾條紋法、結構光法等。
        舉個例子:(Kinect相機)

 

 

 

 

 

參考部落格:Disparity(視差)簡單解釋  連結: https://blog.csdn.net/weixin_40367126/article/details/90753760

參考部落格:HALCON例子:鐳射三角ReconstructConnectionRodCalib 連結: https://weibo.com/ttarticle/p/show?id=230940440767890548