Quantcast
Channel: CAVEDU教育團隊技術部落格
Viewing all 678 articles
Browse latest View live

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

$
0
0

之前的教學文當中主要教學如何安裝與使用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.註冊伺服器公鑰

$ sudo apt-key adv --keyserver keys.gnupg.net --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE || sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE

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

Ubuntu 16請使用下列指令

$ sudo add-apt-repository "deb https://librealsense.intel.com/Debian/apt-repo xenial main" -u

Ubuntu 18 請使用下列指令

$ sudo add-apt-repository "deb https://librealsense.intel.com/Debian/apt-repo bionic main" -u

6.安裝SDK

$ sudo apt-get install librealsense2-utils
$ sudo apt-get install librealsense2-dev

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

$ realsense-viewer

安裝Pyrealsense2

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

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

$ git clone https://github.com/IntelRealSense/librealsense.git
$ cd librealsense

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

$ sudo apt-get update && sudo apt-get upgrade

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

$ sudo apt-get install python3 python3-dev

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

$ mkdir build
$ cd build
$ cmake ../ -DBUILD_PYTHON_BINDINGS:bool=true -DPYTHON_EXECUTABLE=/usr/bin/python3.6
$ make -j5
$ sudo make install

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

$ nano ~/.bashrc
export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3.6/pyrealsense2

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

$ python3
>> import pyrealsense2 as rs

 

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 的區域,並且將一公尺以內的深度影像轉換成文字模式,顯示結果如下。

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

# 導入函示庫

import pyrealsense2 as rs

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

try:
    
# 建立一個context物件存放所有 RealSense 的處理函示

    pipeline = rs.pipeline()

    
# 配置串流物件

    config = rs.config()

    
# 宣告特定設備進行影像串流 ( 定義的相機, 寬, 高, realsense的型態, 幀率 )

    config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)

    
# 開啟影像串流

    pipeline.start(config)

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

    
# 使用 While 迴圈不斷擷取、處理新的影像

    while True:
        
        
# 等待有新的影像資訊才繼續

        frames = pipeline.wait_for_frames()
        
        
# 取得深度影像

        depth = frames.get_depth_frame()

         
# 確保有獲得深度資訊 否則後續程式會出錯

        if not depth: continue

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

# 覆蓋範圍 

        coverage = [0]*64
        
# 逐個像素 進行 距離檢測 ( 高480 寬640)

        for y in range(480):
            for x in range(640):
                
# 透過 get_distance 取得該座標的深度

                dist = depth.get_distance(x, y)
                
# 如果物件在一公尺以內 就把Coverage填上 1 

                if 0 < dist and dist < 1:
                    
# 640(圖片) // 10(字串長度) = 64 ( Coverage大小)

                    coverage[x//10] += 1

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

# 計算了20行的深度後 顯示一次 coverage 並刷新 

            if y%20 is 19:
                line = ""
                for c in coverage:
                    
# 整除25稍微整理一下,讓其比例看起來較像正常的圖像

                    line += " .:nhBXWW"[c//25]
                
# 刷新 coverage

                coverage = [0]*64
                print(line)

透過opencv顯示pipeline的畫面

( opencv_viewer_example.py )

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

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

# 導入函式庫

import pyrealsense2 as rs
import numpy as np
import cv2

# 建立一個context物件存放所有 RealSense 的處理函示

pipeline = rs.pipeline()

# 配置串流物件

config = rs.config()

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

# 可以透過下列程式取得設備資訊

# 透過 resolve 確認第一個可用的設備

pipeline_wrapper = rs.pipeline_wrapper(pipeline)
pipeline_profile = config.resolve(pipeline_wrapper)

# 取得該設備資訊

device = pipeline_profile.get_device()
device_product_line = str(device.get_info(rs.camera_info.product_line))

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

# 建立「深度」影像串流

config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)

# 建立「彩色」影像串流

# 由於 L500 系列的彩色攝影機解析度維 960 x 540 所以才需要取得設備資訊

if device_product_line == 'L500':
    config.enable_stream(rs.stream.color, 960, 540, rs.format.bgr8, 30)
else:
    config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)

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

# 開啟影像串流

pipeline.start(config)

try:
    
    while True:

        
# 等待最新的影像,wait_for_frames返回的是一個合成的影像

        frames = pipeline.wait_for_frames()
        
        
# 可以透過下列函式各自取得深度或彩色影像

        depth_frame = frames.get_depth_frame()
        color_frame = frames.get_color_frame()
        
        
# 確保是否有取得影像

        if not depth_frame or not color_frame:
            continue

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

# 由於 Opencv 顯示格式為 numpy 所以需要轉換成 nparray

        depth_image = np.asanyarray(depth_frame.get_data())
        color_image = np.asanyarray(color_frame.get_data())

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

# 如果要顯示深度影像需要將其轉換成 8-bit 的影像格式

        depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
 

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

        
# 取得影像的維度

        depth_colormap_dim = depth_colormap.shape
        color_colormap_dim = color_image.shape

        
# 如果維度不同直接將 彩色圖片 進行 縮放,最後再水平合併 ( hstack )

        if depth_colormap_dim != color_colormap_dim:
            resized_color_image = cv2.resize(color_image, dsize=(depth_colormap_dim[1], depth_colormap_dim[0]), interpolation=cv2.INTER_AREA)
            images = np.hstack((resized_color_image, depth_colormap))
        else:
            images = np.hstack((color_image, depth_colormap))

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

# 顯示圖片

        cv2.namedWindow('RealSense', cv2.WINDOW_AUTOSIZE)
        cv2.imshow('RealSense', images)
        cv2.waitKey(1)

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

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

import cv2

def count_dis(alpha):
    return (255/alpha)

a = np.asarray( [[6000, 1000, 0, -100, 8000],
                [5000, 100 , 7500, 60, 5],
                [50, -1000, 225, 43, 192]] )

print('\nOriginal')
print(a)

b_alpha = 0.05
print(f'\nAlpha : {b_alpha},\tMax distance : {count_dis(b_alpha)}')
b = cv2.convertScaleAbs(a, alpha=b_alpha)
print(b)

c_alpha = 0.03
print(f'\nAlpha : {c_alpha},\tMax distance : {count_dis(c_alpha)}')
c = cv2.convertScaleAbs(a, alpha=c_alpha)
print(c)

顯示結果如下,可以注意到當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部落格原文連結


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

$
0
0

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

作者/攝影 張嘉鈞
難度

★★☆☆☆(普通)

材料表

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

 

目錄

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

對齊RGB跟Depth畫面並去除背景 ( align-depth2color.py )

這個範例呈現如何將一公尺以外的內容進行去背,此範例的核心價值在於深度影像跟彩色影像如何對齊,對齊後又該使用什麼方式去除背景。

首先,先導入函式庫與宣告 RealSense物件 ( pipeline ) 與定義串流物件 ( config ):

# 導入函式庫

import pyrealsense2 as rs
import numpy as np
import cv2

# 建立一個context物件存放所有 RealSense 的處理函示

pipeline = rs.pipeline()

# 配置串流物件

config = rs.config()

 

接著可以透過wrapper去確認接上去的設備是L500系列還是D400系列,進而去調整RGB攝影機的解析度,最後定義完就可以開啟影像串流,細部的介紹可以參閱上篇程式詳解之內容:

# 可以透過下列程式取得設備資訊

# 透過 resolve 確認第一個可用的設備

pipeline_wrapper = rs.pipeline_wrapper(pipeline)
pipeline_profile = config.resolve(pipeline_wrapper)

# 取得該設備資訊

device = pipeline_profile.get_device()
device_product_line = str(device.get_info(rs.camera_info.product_line))

# 建立「深度」影像串流

config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30) 
# uint 16


# 建立「彩色」影像串流

# 由於 L500 系列的彩色攝影機解析度維 960 x 540 所以才需要取得設備資訊

if device_product_line == 'L500':
    config.enable_stream(rs.stream.color, 960, 540, rs.format.bgr8, 30)
else:
    config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 30)

# 開啟影像串流

profile = pipeline.start(config)

再來就是我們這次範例的重頭戲了 – 對齊,這邊要對齊的不僅是影像也有深度資訊,RealSense感測器獲得的深度資訊如何轉換成實際的公尺單位?深度影像跟RGB影像如何進行畫面對齊?

首先,先來處理深度單位的轉換,我們先取得深度感測器的物件,透過get_depth_scale取得到「RealSense的深度資訊與實際公尺單位的轉換比例」,接著我們要求一公尺以外的資訊要進行去背,所以定義了 clipping_distance_in_meters,但現在定義的是公尺單位需要轉換成深度資訊,所以這邊會再除以剛剛透過get_depth_scale取得到的數值,這樣就能成功轉換成對應的RealSense深度數值了:

# 取得深度感測器物件

depth_sensor = profile.get_device().first_depth_sensor()
# 取得深度感測器的 深度資訊與實際公尺之間的 映射尺度 

# get_depth_scale -> Retrieves mapping between the units of the depth image and meters

depth_scale = depth_sensor.get_depth_scale()
print("Depth Scale is: " , depth_scale)

# 宣告多少公尺以內的資訊要顯示

clipping_distance_in_meters = 1 
#1 meter

# 將 公尺資訊 轉換成 RealSense 的 深度單位 

clipping_distance = clipping_distance_in_meters / depth_scale

緊接著就要來處理深度影像跟彩色影像的對齊,當初在opencv_viewer那個範例我們為了顯示在一起會使用cv2.resize的方式,但是並不是最好的做法 ( 圖片會被壓縮變形 ),pyrealsense提供的對齊方式是align,我們可以透過 rs.align()去處理深度影像需要對齊的內容,這邊就是以彩色影像 ( rs.stream.color )為基礎進行對齊,最後可以使用 process() 來實現對齊的動作,後續會再說明:

# 建立 對齊 物件 ( 以 color 為基準 )

align_to = rs.stream.color
# rs.align 讓 深度圖像 跟 其他圖像 對齊

align = rs.align(align_to)

# 使用 process 來實現剛剛宣告的 align 對齊功能

# aligned_frames = align.process(frames)

上面定義完之後就可以進行即時影像的擷取與處理了,一樣透過 wait_for_frames等待最新的複合式影像物件( frames) 包含彩色影像跟深度影像,接著直接使用 align.process 將深度影像對齊彩色影像:

# 串流迴圈

try:
    while True:
        
        
# 等待最新的影像,wait_for_frames返回的是一個合成的影像

        frames = pipeline.wait_for_frames()
        
# frames.get_depth_frame() is a 640x360 depth image


        
# 使用 process 來實現剛剛宣告的 align 對齊功能

        aligned_frames = align.process(frames)

對齊完之後就可以透過get_depth_frames跟get_color_frames來取得影像了,這邊我也取得了原先的影像,最後註解的地方如果解除註解就會看到原先的解析度跟轉換後的解析度:

# 取得對齊後的影像

        depth_frame = frames.get_depth_frame()
        aligned_depth_frame = aligned_frames.get_depth_frame() 
# aligned_depth_frame is a 640x480 depth image

        color_frame = aligned_frames.get_color_frame()

        
# 驗證是否都有影像

        if not aligned_depth_frame or not color_frame:
            continue

        
# 轉換成 numpy 

        depth_image = np.asanyarray(aligned_depth_frame.get_data())
        color_image = np.asanyarray(color_frame.get_data())

        
# 顯示解析度

        
# print('Org (L500) : ', np.shape(np.asanyarray(depth_frame.get_data())), end='\t')

        
# print('After align : ', np.shape(np.asanyarray(aligned_depth_frame.get_data())))

 

註解掉之後可以發現,解析度從原本的 640×480變成了 960×540:

 

緊接著就是去背問題,我們可以直接透過dstack的方式去將一個維度的資料複製成三個維度 (範例結尾有補充說明),這樣影像的資訊就好比一張灰階照片,接著使用 np.where即可進行條件去背。這邊要注意的是depth_image_3d裡面的數值代表的還是屬於深度資訊;np.where(condition, x, y) 滿足 condition 輸出 x 否則輸出 y,滿足距離大於1公尺以及辨識不出來這兩個條件的就輸出 grey_color,沒有滿足的就輸出 color_image:

# 刪除背景 : 將背景顏色調整成 灰色 

        grey_color = 153
        
# 深度影像只有 1 個 channel,透過 dstack 建立 灰階圖 ( 這邊RGB的數值就是 深度訊息 )

        depth_image_3d = np.dstack((depth_image, depth_image, depth_image)) 
#depth image is 1 channel, color is 3 channels

    
        
# 當 深度大於 1 公尺 或是 偵測不出來 就會 以 grey_color 取代

        bg_removed = np.where((depth_image_3d > clipping_distance) | (depth_image_3d <= 0), grey_color, color_image)

最後將深度圖跟去背圖合併並且當偵測到按下按鈕「q」就會關閉所有視窗:

# 將深度影像轉換成 彩色影像

        depth_colormap = cv2.applyColorMap(cv2.convertScaleAbs(depth_image, alpha=0.03), cv2.COLORMAP_JET)
        
# 合併圖像 左為去背圖,右為深度圖

        images = np.hstack((bg_removed, depth_colormap))

        
# cv2.namedWindow('Align Example', cv2.WINDOW_NORMAL)

        cv2.imshow('Align Example', images)
        key = cv2.waitKey(1)
        
# Press esc or 'q' to close the image window

        if key & 0xFF == ord('q') or key == 27:
            cv2.destroyAllWindows()
            break
finally:
    pipeline.stop()

到這邊這個範例就結束了!

我在稍微針對np.dstack進行補充說明,下列範例是一個2x2的深度影像資訊,我們可以透過dstack轉換成三維度的影像:

import numpy as np

a = np.asanyarray( [[8000, 2000],
                    [0, 125]])

b = np.dstack((a,a,a))

print(a.shape, b.shape)
print('\n')
print(a)
print('\n')
print(b)
 

顯示的結果如下,原本是 ( 2, 2, 1) 變成了 ( 2, 2, 3):

而使用OpenCV顯示的話會類似下圖:

解決掉幀問題 ( frame_queue_example.py )

當我們在進行多個影像串流的時候總是會發生延遲問題導致掉幀,RealSense也提供了一些簡單的方式來處理這個問題。

首先要先製造掉幀的現象,這邊撰寫了slow_processing、slower_processing來模擬掉幀現象,這邊輸入的是影像物件,透過get_frame_number可以獲取現在的影像是第幾幀,於slow_processing我們每20幀就會暫停0.25秒;slower_processing則是每20幀就暫停1秒,用這種方式來模擬掉幀狀況:

# First import the library

import pyrealsense2 as rs
import time

# 每20個frame會暫停0.25秒 製造短暫的延遲

def slow_processing(frame):
    n = frame.get_frame_number() 
    if n % 20 == 0:
        time.sleep(1/4)
    print(n)
# 製造更延遲的狀況

def slower_processing(frame):
    n = frame.get_frame_number() 
    if n % 20 == 0:
        time.sleep(1)
    print(n)

接著與先前一樣先取得RealSense的物件並且宣告影像串流物件:

try:
    
# Create a pipeline

    pipeline = rs.pipeline()

    
# Create a config and configure the pipeline to stream

    
#  different resolutions of color and depth streams

    config = rs.config()
    config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)

接下來會分成幾個部分來展示延遲以及改善的方式,一開始我們先確認之前寫的延遲程式有無問題,運行 slow_processing 5秒看成效如何:

   print("Slow callback")
    
# 開始影像串流

    pipeline.start(config)
    
# 讓 slow_processing 運行5秒就好

    start = time.time()
    while time.time() - start < 5:
        
# 取得最新的影像物件

        frames = pipeline.wait_for_frames()
        
# 運行slow_processing

        slow_processing(frames)
    
# 關閉RealSense物件

    pipeline.stop()

成果如下,可以注意到當frame數到20的時候下一刻會變成27代表這0.25秒中間遺失了7個frame:

接著我們可以加上 queue 來將被丟失的幀存放在記憶體當中,frame_queue( ) 括弧當中的數值代表可以保存的幀數:

# 加上 queue 

    print("Slow callback + queue")
    
# frame_queue(n) n 是可以保留多少幀,這邊保留了50幀的空間

    queue = rs.frame_queue(50)
    
# 開啟串流

    pipeline.start(config, queue)
    
# 執行五秒

    start = time.time()
    while time.time() - start < 5:
        frames = queue.wait_for_frame()
        
# 一樣使用 slow_processing

        slow_processing(frames)

結果如下,可以發現原本的在第20幀的時候會因為延遲而丟失7幀,加上了queue之後就沒有這樣的問題了,那待我們再來測試一下延遲更久的狀況:

一樣的程式碼只是我們將slow_processing 改成 slower_processing:

    print("Slower callback + queue")
    queue = rs.frame_queue(50)
    pipeline.start(config, queue)
    start = time.time()
    while time.time() - start < 5:
        frames = queue.wait_for_frame()
        slower_processing(frames)
    pipeline.stop()

結果如下,可以注意到雖然queue設到50但是因為延遲時間太久所以會導致queue無法進行備份最後直接捨棄掉pool裡的幀:

最後解決這種問題的方法就是keep_frames,我們在宣告frame_queue的時候加上這個參數,讓queue裡面的幀會被保留住:

    print("Slower callback + keeping queue")
    queue = rs.frame_queue(50, keep_frames=True)
    pipeline.start(config, queue)
    start = time.time()
    while time.time() - start < 5:
        frames = queue.wait_for_frame()
        slower_processing(frames)
    pipeline.stop()

這個範例如果介紹的有錯誤或不夠清楚,請在下方留言,也可以參考原廠資料:https://intelrealsense.github.io/librealsense/python_docs/_generated/pyrealsense2.frame_queue.html#pyrealsense2.frame_queue

錄製深度影像 (.bag)

介紹之前先講一下 rosbag (http://wiki.ros.org/rosbag),他是基於ROS所開發的一個紀錄工具,可以記錄機器人運行的數據資料以及影像等等的資訊。那可能因為RealSense開發者大部分是以機器人為主所以他們也直接使用相關的紀錄方式。

要錄製深度影響其實非常的簡單,你只需要在宣告config之後,在宣告enable_record_to_file() 即可,括弧當中應輸入檔案名稱,範例如下。

# 建立一個context物件存放所有 RealSense 的處理函示

pipeline = rs.pipeline()

# 配置串流物件

config = rs.config()
# 建立「深度」影像串流

config.enable_stream(rs.stream.depth, 640, 480, rs.format.z16, 30)

# 將影像數據輸出到 test.bag 當中

config.enable_record_to_file('test.bag')

具體程式可以使用opencv_viewer_example.py來修改,成果在read_bag_example的demo可以看到 ( 下一個範例 ),我自己錄製的畫面。

 

讀取預錄好的深度影像方式( read_bag_example.py )

基本上看到這裡一些基本的動作讀者們應該都知道了,所以我這邊註解會少一些,第一步基本上就是導入函式以及宣告pipeline等等的,比較特別的是這邊config要增加一段 enable_device_from_file(config, ‘test.bag’),告訴config資料要從這個檔案讀取,而不是RealSense:

import pyrealsense2 as rs
import numpy as np
import cv2
import argparse
import os.path

try:
    pipeline = rs.pipeline()

    config = rs.config()

    
# 告訴 config 資訊從檔案讀取

    rs.config.enable_device_from_file(config, 'test.bag')

    
# 一樣要建立深度影像串流

    config.enable_stream(rs.stream.depth, rs.format.z16, 30)

    
# 開啟串流

    pipeline.start(config)

    
# 宣告著色器 預設是 jet colormap

    colorizer = rs.colorizer();

接著我們就像一般使用一樣,取得frames、取得深度影像,轉換成numpy,用opencv顯示:

    while True:
        
        frames = pipeline.wait_for_frames()
        depth_frame = frames.get_depth_frame()

        
# 將深度影像著色成 jet colormap

        depth_color_frame = colorizer.colorize(depth_frame)

        
# 轉換成 numpy array 讓 opencv 顯示

        depth_color_image = np.asanyarray(depth_color_frame.get_data())

        
# Opencv 顯示以及按下 q 離開

        cv2.imshow("Depth Stream", depth_color_image)
        key = cv2.waitKey(1)
        if key == 27:
            cv2.destroyAllWindows()
            break
finally:
    pass

成果如下:

結語

我們詳解了總共六個範例,相信大部分的狀況,讀者們都已經可以Handle了!下一次將會介紹我們如何使用物件偵測搭配RealSense。

 

 

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

【微軟AI+IoT解決方案Azure Percept實作】Auzre Percept DK硬體操作設置

$
0
0

由華碩所開發的Azure Percept  DK是一種 edge AI 開發工具組,專為使用 Azure Percept Studio開發視覺和音訊 AI 解決方案而設計。執行邊緣運算時,則是利用內建的硬體加速功能,不需要透過雲端,已達到即時辨識的效果。而建立Azure Percept Studio開發視覺和音訊時,則有不需透過程式碼的方案。本文將介紹Azure Percept  DK的網路設置,到連線至Azure Percept Studio平台。若要了解Azure Percept  DK的開箱文介紹的讀者,請參考「 Microsoft Edge AI新方案 – Azure Percept 深色」文章

撰寫/攝影 鈺莨
難度

★☆☆☆☆

時間

20分鐘

材料表
  • 具有連網功能和網頁瀏覽器的主機電腦。
  • Azure Percept DK

讀者需在Azure網站建立IoT中樞及IoT device,請到「微軟AI+IoT解決方案Azure Percept實作-建立Auzre網站的IoT中樞」的文章中依照步驟建立,本文介紹Azure Percept  DK的硬體介紹與設置使用。

 

Azure Percept DK的硬體介紹

先來介紹Azure Percept DK音訊設備的部分,其設備在音訊設備由四顆陣列式麥克風、三顆LED指示燈、外接式3.5吋音訊輸出孔及Micro USB孔組成。如下圖所示。

在視訊設備方面,有磁吸的視訊鏡頭,可以用手調整至鏡頭的理想位置。硬體則是搭載Intel® Movidius™ Myriad™ X 神經運算加速晶片,而晶片的外層是散熱鰭片。如下圖所示。

另外音訊及視訊設備,都有藍色的鎖定環,可以調鬆緊度,將角度調製適當位置。如下圖所示。

最後要介紹的是主機,所搭載的是NXP iMX8m 處理器,和可信平台模組(Trusted Platform Module,TPM) 2.0版,放置在鋁製的散熱底盤中。支援Wi-Fi和藍牙,設備的後端有兩處供Wi-Fi天線連接。如下圖所示。

而側邊有兩個USB3.0、Type-C USB孔及乙太網路孔,還有電源開關和HDMI孔,另一處則是電源供應接頭。如下圖所示。

Azure Percept  DK接線與開機

接下來要說明的是主機如何接上Wi-Fi天線,且視訊和音訊設備中與主機接線,然後主機供電後開機。

首先是在主機後側接上天線兩根Wi-Fi天線。如下圖所示。

再來是音訊設備與主機連線,音訊設備的Micro USB孔要對接到主機的USB3.0。如下圖所示。

 

視訊設備與主機連線,視訊設備前有Type C USB孔要對接到主機的Type C USB孔。

上述都確認音訊和視訊設備都與主機連接後,最後一步是主機供電開機,主機的另一側邊有電源插座,接上去即可供電開機。

Azure Percept  DK開機畫面,側邊的電源燈會亮起。

音訊設備的LED指示燈也會亮起黃燈,代表音訊設備初始化。

等到音訊設備的三顆LED指示燈亮起藍燈,代表初始化完成。

Azure Percept  DK Wi-Fi連線設定及連線至Azure Percept Studio平台

以下細分步驟,來說明:

  1. 連線Azure Percept DK 的WiFi。

  1. 網頁會自動開啟,點[下一個]。

  1. Azure Percept DK網路連線至外部網路。

  1. 選擇外部網路Wi-Fi。

  1. 連線Wi-Fi網路成功,點[下一個]。

  1. 同意許可協議打勾後,點[下一個]。

  1. 設定SSH遠端連線帳號密碼。

 

  1. Azure Percept DK連接至Azure 平台,第一次連接,需選[與新設備連接]。

  1. 複製設備代碼,之後按[登錄到Azure],此時會另開分頁。

  1. 輸入設備代碼驗證碼後按[下一步]

  1. 輸入Azure平台的帳號、密碼
  1. 關閉視窗登入Azure平台視窗,回到Azure Percept DK主頁。

13. 將Azure  Percept DK設備分配給您的Azure帳戶

  1. 為您的物聯網設備命名,名稱自訂

  1. 設置中,需等幾分鐘。

  1. 設置完成後,Azure Percept本身的Wi-Fi會斷開,而連接到外部Wi-Fi環境內,此時電腦要改連外網網路,再選擇[連接到Azure門戶]

 

  1. 選取Azure帳戶

 

  1. 進入Azure Percept Studio 平台

補充: 若之前已建立裝置,要如何登入原先裝置

  • 到IOT中樞,選擇IOT中樞名稱
  • 再點選[IOT Edge]
  • 點選 裝置識別碼 名稱

  • 複製 [主要連接字串]

  • 回到Azure Percept DK接線與開機的第8步,選用[現有的連接字符串連接]

  • 貼在欄位中。

 

  • 設備設置完成。

 

相關文章:

微軟原廠網站介紹:

華碩原廠網站介紹:

 

【微軟AI+IoT解決方案Azure Percept實作】建立Azure網站的IoT中樞

$
0
0

本專案是使用Auzre Percept執行Auzre網站的視覺辨識範例及虛擬語音助理範例,而本文為使用Auzre Percept前的前置處理步驟文章,必須在Auzre平台網站的Auzre IoT中樞建立Auzre的IoT device。而Azure IoT 中樞是託管於雲端的受控服務,其特點可在數百萬個IoT 裝置和一個解決方案後端之間啟用可靠且安全的雙向通訊,也使用每個裝置的安全性認證和存取控制來啟用安全通訊。幾乎任何裝置都可以連線到 IoT 中樞,如:樹莓派。IoT 中樞也支援多種語言,如:C、Java、Python,是一套相當完整AI+IoT的方案

撰寫/攝影 鈺莨
難度

★☆☆☆☆

時間

10分鐘

材料表
  • 具有連網功能和網頁瀏覽器的主機電腦。
  • Azure Percept DK

 

在建立IoT 中樞前,必須要先申請好Auzre帳號。本文將一步步帶領讀者來建立IoT中樞和IoT deivce,以下本文開始。

 

1.登入Azure入口網站

https://portal.azure.com/

2. 開啟 Azure IoT Hub 服務

在上方搜尋框輸入 iot hub 再點選搜尋結果中的 IoT 中樞

3. 建立 Azure IoT Hub

3-1點選下方的 Create IoT Hub

3-2填寫 Azure IoT 中樞相關資訊

  • 訂閱欄位選擇所要使用哪個訂閱來存取 Azure 服務,本文選Azure開放授權。
  • 資源群組欄位建立新的資源群組或使用已存在的資源群組,本文選資策會群組。
  • 區域 欄位選擇所要使用哪個區域的 Azure IoT中樞,本文選東南亞東亞。
  • IoT 中樞名稱 欄位輸入容易識別的 IoT Hub 名稱,本文為自訂名稱。
  • 完成時,選取[下一步:網路],以繼續建立中樞。

3-3設定網路功能

  • 選擇可以連線到IoT中樞的端點。可以選取預設設定 [公用端點(所有網路)],或選擇 [私人端點]。本文選[公用端點(所有網路)]
  • 完成時,選取 [下一步:管理],以繼續建立中樞。

 

3-4設定管理功能

  • 定價與級別層欄位選[S1:標準層]本文為自訂名稱。
  • 完成時,選取[下一步:標記]以繼續進入下一個畫面。
[註]: [S1:標準層]才有 Azure IoT Edge 功能

3-5 設定標記

  • 這邊為預設空白,選取[下一步:檢閱+建立]以檢閱您的選擇。

 

3-6選取[建立]以建立新的中樞, 建立中樞需要幾分鐘的時間

3-7 部屬完成

 

在這裡要恭喜讀者完成了建立Auzre網站上的IoT中樞及IoT device,當初筆者也是摸索了一段時間,但是離整個專案只完成了1/3,接下來下一篇將分享作為IoT device的Auzre Percept是如何連接至Auzre網站上的IoT中樞的文章,請各位讀者持續追蹤。

 

相關文章:

Auzre原廠網站:

【微軟AI+IoT解決方案Azure Percept實作】使用Azure Percept DK 建立視訊範例

$
0
0

本文要分享的是在Azure平台上的Azure Percept Studio無程式視覺範例展示。在本範例中,需在Azure Percept Studio建立視覺範例,搭配Azure Percept DK 與Azure Percept視訊設備使用。

讀者需登入Azure Percept Studio的介面來使用試用範例視覺模型,或是讀者可以自行建立視覺原型,之後將模型部屬到Azure Percept DK時,就可以透過Wi-Fi開啟新的分頁來觀看Azure Percept DK視訊鏡頭的影像串流結果。

撰寫/攝影 鈺莨
難度

★☆☆☆☆

時間

20分鐘

材料表
  • 具有連網功能和網頁瀏覽器的主機電腦。
  • Azure Percept DK

 

本文會分享Azure Percept Studio的試用範例視覺模型展示及自行建立視覺原型,部屬在Azure Percept DK的兩種例子。若讀者尚未設定Azure Percept DK裝置及IoT中樞,則可以

參考「微軟AI+IoT解決方案Azure Percept實作-建立Auzre網站的IOT中及「微軟AI+IoT解決方案Azure Percept實作-Auzre Percept DK硬體操作設置兩篇文章。

 

Azure Percept Studio的試用範例視覺模型展示

  1. 進入Azure Percept Studio

  1. 開啟[示範與教學課程]索引標籤

  1. 試用範例視覺模型中按下[檢視]

  1. 部屬視覺辨識範例
  • [Iot 中樞] 下拉式功能表中,選取您的 Azure Percept DK所連線的IoT中樞。
  • [裝置]下拉式功能表中,選取您的 Azure Percept DK裝置。
  • 從程式庫中選取範例模型,然後按一下[部署到裝置]。本範例選擇[一般物件偵測]。

5. 部屬成功,按下[檢視串流],即可成功看到影像。

  1. 開啟分頁的執行結果

 

Azure Percept Studio的自行建立視覺原型

  1. 進入Azure Percept Studio

  1. 開啟[示範與教學課程]索引標籤

3.選建立視覺原型中點選[建立]

  1. 專案詳細資料
  • [專案名稱] 中,可以自訂名稱。
  • [專案描述]中,可以任意填入內容。
  • 建立[資源],需點選[建立新的資源],相關說明請看第5步
  • [專案類型] 中,有物件偵測影像辨識可以選。
[註]兩者的差異在於物件偵測會有方框在同張畫面中框出不同種類物件位置,並可以隨著物件的位置不同而顯示辨識率和物件名稱,而影像辨識則無法框出物件位置,而只能顯示一種物件名稱和辨識率。按下[協助我選擇]會說明兩者的差異。本範例選擇物件偵測
  • 最後[最佳化]有分成正確性低延遲平衡。本範例選擇正確性。
  • 點選視窗底部[建立]。

以下為物件偵測及影像辨識兩者之不同圖示說明。

  1. 建立新的資源。
  • [名稱]中,名稱可以自訂。
  • [訂閱]下拉式功能表中,選取訂閱內容。
  • [資源群組]下拉式功能表中,選取裝置的資源群組。
  • [位置]下拉式功能表中,選取資源區域。本範例選取東南亞
  • [定價層]下拉式功能表中,選取S0。[註]微軟網站建議S0。
  • 點選視窗底部[建立]後,回到第4步。

  1. 設定影像擷取
  • [Iot 中樞] 下拉式功能表中,選取您的 Azure Percept DK所連線的IoT中樞。
  • [裝置]下拉式功能表中,選取您的 Azure Percept DK裝置。
  • 勾選[自動擷取影像],可在[擷取速率] 下拉式功能表中,選取慣用的擷取影像速率。

本範例選取每30秒1個畫面,而目標則選預設的25。

  • 點選視窗底部[下一步:為影像與訓練模型標記標籤]。

  1. 設定影像與訓練模型標記標籤。

按下在自訂視覺中開啟專案後,會開啟Azure 自訂視覺的平台。

8.需輸入帳號、密碼登入Azure自訂視覺平台。

輸入帳密後,需勾選條款就會進入Azure自訂視覺平台。

可以看見在自訂視覺平台已經建立物件辨識的專案,並點選此專案。

9.上傳圖片及標註。

按下[Add images],上傳需要訓練的圖片。

[註]一種類別,最低15張,否則無法訓練

上傳成功,按下[Done]。

標註物體

10. 訓練按下[Train]

11.選擇[Quick Training],之後按下[Train]。

訓練中,需等幾分鐘。

12.訓練完畢,顯示訓練結果。

13.關掉Azure 自訂視覺頁面,返回Azure Percept Studio頁面,並按下[部署模型]

14.部署模型

步驟與Azure Percept Studio的試用範例視覺模型展示的第5步相同,部署模型需花幾分鐘,部署完成按下[檢視串流]。

 

15.影像串流結果

以上為Azure Percept Studio的試用範例視覺模型展示及自行建立視覺原型,部屬在Azure Percept DK的兩種例子分享,其步驟中皆無須寫程式,希望各位讀者可以應用於生活中。

本文為Azure Percept系列文的第四篇,若讀者要建立另一個語音試用範例,請參考「微軟AI+IoT解決方案Azure Percept實作-使用Azure Percept DK 建立語音助理」。

 

相關文章:

微軟原廠操作連結:

 

【微軟AI+IoT解決方案Azure Percept實作】使用Azure Percept DK 建立語音助理

$
0
0

本文要分享的是在Azure平台上的Azure Percept Studio無程式語音助理範例展示。在本範例中,需在Azure Percept Studio建立語音範例,再搭配Azure Percept DKAzure Percept 陣列麥克風使用。控制虛擬物件時,需對著陣列麥克風說關鍵字來喚醒裝置,之後接著命令,例如: 「computer,Turn on/off the TV.」來開啟/關閉虛擬物件。

撰寫/攝影 鈺莨
難度

★☆☆☆☆

時間

20分鐘

材料表
  • 具有連網功能和網頁瀏覽器的主機電腦。
  • Azure Percept DK

 

Azure Percept Studio無程式語音助理有四種範例,分別為: 旅遊、醫療保健、汽車和貨櫃貨物清查範例示範,以下接續前篇「微軟AI+IoT解決方案Azure Percept實作-Auzre Percept DK硬體操作設置文章,從建立語音助理範例開始。若未建立Azure入口網站的IoT中樞及Azure Percept DK設定,請至「微軟AI+IoT解決方案Azure Percept實作-建立Auzre網站的IOT中樞篇,以下開始說明語音助理範例建立步驟。

 

語音助理範例建立

1.進入Azure Percept Studio

  1. 開啟[示範與教學課程]索引標籤。

  1. 點選 [試用語音助理範本]

這會開啟右側視窗。

4.設置試用語音助理範本。

 

  • [Iot中樞] 下拉式功能表中,選取 Azure Percept DK所連線的 IoT 中樞。
  • 在[裝置]下拉式功能表中,選取Azure Percept DK建立的裝置。
  • 選取其中一個可用的語音助理範本,本範例為旅遊服務業
  • 點選[我同意此專案的條款及條件] 核取方塊。
  • 點選頁面底部的 [建立]

  1. 建立語音主題資源
  • [訂用帳戶] 方塊中選取 Azure 訂用帳戶。
  • [資源群組] 下拉式功能表中,選取資源群組。
  • [應用程式前置詞] 中輸入名稱,此欄位名稱可自訂。
  • [區域] 底下,選取要部署資源的區域,只有兩個區域可選,預設(US)。
  • [ LUIS 預測定價層] 下,選取 [標準](免費層不支援語音要求) 。
  • 按一下 [ 建立 ] 按鈕。 語音助理應用程式的資源將會部署至訂用帳戶,需等2~4分鐘建立。

  1. 測試語音助理範例

若要與您的語音助理互動,請說關鍵字後面接著命令。 當陣列麥克風辨識出關鍵字時,裝置會發出聲音 (喇叭或耳機需接上耳機孔) ,而且 Led 將會閃爍藍色。 處理命令時,Led 會切換至白燈並閃爍。 語音助理的命令回應將會以文字的方式列印在示範視窗中,並透過您的喇叭/耳機發出語音。

 

預設關鍵字 ,設定為 [Computer],而每個範本都有一組相容的命令,可讓您在示範視窗中與虛擬物件互動。 例如,您使用旅遊或醫療保健示範,請說「Computer, turn on TV」來開啟虛擬電視。

展示影片:

https://www.facebook.com/CAVEEducation/videos/329531931844445

 

以下說明四種試用範例指令:

醫療保健和旅遊示範都具有可互動的虛擬電視、燈光、百葉窗和恒溫器。 以下是語音命令:

  • “Turn on/off the lights.”
  • “Turn on/off the TV.”
  • “Turn on/off the AC.”
  • “Open/close the blinds.”
  • “Set temperature to X degrees.” (X is the desired temperature, e.g. 75.)

 

汽車示範命令

汽車示範具有虛擬的暖氣、除霜器和車用冷氣,可進行互動。以下是語音命令:

  • “Turn on/off the defroster.”
  • “Turn on/off the seat warmer.”
  • “Set temperature to X degrees.” (X is the desired temperature, e.g. 75.)
  • “Increase/decrease the temperature by Y degrees. “

貨櫃清查示範命令

貨櫃清查示範可選取虛擬藍色、黃色和綠色方塊,與虛擬清查應用程式互動。 以下是語音命令:

  • “Add/remove X boxes.” (X is the number of boxes, e.g. 4.)
  • “Order/ship X boxes.”
  • “How many boxes are in stock?”
  • “Count Y boxes.” (Y is the color of the boxes, e.g. yellow.)
  • “Ship everything in stock. “

 

補充說明

1.查看Azure Percept DK音訊之LED指示燈:

  • 有三個藍色藍色燈表示語音助理已就緒且正在等候關鍵字。

  • 如果LED指示燈為白色,則Azure Percept DK已完成初始化,而且需要使用關鍵字來設定。
  • 如果LED指示燈閃爍白色,則Azure Percept DK音訊尚未完成初始化。 初始化可能需要幾分鐘的時間才能完成。

  1. 語音助理未回應在語音 Azure Percept Studio 中建立的自訂關鍵字
  • 在 Azure Percept Studio 首頁的左側功能表面板中,按一下 [裝置]
  • 尋找並選取您的裝置。
  • [裝置] 視窗中,選取 [語音] 索引標籤。
  • 需確認關鍵字及命令是否有跑掉,可按變更選取。

筆者有執行過旅遊和貨櫃清查的試用範例,發現旅遊範例的句子指令較容易驅動虛擬物件,而貨櫃清查範例會發現Azure Percept 音訊較容易辨識出錯誤句子,而無法驅動虛擬物件的情形發生(也有可能筆者英文發音要多練習…..),以上為筆者的經驗分享,也可以請各位讀者玩玩看其他的適用範例,我們下篇見囉!

 

相關文章:

 

【新品開箱】開箱Jetson Mate把Jetson Nano與Jetson Xavier NX變成Jetson電腦叢集

$
0
0
撰寫/攝影 郭俊廷/部分圖片與資料參考引用自原廠網站文件圖片
難度

★☆☆☆☆

時間

1 hour

材料表

今天要來開箱的是Jetson Mate,首先來看看它實際運作的樣子

 

Jetson Mate是一個載板機殼模組,透過模組內的Gigabit交換器互相通訊可以將最多四個Jetson Nano或Jetson Xavier NX變成一個電腦叢集。(根據原廠說明以及實際測試使用此模組並不支援Jetson Nano Developer Kit A02如有使用A02的使用者須注意)

它的外殼上面有一個大大的風扇可以散熱,上面還有彩色的LED燈。

每一個Jetson裝置各有一個USB3.0可以使用,並且使用65W功率輸出以上的USB Type-C來做為電源供電。

根據原廠資料我們可以看到電源如果是使用Jetson Nano模組需要至少65W支援PD充電的電源輸入,如果都是使用Jetson Xavier NX則需要90W支援PD的電源輸入,外殼的尺寸大小長*寬分別是110mm*110mm。

以下兩張圖片是只有載板上的各個零件的細部介紹,可以看到這個載板有兩個CSI攝影機的Port,還有可以輸出主板畫面的HDMI的Port,最多可以插上四個Jetson Nano或Jetson Xavier NX的系統模組的插槽等。

開箱

接著是我們的開箱時間,本次開箱的Jetson Mate包含載板、風扇與機殼是一體的。

首先先來對照一下盒子的大小,可以看到跟我們的Jetson Nano比起來大概是兩倍大而已。

接著打開盒子可以看到有保護套上面印著Seeed的圖案呢

把保護套拿開,盒子裡面的東西拿出來,可以發現裡面有另外一包零件包,這零件包等等就會使用到。另外盒子裡並沒有附電源變壓器所以請去尋找支援65W或90W支援PD充電的Type-C輸入電源。

零件包打開可以發現裡面有一個小的螺絲起子跟四個NX電源風扇的延長線。四個螺絲則是從風扇的蓋子上拆除的下一步會介紹如何拆除。

打開模組盒子風扇蓋子

零件包裡面附的小螺絲起子是用來拆除風扇跟模組固定的螺絲,螺絲的位置就如下面兩張圖片紅框處。

拆除螺絲後記得不要馬上把風扇跟蓋子用力的拔起來!!!!!!

請慢慢掀開並確認線是否太短需要調整蓋子放置位置或將線放長

因為風扇跟載板本體還有電源線連接(如下圖)太大力拉起可能會導致線壞掉或載板壞掉

掀開風扇蓋子後將它擺置適合的位置(如下圖)

這面就如同上面載板的介紹一樣的配置

另一面就可以看到有WAKE的按鈕(如下圖紅框處),並且標註那個位置是MASTER(主控制板),WORKE1、WORKE2、WORKE3的位置。

WAKE的按鈕就是之後我們將板子插上後都準備好開啟電源的按鈕。

可以根據那快插槽位置靠近兩個CSI攝影機插槽的地方來判斷主控制板的位置在那。

以上我們的初次開箱,下一次將會介紹如何將Jetson Nano或Jetson Xavier NX插上Jetson Mate使用,請各位注意CAVEDU技術BLOG與FB的更新囉。

 

以上部分圖片與資料參考引用自原廠網站文件圖片:https://wiki.seeedstudio.com/Jetson-Mate/

【開箱】華碩Tinker Board 2S 嵌入式系統開箱介紹

$
0
0

近年來人工智慧物聯網AIoT的議題非常熱門,華碩ASUS也針對AIoT主題開發出一系列的產品(https://iot.asus.com/),從工業用電腦到神經網路運算加速器(棒),都有相關的支援產品,其中Tinker Board亦是AIoT開發平台中以類似樹莓派(Raspnerry Pi)的方式推出,這系列的產品在市面上也推出了一段時間,近來華碩亦在Tinker Board系列裡推出一款最新的型號—Tinker Board 2(或2S),這項產品標榜著更為強大的CPU與GPU運算效能,其主打的領域更是鎖定AI的相關應用。

Tinker Board 2(或2S)是一款Arm-based 單板電腦 (SBC),採用 Arm big.LITTLE™ 技術 64 位元處理器,可提供更優異的運算效能且耗電量低。在原廠網站(https://tinker-board.asus.com/tw/product/tinker-board-2s.html)對於Tinker Board 2(或2S)的介紹裡,可以清楚看出Tinker Board 2(或2S)相較前代產品Tinker Board S有著更為新穎與強大的CPU與GPU的架構,此外,更標榜著可透過強大的工具程式(如:FOTA),讓使用者可以輕易透過網路線上更新系統韌體,從這裡在在都可以看出Tinker Board 2(或2S),都著眼朝著人工智慧物聯網AIoT的方向發展。

撰寫/攝影 曾俊霖
難度

★☆☆☆☆

時間

1小時

材料表
  • ASUS  Tinker Board 2S / 2GB

從包裝外盒取出物品,其實主要可以分成3個主要零組件,分別是單板微電腦、超大的處理器散熱片與Wi-Fi天線。

本次取得的是Tinker Board 2S / 2GB的版本,單板微電腦就外觀來看,Tinker Board 2S與Tinker Board 2這兩個版本的各種外接界面規劃其實沒有差異,這兩個版本主要是差異在2S版是有內建16GB的eMMC內部儲存空間,而2版是沒有內建eMMC儲存空間,除此之外,這兩個版本在其他的硬體規格是一模一樣的,相關的硬體規格資訊請參考以下的列表。

 

Tinker Board 2(或2S) 硬體規格列表

項目 型號
SoC Rockchip RK3399
CPU Dual-core Arm® Cortex®-A72 @ 2.0 GHz
Quad-core Arm® Cortex®-A53 @ 1.5 GHz
GPU Arm® Mali™-T860 MP4 GPU @ 800 MHz
Display 1 x HDMI™ with CEC hardware ready
1 x USB Type-C® (DP Alt Mode)
1 x 22-pin MIPI DSI (4 lane)
Memory Size Dual-CH LPDDR4 2GB / 4GB
Storage 16GB eMMC(僅Tinker Board 2S有)
Micro SD(TF) card slot (push/pull)
Connectivity 1 x RTL8211F-CG GbE LAN
1 x M.2 – 802.11 a/b/g/n/ac wireless & BT 5.0 (2T2R)
Audio 1 x HDMI™ audio output
1 x S/PDIF TX pin (from GPIO)
1 x PCM/I2S pins (from GPIO)
USB 3 x USB 3.2 Gen1 Type-A ports
1 x USB 3.2 Gen1 Type-C® OTG port
Camera Interface 1 x 15-pin MIPI CSI-2 (2 lane)
Internal Headers 1 x 40-pin headers includes:
– up to 28 x GPIO pins
– up to 2 x SPI bus
– up to 2 x I2C bus
– up to 2 x UART
– up to 3 x PWM
– up to 1 x PCM/I2S
– up to 1 x S/PDIF TX
– 2 x 5V power pins
– 2 x 3.3V power pins
– 8 x ground pins
1 x 2-pin Recovery header
1 x 2-pin Power-on header
1 x 2-pin Reset header
1 x 2-pin Debug UART header
1 x 2-pin DC Fan header
1 x 2-pin RTC Battery header
Power Connector
(up to 65W)
1 x 12~19V DC Power Input Jack (5.5/2.5 mm)
OS Support Debian 10 / Android 10
Dimension 3.37 inch x 2.125 inch (85 x 56 mm)

 

通訊界面介紹

Tinker Board 2S既然是以AIoT應用開發為主要的訴求,那麼在相關通訊界面的規劃,自然就必須要能夠符合目前現行主要的物聯網通訊界面,如:Wi-Fi、RJ-45有線網路介面與藍牙5.0,在這次的2S版當中相對以往的Tinker Board有著非常大的設計差異,主要在Wi-Fi與藍牙5.0通訊採用PCI-E  M.2介面連接通訊模組的方式進行設計,且通訊用的天線可以採用外接的方式進行安裝,這樣的設計理念,可以較有彈性的去針對未來不同的通訊模組進行更換,天線可以更換也讓使用者可以使用更好的通訊天線進行通訊傳輸。

USB連接介面介紹

有別於先前的Tinker Board,Tinker Board 2S除了設計了3個USB 3.2 Type-A介面外,更把USB 3.2 Type-C設計在系統上,並且透過Type-C介面,實現了除了HDMI視訊介面輸出外的另一組視訊介面輸出,達成了可雙螢幕操作的功能,可以說是不讓Raspberry Pi 4的雙螢幕輸出專美於前。

GPIO周邊擴充連接埠

Tinker Board 2S有著和樹莓派相容接腳順序的40Pins GPIO,透過GPIO允許使用者進行後續電路硬體模組的連接,在這裡也提供了I2C、SPI、UART等專用信號介面,但依據ASUS原廠網站的建議,除了標準的TTL信號的控制輸入輸出外,建議是以第三方支援的套件程式進行驅動程式的安裝,例如:UART建議就安裝pyserial套件等,ASUS也針對不同的信號接腳以不同的顏色底座進行區別,方便使用者在安裝擴充電路模組能快速且正確判斷接腳順序,算是一種貼心的設計。

CSI與DSI影像輸入與輸出介面

Tinker Board 2S也提供了CSI與DSI介面給使用者,CSI介面可以讓使用者安裝類似MIPI樹莓派攝影機,而DSI介面則可以讓使用者安裝類似MIPI樹莓派專用LCD螢幕,這兩種介面可以讓使用者能更加緊緻的安排系統,減輕USB介面的操作負荷。

電源供應

Tinker Board 2S電源電壓必須在12V至19V之間才能使系統正常運作,此外,依照實際外接硬體與系統運作效能的狀態,建議使用輸出額定電流約在3A以上的電源供應器為佳,這裡特別強調,依照原廠的規定,直接在GPIO以5V供應給Tinker Board 2S是無法正常開機操作系統的,電源僅能從直流電源插座(外徑5.5mm / 內徑2.5mm)的電源接頭進行操作。

HDMI影像輸出介面

Tinker Board 2S的影像輸出是透過標準HDMI介面操作,系統可提供4K影像的顯示,此外,系統若是需要以雙螢幕輸出,則需要透過USB Type-C 介面進行第二螢幕的輸出,依據原廠文件的說明,透過強大的GPU與CPU的效能,即使是雙螢幕輸出,系統依然可以4K影像進行輸出。

作業系統

Tinker Board 2S依目前原廠的設計,可以使用兩種作業系統,分別是Debian 10 Linux作業系統與Android 10作業系統,本次開箱測試是安裝Debian 10 Linux,基本上這個作業系統類似Raspberry Pi OS 64Bits版,屬於aarch64的架構,作業系統的原廠下載連結如下:https://tinker-board.asus.com/download-list.html?product=tinker-board-2s

Debian 10 Linux作業系統原廠提供的版本是V2.0.0版,這個版本使用的桌面系統是LXDE,這個桌面系統根據這次的實測,在安裝OpenCV 4.5版本時會因為缺少或斷裂了許多GTK 2.X套件,導致Build Source的時候產生許多問題,而且無法單純的以apt-get方式進行相依套件的安裝,這部分的問題解決方式,會在下一篇教學文章「Tinker Board 2S系統與軟體安裝設定」裡說明。

本次開箱介紹,先到此告一段落,筆者將會在下一篇「Tinker Board 2S系統與軟體安裝設定」,介紹安裝應用在各種AI辨識所需要安裝軟體與系統設定的方式,敬請大家拭目以待。

 

相關文章:


【評測文】Jetson Mate把Jetson Nano與Jetson Xavier NX變成Jetson電腦叢集首次使用教學

$
0
0

上次我們開箱了Jetson Mate與基本介紹,這次來教學如何使用Jetson Mate吧。

撰寫/攝影 郭俊廷/部分圖片與資料參考引用自原廠網站文件圖片
難度

★★☆☆☆

時間

1.5 hours

材料表

 

這次要來介紹如何使用Jetson Mate、如何將Jetson Nano或Jetson Xavier NX

裝上Jetson Mate使用呢?

 

一、準備Jetson Nano或Jetson Xavier NX

首先要先準備好你的Jetson Nano或Jetson Xavier NX

這裡我們都是使用Jetson Nano B01或Jetson Xavier NX,使用JP441這個版本的映像檔進行安裝測試,如有需要請透過下方網址下載並燒錄至您的SD卡中

https://developer.nvidia.com/jetpack-sdk-441-archive

燒錄映像檔的相關教學請參考以下CAVEDU教學文章

 

接著介紹如何將Jetson Nano開發版上的SOM(系統模組)拆解下來放到Jetson Mate上呢?

相信大部分的使用者都是使用Jetson Nano開發版,Jetson Nano開發版如需在Jetson Mate上使用須將Jetson Nano開發版上的SOM(系統模組)拆解下來。

首先如有風扇請將它拆下來,並將開發版上的系統模組固定螺絲卸下來(如下圖紅框處)

卸除後才可以將系統模組拆解下來,拆解方法如下:

可以看到系統模組左右兩邊有個卡榫(如下圖)

用手把它往外側撥動就可以看到系統模組被彈起來

系統模組彈起來後即可將系統模組往上拔出

就可將系統模組拆解下使用(如下圖)

Jetson Xavier NX的拆解情形跟Jetson Nano也差不多,需要注意的是NX的風扇不用也無法拆除但NX風扇電源線拆除的時後須注意不可用蠻力拔除需要使用工具慢慢將固定卡榫慢慢移除否則會導致風扇電源線損毀。(如下圖紅框處)

下圖是NX系統模組風扇電源線拔除後接上零件包的風扇延長線,如果沒接此延長線將會無法使用NX內建的風扇。此延長線是給NX使用的Nano無法使用請注意。

二、將系統模組插入Jetson Mate中

接著我們要把系統模組插入Jetson Mate中

注意插的方向是將Jetson Nano或Jetson Xavier NX系統模組的風扇或散熱片朝向CSI攝影機的方向。

如果是使用Jetson Nano的系統模組為主控制板的人可以直接將Jetson Nano的系統模組插入MASTER插槽不用執行以下部分。

如果是Jetson Xavier NX系統模組為主控制板的人需先將風扇電源延長線插入主板旁邊的風扇電源處(如下圖紅框處),再插入主板,否則先插入系統模組時會沒空間接上風扇電源延長線。

插好風扇電源後即可將Jetson Xavier NX系統模組插入MASTER插槽,用手將Jetson Xavier NX系統模組往下壓聽到卡榫固定的聲音即可,可以確認插槽旁邊的卡榫有無貼緊就是正確插入插槽中。

以下是MASTER插入NX、WORKE1插入NANO的情形。

以下是MASTER插入NX、WORKE1、2、3插入NANO的情形

 

三、插入電源並開機

最後我們將系統模組都插好之後將電源接上即可使用Jetson Mate。

將以下的PD IN插上65W的電源後外殼的風扇跟LED即會啟動。

此時系統模組還沒開起電源需要再按下另一邊的WAKE按鈕才可將系統模組開機。

透過網路線將Jetson Nano與Jetson Xavier NX在同一個網段,即可透過SSH同時連線至多台系統中。

如是使用筆電的話則可以透過Windows內建的網路共享透過無線網路共享給有線網路來使用。

 

以上我們的首次使用教學,之後會介紹更多Jetson Mate的相關應用,請各位注意CAVEDU技術BLOG與FB的更新囉。

以上部分圖片與資料參考引用自原廠網站文件圖片:https://wiki.seeedstudio.com/Jetson-Mate/

 

 

 

【線上初學程式設計 】 《Arduino首次接觸就上手》阿吉老師的5分鐘小教室

$
0
0

學習新事物需要跨出的那一步,是否不太容易呢?對於Arduino初學者來說也是一樣。需要學習硬體知識、程式設計、了解各種接線的連接方式,甚至需掌握焊接技巧;在開始學習Arduino程式設計之前,需要準備的事情很多……

現在只需要擁有《 Arduino首次接觸就上手》就能夠解決您的前期準備的問題喔!

  • 只需先專注程式設計與Arduino的學習,不須在學習初期就要應付繁雜的準備工作。
  • Arduino為控制核心,帶您由基礎學習入門到專題延伸,
  • 操作簡單且無需使用麵包板即可完成專題應用。
  • 讓您輕鬆自學,不卡關!!
撰寫/攝影 怡婷
難度

★☆☆☆☆

時間

約30-50分鐘

材料表

【網購通路】

阿吉老師的5分鐘小教室開張啦!要和大家一起使用《Arduino首次接觸就上手》與專屬圖形化介面「Hangeekduino」,帶您一步步進入Arduino的互動電子裝置世界!

 

前導介紹

 

ep.1 下載程式

介紹如何取得《Arduino首次接觸就上手》的所有線上資源,並下載安裝圖形化介面「Hangeekduino」的步驟教學喔!

ep.2 安裝驅動程式

下載  Hangeekduino 開發環境之後,第二集要來安裝驅動程式,才能讓開發板與圖形化介面完整連結喔~

 

ep.3 LED閃爍

初學程式設計的朋友們一定會知道 Hello World 是什麼意思。Arduino 的 Hello World 就是如何讓LED亮滅,除了是基礎中的基礎之外,對於學習者而言也是相當有成就感的專題展示。影片中將使用「Hangeekduino」圖形化介面來控制「Arduino首次接觸就上手」的LED閃爍

 

ep.4 按鈕控制LED閃爍

學會了LED閃爍,還能夠進階做什麼題目呢?當然是使用輸入感測器來進行控制囉!影片使用「按鈕」來控制「LED」。根據按鈕(輸入)的狀態來控制LED(輸出),是許多專題的必備條件喔~

 

ep.5 蜂鳴器

了解如何發光之後,知道如何使用蜂鳴器來發出不同音調的聲響也是很有趣的體驗。

本影片會告訴您如何指定發音頻率,還能夠使用不同數值來模擬出電話撥號的旋律喔!

 

ep.6 光感測器

光感測器會對於所接受到的光線強弱而有變化,我們可以藉此來決定LED要不要亮起來,還可以在序列介面中看到光感測器的數值變化。

 

ep.7 聲音感測器

本範例與上一個範例很類似,但改用另一款聲音感測器來決定LED模組的亮或暗,並在序列介面看到聲音感測器的數值。拍拍手來看看發生了什麼事情吧

 

ep.8 OLED小螢幕

以往只能顯示在序列介面的數值,如果可以顯示在OLED小螢幕上的話,感覺更方便了呢~

ep.9 溫濕度感測器

「溫濕度感測器」是在物聯網實作專題中常見的感測器之一,第一個範例中會把溫度與濕度顯示在序列介面中;第二個範例則是結合上一個OLED範例,延伸應用這集的教學就可以自製出更多好玩有趣的專題呢!

 

ep.10 氣壓感測器

透過大氣壓力來測量出您所在位置的標高,本集主角 – 氣壓感測器 – 是個可測量所在位置的約略高度的感測器,本次影片含有「顯示在序列埠視窗」與「連接顯示在OLED顯示器上」的兩個範例,一起來學習吧

 

ep.11 三軸加速度計

最後介紹的感測器為「三軸加速度計」,這個感測器可以知道在立體空間中的運動狀況(XYZ),本範例就是要運用這些變化來做出相當動感的專題喔!影片含有「顯示在序列埠視窗」與「連接顯示在蜂鳴器與LED上」,別搖太大力,板子會飛出去啊!

 

更多線上資源:

 

一口氣分享了12支影片,你都完成了嗎?相信聰明地你早都學會囉!

接下來阿吉老師小教室的企劃還會繼續介紹更多關於Arduino首次接觸相關操作影片,期待你與我們分享你的創意或是想法,當然如果有問題的話也可以詢問喔(下方提供表單可以填寫詢問)!

 

《Arduino首次接觸就上手》我想問問題! *有任何問題都歡迎提問!

 

完成了基礎的操作後,也歡迎參考下個新影片企劃「Processing 互動裝置藝術結合 Arduino」喔~影片教學都會更新在CAVEDU Youtube上,歡迎訂閱、分享、開啟小鈴鐺!

 

【技術教學文】Realsense套件安裝內容更新-安裝教學

$
0
0

之前我們有寫過一篇Jetson Nano安裝及使用RealSenseD435/D455的安裝教學(連結如下)

它是使用JetsonHacksNano專案installLibrealsense的安裝檔來執行的,因為版本過舊也不支援JetPack4.4以上的系統,所以我們整理了原廠安裝套件的方法來寫一篇新的安裝教學。Jetson Nano安裝及使用RealSenseD435/D455 – CAVEDU教育團隊技術部落格

撰寫/攝影 郭俊廷
難度

★☆☆☆☆

時間

1H

材料表

以下安裝使用Jetson Nano B01JetPack4.4.1原廠映像來測試(相關載點如下)

https://developer.nvidia.com/jetpack-sdk-441-archive

 

這是按照我們《 初學Jetson Nano不說No-CAVEDU教你一次懂》

P229 安裝RealSenseviewer套件網址部分有更改所更改的內容。

 

根據RealSense原廠github資料顯示安裝下載套件的網址已經從HTTP改成HTTPS,新的網址應以https://librealsense.intel.com 開頭。

如果是按照我們《 初學Jetson Nano不說No-CAVEDU教你一次懂》 書籍內容安裝的或是參考之前JetsonHacksNano文章的人,安裝時應該都會出現以下403網址報錯問題。(如下圖)

RealSense原廠github資料:

https://github.com/IntelRealSense/librealsense/wiki/Release-Notes#release-2430

 

使用錯誤連結下載過修改安裝套件連結辦法:

 

我們首先介紹按照書籍安裝時出現錯誤無法安裝的解決辦法

如果已經使用錯誤的網址安裝套件時,之後就算使用新的網址安裝依然會報錯,這是因為套件網址清單已經被寫入設定檔中,需要修改設定檔的內容才能使用正確的網址更新套件。

 

修改方法如下:

首先移動到設定檔路徑,執行以下指令

cd /etc/apt/

接著執行ls這個指令可以查看有sources.list這個檔案

ls

接著修改檔案內容,把舊的網址刪掉或是註解掉,如果有使用新的網址下載過也可以把新的網址取消註解,執行以下指令修改sources.list檔案。(記得使用sudo權限否則無法儲存檔案)

 

舊的網址: http://realsense-hw-public.s3.amazonaws.com/ 相關網址

deb http://realsense-hw-public.s3.amazonaws.com/Debian/apt-repo bionic main(需刪掉或註解掉)

 

新的網址:https://librealsense.intel.com 開頭

deb https://librealsense.intel.com/Debian/apt-repo bionic main

sudo nano sources.list

修改完畢後,按CTRL+X離開,並按Y確定修改存檔後離開。(如下圖)

以上是有使用過舊的網址下載套件後遇到錯誤的解決辦法,如果沒有使用舊的網址下載過套件可以跳過以上步驟,直接執行以下安裝RealSense Viewer內容。

 

安裝RealSense Viewer

第二部分是JetPack4.4以上的系統如何安裝的步驟

首先是安裝RealSense Viewer的方法

 

1.註冊伺服器公鑰

sudo apt-key adv --keyserver keys.gnupg.net --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE || sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE

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

sudo add-apt-repository "deb https://librealsense.intel.com/Debian/apt-repo bionic main" -u

3.安裝SDK

sudo apt-get install librealsense2-utils
sudo apt-get install librealsense2-dev

4.開啟RealSense Viewer,這裡要記得要接上螢幕、鍵盤、滑鼠才可以開啟RealSense Viewer使用遠端連線操作否則可能發生錯誤

realsense-viewer

安裝Pyrealsense2

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

 

1.下載realsense的github的原廠套件包

git clone https://github.com/IntelRealSense/librealsense.git

 

2.確認apt-get的套件版本是最新的,並更新

sudo apt-get update && sudo apt-get upgrade

3.確認有安裝python環境 ( 以Python3為例 )

sudo apt-get install python3 python3-dev -y

4.安裝缺失套件

sudo apt-get install libssl-dev

5.移動到librealsense資料夾,並透過CMake建置,且強制使用Python3.6 來編譯(這一步驟花費時間可能需要安裝編譯至1小時請耐心等候並編譯)請一行一行依序執行。

cd librealsense
mkdir build
cd build
cmake ../ -DBUILD_PYTHON_BINDINGS:bool=true  -DPYTHON_EXECUTABLE=/usr/bin/python3.6
make -j$(nproc)
sudo make install

6.將pyrealsense2的函式庫加入環境變數中,回家目錄,將以下內容加入.bashrc檔案中(如下圖紅框處)

export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3.6/pyrealsense2

 

修改完畢後,按CTRL+X離開,並按Y確定修改存檔後離開。

cd ~
nano ~/.bashrc

7.重新開機或是使用一下指令重啟環境變數

source ~/.bashrc 

8.接著使用python3指令導入函式庫,沒有報錯就代表安裝成功了,如要離開輸入exit()即可離開。

python3
>> import pyrealsense2 as rs
>> exit()

可以去尋找以下路徑程式librealsense/wrappers/python/examples/opencv_viewer_example.py 

執行opencv_viewer_example.py程式測是可否正常使用Realsense。

 

 

NVIDIA CUDA核心GPU實做:Jetson Nano 運用TensorRT加速引擎 – 上篇

$
0
0

今天的內容很多所以分成了上下篇,上篇主要在講述TensorRT的概念以及使用ONNX模型等技巧,下篇會進入TensorRT應用的部分。

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

目錄

  • TensorRT
  • TensorRT 的優化方式
  • TensorRT vs Tensorflow Lite
  • TensorRT建構流程
  • ONNX (Open Neural Network Exchange)
  • Jetson Nano安裝TensorRT.
  • PyTorch 匯出 ONNX.
  • 透過ONNX RUNTIME運行ONNX Model
  • 使用TensorRT運行ONNX
  • PyTorch使用TensorRT最簡單的方式
  • YOLOv5使用TensorRT引擎方式
  • 結語

TensorRT

TensorRT是由 NVIDIA 所推出的深度學習加速引擎 ( 以下簡稱trt ),主要的目的是用在加速深度學習的 Inference,按照官方提出TensorRT比CPU執行快40倍的意思,就像是YOLOv5針對一張圖片進行推論用CPU的話大概是1秒,如果用上TensorRT的話可能就只要0.025秒而已,這種加速是非常明顯的!而這種加速大部分都是運用的邊緣裝置上 ( Edge Device ),由於邊緣裝置上的效能沒有一般電腦來的好,所以往往需要這種軟體加速。

TensorRT 的優化方式

圖源自NVIDIA原廠文件

 

TensorRT主要的優化過程有這些: Precision Calibration、Layer & Tensor Fusion、Kernel Auto-Tuning、Dynamic Tensor Memory、Multi-Stream Execution,今天會介紹前兩種,後面三種比較底層資訊也比較少所以就先不介紹了。

降低資料精準度(Precision Calibration

在官網上有提到trt支援INT8 和 FP16兩種更簡化的精度格式。神經網路模型再進行訓練的時候都需要將數據轉成張量 ( Tensor ),而 Tensor 的資料型態為FP32 ( 單經度浮點數 ),總共會耗費32個bit,而trt優化的FP16 ( 半經度浮點數 ) 則直接少一半,INT8又再少一半,在DLI的投影片中有提到 INT8所需的記憶體比FP32小了61%。但減少位元數雖然可以大幅降低模型的大小,但相對而言你的精準度勢必會下降,所以NVDIA也有提出了相關的解決方法。

對模型進行重構與優化(Layer & Tensor Fusion

1.第一步先刪除沒有使用到的輸出層

2.垂直優化:由於CUDA會在每一層輸入的時候啟動,而這個垂直優化就是透過將常使用的層作合併,像圖中將Conv、bias、relu合併為CBR,減少CUDA啟動關閉的次數來達到時間上的縮減。

圖源自NVIDIA原廠文件

3.水平優化:理論同上,如果同層其他分支也在運作一樣的架構則直接合併,要注意的地方是合併成同一層之後輸出必須要做分割,在輸出到不同層去。

圖源自NVIDIA原廠文件

 

TensorRT vs Tensorflow Lite

如同Tensorflow lite ( 以下簡稱 tflite ),他們都是用來加速的方法。他們倆者的主要差別在於trt是由NVIDIA推出的,如果使用NVIDIA的GPU來運作效果會比tflite還要快很多,但其實市面上還有很多設備是只有CPU或是沒有CUDA核心的GPU,那些設備就比較適合用tflite;我們今天的主角是Jetson Nano,它最大的優勢在於它擁有CUDA核心的GPU,能夠進行trt加速,它將會比其他邊緣裝置更適合用來開發AI相關的專案。

 

TensorRT建構流程

  1. ONNX parser:將模型轉換成ONNX的模型格式。
  2. Builder:將模型導入TensorRT並且建構TensorRT的引擎。
  3. Engine:引擎會接收輸入值並且進行Inference跟輸出。
  4. Logger:負責記錄用的,會接收各種引擎在Inference時的訊息。

基本上TensorRT的運作都需要先轉換成ONNX才行,那ONNX到底是什麼東西呢?

 

ONNX (Open Neural Network Exchange)

好玩的地方在於ONNX的名稱為Open Neural Network Exchange ( 神經網路之間的開源交流 ),所以其實從名稱來看就知道,他是一個標準化神經網路模型的工具。

圖源自NVIDIA原廠文件

 

因為現在大部分的硬體加速都是倚賴NVIDIA的GPU,幾乎就是AI世界的龍頭,所以其實各大框架都陸續支援trt的SDK,但是各大框架為了獨特性都會推出自己的模型格式,像是 PyTorch輸出模型格式為.pt、.pth而Tnesorflow輸出的模型為 .h5,各種不同的檔案格式對於trt來說要優化他們會很辛苦,所以ONNX推出了一個統一的模型格式 ONNX,透過ONNX的檔案格式便可以導入TensorRT來進行加速;對了,目前較熱門的Tensorflow也有合作哦!只是不是透過ONNX的方式來轉換。

 

Jetson Nano安裝TensorRT

安裝方法有提供兩種,第一種是官方的安裝方法,第二種是直接安裝我的映像檔,如果是體驗導向我會建議直接安裝我的映像檔。

1.  官方作法

https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html#installing-tar

詳細的安裝步驟可以參考官方網站,要注意的是 TensorRT 7 是還沒有支援 Jetson 系列的,所以可以考慮安裝6。這個會耗費大量的時間,所以另一個方法是使用我提供的映像檔,其中已經包含 tensorrt 以及 uff 等相關套件。

 

2.  我的映像檔

連結如下:

https://www.dropbox.com/sh/rgxe2uf8wodb3bx/AAAcBg0QnAnZIlgaQAD63eOza?dl=0。要注意的地方用SanDisk的SD卡可能會有容量不夠的問題,建議使用Samsung 64GB以上的記憶卡。

將TensorRT連結到virtualenv

$ vim ~/.bashrc
export CUDA_HOME=/usr/local/cuda
export PATH=$CUDA_HOME/bin:$PATH
export LD_LIBARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
export PYTHONPATH=/usr/lib/python3.6/dist-packages:$PYTHONPATH

完成之後進到虛擬環境中應該就可以看到虛擬環境連結到tensorrt了。

PyTorch 匯出 ONNX

官方介紹文件連結如下:https://pytorch.org/docs/stable/onnx.html。PyTorch為了追上AI加速的NVIDIA列車,早已在框架中也包含了ONNX模型匯出的函式庫,但是還是需要先安裝ONNX才行,基本上我們只要透過導入ONNX函式庫並且透過torch.onnx.export即可匯出ONNX的模型。

Torch.onnx.export

torch.onnx.export(model, args, f, export_params=True, verbose=False, training=False, input_names=None, output_names=None, aten=False, export_raw_ir=False, operator_export_type=None, opset_version=None, _retain_param_name=True, do_constant_folding=False, example_outputs=None, strip_doc_string=True, dynamic_axes=None, keep_initializers_as_inputs=None)

其中model就是要轉換的模型;args可以想像成是輸入的維度,以 [ batch , C , H , W ]為主,這邊順道提一下也有 dynamic_axes動態輸入維度的選項可以選擇,默認值export_param為True所以都會導出權重值;剩下的有興趣在去原廠的文件查看。

 

使用方法

使用onnx.export的方法也是非常的簡單,我們使用Alexnet來當作範例,這個是取自官方的文件,可以注意到他有定義輸入跟輸出的名稱,目的是為了後續調用方便:

import torch
import torchvision

dummy_input = torch.randn(1, 3, 224, 224, device='cuda')
model = torchvision.models.alexnet(pretrained=True).cuda()

input_names = [ "actual_input_1" ] + [ "learned_%d" % i for i in range(16) ]
output_names = [ "output1" ]

torch.onnx.export(model, dummy_input, "alexnet.onnx", verbose=True, input_names=input_names, output_names=output_names)

因為匯出的時候選擇verbose=True所以會將轉換的進度打印出來:

這邊直接引用原廠文件的內容:

The resulting alexnet.onnx is a binary protobuf file which contains both the network structure and parameters of the model you exported (in this case, AlexNet). The keyword argument verbose=True causes the exporter to print out a human-readable representation of the network:

匯出的是一個二進制的protobuf的檔案,這是一種序列化的資料結構,ONNX會依靠這種資料結構來描述模型檔案,在Caffe等AI框架也都是使用一樣的資料結構形式,那這個binary protobuf包含了神經網路的架構跟權重,之前在開發PyTorch的時候是被建議儲存權重就好,架構要再另外寫,有時候會覺得稍微有一點麻煩,但是ONNX就改善這個問題了,他只需要導入檔案,模型的架構也都包含在其中不用額外建構了。

 

檢查ONNX模型

首先我們要先安裝ONNX套件:

$ pip install onnx

我的結果如下,可以注意到它會連同protobuf也一起安裝了。

剛剛執行完程式之後應該可以注意到檔案中已經多了一個alexnet.onnx,這個就是我們匯出成功的檔案,接著可以透過下列程式來確認:

import onnx

# Load the ONNX model

model = onnx.load("alexnet.onnx")

# Check that the IR is well formed

print(onnx.checker.check_model(model))

print('-'*50)

# Print a human readable representation of the graph

print('Model :\n\n{}'.format(onnx.helper.printable_graph(model.graph)))

圖形化顯示ONNX模型

廣大的網友們都推薦使用Netron這套軟體,直接透過PyPI即可安裝。

透過下列程式碼可以查看圖形化模型,執行完他會產生一個localhost來存放圖檔:

$ netron [FILE]

點擊Block便可以獲得相關資訊:

可以看到我們當初在匯出的時候宣告了輸入的維度所以這邊輸入維度也是顯示當初設定的數值,在右側也可以看到相關資訊,包括連PyTorch的版本資訊也有顯示出來。

 

透過ONNX RUNTIME運行ONNX Model

獲得到ONNX後要怎麼執行呢?他自己也提供了一個平台(框架)可以運行,叫做ONNX RUNTIME ( 以下簡稱 ORT ),他兼容了許多硬體加速平台,像是今天的主角TensorRT,還有Intel的OpenVINO等等的,也因為ONNX模型的關係,所以他也兼融了各大平台的模型,等於說使用者透過TF、PyTorch建構的神經網路模型,都可以再ORT上進行推論跟訓練。

先來安裝ONNX RUN TIME:

$ pip install onnxruntime

使用ORT 來進行模型的推論之範例程式:

import onnxruntime as ort
ort_session = ort.InferenceSession('alexnet.onnx')
outputs = ort_session.run(None, {'actual_input_1': np.random.randn(10, 3, 224, 224).astype(np.float32)})
print(outputs[0])

基本上有兩個重點,第一個是導入需要用InferenceSession接著直接用run即可進行推論;第二個重點在於run的引數是要用字典形式來輸入,所以需要給定字典的欄位名稱並且告知輸入的數值。

 

ORT 運行 AlexNet

開始之前我先寫了一個整理顯示資訊的程式,檔名為log.py,特別將文字改了顏色:

import time

def print_div(text, custom='', end='\n\n'):
    print('-'*50, '\n')
    print(f"{text}{custom}", end=end)

class timer():
    
    def __init__(self, text):
        print_div(text, '...', end=' ')
        self.t_start = time.time()

    def end(self):
        t_cost = time.time() - self.t_start
        print('\033[35m', end='')
        print('Done ({:.5f}s)'.format(t_cost))
        print('\033[0m')

class logger():

    def __init__(self, text):
        print_div(text)

接著開啟一個新檔案 3_run_onnx.py將函式庫以及剛剛寫的log導入:

import onnxruntime as ort
import time
from PIL import Image
import numpy as np
from torchvision import transforms as T

# Custom 

from log import timer, logger

先讀取資料並且轉換成對應格式:

trans = T.Compose([T.Resize(256), T.CenterCrop(224), T.ToTensor()])
img = Image.open('../test_photo.jpg')
img_tensor = trans(img).unsqueeze(0)
img_np = np.array(img_tensor)
logger('Image : {} >>> {}'.format(np.shape(img) , np.shape(img_tensor)))

宣告ORT的Session並且不同於範例的做法我直接取得第一層的名稱,這個作法是為了避免打錯字或是忘記自己當初定義的名稱:

# ONNX Run Time

load_onnx = timer('Load ONNX Model')
ort_session = ort.InferenceSession('alexnet.onnx')
load_onnx.end()

# run( out_feed, in_feed, opt )

input_name = ort_session.get_inputs()[0].name

infer_onnx = timer('Run Infer')
outputs = ort_session.run(None, {input_name: img_np})[0]
infer_onnx.end()

獲得結果後將標籤給顯示出來:

# Get Labels

f = open('../imagenet_classes.txt')
t = [ i.replace('\n','') for i in f.readlines()]
logger("Result : {}".format(t[np.argmax(outputs)]))

運行結果如下:

ORT運行.onnx與PyTorch運行.pth速度差異

這邊我將輸出的數值做了softmax縮限在 [0, 1]之間。

稍微整理一下,可以發現光ONNX與PyTorch模型載入速度就有顯著的差異了,在Inference的時間上也有將近45倍的差距!由此可知ONNX確實能夠簡化模型並且加速Inference的時間,接著要使用TensorRT引擎來運行ONNX模型!

 

參考文章

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

NVIDIA線上課程:深度影像串流-DeepStream實作解說,使用網路影像串流進行深度學習辨識

$
0
0

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

Deep Stream

在過去的專案中,我們常常在使用網路攝影機或一般的USB攝影機來做影像辨識,自己在建構模型或開發專案的時候是否有更強大以及更簡單的開發工具?NVIDIA都知道大家的困難,所以它整合了一套工具叫做「DeepStream」,透過AI來分析串流媒體的資訊,讓使用者可以更清楚環境資訊,文中有提到像是城市街道上的交通跟行人;醫院病人的安全跟健康;工廠中機器加工的狀態,這些都可以透過DeepStream這套工具來開發。

DeepStream開發上較常見是Python但是底層是由C/C++所建構而成,他們為了讓使用者更容易入門,也提供了許多能夠參考的應用,可以到該github去看看https://github.com/NVIDIA-AI-IOT/deepstream_python_apps

在DeepStream中比較特別的部分除了提供安全的認證機制之外還有就是導入了TensorRT,目的是為了讓資料量減少,這個部份我們將會在特別寫一篇相關的技術給大家。接下來是DeepStream的架構圖:

從這張圖就可以看出整個運作的流程,從攝影機端獲得了影像之後先進行編碼跟基本的影像前處理,進行批次處理以及深度神經網路的inference,VIZ是視覺化的意思,神經網路模型運算結束後可能會有BoundingBox、Segmentation、Label需要顯示在影像上面,最後輸出的時候有提供各種儲存方法,像是繼續使用RTSP輸出或是儲存到電腦等等的。

至於分隔線以下的表示用到的工具以及技術,接下來稍微介紹一下各插件的功能,這個對於想取得DeepStream學習證明的人非常有幫助:

  1. 編碼:使用的插件為Gst-nvvideo4linux2,技術名稱叫做NVDEC
  2. 圖像前處理:Gst-nvdewarper用於改善魚眼鏡頭或全景相機;Gst-nvvideoconvert負責顏色格式轉換,以上用的硬體是GPU、VIC ( vision image compositor )。
  3. 批次處理:Gst-nvstreammux,讓DeepStream能獲得最佳推理。
  4. 在DNN的部分,提供了兩種進行Inference的方法,第一種是在本地端進行TensorRT的Inference,使用的方法是GST-nvinfer;第二種是在NVIDIA提供的雲端推論平台Triton,而用這個Triton技術的話是GST-nvinferserver。
  5. 推論完可能還會牽扯到是否追蹤物件來進行第二次的圖片分類,而這邊有提供Gst-nvtracker來處理這塊,從高效能到高精度都可以做選擇。
  6. 接著是可視化工具Gst-nvdsosd。
  7. 最後輸出的時候,Gst-nvmsgconv是為了將數據上傳到雲端上,需要做點格式轉換來減輕負載,Gst-nvmsgbroker則是為了建立跟雲端的連結。

上方的圖是一個針對inference流程做解釋,在批次處理到第二段的分類器這些都是屬於神經網路的範疇,這裡強調的是可以不只是做一次物件辨識,還可以透過tracker以及Secondary Classifier來進行N次辨識,最後輸出一樣可以放在EDGE端跟CLOUD端。

 

使用JetsonNano運作DeepStream範例

深刻了解DeepStream之後我們就可以開始進行實作了,以下實作內容大部分與NVIDIA課程內容相同,並且我們使用Jetson Nano 4G版本來運作。

準備Jetson Nano

下載DLI的映像檔:https://developer.download.nvidia.com/training/nano/dsnano_v1-0-0_20GB_200131A.zip,並且透過Etcher燒錄安裝並且遠端連線,可以參考此篇文章 (https://blog.cavedu.com/2019/04/03/jetson-nano-installsystem/ ),燒錄後Linux系統預設帳號密碼為「dlinano」,接著可以將MicroUSB接到您的電腦。

連線至Jupyter Lab

NVIDIA提供的DLI映像檔已經幫我們安裝好Jupyter Lab的功能,我們可以透過內網或外網遠端連線至Jetson Nano,只要取得虛擬IP的位址,如果是透過MicroUSB連接統一都是192.168.55.1,而透過WIFI遠端就會不太一樣,像我的裝置是192.168.12.152,要注意不論是哪一個IP位置都要加上埠號8888,使用方法是在IP的後方加上冒號與連接埠號,這樣才能連動到Jupyter Lab。

輸入帳號密碼後的畫面如下,我們要使用的程式碼會放在 ~/Notebooks資料夾中:

進入該資料夾後會看到NVIDIA提供的六個範例,

第一個是能夠偵測串流影像中的物件 ( 人、車等等 );

第二個是透過多個網路對串流影像進行辨識,除了能夠辨識物件之外還能得到車子的品牌/顏色等資訊;

第三個是多個串流影像的做法;

第四個則是輸出成影片,包含Bounding Box;

第五個則是透過Webcam來做即時影像辨識。

安裝 & 使用 VLC

VLC是一個常見的媒體撥放器,而在Windows端下載VLC目的是要連動到JetsonNano的影像畫面,因為JupyterLab無法開啟JetsonNano的視窗所以影像相關需要透過網路傳到VLC上,安裝方法可以直接上官方網站進行下載安裝。

開啟VLC之後,在媒體的選項中可以開啟網路串流,開啟後需要輸入{IP_Adress}:8554/ds-test,接下來就只要執行程式即可看到輸出的畫面:

01_ObjDetection.ipynb

這個範例是透過Nvidia提供的模型嘗試在串流影像中進行即時的物件偵測,它能辨識的物件總共有四種1. Vehicles 2. Bicycles 3. Persons 4. Roadsigns。

 

實行程式的方法很簡單,只需make它提供的資料夾,並且執行欲串流的影片即可,這邊要注意的是它只吃h264的編碼格式,如果是.mp4還需轉成.264才行,這裡讓我困惑的點是我當初也是透過h264的編碼格式輸出成mp4,結果它也是不能吃…可能是兩種副檔名提供的某些資訊不太相同~下圖為我執行西門町路況影像的結果:

在實作的部分,官方提供了兩個練習給大家操作,第一個是更改Bounding Box的項目,原本四個種類都會被標註,現在它希望更改成只標註腳踏車、汽車,而你只需要更動dstest1_pgie_config.txt的部分,將其改成對應標籤數字,對於不必要出現的項目只要將threshold更改為1即可。

[class-attrs-all]

threshold=0.2

eps=0.2

group-threshold=1

[class-attrs-1]

threshold=0.2

eps=0.2

 

第二個實作則是改變影像上面的標籤顯示,在左上方可以看到有顯示計算的數值,這部分的話就要去修改deepstream_test1_app.c的檔案,過程比較繁雜一點。

1.定義巨集,可以想像就是給予一個變數定值

2.新增變數

3.新增判斷並且增加上述變數的數值

4.改變顯示的內容

5.執行結果

02_MultipleNetworks.ipynb

它會在偵測到物件之後進行裁切接著在透過別的模型來進行更進一步的分類,相當有趣的一個範例,流程相當容易理解,進行第一次的物件辨識之後會透過tracker將該物件擷取出來進行第二次、第三次等地輔助辨識。

下圖為運行的結果:

稍微學會怎麼去更改這個程式吧!主要分為四個階段:

1.Define

2.Instantiate

3.bin/link

4.Configure

 

5.執行結果

6.還有第三個範例是「車子的種類」,讀者們可以自己去嘗試看看。

 

03_MultiStream.ipynb

04_VideoFileOutput.ipynb

檔案輸出的部分就不多說了,整體操作很簡單,主要在探討如何輸出、輸出的畫面調整、輸出的檔案格式。

05_DiffNetworks.ipynb

它除了內建的模型之外還提供了fasterRCNN、SSD、YOLO的模型,使用之前需要先進行下載,每個資料夾/ deepstream_sdk_v4.0.2_jetson/sources/objectDetector/ 中都有ReadMe可以查看。

06_DSWebcam.ipynb

當然最基本的開啟攝影機也不會少,透過USB外接網路攝影機並且執行該程式便可以進行即時的影像辨識,在下面影片中卡頓較嚴重的原因除了本身inference的延遲之外也有可能是因為網路延遲所導致,這邊大家就參考看看,實際速度還是因人而異,那這個部分當然也可以使用其他模型來運作。

結語

整體而言對於DeepStream提供的一些功能還是相當強大的,因為在串流影像的部分你不只需要注意AI模型的好壞,你還需要注意相當多的資料傳輸與網路問題,NVIDIA將這塊做好之後開發者當然就少去相當多的煩惱了,剩下的就是如何熟悉跟習慣這些工具的用法,下一篇我將會帶大家認識TensorRT,以及又該如何去使用它。

 

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

深入使用NVIDIA Jetson Inference機器學習專案 –物件辨識、語意分割以及訓練自己的物件辨識模型

$
0
0

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

作者/攝影 張嘉鈞
難度

★★☆☆☆(普通)

材料表
  1. Jetson Nano
  2. Webcam

物件辨識Objected Detection

物件辨識與圖片分類的最大差別就在於會提供「座標資訊」,並且通常會用於「多個物件」上面;因此訓練的時候就不是提供一個照片跟標籤,而是提供照片、標籤以及座標資訊等其他資訊 ( Xmin、Xmax、Ymin、Ymax )。

 

執行 detectnet

由於三個電腦視覺的範例執行方法都雷同,這部分就不多做解釋

$ cd build/aarch64/bin
$ ./detectnet.py ./images/airplane_1.jpg ./images/test/airplane_1.jpg

推論完會將輸出的資訊覆寫在圖片上,與圖片分類不同的地方在於因為objected detection有提供座標資訊,所以我們可以在inference的圖片上看到座標框出來的內容,並且也有辨識的結果:

此外終端機的內容也提供相當多的資訊,辨識到幾個物件,每個物件的開頭會是 <detectNet.Detection object>,接下來的ClassID就是在標籤當中編號第幾個,Confidence則是信心指數,接著就是座標的資訊。

如果要使用USB網路攝影機運行即時影像的話則是使用:

$ ./detectnet.py /dev/video0

可以辨識哪些種類?

Jetson-Inference在物件辨識的部分提供了不同種的神經網路模型,同時也有不同的數據集,接下會稍微介紹一下各神經網路模型可以辨識的類別。

 

可以使用哪些神經網路模型?

我們預設使用的神經網路模型是用ssd-mobilenet-v2,而所有神經網路的資訊如下

 Model CLI argument NetworkType enum Object classes
SSD-Mobilenet-v1 ssd-mobilenet-v1 SSD_MOBILENET_V1 91 (COCO classes)
SSD-Mobilenet-v2 ssd-mobilenet-v2 SSD_MOBILENET_V2 91 (COCO classes)
SSD-Inception-v2 ssd-inception-v2 SSD_INCEPTION_V2 91 (COCO classes)
DetectNet-COCO-Dog coco-dog COCO_DOG dogs
DetectNet-COCO-Bottle coco-bottle COCO_BOTTLE bottles
DetectNet-COCO-Chair coco-chair COCO_CHAIR chairs
DetectNet-COCO-Airplane coco-airplane COCO_AIRPLANE airplanes
ped-100 pednet PEDNET pedestrians
multiped-500 multiped PEDNET_MULTI pedestrians, luggage
facenet-120 facenet FACENET faces

在最後一個欄位是他所使用的數據集,從數據集可以看出這個神經網路模型可以辨識什麼樣的資料,第一個coco dataset就是日常所見的91個類別,像是人、電腦、水果、食物類的都有,而接下來的神經網路使用的類別,感覺是從COCO當中取出特定類別;官方提供的ped是pedestrians只有行人的意思,multiped則包含luggage (行李),dacenet則是只有臉。

 

該如何使用其他神經網路模型?

三種電腦視覺任務都可以使用 –network來使用其他模型:

$ ./detectnet.py --network=pednet ./images/peds_1.jpg ./images/test/peds_1.jpg

這邊我使用的是peds_1.jpg,照片包含一個人跟一台車,如果使用預設的神經網路模型的話 (SSD_MOBILENET_V2) 車子將會被辨識到;若使用pednet的話,由於只辨識行人所以車子就不會被匡列進去。

SSD-Mobilenet-v2:

ped-100:

語意分割Image Segmentation

語意分割、語意分析,在三種電腦視覺的任務當中算是最難的一個,因為它需要把所有的像素(pixel)都進行分類;圖片分類只需要在圖片中辨識到對應物件就好;物件辨識需要將圖片每個物件辨識、並框出位置;語意分割則是把每個像素都進行辨識,最後可以框出該物件的輪廓,因為每個像素都被進行分類了!

常常用於無人機的環境了解,畢竟這個比物件辨識還要更細部,通常可以獲得更多資訊;常見的AI去背景,有些也是用類似的技術。

 

執行 segnet

由於三個電腦視覺的範例執行方法都雷同,所以我就不多做解釋,在這邊我們使用的是segnet.py。

$ cd build/aarch64/bin
$ ./segnet.py ./images/horse_0.jpg ./images/test/horse_0.jpg

推論完會將輸出的資訊一樣會覆寫在圖片上,這邊會提供給你一張含有分割色塊的原圖,並一個則是單純色塊能更清楚的了解語意:

可以分割哪些物件?

可以注意到這裡用其不太一樣,也沒有提到神經網路模型,因為我們使用的都是fcn-resnet18這個模型,差別只在於數據集而已,所以我們稍後會針對數據集介紹一下,這裡我們預設使用的神經網路模型是用PascalVOC,而所有的資訊如下

 Dataset Resolution CLI Argument Accuracy
Cityscapes 512×256 fcn-resnet18-cityscapes-512×256 83.3%
Cityscapes 1024×512 fcn-resnet18-cityscapes-1024×512 87.3%
Cityscapes 2048×1024 fcn-resnet18-cityscapes-2048×1024 89.6%
DeepScene 576×320 fcn-resnet18-deepscene-576×320 96.4%
DeepScene 864×480 fcn-resnet18-deepscene-864×480 96.9%
Multi-Human 512×320 fcn-resnet18-mhp-512×320 86.5%
Multi-Human 640×360 fcn-resnet18-mhp-512×320 87.1%
Pascal VOC 320×320 fcn-resnet18-voc-320×320 85.9%
Pascal VOC 512×320 fcn-resnet18-voc-512×320 88.5%
SUN RGB-D 512×400 fcn-resnet18-sun-512×400 64.3%

Pascal VOC Dataset ( default )

這個數據集總共可以辨識19個物件,在該數據集的介紹當中區分為四個類別Vehicles、Household、Animals、Person又各分細項:

Vehicles 汽車 Car、Bus、Bicycle、Motorbike、Boat、Train
Household 家庭 Chair、Sofa、Dining table、TV/monitor、Bottle、Potted plant
Animals 動物 Cat、Dog、Cow、Horse、Sheep、Bird
Person 人 Person

Cityscapes

這個也是能辨識19個類別,他是在不同的程式去蒐集「街景」,所以日常在街景可以看到的東西,都被收納在這個數據集當中。

 

DeepScene

這個數據集則比較小一點,能辨識的類別也只有6個,分別為 無效(void),道路(trail),草叢(grass),植被(vegetation),天空(sky)和障礙物(obstacle)。

 

SUN RGB

這個數據集主要用於室內設計上面,提供了10,335張不同的室內圖片,總共的類別有牆、地板、門、窗戶、桌子、檯燈等21個類別。

 

Multi-Human

這個部分也是提供了21個類別,但主要著重在人體上的語意分割,像是 頭髮、T-shirt、襪子、腳、眼鏡等等的。

 

如何查看神經網路模型辨識的標籤

我們可以在工作的資料夾發現除了有Images的資料夾也有Network資料夾,這個Network存放的是所有下載的神經網路模型,我們可以透過進入那些神經網路的資料夾尋找classes.txt來獲取它所有的標籤類別哦!這邊以Pascal為例:

$ cd /jetson-inference/data/networks/FCN-ResNet18-Pascal-VOC-320x320
$ ls -la

接著我們可以直接使用cat來查看內容,這邊我加上了 -n 讓內容可以顯示行號,進而知道我們的標籤總共有多少個哦!

$ cat -n classes.txt

這樣你就知道怎麼樣去查到一個神經網路模型到底可以辨識哪一些類別了!

 

如何使用其他神經網路模型?

使用其他神經網路模型的方法也是一樣的,使用–network即可。

$ ./segnet.py --network= fcn-resnet18-mhp-512x320 ./images/peds_1.jpg ./images/test/peds_1.jpg

程式解析

在這裡我們將會解析Jetson Inference的imagenet.py、detectnet.py、segnet.py,這將能幫助到想要使用Jetson Inference來開發的使用者,因為Jetson Infernece已經提供訓練好的模型,並且已經轉成可以用TensorRT加速的onnx了 ( 這部分下一篇會再介紹 ),所以使用Jetson Inference開發真的是快速又方便;可以注意到我上述的介紹式寫 .py代表我們接下來會介紹的都是Python語言,而PyTorch底層是C++所以Inference也有提供C++的程式。

 

Imagenet.py

1、首先一定要導入它提供的API:

#!/usr/bin/python3


import jetson.inference	
import jetson.utils

2、這邊的範例使用的是影像串流,所以他會先擷取到攝影機物件,接著再用While迴圈不斷擷取當前畫面,來達到即時影像的功能:

net = jetson.inference.detectNet("ssd-mobilenet-v2", threshold=0.5)
camera = jetson.utils.videoSource("csi://0")      
# '/dev/video0' for V4L2


while display.IsStreaming():

3、在迴圈當中,第一步要擷取當前影像,接著將影像丟進模型當中,這邊會自動幫你做overlay的動作,也就是辨識完的結果會直接顯示在圖片上:

    img = camera.Capture()
    detections = net.Detect(img)

4、最後使用Render將圖片覆寫,使用SetStatus設定標題的內容:

    display.Render(img)
    display.SetStatus("Object Detection | Network {:.0f} FPS".format(net.GetNetworkFPS()))

使用Docker的請注意

使用Docker的同學,記得先新增一個資料夾、並且每次開啟Docker的時候都要做mount的動作,當然也可以寫進.sh當中,每次執行就不用再額外宣告。

1、新建要掛載的目錄,並將程式改為執行檔:

$ cd ~/
$ mkdir my-recognition-python
$ cd my-recognition-python
$ touch my-recognition.py
$ chmod +x my-recognition.py

2、開啟Docker的時候需要進行mount:

$ docker/run.sh --volume ~/my-recognition-python:/my-recognition-python   
# mounted inside the container to /my-recognition-python

 

結論

到目前為止,一些基本的使用方式都已經帶給各位了,也有教基本的程式碼使用,因為Jetson Inference的整合讓整個AI應用變得相當簡單,未來會在出一篇進階版本的,會教導如何使用Open Image的資料集訓練客製化的模型,也會教導如何蒐集自己的資料,可以盡請期待哦!

 

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

 

NVIDIA CUDA核心GPU實做:Jetson Nano 運用TensorRT加速引擎 – 下篇

$
0
0

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

使用TensorRT運行ONNX

要來運行TensorRT了,來複習一下TensorRT的流程:

  1. ONNX parser:將模型轉換成ONNX的模型格式。
  2. Builder:將模型導入TensorRT並且建構TensorRT的引擎。
  3. Engine:引擎會接收輸入值並且進行Inference跟輸出。
  4. Logger:負責記錄用的,會接收各種引擎在Inference時的訊息。

 

第一個我們已經完成了,接下來的部分要建構TensorRT引擎,這個部分可以參考於NVIDIA的官網文件,主要程式如下,總共三個副函式build_engine、save_engine、load_engine,就如字面上的意思一樣是建置、儲存、載入,而log函式庫是我自己寫的用來顯示狀態以及計時:

import tensorrt as trt
from log import timer, logger

TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
trt_runtime = trt.Runtime(TRT_LOGGER)

if __name__ == "__main__":
    
    onnx_path = 'alexnet.onnx'
    trt_path = 'alexnet.trt'
    input_shape = [1, 224, 224, 3]
    
    build_trt = timer('Parser ONNX & Build TensorRT Engine')
    engine = build_engine(onnx_path, input_shape)
    build_trt.end()
    
    save_trt = timer('Save TensorRT Engine')
    save_engine(engine, trt_path)
    save_trt.end()

build_engine的程式碼,max_workspace是指GPU的使用暫存最大可到多少,因為TensorRT可以支援到Float Point 16,這次模式選擇fp16,在建構引擎之前需要先解析 (Parser) ONNX模型,接著再使用build_cuda_engine來建構:

def build_engine(onnx_path, shape = [1,224,224,3]):
    
    with trt.Builder(TRT_LOGGER) as builder, builder.create_network(1) as network, trt.OnnxParser(network, TRT_LOGGER) as parser:
        
        builder.max_workspace_size = (256 << 20)    
# 256MiB

        builder.fp16_mode = True 
# fp32_mode -> False

        
        with open(onnx_path, 'rb') as model:
            parser.parse(model.read())

        engine = builder.build_cuda_engine(network)

        return engine

save_engine的程式碼,儲存的時候需要將引擎給序列化以供儲存以及載入:

def save_engine(engine, engine_path):
    
    buf = engine.serialize()
    with open(engine_path, 'wb') as f:
        f.write(buf)

load_engine的程式碼,主要在於要反序列化獲得可運行的模型架構:

def load_engine(trt_runtime, engine_path):
    
    with open(engine_path, 'rb') as f:
        engine_data = f.read()
    engine = trt_runtime.deserialize_cuda_engine(engine_data)

    return engine

執行的結果如下,其實沒有耗費很多時間:

可以看到已經有一個 “ Alexnet.trt “ 生成出來了,或許因為經過序列化處理,所以檔案少了非常多的容量:

接下來就是重頭戲了,使用TensorRT進行Inference,先導入函式庫,這邊要注意common是從 /usr/src/tensorrt/samples/python/common.py複製出來的,engine是剛剛建構引擎的程式,log是我另外寫的用來計時跟顯示,其中trt的logger跟runtime也都先定義好了方便之後的呼叫:

import tensorrt as trt
from PIL import Image
import torchvision.transforms as T
import numpy as np

import common
from engine import load_engine
from log import timer, logger

TRT_LOGGER = trt.Logger(trt.Logger.WARNING)
trt_runtime = trt.Runtime(TRT_LOGGER)

載入資料的副函式,這邊需要轉成numpy格式,因為trt的引擎只吃numpy:

def load_data(path):
    trans = T.Compose([
        T.Resize(256), T.CenterCrop(224), T.ToTensor()
    ])

    img = Image.open(path)
    img_tensor = trans(img).unsqueeze(0)
    return np.array(img_tensor)

接著載入引擎並且分配內存,binding是存放input、output所要佔用的空間大小,stream則是pycuda的東西 ( cuda.Stream() ),是cuda計算缺一不可的成員;這邊將inputs的內容替換成我要inference的照片,.host的意思是input的內存空間。

# load trt engine

load_trt = timer("Load TRT Engine")
trt_path = 'alexnet.trt'
engine = load_engine(trt_runtime, trt_path)
load_trt.end()

# allocate buffers

inputs, outputs, bindings, stream = common.allocate_buffers(engine)
# load data

inputs[0].host = load_data('../test_photo.jpg')

推論的部分則是透過common.do_inference來進行,create_execution_context是必要的旦沒有開源所以不太清楚裡面的內容,:

# inference

infer_trt = timer("TRT Inference")
with engine.create_execution_context() as context:
    trt_outputs = common.do_inference(context, bindings=bindings, inputs=inputs, outputs=outputs, stream=stream)
preds = trt_outputs[0]
infer_trt.end()

最後取得標籤以及對應的信心指數:

# Get Labels

f = open('../imagenet_classes.txt')
t = [ i.replace('\n','') for i in f.readlines()]
logger(f"Result : {t[np.argmax(preds)]}")

接著稍微比較了所有的框架,但可能因為同時進行三種不同的框架,Jetson Nano負荷不來所以時間都被拉長了,但我們仍然可以從比例看的出來彼此之間的差距,PyTorch:ORT:TRT大約是7:2:1,代表運行PyTorch所耗費的時間是開啟TRT引擎的7倍!

從下圖可以看到蠻有趣的一點是理論上精度最高的是PyTorch的版本,結果在信心指數的部分卻是最低的。

PyTorch使用TensorRT最簡單的方式

 

torch2trt套件

接下來來介紹一下這個套件,可以只用少少的程式碼將PyTorch的模型轉換成trt的模型,對於torch的愛好者來說實在是太棒了:

安裝方法如下,這邊我是採用我的映像檔並且開啟torch虛擬環境:

$ git clone https://github.com/NVIDIA-AI-IOT/torch2trt
$ cd torch2trt
$ workon torch
(torch) $ python3 setup.py install

torch2trt 將 PyTorch的模型轉換成tensorrt

使用方法如下,透過torch2trt就可以直接轉換,一樣需要宣告輸入的維度大小;接著也可以使用pytorch的方式進行儲存;導入則需要使用TRTModule:

import torch
from torch2trt import torch2trt
from torchvision.models.alexnet import alexnet

# Load Alexnet Model

model = alexnet(pretrained=True).eval().cuda()

# TRT Model

x = torch.ones((1, 3, 224, 224)).cuda()
model_trt = torch2trt(model, [x])

# Save Model

alexnet_trt_pth = 'alexnet_trt.pth'
torch.save(model_trt.state_dict(), alexnet_trt_pth)

# Load Model


from torch2trt import TRTModule
model_trt = TRTModule()
model_trt.load_state_dict( torch.load('alexnet_trt.pth'))

完整程式碼如下:

import torch
from torch2trt import torch2trt
from torchvision import transforms as T
from torchvision.models.alexnet import alexnet
import time

# Use to print info and timing

from print_log import log

# Load Model

alexnet_pth = 'alexnet.pth'
load_model = log("Load Model...")
model = alexnet(pretrained=True).eval().cuda()
torch.save(model.state_dict(), alexnet_pth, _use_new_zipfile_serialization=False)
load_model.end()

# TRT Model

convert_model = log("Convert Model...")
x = torch.ones((1, 3, 224, 224)).cuda()
model_trt = torch2trt(model, [x])
convert_model.end()

# Save Model

alexnet_trt_pth = 'alexnet_trt.pth'
save_model = log("Saving TRT...")
torch.save(model_trt.state_dict(), alexnet_trt_pth)
save_model.end()

在 JetsonNano上的運作結果如下,轉換的時間為127秒左右,儲存的時間為160秒左右,基本上時間會因各個裝置不同而改變,執行完之後就會看到多了兩個檔案 alexnet以及alexnet_trt:

接著我稍微改動了Github的範例,使用自己的貓咪照片來當作預測資料,首先載入模型、資料、標籤檔:

import torch
import torch.nn as nn
from torchvision import transforms as T
from torchvision.models.alexnet import alexnet

from torch2trt import torch2trt
from torch2trt import TRTModule

import os
import cv2
import PIL.Image as Image
import time

# Use to print info and timing

from print_log import log

def load_model():

    model_log = log('Load {} ... '.format('alexnet & tensorrt'))
    
    model = alexnet().eval().cuda()
    model.load_state_dict(torch.load('alexnet.pth'))
    model_trt = TRTModule()
    model_trt.load_state_dict(torch.load('alexnet_trt.pth'))
    
    model_log.end()

    return (model, model_trt)

def load_data(img_path):
    
    data_log = log('Load data ...')
    
    img_pil = Image.open(img_path)
    trans = T.Compose([T.Resize(256),T.CenterCrop(224), T.ToTensor()])
    
    data_log.end()

    return trans(img_pil).unsqueeze(0).cuda()

def load_label(label_path):
    f = open( label_path, 'r')
    return f.readlines()   

接著先寫好了inference的過程:

def infer(trg_model, trg_label, trg_tensor, info = 'Normal Model'):
    
    softmax = nn.Softmax(dim=0)
    infer_log = log('[{}] Start Inference ...'.format(info))

    with torch.no_grad():
        predict = trg_model(trg_tensor)[0]
        predict_softmax = softmax(predict)
    
    infer_log.end()
    label = trg_label[torch.argmax(predict_softmax)].replace('\n',' ')
    value = torch.max(predict_softmax)
    return ( label, value)

最後就是整個運作的流程了:

if __name__ == "__main__":

    
# Load Model

    model, model_trt = load_model()

    
# Input Data

    img_path = 'test_photo.jpg'
    img_tensor = load_data(img_path)

    
# Label

    label_path = 'imagenet_classes.txt'
    labels = load_label(label_path)

    
# Predict : Normal

    label, val = infer(model, labels, img_tensor, "Normal AlexNet")
    print('\nResult: {}  {}\n'.format(label, val))

    
# Predict : TensorRT

    label_trt, val_trt = infer(model_trt, labels, img_tensor, "TensorRT AlexNet")
    print('\nResult: {}  {}\n'.format(label_trt, val_trt))

獲得的結果如下:

接著我們來嘗試運作物件辨識的範例吧!我第一個想到的就是torchvision中常見的物件辨識fasterrcnn,但是他轉換成trt過程問題很多,從這點也看的出來trt的支援度還沒有非常高,常常因為一些沒支援的層而無法轉換這時候你就要自己去重新定義,對於新手而言實在是非常辛苦,所以Fasterrcnn這部分我就先跳過了,轉戰YOLOv5去嘗試運行TensorRT看看。

 

YOLOv5使用TensorRT引擎方式

其實排除上述介紹的簡單方式,正規的方式應該是先轉成ONNX再轉成TensorRT,其中yolov5就有提供轉換成ONNX的方式

 

1.  轉換成 ONNX格式再導入TensorRT ( 僅到匯出 )

這邊我們直接使用YOLOv5來跑範例,先下載YOLOv5的Github並且開啟虛擬環境,如果你是使用自己的環境則可以透過安裝YOLOv5相依套件來完成:

$ git clone https://github.com/ultralytics/yolov5
$ cd yolov5
$ workon yolov5

Nano 上安裝ONNX、coremltools:

$ sudo apt-get install protobuf-compiler libprotoc-div
$ pip install onnx
$ pip install coremltools==4.0

進行ONNX的轉換:

$ source ~/.bashrc
$ workon yolov5
(yolov5) $ python models/export.py

預設是yolov5s.pt,執行完之後可以發現多了yolov5s.onnx以及yolov5.torchscript.pt,接著就可以使用ONNX的方法去導入使用,不過在yolo系列很少人會這樣做,主要是因為yolo有自定義的層,可能會導致trt無法轉換,但是也因為yolo已經很出名了,所以轉換的部分已經有人整合得很好,可以直接拿來使用。

1.  使用tensorrtx直接轉換 ( 可執行 )

YOLOv5有提供直接從.pt轉成trt的方式,這時候就要參考另外一個github了 https://github.com/wang-xinyu/tensorrtx,裡面有個yolov5的資料夾,按照ReadMe進行即可完成轉換並且進行inferece:

1.複製兩個Github並複製py到yolov5資料夾,運行gen_wts.py來生成yolov5s.wpt,這個是讓TensorRT引擎運行的權重檔。

(yolov5) $ git clone https://github.com/wang-xinyu/tensorrtx.git
(yolov5) $ git clone https://github.com/ultralytics/yolov5.git
(yolov5) $ cd yolov5 
(yolov5) $ cp yolov5s.pt weights/
(yolov5) $ cp ~/tensorrtx/yolov5/gen_wts.py .
(yolov5) $ python gen_wts.py

2.由於tensorrt引擎是基於C++,所以常常會使用cmake來建構成執行檔。

(yolov5) $ cd ~/tensorrtx/yolov5
(yolov5) $ cp ~/yolov5/yolov5s.wts .
(yolov5) $ mkdir build
(yolov5) $ cd build
(yolov5) $ cmake ..
(yolov5) $ make
(yolov5) $ sudo ./yolov5 -s             // serialize model to plan file i.e. 'yolov5s.engine' 

建構完之後就可以直接透過下列指令執行,會輸出圖檔 _bus.jpg、_zidane.jpg:

(yolov5) $ sudo ./yolov5 -d  ~yolov5/data/images  

接下來還可以使用Python來進行Inference,需安裝tensorrt跟pycuda:

(yolov5) $ pip install pycuda
(yolov5) $ python yolov5_trt.py

執行結果如下:

接著使用原生的yolov5進行inference,耗費時間約為0.549s、0.244s:

不曉得為什麼跑了那麼多範例,yolov5的速度沒有提升反而下降,這個部分還需要研究一下…如果廣大讀者們知道的話麻煩在留言告訴我~

結語

從圖片分類的範例來看的話,TensorRT還是非常的厲害的!但是目前支援度還是不太高,入門的難易度很高,所以如果有要使用自己的模型要好好研究一番,但如果是用GPU模型並且是直接使用常見模型的話TensorRT絕對一個大趨勢,畢竟加速的效果真的不錯。

 

參考文章

 

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


在 Jetson Nano 上執行 Google Mediapipe,立即可用的辨識方案超好用!

$
0
0
撰寫/攝影 曾吉弘
難度

★★★☆☆

時間 1.5小時(包含下載與燒錄SD卡)

如果Jetson nano 已開機則為30分鐘

材料表

Google Mediapipe

    Google Mediapipe 針對即時串流媒體提供了開放原始碼且跨平台的機器學習解決方案,不需要深度攝影機就能偵測臉部、臉部格點、姿勢、2D物件體積以及手指等等,非常厲害。支援的平台包含 Android, iOS, C++ python、JavaScript 與自家的 Coral 運算裝置等平台,另外經過 CAVEDU 實際測試,在  Jetson nano 與 Raspberry Pi 上都有很不錯的執行速度。 

  Google Mediapipe 提供了非常多立即可用的應用,根據首頁說明,目前即可用的方案約有16種,請注意,目前並非所有平台都支援所有方案,請根據所要的應用來看看是否有更快上手的方法。但基礎應用如臉部偵測、臉部網格、手勢、姿勢等則各平台都有。

 迫不急待想要先玩一下的朋友,mediapipe 提供了 colab 的版本,直接點開來就可以玩啦,如以下就是 hand 範例 的 colab 執行畫面,自行上傳一張有手的照片就可以辨識手部的細微動作與各關節位置。對於各個方案所使用的神經網路模型請點我

在 Jetson Nano 上安裝 Mediapipe

    本文根據PINTO0309網友的教學,成功在 Jetson Nano 上完成 mediepipe 的環境,並可順利執行各個 python 範例。它另外也提供了 Raspberry Pi 的做法,希望對您有幫助,happy making ~

  1. 取得一套可開機的 Jetson Nano ,歡迎參考CAVEDU部落格的Jetson相關文章喔!也歡迎買一本書來慢慢跟著做~
  2. 開機,並開啟 ternimal,依序輸入以下指令來安裝所需套件。
sudo pip3 install opencv_contrib_python
sudo apt-get install curl
git clone https://github.com/PINTO0309/mediapipe-bin
cd mediapipe-bin
./v0.8.5/numpy119x/mediapipe-0.8.5_cuda102-cp36-cp36m-linux_aarch64_numpy119x_jetsonnano_L4T32.5.1_download.sh   (這個 sh 檔會下載一些檔案)
sudo pip3 install numpy-1.19.4-cp36-none-manylinux2014_aarch64.whl
sudo pip3 install mediapipe-0.8.5_cuda102-cp36-none-linux_aarch64.whl
sudo pip3 install opencv-python dataclasses
cd ~
git clone https://github.com/Kazuhito00/mediapipe-python-sample 
cd mediapipe-python-sample

經過一番奮戰,終於完成囉!

執行範例

    在此直接使用 https://github.com/Kazuhito00/mediapipe-python-sample 的範例,在部分情況下 FPS 可到 40 以上!您也可以試試看 mediapipe 原廠的 python 範例

手勢偵測

$ python3 sample_hand.py

 

相關文章:

 

 

BBC micro:bit V2使用DHT11溫溼度感測器模組方法

$
0
0
作者/攝影  郭俊廷
時間  1hour
難度 ★☆☆☆☆
材料表

在我們的cavedu的gitbook當中有很多套件的教學,這其中也包含了我們的洞洞么教學材料包,其中裡面有使用到micro:bit連接DHT11溫溼度感測器模組的方法,我們發現有人使用新版的micro:bit V2搭配上舊的函式庫時會有無法正常顯示溫溼度的情形,測試之後發現micro:bit V2無法使用一些DHT11的舊的函式庫,需要使用另一個函式庫且輸入電壓需要調整到3.3V才能正常顯示溫溼度。

 

更多洞洞么教學材料包的模組使用教學:模組使用教學- cavedu

更多的micro:bit教學影片:micro:bit影片教學- cavedu

至於新版的micro:bit V2多了那些功能可以參考以下文章:新版BBC micro:bit,多了麥克風與小喇叭還有觸碰功能! – CAVEDU教育團隊技術部落格

 

micro:bit電路圖

DHT11溫溼度感應器模組數位訊號輸出, 可以接「0、 1、 2、 8、 12、13、14、 15、 16、 19、20」的 micro:bit訊號端上,建議使用的是0、1、2腳位。本範例連接到「P0

 

 

注意: 測試時發現輸入電壓如果切換到5V時會發生無法正常顯示溫、濕度的問題、請記得把V1切到3V3當中(如上圖紅框處)。

以下函式庫測試後適用於micro:bit v2,發現一開始如果溫、濕度顯示-999.0為正常,請等程式驗證後即可正常顯示溫、濕度,如還是無法正常顯示可以嘗試將MICRO USB供電改為擴充版供電、重新插拔感測器的3pin排線或換一條線或是按板子背後的RESET鈕重置程式讓他重新讀取數值。

如無法正常顯示溫濕度請先檢查上述問題,有無正確測試過。

如上述步驟檢查過使用我們洞洞么教學材料包裡面的DHT11模組,在使用micro:bit時,無法正常顯示溫濕度,請聯絡我們。

 

首先需要先進入Microsoft MakeCode網頁線上編輯器,網址如下

https://makecode.microbit.org/#editor

在使用DHT11溫溼度感應器之前,需要擴展DHT11溫溼度感應器的指令庫。打開makecode程式設計平臺,滾動至指令區最底部,依序點擊進階-擴展,並使用以下網址安裝套件。(經測試此函式庫DHT22感測器也可正常使用)

DHT11溫溼度感應器套件安裝網址:

https://github.com/alankrantas/pxt-DHT11_DHT22

 

進階;擴展套件的位置
使用網址安裝sensors的套件方法
使用搜尋DHT11安裝sensors的套件方法

新增後在上方可以看見增加的DHT11/DHT22套件

Microsoft MakeCode積木畫布 (適用microbit v2)

使用pxt-DHT11_DHT22此函式庫時(完整程式如下),需先宣告你要使用攝氏溫度還是華氏溫度

並且要設定此感測器Query為DHT11(如為DHT22感測器請選擇DHT22)

設定Data pin為P0

Pin pull up為true

Serial output為false

Wait 2 sec after query為true

可透過micro:bit顯示指示燈看到DHT11溫溼度感應器的溫度和濕度的狀態。會四捨五入小數點輪流顯示T:目前溫度H:目前濕度。

JavaScript 程式

basic.forever(function () {
   basic.pause(100)
   dht11_dht22.selectTempType(tempType.celsius)
   dht11_dht22.queryData(
   DHTtype.DHT11,
   DigitalPin.P0,
   true,
   false,
   true
   )
   basic.showString("T:")
   basic.showString("" + (Math.round(dht11_dht22.readData(dataType.temperature))))
   basic.showString("H:")
   basic.showString("" + (Math.round(dht11_dht22.readData(dataType.humidity))))
})

 

LinkIt 7697車體組裝攻略(其實就組裝說明,但「攻略」看起來就威)

$
0
0

日前慶祝我大臺灣於東京奧運奪牌,就拿出沒公開上市的車體來贈送,發行後才想到沒有寫組裝說明攻略,趕快來補上。

作者/攝影 腦波弱老闆
時間 組裝大約10分鐘,如果是流水線組裝就會更快。
成本 大約1,400元
難度 我腦波弱都做得出來,是能有多難
材料表 藍牙自走車基本材料包(使用LinkIt™ 7697)

自從有了「LinkIt™ 7697開發板(以下簡稱LinkIt 7697)+ LinkIt™ 7697機器人擴充板RobotShield V2.0(以下簡稱RobotShield)」,增加了我們很多在教學與創作上的樂趣。

只要可以固定馬達、輪胎,再配上支撐用的惰輪,就可以做出會動的作品。

我們嘗試過很多有趣的材料,像是飲料利樂包、寶特瓶、紙箱、舊玩具等,但很多時候,我們也要依用戶的需求,製作成教學用的小車來交貨。這次拿來講的車體就是這樣來的,所以上面會有一些神祕的孔洞,那是幫之前客人裝感測器用的,如果您覺得看起來礙眼,也歡迎跟我們採購對應的模組裝上去。

 

清點材料:

如果是跟本公司購買的套件,您應該會收到以下這些:

  • 四片壓克力板:通常保護膜還沒撕下來,左右側板、頂板、底板。

三組螺絲包:各有不同用處,①馬達與惰輪螺絲包、②塑膠螺絲包、③車體螺絲包。

  • 馬達與惰輪螺絲包:M2長螺絲與螺帽是用來固定馬達用的,兩個M3螺絲與螺帽固定惰輪。

  • 塑膠螺絲包:用來固定RobotShield用的,有四個 M2螺絲、支撐柱與螺帽。

  • 車體螺絲包:內有八個M3螺絲與螺帽,固定車體用。

LinkIt™ 7697開發板與RobotShield各一個,馬達(已銲線)、輪胎各兩個,惰輪(又稱牛眼輪)一個

 

有缺少請趕快跟我們聯絡補充,多出來的就收下當備品。

 

工具:

  • 十字起子用來鎖螺絲用
  • 一字起子是馬達電源線要鎖上端子台用

 

製作步驟:

1.車體假組合:

假組合可以先幫助我們了解各零件的相對位置與方向,先把四片壓克力板組裝起來,注意一下方向與位置,這個階段不用鎖螺絲。

確定位置之後,把壓克力上的保護膜撕掉。

 

2.把惰輪鎖上底板。

 

3.馬達鎖上側板,注意方向

鎖上螺帽

左右側都要裝,注意方向。

 

4.塑膠支撐柱鎖上頂板。

RobotShield晚一點再鎖

 

5.組裝車體:

側板(不要兩側都裝)跟頂板結合,並將馬達線路引出。

組裝底板

裝上另一側的底板,也要將馬達線引出喔。

6.鎖上RobotShield,並接上馬達線路

7.裝上LinkIt 7697開發板(注意方向)

 

8.執行測試程式

請參閱本團隊文章說明,測試馬達是否如預期地轉動

  • 【LinkIt 7697 專題教學】想自己動手做藍牙遙控車?就是這一篇了!

【教學】想自己動手做藍牙遙控車?就是這一篇了!

  • 【教學】以ArduinoIDE設計LinkIt 7697藍牙遙控車

【教學】以ArduinoIDE設計LinkIt 7697藍牙遙控車

 

9.裝上輪子

是的,建議您最後再裝上輪子,並在安全的區域內操控這台車,以免影響或損壞您愉快的心情與寶貴的資產。

故障排除

您可能會遇到車子移動的方向跟您想像的不一樣,例如按前進鍵,車子卻轉彎或後退。

建議您依下列順序處理,如果問題解決了,就不用繼續往下試。

  1. 確定程式碼是對的。
  2. 觀察馬達有沒有在轉,沒在轉可能是電源線鬆脫或是斷了,重新接線跟檢查線路有沒有斷裂。
  3. 馬達轉動方向相反,把端子台的馬達線反過來接。
  4. 拿一個確定是功能正常的馬達來接接看。
  5. 上述手段都不能解決問題時,請再買一套跟我們聯絡。

 

走得不夠直

跟您報告一個事實,這是絕症,它一定不會直直走。

車子的移動受很多外力影響,就算是我們可以找到兩顆在同電力狀況下,轉速表現一致的馬達,車子還是會因為輪胎的狀況、地面狀況、車體負載與配重等因素而影響移動狀況。也就是為什麼我們會透過有方向控制鍵或是各種感測器來修正車子的移動方向。

頂板上面還有一些神秘的孔洞,是預留安裝感測器(如下圖)或是其他您想像力與預算所及的邊界。如果您對這個車體設計不滿意,我們很樂意在您的預算範圍內,提供客製化服務。

 

範例:加裝紅外線測距感測器。

相關文章:

 

 

Teachable Machine 嵌入式神經網路 – Arduino 也可以做視覺分類!

$
0
0
作者/攝影 曾吉弘
時間 1.5 小時
難度

★★★☆☆

材料表
  • Arduino Nano 33 BLE Sense
  • OV7670 相機模組
  • 母/母杜邦線材
  • PC / NB (作業系統不限),用於執行 Processing IDE / Arduino IDE / Teachable Machine(網頁開啟)

Teachable Machine 嵌入式神經網路 – Arduino 也可以做視覺分類!

Google Teachable Machine 最近推出了新的神經網路匯出方案,需要使用 Arduino Nano 33 BLE Sense 搭配 OV7670 相機模組,就可以讓 Arduino 透過匯出的 tensorflow lite 檔案來做到邊緣裝置端的”即時”影像分類。

說是即時,但都在 Arduino 上執行了,當然不可能快到哪裡去,圖片也是黑白的,這都是針對 Arduino 的運算能力來考量,且 Arduino Nano 33 BLE Sense 與 OV7670 相機模組這兩個買起來也快接近 Raspberry Pi 3 了。另外,ESP32cam 搭配 tensorflow lite 很早就能做到深度學習視覺分類應用,但用 teachable machine 可以自行訓練所要目標,也是不錯的選擇。老話一句,看您的專案需求來決定使用哪些軟硬體喔!

本文會帶您完成相關的軟硬體環境設定,並操作  Teachable Machine 透過相機模組來搜集照片、訓練神經網路,最後匯出檔案給 Arduino 執行即時影像(灰階)分類!別說這麼多了,先看影片!

手邊有設備的朋友歡迎跟著這一篇文章做做看,也歡迎與我們分享成果喔。教學中會用到 Processing 來呈現辨識結果,也歡迎從阿吉老師的 Processing 小教室來學習 Processing 的應用喔~

以下操作步驟根據 teachable Machine 網站說明 https://github.com/googlecreativelab/teachablemachine-community/blob/master/snippets/markdown/tiny_image/GettingStarted.md

硬體 

Arduino Nano 33 BLE Sense / Nano 33 BLE

 目前指定只能用這片板子,其他板子編譯會有問題,看看之後有沒有機會在別的板子上執行囉,詳細規格請參考原廠網站

(照片來自 Arduino 網站)

 

以下是實物照片,板子都愈來愈小呢(視力挑戰)

重要資訊有寫在盒裝背面,當然看原廠網站是最快的。

Ov7670 相機模組

由 OmniVision 推出的相機模組,本範例會把它接在Arduino上,並直接從 Teachable Machine 來擷取黑白影像作為訓練資料集。

規格請點我。實體照片如下

 

接下來是大工程,使用母母杜邦線並根據下表完成接線,請細心完成囉。

0v7670 相機模組腳位名稱 Arduino 腳位名稱
3.3v 3.3v
GND GND (所有GND都可使用)
SCL/SIOC A5
SDA/SIOD A4
VS/VSYNC D8
HS/HREF A1
PCLK A0
MCLK/XCLK D9
D7 D4
D6 D6
D5 D5
D4 D3
D3 D2
D2 D0 / RX
D1 D1 / TX
D0 D10

完成如下圖

軟體 – Arduino IDE

請先取得 Arduino IDE,我使用 Arduino 1.8.5。OV7670 相機模組需要匯入一些函式庫,請根據以下步驟操作:

  1. 安裝 Arduino_TensorFlowLite 函式庫:Arduino IDE,請開啟 Tools -> Manage Libraries,並搜尋 Arduino_TensorFlowLite.,請選擇 Version 2.4.0-ALPHA 之後的版本,點選安裝。

2.安裝 Arduino_OV767X 函式庫:搜尋 Arduino_OV767X 並安裝。

軟體 – Processing

Processing 是用來連接 Arduino 與 Teachable Machine。請先下載 Processing IDE 3.X 版本。下載好 Processing IDE 之後,請開啟 Sketch -> Add Library -> Manage Libraries,並搜尋 ControlP5 Websockets,點選安裝就完成了

軟體 – Teachable Machine

根據網站說明,embedded model 是標準影像分類神經網路模型的迷你版,因此可在微控制器上運行。

這應該是最簡單的地方啦,但在操作 TM 之前要先完成上述的軟硬體設定。完成之後請根據以下步驟操作:

1.下載 TMUploader Arduino Sketch,解壓縮之後於 Arduino IDE 開啟同名的 .ino 檔。板子類型要選擇 Arduino Nano 33,COM port 也要正確設定否則將無法燒錄。本程式負責把 Arduino 所拍攝的影像送往 Processing。

2.下載 TMConnector Processing Sketch, 解壓縮之後於 Arduino IDE 開啟同名的 .pde 檔。點選左上角的執行(Play)鍵,會看到如下的畫面,並列出可用的 COM port 與連線狀態。

3.請由畫面中來選擇您的 Arduino,如果列出很多裝置不知道怎麼選的話,可由 Arduino IDE 中來交叉比對。順利的話就會在 Processing 執行畫面中看到相機的即時預覽畫面。如果畫面停頓或是沒有畫面,請檢查接線是否都接對了。如果畫面有更新但是模糊,請轉動相機模組前端圓環來調整焦距。

4.回到 Teachable Machine 網站,新增一個 Image Project 專案。先點選 Device,再點選 [Attempt to connect to device] 選項,順利的話應該就可以看到 OV7670 的畫面了。

收集資料與訓練

接下來的步驟就一樣了,請用您的照相機來蒐集想要訓練的圖片吧,圖片格式為 96 x 96 灰階。請用相機對準想要辨識的物體,從 [webcam] 選項來收集照片。請注意,即便用 [Upload] 選項去上傳彩色照片,訓練完的模型一樣只能接受單色(灰階)輸入。請盡量讓資料收集與後續測試時使用同一個相機模組 (原場考照的概念~)

訓練完成(很快)之後,於 Teachable Machine 右上角點選 [Export Model],於彈出畫面中選擇 Tensorflow Lite 並勾選下方的 Tensorflow Lite for Microcontrollers ,最後點選 [Download my Model] 就好了!轉檔需要稍等一下(有可能要幾分鐘),完成就會下載一個 converted_tinyml.zip,檔名如果不對,就代表之前的選項選錯了喔

解壓縮可以看到 converted_tinyml 相關內容

執行於 Arduino

關閉所有 Processing app,因為我們暫時不需要收集照片了,且這樣占住 COM port 而無法上傳 Arduino 程式。上傳完成,請開啟 Arduino IDE 的 Serial Monitor,就會看到每一個畫面的辨識結果與信心指數 (-128 to 127),請回顧本文一開始的執行影片就知道囉,happy making !

TMUploader Arduino 程式

#include <Arduino.h>
#include <Arduino_OV767X.h>

#include "ImageProvider.h"


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
      digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(400);                       // wait for a second
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
    delay(400);                       // wait for a second
      digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(400);                       // wait for a second
    digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
    delay(400);                       // wait for a second
  
  Serial.begin(9600);
  while (!Serial);

      
}

const int kNumCols = 96;
const int kNumRows = 96;
const int kNumChannels = 1;
const int bytesPerFrame = kNumCols * kNumRows;

 // QVGA: 320x240 X 2 bytes per pixel (RGB565)
uint8_t data[kNumCols * kNumRows * kNumChannels];

void flushCap() {
  for (int i = 0; i < kNumCols * kNumRows * kNumChannels; i++) {
    data[i] = 0;
  }
}

void loop() {
//  Serial.println(000"creating image");
  GetImage(kNumCols, kNumRows, kNumChannels, data);
//  Serial.println("got image");
  Serial.write(data, bytesPerFrame);
//  flushCap();
}

TMConnector Processing 程式

import processing.serial.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import websockets.*;
import javax.xml.bind.DatatypeConverter;
import controlP5.*;
import java.util.*;

Serial myPort;
WebsocketServer ws;

// must match resolution used in the sketch
final int cameraWidth = 96;
final int cameraHeight = 96;
final int cameraBytesPerPixel = 1;
final int bytesPerFrame = cameraWidth * cameraHeight * cameraBytesPerPixel;

PImage myImage;
byte[] frameBuffer = new byte[bytesPerFrame];
String[] portNames;
ControlP5 cp5;
ScrollableList portsList;
boolean clientConnected = false;

void setup()
{
  size(448, 224);
  pixelDensity(displayDensity());
  frameRate(30);
  cp5 = new ControlP5(this);
  portNames = Serial.list();
  portNames = filteredPorts(portNames);
  ws = new WebsocketServer(this, 8889, "/");
  portsList = cp5.addScrollableList("portSelect")
    .setPosition(235, 10)
    .setSize(200, 220)
    .setBarHeight(40)
    .setItemHeight(40)
    .addItems(portNames);

  portsList.close();
  // wait for full frame of bytes
  //myPort.buffer(bytesPerFrame);   
  //myPort = new Serial(this, "COM5", 9600);
  //myPort = new Serial(this, "/dev/ttyACM0", 9600);
  //myPort = new Serial(this, "/dev/cu.usbmodem14201", 9600);   

  myImage = createImage(cameraWidth, cameraHeight, RGB);
  noStroke();
}

void draw()
{  
  background(240);
  image(myImage, 0, 0, 224, 224);

  drawConnectionStatus();
}

void drawConnectionStatus() {
  fill(0);
  textAlign(RIGHT, CENTER);
  if (!clientConnected) {
    text("Not Connected to TM", 410, 100);
    fill(255, 0, 0);
  } else {
    text("Connected to TM", 410, 100);
    fill(0, 255, 0);
  }
  ellipse(430, 102, 10, 10);
}
void portSelect(int n) {
  String selectedPortName = (String) cp5.get(ScrollableList.class, "portSelect").getItem(n).get("text");

  try {
    myPort = new Serial(this, selectedPortName, 9600);
    myPort.buffer(bytesPerFrame);
  } 
  catch (Exception e) {
    println(e);
  }
}


boolean stringFilter(String s) {
  return (!s.startsWith("/dev/tty"));
}
int lastFrame = -1;
String [] filteredPorts(String[] ports) {
  int n = 0;
  for (String portName : ports) if (stringFilter(portName)) n++;
  String[] retArray = new String[n];
  n = 0;
  for (String portName : ports) if (stringFilter(portName)) retArray[n++] = portName; 
  return retArray;
}

void serialEvent(Serial myPort) {
  // read the saw bytes in
  myPort.readBytes(frameBuffer);
  //println(frameBuffer);

  // access raw bytes via byte buffer
  ByteBuffer bb = ByteBuffer.wrap(frameBuffer);
  bb.order(ByteOrder.BIG_ENDIAN);
  int i = 0;
  
  while (bb.hasRemaining()) { 
    //0xFF & to treat byte as unsigned.
    int r = (int) (bb.get() & 0xFF);
    myImage.pixels[i] = color(r, r, r);
    i++;
    //println("adding pixels");
  }
  if (lastFrame == -1) {
    lastFrame = millis();
  }
  else {
    int frameTime = millis() - lastFrame;
    print("fps: ");
    println(frameTime);
    lastFrame = millis();
  }
  
  myImage.updatePixels();
  myPort.clear();
  String data = DatatypeConverter.printBase64Binary(frameBuffer);
  ws.sendMessage(data);
}

void webSocketServerEvent(String msg) {
  if (msg.equals("tm-connected")) clientConnected = true;
}

 

相關文章:

 

Tinker Board 2S系統與軟體安裝設定

$
0
0

在之前的開箱文介紹了Tinker Board 2S / 2GB的相關硬體規格,可以明顯看出Tinker Board 2S / 2GB其實在硬體性能方面的已經具備不錯的條件,此外,開箱文的介紹裡,也提到了Tinker Board 2S採用了aarch64的作業系統架構,以Debian 10 Linux的LXDE桌面環境,更讓使用者有著相當不錯的GUI使用體驗。

Tinker Board 2S在原廠網站上提供了Debian 10 Linux作業系統給使用者進行安裝,相關LXDE桌面環境的套件軟體程式,都有相當完整的支援,本篇教學文將會著眼在Tinker Board 2S應用在AI範疇中,所應該要在後續的套件軟體程式的安裝介紹,在這次的系統安裝測試過程,我們發現了在Tinker Board 2S安裝的Debian 10 Linux作業系統裡,為了安裝一些常用的AI支援套件程式,在安裝過程中仍要補足許多缺漏的相依套件程式,甚至在測試安裝的過程裡,也發現了有部分的相依套件程式有斷裂的問題,甚至無法單純採用pip3 install或apt-get install的方式進行相依套件程式的安裝,得要透過一些其他套件程式進行修補斷裂的安裝,這部分將會在後續的教學內容中會詳細說明。

撰寫/攝影 曾俊霖
難度

★★★☆☆

時間

6小時以上

材料表
  • ASUS  Tinker Board 2S / 2GB

本篇教學文將會針對以下這些AI應用程式設計中常用的套件程式安裝進行說明:

  1. nano (用於簡易文字編輯器操作)
  2. OpenCV 4.5.0 (用於相關視覺影像的介面操作)
  3. imutils (用於視覺影像處理的介面操作)
  4. pillow (用於視覺影像處理的介面操作)
  5. tkinter (用於圖形化使用者介面 GUI 程式設計)
  6. Tensorflow 2.4.1 與 Tensorflow-Lite Runtime 2.5.0 (用於神經網路運算)
  7. Python3-Coral (用於Google Coral 邊緣張量處理單元Edge-TPU加速器運算)
  8. SciKit-Learn (用於神經網路運算)

 

一、安裝簡易文字編輯器nano

由於在許多的終端機操作環境下需要快速編修文件,採用精巧且功能完整的文字編輯器nano,一直是許多系統操作者的最愛之一,以下說明安裝流程:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install nano

二、安裝GTK-2.0相依套件libgtk2.0-dev

本次安裝測試的過程當中,在安裝OpenCV 4.5.0套件程式時,發生了相依套件斷裂的問題,在Tinker Board 2S的Debian 10 Linux系統中因為沒有安裝GTK-2.0  的libgtk2.0-dev套件程式,這將導致在OpenCV 4.5.0因cmake無法將 libgtk2.0-dev相依套件進行編譯設定,雖然在後續的make流程都能完成,但最後會在最後Python程式執行階段無法正確使用如imshow、putText等畫面顯示或繪圖的函數,並且會在執行階段報錯,並且提示需要重新進行cmake。
為了將libgtk2.0-dev相依套件程式安裝至系統,筆者初期使用sudo apt-get install libgtk2.0-dev這種方式安裝相依套件程式,但系統卻又報錯,表示還有許多其他相關相依套件有「相依斷裂」的問題,筆者嘗試再以sudo apt-get install去安裝那些相依套件程式,卻依然發現更多的「相依斷裂」,更糟糕的是還發生「循環相依」,所謂「循環相依」表示其他的相依套件程式又循環相依libgtk2.0-dev。
為了解決這種「相依斷裂」與「循環相依」的問題,最後只能透過額外安裝「套件安裝設定程式」的方式來解決,本次教學使用的是安裝「aptitude」套件程式來解決這個問題。
透過「aptitude」套件程式便可以進行libgtk2.0-dev套件程式安裝,以下說明安裝流程:

sudo apt-get install aptitude
sudo aptitude install libgtk2.0-dev

三、安裝OpenCV 4.5.0套件程式

在本篇教學採用OpenCV 4.5.0進行視覺影像介面處理,筆者曾嘗試以sudo apt-get install python-opencv進行套件程式的安裝,結果經過檢查發現,以這種方式安裝的OpenCV版本是3.6版,雖然簡單Python程式函數還是可以執行,可是當遇到更進階的函數如DNN等相關進階應用時,便會產生函數缺漏的問題,有鑑於此,筆者選擇重新以Build from Source的方式進行安裝。
在這裡要特別強調一個重要關鍵,在安裝OpenCV 4.5.0套件程式之前,「必須」將前述的GTK-2.0相依套件libgtk2.0-dev先行安裝完成,切莫跳過這個重要步驟。
由於OpenCV 4.5.0的安裝過程需要大量的記憶體運作空間以進行後續的make流程,因此必須先行安裝虛擬記憶體的套件程式,並且將虛擬記憶體設為10240MB,並且將Tinker Board 2S重新開機,以下說明虛擬記憶體設定流程:

sudo apt-get update

sudo apt-get upgrade

 

#安裝dphys-swapfile套件程式

sudo apt-get install dphys-swapfile

 

#以nano編輯 /etc/dphys-swapfile設定檔案

sudo nano /etc/dphys-swapfile

#尋找 #CONF_SWAPSIZE=  字串內容,並且將註解符號 # 取消。

#設定CONF_SWAPSIZE=10240

#離開nano文字編輯器

#重新開機

sudo reboot

下載並編譯安裝OpenCV 4.5.0,請注意,這個階段的安裝時間非常久,筆者大約安裝了近4小時,且在make階段時Tinker Board 2S的散熱片會產生高溫,筆者嘗試使用make -j2或make -j4等多核心的編譯指令,雖然可以加快make流程,但是這種編譯方式會讓CPU的散熱片的溫度飆升,甚至導致熱當機的狀況很多次,造成make失敗多次,因此筆者建議只要採用make這種單核心的編譯為佳,且在編譯過程務必確保電源穩定,且適當以電風扇在旁邊幫助散熱,雖然時間很久,但可以確保編譯過程安全無誤,以下說明OpenCV 4.5.0的安裝流程:

sudo apt-get update
sudo apt-get upgrade

sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev

sudo apt-get install libjpeg-dev libpng-dev
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install libgtk2.0-dev libcanberra-gtk* libgtk-3-dev
sudo apt-get install python3-dev python3-numpy python3-pip
sudo apt-get install libtbb2 libtbb-dev libdc1394-22-dev
sudo apt-get install libv4l-dev v4l-utils
sudo apt-get install libopenblas-dev libatlas-base-dev libblas-de
sudo apt-get install liblapack-dev gfortran libhdf5-dev
sudo apt-get install libprotobuf-dev libgoogle-glog-dev libgflags-dev
sudo apt-get install protobuf-compiler
sudo apt-get install qt5-default

wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.0.zip

wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.5.0.zip

unzip opencv.zip
unzip opencv_contrib.zip

mv opencv-4.5.0 opencv
mv opencv_contrib-4.5.0 opencv_contrib

cd ~/opencv
mkdir build
cd build

cmake -D CMAKE_BUILD_TYPE=RELEASE \
-D CMAKE_INSTALL_PREFIX=/usr/local \
-D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
-D ENABLE_NEON=ON \
-D WITH_OPENMP=ON \
-D BUILD_TIFF=ON \
-D WITH_FFMPEG=ON \
-D WITH_TBB=ON \
-D BUILD_TBB=ON \
-D BUILD_TESTS=OFF \
-D WITH_EIGEN=OFF \
-D WITH_GSTREAMER=OFF \
-D WITH_V4L=ON \
-D WITH_LIBV4L=ON \
-D WITH_VTK=OFF \
-D WITH_QT=OFF \
-D OPENCV_ENABLE_NONFREE=ON \
-D INSTALL_C_EXAMPLES=OFF \
-D INSTALL_PYTHON_EXAMPLES=OFF \
-D BUILD_NEW_PYTHON_SUPPORT=ON \
-D BUILD_opencv_python3=TRUE \
-D OPENCV_GENERATE_PKGCONFIG=ON \
-D BUILD_EXAMPLES=OFF \
-D WITH_GTK=ON ..

make
sudo make install
sudo ldconfig
make clean

至 .bashrc 設定OpenCV 4.5.0路徑,安裝完成OpenCV 4.5.0之後,必須要設定相關執行路徑,若跳過這個步驟,會導致Python程式在import cv2時產生allocation memory 報錯,以下說明 .bashrc 路徑設定方式:

cd ~

 

#以nano文字編輯器編輯 .bashrc 設定檔

sudo nano ~/.bashrc

 

#到文件末端將以下敘述補在最後一行

export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libgomp.so.1

#執行 .bashrc 內容

source ~/.bashrc

 

 

四、安裝其他視覺影像處理與圖形化使用者介面套件程式

#安裝pillow套件程式
cd ~
sudo apt-get update
sudo apt-get upgrade
pip3 install setuptools
pip3 install pillow

#安裝tkinter套件程式
cd ~
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3-tk
sudo apt-get install python3-pil.imagetk

#安裝imutils套件程式
cd ~
sudo apt-get update
sudo apt-get upgrade
pip3 install imutils

五、安裝Tensorflow 2.4.1 神經網路運算套件程式

Tinker Board 2S 具有強大的CPU與GPU運算效能,可進行神經網路運算,搭配OpenCV可以進行各種AI影像辨識的應用,依照Tinker Board 2S的各種硬體規格,筆者認為神經網路的框架可採用Tensorflow 2.4.1來進行神經網路的推論(Inference)運算,以下說明套件程式安裝流程:

#更新作業系統套件資訊
sudo apt-get update
sudo apt-get upgrade

#更新安裝pip3套件程式
sudo apt-get install python-pip python3-pip

#移除舊版Tensoflow套件程式
sudo pip uninstall tensorflow
sudo pip3 uninstall tensorflow

#安裝各種系統相依套件程式
sudo apt-get install gfortran
sudo apt-get install libhdf5-dev libc-ares-dev libeigen3-dev
sudo apt-get install libatlas-base-dev libopenblas-dev libblas-dev
sudo apt-get install liblapack-dev

#安裝各種Python3各種套件程式
sudo -H pip3 install --upgrade setuptools
sudo -H pip3 install pybind11
sudo -H pip3 install Cython==0.29.21
sudo -H pip3 install h5py==2.10.0

#安裝下載工具
pip3 install gdown
sudo cp ~/.local/bin/gdown /usr/local/bin/gdown

#下載Tensorflow 2.4.1套件程式安裝檔
gdown https://drive.google.com/uc?id=1WDG8Rbi0ph0sQ6TtD3ZGJdIN_WAnugLO

#安裝Tensorflow 2.4.1套件程式
sudo -H pip3 install tensorflow-2.4.1-cp37-cp37m-linux_aarch64.whl

六、安裝Tensorflow-Lite Runtime 2.5.0 套件程式

對於Tinker Board 2S / 2GB而言,由於受限於主記憶體僅有2GB的緣故,因此對於神經網路進行推論運算時所需使用的主記憶體容量,就必須要謹慎運用這有限的容量,若需要在神經網路推論時有較高的運算效能,往往就必須要選擇神經網路模型規模較小的模型格式,在Tensorflow族系裡有種Tensorflow-Lite格式就是一種模型規模較小的格式,在Tensorflow的原廠網站裡也特別將Tensorflow-Lite格式定義適用於物聯網IoT應用的場合當中,以下說明套件程式安裝的方式:

cd ~
sudo apt-get update
sudo apt-get upgrade

pip3 install https://github.com/google-coral/pycoral/releases/download/v1.0.1/tflite_runtime-2.5.0-cp37-cp37m-linux_aarch64.whl

七、安裝google Coral Edge-TPU Pthon套件程式

若想在邊緣裝置提升神經網路的運算效能,常會在邊緣運算裝置上外加神經網路運算加速裝置,最常用的做法,便是透過USB連接神經網路運算加速裝置的方式進行擴充,Tinker Board 2S有強大的USB 3.0介面可以運用,筆者為了能夠在Tinker Board 2S上充分發揮Tensorflow-Lite的效能,因此選擇透過google推出的Coral Edge-TPU USB Accelerator安裝在Tinker Board 2S上,透過Edge-TPU強大的運算效能,讓AI的各種應用都能有高速的反應。

以下說明Python3-Coral套件程式安裝方式:

echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | sudo tee /etc/apt/sources.list.d/coral-edgetpu.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-get update

sudo apt-get install libedgetpu1-std
sudo apt-get install python3-pycoral

八、安裝其他支援神經運算的套件程式SciKit-Learn

cd ~
sudo apt-get update
sudo apt-get upgrade

sudo pip3 install sklearn

以上是針對Tinker Board 2S在後續應用在AIoT主題開發所安裝的各種套件程式安裝教學,筆者將會在下一篇「Tinker Board 2S 系統評測」中介紹Tinker Board 2S在神經網路運算的效能,屆時將會透過筆者設計的Python3範例程式進行本篇各種套件程式的測試效能,敬請各位讀者拭目以待囉!

 

相關文章:

Viewing all 678 articles
Browse latest View live