JETBOT - collision_avoidance /Data Collection


Traitlets 是 IPython 和 Jupyter 的配置系統以及為 IPython 交互式小部件的API 提供支持。


From XXX import XXX與import的差異

  • 如果使用"Import"來使用module時,會保留獨立的symbol table,所以就不用擔心function name衝突的問題。

  • 使用"from XXX import XXXX"來使用module時,會將被匯入的function 加入目前module的symbol table,所以就可能造成名稱衝突的問題


Collision Avoidance - Data Collection 程式碼說明

#以下是顯示即時的影像,所以要先完成系統配置以及物件的初始化、連結設定,最後顯示鏡頭的即時影像

#神經網絡將 224x224 像素的圖像作為輸入。相機設置為最小的大小,這樣可以最小化datasets的檔案大小


import traitlets

import ipywidgets.widgets as widgets

#匯入IPython與Jupter的系統配置與IPython軟體小工具的物件函式庫

from IPython.display import display

#從IPython.display匯入display 函式

from jetbot import Camera, bgr8_to_jpeg

#jetbot匯入Camera, bgr8_to_jpeg function,bgr8是OpenCV函式預期的影象編碼

camera = Camera.instance(width=224, height=224) #設定camera實例顯示的大小

image = widgets.Image(format='jpeg', width=224, height=224) #軟體小工具的影像設定檔案格式與長寬,這裡的影像大小不一定需要跟上面camera一樣大

camera_link = traitlets.dlink((camera, 'value'), (image, 'value'), transform=bgr8_to_jpeg)

#將camera與image的設定以及影像編碼轉換格式做連結

display(image)

#顯示camera的即時影像


#匯入OS函式庫,並創建一個dataset的資料夾,在底下細分為兩個類別blocked跟free的資料夾來放置影像,後面的範例會各拍100張

import os #匯入OS函式庫,定義資料夾的路徑與名稱

blocked_dir = 'dataset/blocked'

free_dir = 'dataset/free'

# 如果資料夾已經存在就會發生錯誤訊息

try:

os.makedirs(free_dir)

os.makedirs(blocked_dir)

#建立指定名稱的兩個資料夾與上面的dataset資料夾,名稱都可以改

except FileExistsError:

print('Directories not created because they already exist')


#按鈕的樣式設定

button_layout = widgets.Layout(width='128px', height='64px')

free_button = widgets.Button(description='add free', button_style='success', layout=button_layout)

blocked_button = widgets.Button(description='add blocked', button_style='danger', layout=button_layout)

#軟體部件是IntText,顯示數值為取得指定資料夾的檔案數

#len是取得長度或物件數

free_count = widgets.IntText(layout=button_layout, value=len(os.listdir(free_dir)))

blocked_count = widgets.IntText(layout=button_layout, value=len(os.listdir(blocked_dir)))

#顯示軟體小部件,要有下面兩行才會顯示,下面會再執行一次

display(widgets.HBox([free_count, free_button]))

display(widgets.HBox([blocked_count, blocked_button]))

#截至目前的程式碼執行都不會有任何的東西,因為還沒有設定存檔的與on_click 觸發的程式碼

#下面一段程式碼是定義存檔的檔案名稱與執行存檔的動作

from uuid import uuid1

#匯入第一代的uuid二進制的隨機名稱,不會有重複

def save_snapshot(directory):

image_path = os.path.join(directory, str(uuid1()) + '.jpg')

with open(image_path, 'wb') as f:

f.write(image.value)

#定義一個函數save_snapshot(directory),先設定產生影像的路徑與檔案名稱,然後以二進制的方式寫入並關閉檔案

def save_free():

global free_dir, free_count

save_snapshot(free_dir)

free_count.value = len(os.listdir(free_dir))

#安全區的存檔以及更新目前檔案數

def save_blocked():

global blocked_dir, blocked_count

save_snapshot(blocked_dir)

blocked_count.value = len(os.listdir(blocked_dir))

#區的存檔以及更新目前檔案數

free_button.on_click(lambda x: save_free())

blocked_button.on_click(lambda x: save_blocked())

#使用lambda函式來忽略每次呼叫拍照存檔並更新資料夾內檔案數時會出現的參數

#顯示攝影機的即時影像,執行這一行時才會顯示影像

display(image)

#下面的兩行其實上面已經執行過了,再執行也無訪

display(widgets.HBox([free_count, free_button]))

display(widgets.HBox([blocked_count, blocked_button]))

就開始拍照,蠻多教學都建議兩個分類都100張

#拍完照後,結束攝影機

camera.stop()

將dataset資料夾包含以內的內容都打包成ZIP

!zip -r -q dataset.zip dataset

#dataset是資料夾名稱,根據自己的去修改,dataset.zip是壓縮完的檔名,也可以修改