Intel景深攝影機Python程式詳解1-於NVIDIA Jetson Nano執行RealSense D435 範例

之前的教學文當中主要教學如何安裝與使用RealSense,本次針對RealSense的Python 範例進行詳解。現在市面上相當多專案都使用上RealSense了,越來越多人有撰寫客製化程式的需求,這邊就帶大家認識Intel提供的Sample Code以及我們可以稍微修改的內容吧!

*本文由RS components 贊助發表,轉載自DesignSpark部落格原文連結

作者/攝影 張嘉鈞
難度

★★☆☆☆(普通)

材料表

RK-NVIDIA® Jetson Nano™ Developer Kit B01 套件

 

目錄

  • 安裝RealSense Viewer
  • 安裝Pyrealsense2
  • Python 範例程式詳解
  • pyrealsense的基礎 ( python-tutorial-1-depth.py )
  • 透過opencv顯示pipeline的畫面 ( opencv_viewer_example.py )
  • 結語

 

安裝RealSense Viewer

要使用RealSense系列的攝影機建議先安裝 RealSense Viewer,有一些圖形化的選項參數可以做微調與顯示,沒有驅動的時候也會自動搜尋並安裝,每次我要安裝新系統都會先安裝Viewer,確認抓得到深度攝影機之後才會再安裝pyrealsense2。

 

安裝RealSense Viewer的方法很簡單,在 librealsense 這個Github當中有介紹如何使用Jetson Nano來安裝Viewer,我擷取幾個重點步驟,想要了解更詳細的資訊可以到下列網址:https://github.com/IntelRealSense/librealsense/blob/master/doc/installation_jetson.md

 

1.準備好你的 Jetson Nano

2.確保你的環境是 NVIDIA®L4T Ubuntu 16.04 / 18.043 ( NVIDIA 原廠提供的映象檔)

3.選擇 RealSense SDK 的後端 (Backend ):這步可省略,通常需要客製化的使用者才需要來改變後端的API,我們使用預設的就可以了。

4.註冊伺服器公鑰

[pastacode lang=”python” manual=”%24%20sudo%20apt-key%20adv%20–keyserver%20keys.gnupg.net%20–recv-key%20F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE%20%7C%7C%20sudo%20apt-key%20adv%20–keyserver%20hkp%3A%2F%2Fkeyserver.ubuntu.com%3A80%20–recv-key%20F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE” message=”” highlight=”” provider=”manual”/]

5.將伺服器加入repositories,待會透過apt-get去安裝才抓得到來源

Ubuntu 16請使用下列指令

[pastacode lang=”python” manual=”%24%20sudo%20add-apt-repository%20%22deb%20https%3A%2F%2Flibrealsense.intel.com%2FDebian%2Fapt-repo%20xenial%20main%22%20-u” message=”” highlight=”” provider=”manual”/]

Ubuntu 18 請使用下列指令

[pastacode lang=”python” manual=”%24%20sudo%20add-apt-repository%20%22deb%20https%3A%2F%2Flibrealsense.intel.com%2FDebian%2Fapt-repo%20bionic%20main%22%20-u” message=”” highlight=”” provider=”manual”/]

6.安裝SDK

[pastacode lang=”python” manual=”%24%20sudo%20apt-get%20install%20librealsense2-utils%0A%24%20sudo%20apt-get%20install%20librealsense2-dev” message=”” highlight=”” provider=”manual”/]

7.開啟RealSense Viewer,可於終端機中輸入指令開啟

[pastacode lang=”python” manual=”%24%20realsense-viewer” message=”” highlight=”” provider=”manual”/]

安裝Pyrealsense2

Pyrealsense是Intel RealSense的Python函式庫,透過這個函式庫可以開啟RealSense所有鏡頭以及取得到感測器的數值,對於Windows用戶,Intel已經提供 PyPI的發行版本可以透過 pip install pyrealsense2 來安裝,但是 Jetson Nano ( Ubuntu ) 只能從源頭安裝這個函式庫。

1.從源頭來安裝就需要將整個realsense的github下載下來:

[pastacode lang=”python” manual=”%24%20git%20clone%20https%3A%2F%2Fgithub.com%2FIntelRealSense%2Flibrealsense.git%0A%24%20cd%20librealsense” message=”” highlight=”” provider=”manual”/]

2. 確保apt-get的版本是最新的

[pastacode lang=”python” manual=”%24%20sudo%20apt-get%20update%20%26%26%20sudo%20apt-get%20upgrade” message=”” highlight=”” provider=”manual”/]

3.確保有安裝Python環境 ( 以Python3為例 )

[pastacode lang=”python” manual=”%24%20sudo%20apt-get%20install%20python3%20python3-dev” message=”” highlight=”” provider=”manual”/]

4.透過CMake建置,並且強制使用Python3 來編譯

[pastacode lang=”python” manual=”%24%20mkdir%20build%0A%24%20cd%20build%0A%24%20cmake%20..%2F%20-DBUILD_PYTHON_BINDINGS%3Abool%3Dtrue%20-DPYTHON_EXECUTABLE%3D%2Fusr%2Fbin%2Fpython3.6%0A%24%20make%20-j5%0A%24%20sudo%20make%20install%0A” message=”” highlight=”” provider=”manual”/]

5.將realsense的函式庫加入環境變數中

[pastacode lang=”python” manual=”%24%20nano%20~%2F.bashrc%0Aexport%20PYTHONPATH%3D%24PYTHONPATH%3A%2Fusr%2Flocal%2Flib%2Fpython3.6%2Fpyrealsense2″ message=”” highlight=”” provider=”manual”/]

6.接著可以導入函式庫,基本上沒報錯就沒問題了

[pastacode lang=”python” manual=”%24%20python3%0A%3E%3E%20import%20pyrealsense2%20as%20rs” message=”” highlight=”” provider=”manual”/]

 

Python 範例程式詳解

首先,先來丟個pyrealsense的文件,想要了解更多函式的用法建議一定要去看文件:https://intelrealsense.github.io/librealsense/python_docs/_generated/pyrealsense2.html

接著,這邊提供幾個範例程式的詳細解說,注意,此部分將不會放上完整程式碼,完整程式碼請至librealsense/wrappers/python/examples/ 中去查看:

 

Pyrealsense2基礎 ( python-tutorial-1-depth.py )

這個例子主要教學如何透過pyrealsense2開啟影像並擷取特定位置的深度資訊,此範例會將該即時影像劃之像素分成多個 10 x 20 的區域,並且將一公尺以內的深度影像轉換成文字模式,顯示結果如下。

首先我們需要導入函式庫:

[pastacode lang=”python” manual=”%23%20%E5%B0%8E%E5%85%A5%E5%87%BD%E7%A4%BA%E5%BA%AB%0A%0Aimport%20pyrealsense2%20as%20rs” message=”” highlight=”” provider=”manual”/]

使用pipline的方法存取RealSense攝影機並且透過config宣告基本的參數:

[pastacode lang=”python” manual=”try%3A%0A%20%20%20%20%0A%23%20%E5%BB%BA%E7%AB%8B%E4%B8%80%E5%80%8Bcontext%E7%89%A9%E4%BB%B6%E5%AD%98%E6%94%BE%E6%89%80%E6%9C%89%20RealSense%20%E7%9A%84%E8%99%95%E7%90%86%E5%87%BD%E7%A4%BA%0A%0A%20%20%20%20pipeline%20%3D%20rs.pipeline()%0A%0A%20%20%20%20%0A%23%20%E9%85%8D%E7%BD%AE%E4%B8%B2%E6%B5%81%E7%89%A9%E4%BB%B6%0A%0A%20%20%20%20config%20%3D%20rs.config()%0A%0A%20%20%20%20%0A%23%20%E5%AE%A3%E5%91%8A%E7%89%B9%E5%AE%9A%E8%A8%AD%E5%82%99%E9%80%B2%E8%A1%8C%E5%BD%B1%E5%83%8F%E4%B8%B2%E6%B5%81%20(%20%E5%AE%9A%E7%BE%A9%E7%9A%84%E7%9B%B8%E6%A9%9F%2C%20%E5%AF%AC%2C%20%E9%AB%98%2C%20realsense%E7%9A%84%E5%9E%8B%E6%85%8B%2C%20%E5%B9%80%E7%8E%87%20)%0A%0A%20%20%20%20config.enable_stream(rs.stream.depth%2C%20640%2C%20480%2C%20rs.format.z16%2C%2030)%0A%0A%20%20%20%20%0A%23%20%E9%96%8B%E5%95%9F%E5%BD%B1%E5%83%8F%E4%B8%B2%E6%B5%81%0A%0A%20%20%20%20pipeline.start(config)” message=”” highlight=”” provider=”manual”/]

接著因為是即時影像,所以需要使用While來運行,不斷的截取與處理新的影像,我們可以透過wait_for_frames取得最新的影像,因為我們一開始設定的pipeline是深度的攝影機 ( rs.stream.depth ),並且需要透過 get_depth_frame來取得深度影像,最後再做二次確認,如果沒有取得影像資訊後面的程式會報錯:

[pastacode lang=”python” manual=”%20%20%20%20%0A%23%20%E4%BD%BF%E7%94%A8%20While%20%E8%BF%B4%E5%9C%88%E4%B8%8D%E6%96%B7%E6%93%B7%E5%8F%96%E3%80%81%E8%99%95%E7%90%86%E6%96%B0%E7%9A%84%E5%BD%B1%E5%83%8F%0A%0A%20%20%20%20while%20True%3A%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%23%20%E7%AD%89%E5%BE%85%E6%9C%89%E6%96%B0%E7%9A%84%E5%BD%B1%E5%83%8F%E8%B3%87%E8%A8%8A%E6%89%8D%E7%B9%BC%E7%BA%8C%0A%0A%20%20%20%20%20%20%20%20frames%20%3D%20pipeline.wait_for_frames()%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%23%20%E5%8F%96%E5%BE%97%E6%B7%B1%E5%BA%A6%E5%BD%B1%E5%83%8F%0A%0A%20%20%20%20%20%20%20%20depth%20%3D%20frames.get_depth_frame()%0A%0A%20%20%20%20%20%20%20%20%20%0A%23%20%E7%A2%BA%E4%BF%9D%E6%9C%89%E7%8D%B2%E5%BE%97%E6%B7%B1%E5%BA%A6%E8%B3%87%E8%A8%8A%20%E5%90%A6%E5%89%87%E5%BE%8C%E7%BA%8C%E7%A8%8B%E5%BC%8F%E6%9C%83%E5%87%BA%E9%8C%AF%0A%0A%20%20%20%20%20%20%20%20if%20not%20depth%3A%20continue” message=”” highlight=”” provider=”manual”/]

將輸入圖片 ( 480 x 640 ) 劃分成 ( 20 x 10 ) 的像素區塊進行深度的解析並將一公尺以內的畫面轉換成文字顯示,這部份我們將分成兩個部分介紹,首先先宣告文字覆蓋的陣列 ( coverage ),接著我們使用兩個For迴圈將所有的像素都讀取過一次,在讀取的同時先取得深度訊息 ( get_distance ) 再判斷是否於一公尺內,如果是的話就針對 coverage 的內容「加1」,這邊演算法比較特別的地方是由於 coverage的長度是64所以我們必須以10個單位內的像素做一個總和 ( 640/10=64 ),舉例來說如果位置0~9的像素都是一公尺以內的話最後coverage[0] 的數值就是10:

[pastacode lang=”python” manual=”%23%20%E8%A6%86%E8%93%8B%E7%AF%84%E5%9C%8D%20%0A%0A%20%20%20%20%20%20%20%20coverage%20%3D%20%5B0%5D*64%0A%20%20%20%20%20%20%20%20%0A%23%20%E9%80%90%E5%80%8B%E5%83%8F%E7%B4%A0%20%E9%80%B2%E8%A1%8C%20%E8%B7%9D%E9%9B%A2%E6%AA%A2%E6%B8%AC%20(%20%E9%AB%98480%20%E5%AF%AC640)%0A%0A%20%20%20%20%20%20%20%20for%20y%20in%20range(480)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20x%20in%20range(640)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%23%20%E9%80%8F%E9%81%8E%20get_distance%20%E5%8F%96%E5%BE%97%E8%A9%B2%E5%BA%A7%E6%A8%99%E7%9A%84%E6%B7%B1%E5%BA%A6%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20dist%20%3D%20depth.get_distance(x%2C%20y)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%23%20%E5%A6%82%E6%9E%9C%E7%89%A9%E4%BB%B6%E5%9C%A8%E4%B8%80%E5%85%AC%E5%B0%BA%E4%BB%A5%E5%85%A7%20%E5%B0%B1%E6%8A%8ACoverage%E5%A1%AB%E4%B8%8A%201%20%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%200%20%3C%20dist%20and%20dist%20%3C%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%23%20640(%E5%9C%96%E7%89%87)%20%2F%2F%2010(%E5%AD%97%E4%B8%B2%E9%95%B7%E5%BA%A6)%20%3D%2064%20(%20Coverage%E5%A4%A7%E5%B0%8F)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20coverage%5Bx%2F%2F10%5D%20%2B%3D%201″ message=”” highlight=”” provider=”manual”/]

我們在上述程式中處理了10 x 20像素區域10的部分,接著要處理20的部分並且最後要將文字顯示出來,因為像素區域高是20並且位置是從0開始所以我們取20的餘數等於19來判斷是否20行了,這裡我們需要將深度資訊轉換成文字內容,所以先宣告了一個line來存放文字資訊,接著去解析長度為64的coverage內容,針對coverage的內容整除25來轉換成文字,這邊除以25的部分我個人認為是為了讓輸出的文字模式圖像比例較為正常,最後再刷新coverage:

[pastacode lang=”python” manual=”%23%20%E8%A8%88%E7%AE%97%E4%BA%8620%E8%A1%8C%E7%9A%84%E6%B7%B1%E5%BA%A6%E5%BE%8C%20%E9%A1%AF%E7%A4%BA%E4%B8%80%E6%AC%A1%20coverage%20%E4%B8%A6%E5%88%B7%E6%96%B0%20%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20y%2520%20is%2019%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20line%20%3D%20%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20c%20in%20coverage%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%23%20%E6%95%B4%E9%99%A425%E7%A8%8D%E5%BE%AE%E6%95%B4%E7%90%86%E4%B8%80%E4%B8%8B%EF%BC%8C%E8%AE%93%E5%85%B6%E6%AF%94%E4%BE%8B%E7%9C%8B%E8%B5%B7%E4%BE%86%E8%BC%83%E5%83%8F%E6%AD%A3%E5%B8%B8%E7%9A%84%E5%9C%96%E5%83%8F%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20line%20%2B%3D%20%22%20.%3AnhBXWW%22%5Bc%2F%2F25%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%23%20%E5%88%B7%E6%96%B0%20coverage%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20coverage%20%3D%20%5B0%5D*64%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(line)” message=”” highlight=”” provider=”manual”/]

透過opencv顯示pipeline的畫面

( opencv_viewer_example.py )

這個範例的重點在於「如何同時開啟深度與RGB攝影機」、「如何轉換成OpenCV並且將其顯示出來」,那就讓我們開始解析程式吧!

首先導入函式庫以及宣告pipeline跟config:

[pastacode lang=”python” manual=”%23%20%E5%B0%8E%E5%85%A5%E5%87%BD%E5%BC%8F%E5%BA%AB%0A%0Aimport%20pyrealsense2%20as%20rs%0Aimport%20numpy%20as%20np%0Aimport%20cv2%0A%0A%23%20%E5%BB%BA%E7%AB%8B%E4%B8%80%E5%80%8Bcontext%E7%89%A9%E4%BB%B6%E5%AD%98%E6%94%BE%E6%89%80%E6%9C%89%20RealSense%20%E7%9A%84%E8%99%95%E7%90%86%E5%87%BD%E7%A4%BA%0A%0Apipeline%20%3D%20rs.pipeline()%0A%0A%23%20%E9%85%8D%E7%BD%AE%E4%B8%B2%E6%B5%81%E7%89%A9%E4%BB%B6%0A%0Aconfig%20%3D%20rs.config()” message=”” highlight=”” provider=”manual”/]

接著這邊提供了取得設備資訊的方式,最後的 device_product_line 包含了首個可用設備的名稱:

[pastacode lang=”python” manual=”%23%20%E5%8F%AF%E4%BB%A5%E9%80%8F%E9%81%8E%E4%B8%8B%E5%88%97%E7%A8%8B%E5%BC%8F%E5%8F%96%E5%BE%97%E8%A8%AD%E5%82%99%E8%B3%87%E8%A8%8A%0A%0A%23%20%E9%80%8F%E9%81%8E%20resolve%20%E7%A2%BA%E8%AA%8D%E7%AC%AC%E4%B8%80%E5%80%8B%E5%8F%AF%E7%94%A8%E7%9A%84%E8%A8%AD%E5%82%99%0A%0Apipeline_wrapper%20%3D%20rs.pipeline_wrapper(pipeline)%0Apipeline_profile%20%3D%20config.resolve(pipeline_wrapper)%0A%0A%23%20%E5%8F%96%E5%BE%97%E8%A9%B2%E8%A8%AD%E5%82%99%E8%B3%87%E8%A8%8A%0A%0Adevice%20%3D%20pipeline_profile.get_device()%0Adevice_product_line%20%3D%20str(device.get_info(rs.camera_info.product_line))” message=”” highlight=”” provider=”manual”/]

接著要宣告影像串流,這次範例提供了深度與RGB影像,但因為L500系列之RGB攝影機解析度與其他系列不同,所以才需要取得攝影機名稱,這裡我們需要加上一個判斷,如果L500系列則RGB影像串流需要設定成960 x 540:

[pastacode lang=”python” manual=”%23%20%E5%BB%BA%E7%AB%8B%E3%80%8C%E6%B7%B1%E5%BA%A6%E3%80%8D%E5%BD%B1%E5%83%8F%E4%B8%B2%E6%B5%81%0A%0Aconfig.enable_stream(rs.stream.depth%2C%20640%2C%20480%2C%20rs.format.z16%2C%2030)%0A%0A%23%20%E5%BB%BA%E7%AB%8B%E3%80%8C%E5%BD%A9%E8%89%B2%E3%80%8D%E5%BD%B1%E5%83%8F%E4%B8%B2%E6%B5%81%0A%0A%23%20%E7%94%B1%E6%96%BC%20L500%20%E7%B3%BB%E5%88%97%E7%9A%84%E5%BD%A9%E8%89%B2%E6%94%9D%E5%BD%B1%E6%A9%9F%E8%A7%A3%E6%9E%90%E5%BA%A6%E7%B6%AD%20960%20x%20540%20%E6%89%80%E4%BB%A5%E6%89%8D%E9%9C%80%E8%A6%81%E5%8F%96%E5%BE%97%E8%A8%AD%E5%82%99%E8%B3%87%E8%A8%8A%0A%0Aif%20device_product_line%20%3D%3D%20’L500’%3A%0A%20%20%20%20config.enable_stream(rs.stream.color%2C%20960%2C%20540%2C%20rs.format.bgr8%2C%2030)%0Aelse%3A%0A%20%20%20%20config.enable_stream(rs.stream.color%2C%20640%2C%20480%2C%20rs.format.bgr8%2C%2030)” message=”” highlight=”” provider=”manual”/]

接著就可以開始串流並且取得最新的影像資訊:

[pastacode lang=”python” manual=”%23%20%E9%96%8B%E5%95%9F%E5%BD%B1%E5%83%8F%E4%B8%B2%E6%B5%81%0A%0Apipeline.start(config)%0A%0Atry%3A%0A%20%20%20%20%0A%20%20%20%20while%20True%3A%0A%0A%20%20%20%20%20%20%20%20%0A%23%20%E7%AD%89%E5%BE%85%E6%9C%80%E6%96%B0%E7%9A%84%E5%BD%B1%E5%83%8F%EF%BC%8Cwait_for_frames%E8%BF%94%E5%9B%9E%E7%9A%84%E6%98%AF%E4%B8%80%E5%80%8B%E5%90%88%E6%88%90%E7%9A%84%E5%BD%B1%E5%83%8F%0A%0A%20%20%20%20%20%20%20%20frames%20%3D%20pipeline.wait_for_frames()%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%23%20%E5%8F%AF%E4%BB%A5%E9%80%8F%E9%81%8E%E4%B8%8B%E5%88%97%E5%87%BD%E5%BC%8F%E5%90%84%E8%87%AA%E5%8F%96%E5%BE%97%E6%B7%B1%E5%BA%A6%E6%88%96%E5%BD%A9%E8%89%B2%E5%BD%B1%E5%83%8F%0A%0A%20%20%20%20%20%20%20%20depth_frame%20%3D%20frames.get_depth_frame()%0A%20%20%20%20%20%20%20%20color_frame%20%3D%20frames.get_color_frame()%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%23%20%E7%A2%BA%E4%BF%9D%E6%98%AF%E5%90%A6%E6%9C%89%E5%8F%96%E5%BE%97%E5%BD%B1%E5%83%8F%0A%0A%20%20%20%20%20%20%20%20if%20not%20depth_frame%20or%20not%20color_frame%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20continue” message=”” highlight=”” provider=”manual”/]

接著就是如何讓OpenCV可以顯示的部分了,首先要先來解決數據格式的問題,因為OpenCV吃的是Numpy格式所以我們需要先將其轉換成numpy array:

[pastacode lang=”python” manual=”%23%20%E7%94%B1%E6%96%BC%20Opencv%20%E9%A1%AF%E7%A4%BA%E6%A0%BC%E5%BC%8F%E7%82%BA%20numpy%20%E6%89%80%E4%BB%A5%E9%9C%80%E8%A6%81%E8%BD%89%E6%8F%9B%E6%88%90%20nparray%0A%0A%20%20%20%20%20%20%20%20depth_image%20%3D%20np.asanyarray(depth_frame.get_data())%0A%20%20%20%20%20%20%20%20color_image%20%3D%20np.asanyarray(color_frame.get_data())” message=”” highlight=”” provider=”manual”/]

接著處理深度影像資訊的色彩格式,這部分稍微複雜了一些,先介紹一下功能,這邊會使用 cv2. convertScaleAbs將深度數值縮放到0~255之間並轉換成uint 8 的數據型態,再透過 applyColorMap將顏色對應上數值:

[pastacode lang=”python” manual=”%23%20%E5%A6%82%E6%9E%9C%E8%A6%81%E9%A1%AF%E7%A4%BA%E6%B7%B1%E5%BA%A6%E5%BD%B1%E5%83%8F%E9%9C%80%E8%A6%81%E5%B0%87%E5%85%B6%E8%BD%89%E6%8F%9B%E6%88%90%208-bit%20%E7%9A%84%E5%BD%B1%E5%83%8F%E6%A0%BC%E5%BC%8F%0A%0A%20%20%20%20%20%20%20%20depth_colormap%20%3D%20cv2.applyColorMap(cv2.convertScaleAbs(depth_image%2C%20alpha%3D0.03)%2C%20cv2.COLORMAP_JET)%0A%20″ message=”” highlight=”” provider=”manual”/]

最後因為深度攝影機與RGB攝影機解析度不同的關係,需要將輸出圖片進行縮放才能夠合併在一起,需要先取得彼此維度 ( shape ),經過判斷之後再使用一般的 cv2.resize就可以縮放特定圖片了:

[pastacode lang=”python” manual=”%20%20%20%20%20%20%20%20%0A%23%20%E5%8F%96%E5%BE%97%E5%BD%B1%E5%83%8F%E7%9A%84%E7%B6%AD%E5%BA%A6%0A%0A%20%20%20%20%20%20%20%20depth_colormap_dim%20%3D%20depth_colormap.shape%0A%20%20%20%20%20%20%20%20color_colormap_dim%20%3D%20color_image.shape%0A%0A%20%20%20%20%20%20%20%20%0A%23%20%E5%A6%82%E6%9E%9C%E7%B6%AD%E5%BA%A6%E4%B8%8D%E5%90%8C%E7%9B%B4%E6%8E%A5%E5%B0%87%20%E5%BD%A9%E8%89%B2%E5%9C%96%E7%89%87%20%E9%80%B2%E8%A1%8C%20%E7%B8%AE%E6%94%BE%EF%BC%8C%E6%9C%80%E5%BE%8C%E5%86%8D%E6%B0%B4%E5%B9%B3%E5%90%88%E4%BD%B5%20(%20hstack%20)%0A%0A%20%20%20%20%20%20%20%20if%20depth_colormap_dim%20!%3D%20color_colormap_dim%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20resized_color_image%20%3D%20cv2.resize(color_image%2C%20dsize%3D(depth_colormap_dim%5B1%5D%2C%20depth_colormap_dim%5B0%5D)%2C%20interpolation%3Dcv2.INTER_AREA)%0A%20%20%20%20%20%20%20%20%20%20%20%20images%20%3D%20np.hstack((resized_color_image%2C%20depth_colormap))%0A%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20images%20%3D%20np.hstack((color_image%2C%20depth_colormap))” message=”” highlight=”” provider=”manual”/]

接著就可以顯示合併後的圖片了:

[pastacode lang=”python” manual=”%23%20%E9%A1%AF%E7%A4%BA%E5%9C%96%E7%89%87%0A%0A%20%20%20%20%20%20%20%20cv2.namedWindow(‘RealSense’%2C%20cv2.WINDOW_AUTOSIZE)%0A%20%20%20%20%20%20%20%20cv2.imshow(‘RealSense’%2C%20images)%0A%20%20%20%20%20%20%20%20cv2.waitKey(1)” message=”” highlight=”” provider=”manual”/]

針對convertScaleAbs 可以有一些更深入的理解,這個函式的目的是將數值縮限到0~255之間並且計算絕對值後轉換成 uint-8 的數據形式,公式如下:

我們可以透過控制 alpha值來計算最後顯示的顏色最大距離是多少,寫一個簡單的程式來計算一下,我先宣告了一個簡單的陣列 (a),並且控制了b_alpha跟c_alpha的數值,各別為0.05、0.03,進行covert之後再顯示出來。

[pastacode lang=”python” manual=”import%20cv2%0A%0Adef%20count_dis(alpha)%3A%0A%20%20%20%20return%20(255%2Falpha)%0A%0Aa%20%3D%20np.asarray(%20%5B%5B6000%2C%201000%2C%200%2C%20-100%2C%208000%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B5000%2C%20100%20%2C%207500%2C%2060%2C%205%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B50%2C%20-1000%2C%20225%2C%2043%2C%20192%5D%5D%20)%0A%0Aprint(‘%5CnOriginal’)%0Aprint(a)%0A%0Ab_alpha%20%3D%200.05%0Aprint(f’%5CnAlpha%20%3A%20%7Bb_alpha%7D%2C%5CtMax%20distance%20%3A%20%7Bcount_dis(b_alpha)%7D’)%0Ab%20%3D%20cv2.convertScaleAbs(a%2C%20alpha%3Db_alpha)%0Aprint(b)%0A%0Ac_alpha%20%3D%200.03%0Aprint(f’%5CnAlpha%20%3A%20%7Bc_alpha%7D%2C%5CtMax%20distance%20%3A%20%7Bcount_dis(c_alpha)%7D’)%0Ac%20%3D%20cv2.convertScaleAbs(a%2C%20alpha%3Dc_alpha)%0Aprint(c)” message=”” highlight=”” provider=”manual”/]

顯示結果如下,可以注意到當alpha值為0.05最大距離數值為5100,所以大於5100都會被標為255,此外由於有絕對值所以負值都會被轉換成正值,1000跟 (-1000) 的數值都轉換後的都是50:

我們用更直觀的方式來了解,這邊使用的是D435,由於轉換後的數值會影響ColorMap的結果,所以我們一樣使用0.03跟0.05來測試一下,先給予cv2.COLORMAP_JET的色度圖如下

可以看到由於數值0.03的時候最大距離為8公尺,我距離門只有2公尺所以顏色分布都還在前半段,可以想像將色度圖切成八等分去抓顏色分布;而數值0.05最大距離為5公尺,所以2公尺處顏色分布會落在偏中間也就是綠色的位置:

Alpha : 0.03 Alpha : 0.05

 

我們將會在下一篇介紹其他功能:

  1. 對齊RGB跟Depth畫面並去除背景 ( align-depth2color.py )
  2. 解決掉幀問題 ( frame_queue_example.py )
  3. 讀取預錄好的深度影像方式 ( read_bag_example.py )

結語

在這篇我們學會怎麼在Jetson Nano上安裝RealSense Viewer以及Python函式庫 pyrealsense2,除此之外還深入了解了兩個範例程式的內容,下一篇將把剩餘的範例程式一一介紹完,後續也會撰寫一些簡單的程式給大家參考。

 

相關文章

 

*本文由RS components 贊助發表,轉載自DesignSpark部落格原文連結

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *