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

  • 2019 年 10 月 3 日
  • 筆記

 

原文作者: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為:

雷射三角測距原理

 

單點雷射測距原理

單點雷射測距原理圖如下圖2-6所示,
Lasersfβ

ObjectP

這裡寫圖片描述
圖: 單點雷射測距示意圖

由幾何知識可作相似三角形,雷射頭、攝影機與目標物體組成的三角形,相似於攝影機、成像點PP

PP=xqd

                f/x=q/s  ==>  q=fs/x  

 

可分為兩部分計算:

        X=x1+x2= f/tan⁡β + pixelSize* position  

 

其中pixelSize是像素單位大小, position是成像的像素坐標相對於成像中心的位置。

最後,可求得距離d:

                     d=q/sin⁡β 

 

3.程式碼註解

 

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

 

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

 

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

 

 

 

 

 

一般dev_update_off放在開始,如果原來的程式有殘留一些窗口什麼的就可以關閉,dev_update_on放在程式結束

dev_update_window:定義 程式執行打開和關閉期間,影像對象是否在圖形窗口中顯示;在單步模式下,該規則無效,單個運算元調用以後,對象總是顯示在圖形窗口上;在測量一系列運算元的運行時間的時候,應該設置為OFF,以減少HDevelop中GUI更新的運行時間的影響

dev_update_pc:在程式執行期間,控制程式計數器的更新

dev_update_var:在程式執行期間控制變數窗口的更新或關閉,則每當程式修改變數時,更改變數窗口(圖標和控制項變數)的內容。 dev_update_time:控制是否顯示運算元的執行時間

* 首先,創建一個片光模型,並設置合適的參數,接下來連續採集一系列輪廓影像。    * 最後,從模型中檢索視覺差影像,分數影像,標定坐標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=2309404407678905483355