1. 程式人生 > >【halcon】雙目視覺的實現

【halcon】雙目視覺的實現

一、介紹

  關於雙目視覺的原理請參閱上一篇博文(https://blog.csdn.net/Ketal_N/article/details/83744626), 本文主要介紹基於halcon的雙目視覺的 相機標定三維重建

二、相機標定

系統搭建如下:
          在這裡插入圖片描述
 標定程式參考了halcon中的雙目標定示例binocular_calibration.hdev,標定步驟為:
  1)程式的初始化設定;
  2)建立標定資料模型(也可以不用標定資料模型,下面的程式碼就沒有使用),為相機內參設定初始值;
  3)描述標定物件;
  4)迴圈讀取多幅影象,提取標定板上的標記點及標定板位姿。
  5)執行標定;
  *6)進行影象對校正。
 程式碼如下:

*
* 該程式演示瞭如何使用 find_caltab, find_marks_and_pose和binocular_calibration 運算元進行雙目立體視覺系統的標定
* 共50幅(左右兩相機分別25幅)。標定完成後,利用對極幾何對影象對進行校正。
* 
* ---------------------------------------------------------
* 設定圖片路徑
ImgPath := 'C:/BinocualrCalibration/calibrationImgs/'
* 讀取第一幅影象,並獲取影象尺寸
Index := 1
read_image (ImageL, ImgPath + 'L' + Index$'02d')
read_image (ImageR, ImgPath + 'R' + Index$'02d')
* 開啟合適尺寸大小的視窗
dev_close_window ()
dev_update_off ()
get_image_size (ImageL, WidthL, HeightL)
dev_open_window (0, 0, 0.4*WidthL,0.4* HeightL, 'black', WindowHandle1)
dev_set_draw ('margin')
dev_set_color ('green')
set_display_font (WindowHandle1, 14, 'mono', 'true', 'false')
get_image_size (ImageR, WidthR, HeightR)
dev_open_window (0, 0.4*WidthL + 12, 0.4*WidthL, 0.4*HeightL, 'black', WindowHandle2)
dev_set_draw ('margin')
dev_set_color ('green')
* 讀取標定板模型.
CaltabFile := 'caltab_30mm.descr'
caltab_points (CaltabFile, X, Y, Z)
* 為相機內參設定初始值
StartCamParL := [0.016,0,3.75e-6,3.75e-6,WidthL / 2.0,HeightL / 2.0,WidthL,HeightL]
StartCamParR := StartCamParL
* find_caltab 和 find_marks_and_pose引數設定
SizeGauss := 3
MarkThresh := 120
MinDiamMarks := 5
StartThresh := 128
DeltaThresh := 10
MinThresh := 18
Alpha := 0.9
MinContLength := 15
MaxDiamMarks := 100
* 建立陣列,用於存放影象座標系下的標定點座標和標定板的初始位姿
RowsL := []
ColsL := []
StartPosesL := []
RowsR := []
ColsR := []
StartPosesR := []
*迴圈讀取標定影象
for Index := 1 to 25 by 1
    * 讀取標定影象
    read_image (ImageL, ImgPath + 'L' + Index$'02d')
    read_image (ImageR, ImgPath + 'R' + Index$'02d')
    * 尋找標定板
    find_caltab (ImageL, CaltabL, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)
    find_caltab (ImageR, CaltabR, CaltabFile, SizeGauss, MarkThresh, MinDiamMarks)
    * 顯示標定板區域
    dev_set_window (WindowHandle1)
    dev_display (ImageL)
    dev_display (CaltabL)
    dev_set_window (WindowHandle2)
    dev_display (ImageR)
    dev_display (CaltabR)
    * (左相機)提取標記點和標定板位姿,並顯示位姿座標
    find_marks_and_pose (ImageL, CaltabL, CaltabFile, StartCamParL, StartThresh, DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks, RCoordL, CCoordL, StartPoseL)
    disp_caltab (WindowHandle1, CaltabFile, StartCamParL, StartPoseL, 1)
    *(右相機)提取標記點和標定板位姿,並顯示位姿座標
    find_marks_and_pose (ImageR, CaltabR, CaltabFile, StartCamParR, StartThresh, DeltaThresh, MinThresh, Alpha, MinContLength, MaxDiamMarks, RCoordR, CCoordR, StartPoseR)
    disp_caltab (WindowHandle2, CaltabFile, StartCamParR, StartPoseR, 1)
    * 計算標記點在影象座標系下的位姿,並估算所有影象對間的相對位姿
    RowsL := [RowsL,RCoordL]
    ColsL := [ColsL,CCoordL]
    StartPosesL := [StartPosesL,StartPoseL]
    RowsR := [RowsR,RCoordR]
    ColsR := [ColsR,CCoordR]
    StartPosesR := [StartPosesR,StartPoseR]
endfor
*
* 執行標定
* 
binocular_calibration (X, Y, Z, RowsL, ColsL, RowsR, ColsR, StartCamParL, StartCamParR, StartPosesL, StartPosesR, 'all', CamParamL, CamParamR, NFinalPoseL, NFinalPoseR, cLPcR, Errors)
* 可以將標定結果存入檔案中:
* write_cam_par (CamParamL, 'cam_left-125.dat')
* write_cam_par (CamParamR, 'cam_right-125.dat')
* write_pose (cLPcR, 'pos_right2left.dat')
* 生成校正的對映圖
gen_binocular_rectification_map (MapL, MapR, CamParamL, CamParamR, cLPcR, 1, 'geometric', 'bilinear', RectCamParL, RectCamParR, CamPoseRectL, CamPoseRectR, RectLPosRectR)
* 讀取已標定系統的一個影象對
read_image (ImageL, ImgPath + 'L01')
read_image (ImageR, ImgPath + 'R01')
* 校正影象對並顯示
map_image (ImageL, MapL, ImageRectifiedL)
map_image (ImageR, MapR, ImageRectifiedR)
* 檢查校正影象的對極約束並顯示結果(包含一些對應的極線)
check_epipolar_constraint (ImageRectifiedL, ImageRectifiedR, RectCamParL, RectCamParR, WindowHandle1, WindowHandle2, CaltabFile, EpipolarError)

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

三、三維重建

   用採集的一對影象對來說明三維立體重建的過程。
  在這裡插入圖片描述
   三維重建步驟如下:
     1)讀取影象對
     2)輸入相機引數
     3)校正影象對
     4)計算視差
     5)對視差圖進行處理
     6)將視差圖轉換為X、Y、Z分量圖
     7)3D點的視覺化
  程式碼如下:

* 該程式演示瞭如何使用'disparity_image_to_xyz'運算元。
* 首先進行影象對的校正,然後計算所有視差圖中所有點的 x,y,z 座標,最後將將3D點視覺化。
* 
* 初始化設定
dev_close_window ()
dev_update_off ()
dev_set_preferences ('graphics_window_context_menu', 'false')
dev_set_preferences ('suppress_handled_exceptions_dlg', 'true')
* 
* 定義要選擇的左右影象對
ImagePath := 'C:/BinocualrCalibration/TestObject/'
Image1 := ImagePath + '/LT08'
Image2 := ImagePath + '/RT08'
* 
* 定義相機引數
CamParamL := [0.0162229,-21.9492,3.7503e-006,3.75e-006,622.487,523.778,1280,960]
CamParamR := [0.0160868,-161.835,3.7492e-006,3.75e-006,615.622,514.203,1280,960]
RelPose := [0.13018,-0.000356889,0.0248832,0.434254,343.51,359.836,0]
* 
* 生成視差圖
* ******************************************
* 
* 生成校正對映影象對
gen_binocular_rectification_map (MapL, MapR, CamParamL, CamParamR, RelPose, 1, 'geometric', 'bilinear', RectCamParL, RectCamParR, CamPoseRectL, CamPoseRectR, RectLPosRectR)
* 
* 讀取原影象對並進行校正,得到校正後的影象對
read_image (ImageL, Image1)
read_image (ImageR, Image2)
map_image (ImageL, MapL, ImageRectifiedL)
map_image (ImageR, MapR, ImageRectifiedR)
* 
* 顯示校正後的左側影象
get_image_size (ImageRectifiedL, WidthL, HeightL)
dev_open_window (0, 0, 0.4*WidthL,0.4* HeightL, 'black', WindowHandle1)
set_display_font (WindowHandle1, 11, 'mono', 'true', 'false')
dev_display (ImageRectifiedL)
disp_message (WindowHandle1, 'Left rectified image', 'window', 10, 10, 'black', 'true')
* 
* 顯示校正後的右側影象
dev_open_window (0, 0.4*WidthL + 10, 0.4*WidthL, 0.4*HeightL, 'black', WindowHandle2)
set_display_font (WindowHandle2, 11, 'mono', 'true', 'false')
dev_display (ImageRectifiedL)
disp_message (WindowHandle2, 'Right rectified image', 'window', 10, 10, 'black', 'true')
disp_continue_message (WindowHandle2, 'black', 'true')
stop ()
* 
* 計算視差
binocular_disparity (ImageRectifiedL, ImageRectifiedR, DisparityImage, Score, 'ncc', 33, 33, 0, -36, 20, 1, 0.3, 'left_right_check', 'interpolation')
* 
* 填充視差圖中的缺陷
get_domain (DisparityImage, RegionInpainting)
complement (RegionInpainting, RegionInpainting)
full_domain (DisparityImage, DisparityImage)
harmonic_interpolation (DisparityImage, RegionInpainting, DisparityImage, 0.001)
* 
* 顯示視差圖
dev_set_window (WindowHandle1)
dev_set_lut ('temperature')
dev_display (DisparityImage)
disp_message (WindowHandle1, 'Disparity image', 'window', 10, 10, 'black', 'true')
* 
* 計算點的3D座標
* *******************************************
* 
* 將視差圖轉換成X,Y,Z分量圖,分量圖中的灰度值表示各分量的座標
disparity_image_to_xyz (DisparityImage, X, Y, Z, RectCamParL, RectCamParR, RectLPosRectR)
* 
* 3D點的視覺化
* *******************************************
* 
* 將點雲的中心移至原點附近,並進行z方向上的尺度縮放
min_max_gray (X, X, 5, MinX, MaxX, RangeX)
min_max_gray (Y, Y, 5, MinY, MaxY, RangeY)
min_max_gray (Z, Z, 5, MinZ, MaxZ, RangeZ)
scale_image (X, X, 1.0, -MinX - 0.5 * RangeX)
scale_image (Y, Y, 1.0, -MinY - 0.5 * RangeY)
scale_image (Z, Z, 4.0, -4.0 * MinZ - 2.0 * RangeZ)
* 
* 顯示校正後的右影象
dev_set_window (WindowHandle2)
dev_display (ImageRectifiedR)
disp_message (WindowHandle2, 'Computed 3D points in 3D space', 'window', 10, 10, 'black', 'true')
disp_message (WindowHandle2, 'Left button:  rotate', 'window', 205, 10, 'white', 'false')
disp_message (WindowHandle2, 'Right button: exit', 'window', 220, 10, 'white', 'false')
* 
* 對3D點雲迴圈旋轉操作的設定
RelQuaternion := [0,0,0,1]
NumAddIn := 0
Cx := WidthL * 0.5
Cy := HeightL * 0.5
* 
* 旋轉迴圈
visualize_3D_space (DisparityImage, X, Y, Z, ImageRectifiedL, WindowHandle2, Cx, Cy, HeightL, WidthL, RelQuaternion, NumAddIn, MinX, MinY, MinZ, RangeX, RangeY, RangeZ, RectCamParL)

得到的視差圖如圖3所示,可以看到,目標物體的孔徑周圍有基礎缺陷(白色部分),這是由於在輸入的影象對中,目標物的孔徑周圍反光,顯示為白色,而在計算視差圖時,應儘量避免這種整塊出現的單一顏色區域。
      在這裡插入圖片描述
在這裡插入圖片描述
此外,還可以通過建立3D物件模型的方式將結果視覺化。用到的運算元為:xyz_to_object_model_3d( ), create_pose( ), visualize_object_model_3d( )。
         在這裡插入圖片描述
注:3D重建的顯示效果和相機標定的精度、拍攝環境、視差圖的演算法等因素相關,其中計算視差圖用到的運算元為binocular_disparity( ),包含的引數較多,需要選擇合適的引數才得到較好的視差圖。


ps:如有錯誤,謝謝指出。整理不易,轉載請註明出處。