作者:Stephen Evanczuk
3D 飛行時間 (ToF)成像為視頻成像提供了一種有效的替代方法,可用于包括工業安全、機器人導航、手勢控制界面等在內的廣泛應用。但是,這種方法需要慎重整合光學設計、精密定時電路和信號處理功能,常常會讓開發人員難以實現有效的3D ToF 平臺。
本文將說明 ToF 技術的微妙之處,然后展示兩個現成的 3D ToF 套件——Analog Devices 的 AD-96TOF1-EBZ 開發平臺和ESPROS Photonics 的 EPC660 評估套件,介紹它們如何幫助開發人員快速設計 3D ToF 應用原型,并獲得所需的經驗來實現 3D ToF設計以滿足開發人員的獨特要求。
什么是 ToF 技術?
ToF 技術基于一個大家熟悉的原理,即物體與某個源點之間的距離可以通過測量源點發射能量的時間與源點收到反射信號的時間之差來得出(圖 1)。
盡管基本原理相同,ToF 解決方案卻千差萬別,并且因為采用不同的基礎技術——包括超聲波、光檢測和測距 (LiDAR)、相機、毫米波 (mmWave)射頻信號——而具有一些固有的能力和局限性:
超聲波 ToF 解決方案成本低,但物體的范圍和空間分辨率有限
光學 ToF 解決方案可以實現比超聲波系統更高的范圍和空間分辨率,但會受到濃霧或煙霧的影響
基于毫米波技術的解決方案通常更為復雜和昂貴,但不受煙、霧或雨的影響,能在較大范圍內工作,并提供有關目標物體的速度和航向的信息
制造商可以根據需要利用不同技術的能力來滿足特定需求。例如,超聲波傳感器非常適合檢測障礙物,可以幫助機器人越過道路,或幫助駕駛員停車。相比之下,毫米波技術可為車輛提供長距離感測能力,從而在其他傳感器因為惡劣天氣狀況而無法工作的情況下,也能檢測到正在接近的道路危險。
ToF 設計可以圍繞一對發射器/接收器來構建。例如,簡單的光學 ToF 設計在概念上僅需一個 LED來照亮某個目標區域,以及一個光電二極管來檢測該目標區域內物體的反射。盡管如此,這種看似簡單的設計仍需要精確的定時和同步電路來測量延遲。另外,可能需要調制和解調電路來將照明信號與背景源區分開來,或支持更復雜的連續波方法。
隨著開發人員努力提高信噪比 (SNR) 并消除 ToF系統中的偽影,設計復雜度迅速攀升。讓復雜性進一步加劇的是,更先進的檢測解決方案會采用多個發射器和接收器來跟蹤多個物體,或支持更復雜的運動跟蹤算法。例如,毫米波系統常常會運用多個接收器來跟蹤多個獨立物體的航向和速度。(請參閱“使用毫米波雷達套件快速開發精密目標檢測設計”。)
3D 光學 ToF 系統
3D 光學 ToF 系統擴展了使用更多接收器的理念,即采用通常基于電荷耦合器件 (CCD) 陣列的成像傳感器。當一組透鏡將某個目標區域聚焦到 CCD陣列上時,該區域中的相應點會反射光線,返回的光線會為 CCD 陣列中的每個電荷儲存器件充電。到達 CCD陣列的反射光與脈沖或連續波照明同步后,基本上分別在一系列窗口或相位中得到捕獲。此類數據會經過進一步處理,可創建一個由體素 (VOlume piXEL) 組成的3D 深度圖,其值表示到目標區域中相應點的距離。
像視頻中的幀一樣,可以依次捕獲各個深度圖,以提供具有時間分辨率(僅受圖像捕獲系統的幀率限制)和空間分辨率(僅受 CCD陣列和光學系統限制)的測量結果。隨著更大的 320 x 240 CCD 成像儀的出現,更高分辨率的 3D 光學 ToF系統能應用于更廣泛的領域,包括工業自動化和無人機 (UAV),甚至手勢界面(圖 2)。
與大多數基于相機的方法不同,3D ToF 系統可以在陰影或光照不斷變化的條件下提供精確結果。這些系統會提供自己的照明,通常使用激光器或大功率紅外LED(例如 Lumileds 的 Luxeon IR LED),這些 LED 能以此類系統使用的兆赫茲 (MHz) 開關速率工作。與立體攝像機等方法不同,3DToF 系統提供了一種緊湊型解決方案來生成詳細的距離信息。
預置解決方案
然而,為了實現 3D ToF系統,開發人員面臨多項設計挑戰。除了前面提到的定時電路之外,這些系統還依賴于精心設計的信號處理流水線,該流水線須進行優化,以便針對每個窗口或相位測量快速讀取CCD 陣列中的結果,然后完成所需的處理,將原始數據轉換為深度圖。先進的 3D ToF 成像儀如 ESPROS Photonics 的EPC660-CSP68-007 ToF 成像儀,集 320 x 240 CCD 陣列與所需的全部配套定時和信號處理能力于一體,可執行 3D ToF測量并提供每像素 12 位距離數據(圖 3)。
ESPROS Photonics 的 EPC660-007 卡邊緣連接器芯片載板將 epc650 成像儀安裝在 37.25 x 36.00 毫米 (mm)的印刷電路板(PC 板)上,并配有去耦電容器和卡邊緣連接器。盡管此芯片載板解決了 3D ToF
系統設計中的基本硬件接口問題,但開發人員要負責在前端完成適當光學設計,并在后端提供處理資源。ESPROS Photonics 的 epc660評估套件提供完整的 3D ToF 應用開發環境,其中包括預置 3D ToF 成像系統和相關軟件,無需開發人員完成上述任務(圖 4)。
ESPROS 套件設計用于評估和快速原型開發,提供了一個預裝配好的相機系統,其中整合了 epc660 CC 芯片載板、光學透鏡組件和一組八個LED。除相機系統外,BeagleBone Black 處理器板具有 512 MB RAM 和 4 GB 閃存,可用作主機控制器和應用處理資源。
ESPROS 還提供了 epc660評估套件支持軟件,該軟件可從其網站下載。該軟件需要密碼才能打開,密碼可從該公司的當地銷售辦事處索取。獲得該軟件的使用權后,開發人員只需使用所提供的配置文件之一運行一個圖形用戶界面(GUI) 應用程序,即可開始操作相機系統。此外,GUI應用程序還提供了控制和顯示窗口,可用于設置其他參數,包括空間和時間濾波器設置,以及用于查看結果。開發人員可以毫不費力地使用該套件實時捕獲深度圖,并將其用作自己的應用軟件輸入。
增強分辨率的 3D ToF 系統
諸如 ESPROS epc660 之類的 320 x 240成像儀可以服務于許多應用,但分辨率可能不足以檢測手勢界面中的微小移動,或在不嚴格限制目標范圍的情況下區分微小物體。對于這些應用,基于 640 x 480 ToF傳感器的現成開發套件的出現,能夠讓開發人員快速開發高分辨率應用原型。
Seeed Technology 的 DepthEye Turbo 深度相機將 640 x 480 ToF 傳感器、四個 850 納米 (nm)
垂直腔表面發射激光器 (VCSEL) 二極管、照明和感測操作電路、電源及 USB 接口支持集成在一個尺寸為 57 x 57 x 51 mm的自足式立方體中。軟件支持通過開源的 libPointCloud SDK github 存儲庫提供,并支持 Linux、Windows、Mac OS 和Android 平臺。
除了 C++ 驅動程序、庫和示例代碼之外,libPointCloud SDK 發行版還包括用于快速開發原型的 Python API和可視化工具。在主機開發平臺上安裝發行包之后,開發人員可以通過 USB將相機連接到計算機,然后即可開始使用可視化工具顯示相位、幅度或點云圖;這些圖本質上是使用紋理表面渲染的增強深度圖,可提供更平滑的 3D 圖像(圖 5)。
Analog Devices 的 AD-96TOF1-EBZ 3D ToF 評估套件提供了一個更為開放的硬件設計,它由一對板構建,專門使用Raspberry Pi 的 Raspberry Pi 3 Model B+ 或 Raspberry Pi 4 作為主機控制器和本地處理資源(圖 6)。
該套件的模擬前端 (AFE) 板容納了光學組件、CCD陣列和緩沖器、固件存儲以及一個處理器;該處理器管理相機的整體操作,包括照明定時、傳感器同步和深度圖生成。第二塊板容納了四個 850 nm VCSEL激光二極管和驅動器,能連接到 AFE 板,以使激光二極管環繞光學組件,如上圖所示。
Analog Devices 通過開源的 3D ToF 軟件套件來支持 AD-96TOF1-EBZ 套件,軟件套件含有 3D ToF SDK 以及C/C++、Python、Matlab 的示例代碼和包封。為了在網絡環境中同時支持主機應用和底層硬件交互,Analog Devices 將 SDK劃分為兩部分:一個是針對 USB 和網絡連接優化的主機部分,一個是在嵌入式 Linux 上運行并基于 Video4Linux2 (V4L2)驅動程序的底層部分(圖 7)。
這個支持網絡的 SDK 允許聯網主機上運行的應用程序與 ToF 硬件系統遠程協作,以訪問相機并捕獲深度數據。此外,用戶程序也可以在嵌入式 Linux部分中運行,并充分利用該層級提供的高級選項。
作為軟件分發的一部分,Analog Devices 提供了示例代碼來展示關鍵的底層操作功能,例如在主機上以及在本地使用嵌入式 Linux進行相機初始化、基本幀捕獲、遠程訪問和跨平臺捕獲。其他示例應用程序基于這些基本操作而構建,用以說明如何在更高級別的應用(如點云生成)中使用捕獲的數據。事實上,有一個示例應用程序展示了如何使用深度神經網絡(DNN) 推理模型對相機系統生成的數據進行分類。該 DNN 示例應用程序 (dnn.py) 用 Python編寫,逐步展示了獲取數據和通過推理模型準備數據分類的過程(清單 1)。
import aditofpython as tof
import numpy as np
import cv2 as cv
。。. try:
net = cv.dnn.readNetFromCaffe(args.prototxt, args.weights)
except:
print(“Error: Please give the correct location of the prototxt and
caffemodel”)
sys.exit(1)
swapRB = False
classNames = {0: ‘background’,
1: ‘aeroplane’, 2: ‘bicycle’, 3: ‘bird’, 4: ‘boat’,
5: ‘bottle’, 6: ‘bus’, 7: ‘car’, 8: ‘cat’, 9: ‘chair’,
10: ‘cow’, 11: ‘diningtable’, 12: ‘dog’, 13: ‘horse’,
14: ‘motorbike’, 15: ‘person’, 16: ‘pottedplant’,
17: ‘sheep’, 18: ‘sofa’, 19: ‘train’, 20: ‘tvmonitor’}
system = tof.System()
status = system.initialize()
if not status:
print(“system.initialize() failed with status: ”, status)
cameras = []
status = system.getCameraList(cameras)
。。. while True:
Capture frame-by-frame
status = cameras[0].requestFrame(frame)
if not status:
print(“cameras[0].requestFrame() failed with status: ”, status)
depth_map = np.array(frame.getData(tof.FrameDataType.Depth), dtype=“uint16”,
copy=False)
ir_map = np.array(frame.getData(tof.FrameDataType.IR), dtype=“uint16”,
copy=False)
Creation of the IR image
ir_map = ir_map[0: int(ir_map.shape[0] / 2), :]
ir_map = np.float32(ir_map)
distance_scale_ir = 255.0 / camera_range
ir_map = distance_scale_ir * ir_map
ir_map = np.uint8(ir_map)
ir_map = cv.cvtColor(ir_map, cv.COLOR_GRAY2RGB)
Creation of the Depth image
new_shape = (int(depth_map.shape[0] / 2), depth_map.shape[1])
depth_map = np.resize(depth_map, new_shape)
distance_map = depth_map
depth_map = np.float32(depth_map)
distance_scale = 255.0 / camera_range
depth_map = distance_scale * depth_map
depth_map = np.uint8(depth_map)
depth_map = cv.applyColorMap(depth_map, cv.COLORMAP_RAINBOW)
Combine depth and IR for more accurate results
result = cv.addWeighted(ir_map, 0.4, depth_map, 0.6, 0)
Start the computations for object detection using DNN
blob = cv.dnn.blobFromImage(result, inScaleFactor, (inWidth, inHeight),
(meanVal, meanVal, meanVal), swapRB)
net.setInput(blob)
detections = net.forward()
。。. for i in range(detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence 》 thr:
class_id = int(detections[0, 0, i, 1])
。。. if class_id in classNames:
value_x = int(center[0])
value_y = int(center[1])
label = classNames[class_id] + “: ” +
“{0:.3f}”.format(distance_map[value_x, value_y] / 1000.0 * 0.3) + “ ” +
“meters”
。。. # Show image with object detection
cv.namedWindow(WINDOW_NAME, cv.WINDOW_AUTOSIZE)
cv.imshow(WINDOW_NAME, result)
Show Depth map
cv.namedWindow(WINDOW_NAME_DEPTH, cv.WINDOW_AUTOSIZE)
cv.imshow(WINDOW_NAME_DEPTH, depth_map)
清單 1:摘自 Analog Devices 的 3D ToF SDK 發行版中示例應用程序的代碼片段,展示了獲取深度和 IR
圖像并通過推理模型進行分類所需的幾個步驟。(代碼來源:Analog Devices)
該過程首先使用 OpenCV 的 DNN 方法 (cv.dnn.readNetFromCaffe) 讀取現有推理模型的網絡和相關權重。本例中的模型是Google MobileNet Single Shot Detector (SSD) 檢測網絡的 Caffe實現,該網絡以使用相對較小的模型大小實現高精度而聞名。在使用支持的類標識符和類標簽加載類名稱之后,該示例應用程序識別可用的相機并執行一系列初始化例程(未顯示在清單1 中)。
示例代碼的大部分內容是準備深度圖 (depth_map) 和 IR 圖 (ir_map),然后將其 (cv.addWeighted)合并成單個數組以提高精度。最后,代碼調用另一個 OpenCV DNN 方法 (cv.dnn.blobFromImage),該方法將合并的圖像轉換為推理所需的四維blob 數據類型。下一行代碼將得到的 blob 設置為推理模型的輸入 (net.setInput(blob))。對 net.forward()的調用將激活返回分類結果的推理模型。示例應用程序的其余部分識別超過預設閾值的分類結果,并為這些結果生成標簽和邊框,來顯示捕獲的圖像數據、由推理模型識別的標簽及其與相機的距離(圖 8)。
正如 Analog Devices 的 DNN 示例應用程序所示,開發人員可以結合使用 3D ToF深度圖與機器學習方法,來創建更復雜的應用功能。雖然要求低延遲響應的應用程序更有可能使用 C/C++ 來構建這些功能,但基本步驟是一樣的。
通過使用 3D ToF數據和高性能推理模型,工業機器人系統可以更安全地將其動作與其他設備同步,甚至在人與機器人緊密協作的“協作機器人”環境中與人同步。借助不同的推理模型,另一個應用程序可以使用高分辨率3D ToF 相機,對手勢界面涉及的精細動作進行分類。在汽車應用中,這種方法可以幫助提高高級輔助駕駛系統 (ADAS) 的精度,同時能充分利用 3D ToF系統提供的高時空分辨率。
總結
在幾乎所有依賴系統與其他物體之間距離精確測量的系統中,ToF 技術都起著關鍵作用。在諸多 ToF 技術中,光學 3D ToF可以同時提供高空間分辨率和高時間分辨率,因而能夠更精細地區分更小的物體,并對其相對距離進行更精確的監測。
但是,要利用這項技術,開發人員需要應對與這些系統的光學設計、精確定時和同步信號采集相關的多種挑戰。如本文所述,諸如 Analog Devices 的AD-96TOF1-EBZ 開發平臺和 ESPROS Photonics 的 EPC660 評估套件之類預置 3D ToF系統的推出,消除了將該技術應用于工業系統、手勢界面、汽車安全系統等領域的上述障礙。
-
CCD
+關注
關注
32文章
881瀏覽量
142260 -
接收器
+關注
關注
14文章
2472瀏覽量
71911 -
3D
+關注
關注
9文章
2878瀏覽量
107538 -
TOF
+關注
關注
9文章
483瀏覽量
36350 -
視頻成像
+關注
關注
0文章
3瀏覽量
6251
發布評論請先 登錄
相關推薦
評論