你觉得这篇文章怎么样? 帮助我们为您提供更好的内容。
Thank you! Your feedback has been received.
There was a problem submitting your feedback, please try again later.
你觉得这篇文章怎么样?
作者 | Dan 羅傑瑞 |
難度 | 中等 |
所需時間 | 1.5小時 |
最近幾年以來,Raspberry Pi迅速發展不同應用。 現在人們開始研究更成熟的主題,例如將Raspberry Pi用於深度學習應用程式。 在本文中,我們想知道如何將Raspberry Pi用於基本的深度學習應用程式,例如圖像分類。本文提供 一個非常簡單的示例,我們使用卷積神經網路(CNN)預訓練了一個簡單的手部識別模型。 以下是樣本訓練圖像:
手 | 其他 |
本文的目的是演示使用Raspberry Pi處理圖像的示例深度學習應用程式。 我們想要識別Raspberry Pi相機看到的圖像,並將其分類為手或其他。 在這種情況下,其他物件是位於白色背景前面的任何其他物件。 一旦檢測到手,就可以打開/關閉繼電器以打開/關閉電氣設備。
以下是我們將用於此專案的組件:
材料和組件
- Raspberry Pi 3B +
- Raspberry Pi相機v2
- 16GB(或32GB)空白SD卡
- USB電源
- 7英寸Raspberry Pi顯示幕
- 5V繼電器板
自選:
- SD卡讀卡器
說明:
步驟1:克隆我們的Raspbian OS img
為了避免花太多時間安裝庫、套裝軟體等,我們準備了一個備份.img檔,可以將其直接複製到SD卡中。這是推薦的方式,因為在Raspberry Pi中安裝Python庫非常繁瑣且耗時。
1.1 首先,下載我們的.img文件:
https://drive.google.com/drive/folders/1BHYqwTJtz7ipFddYJ2rRp8wxOiB0yinK?usp=sharing
1.2 這樣做之後,請下載Win32 Disk Imager。
https://sourceforge.net/projects/win32diskimager/
1.3 安裝Win32 Disk Imager後,將其打開並將SD卡讀取器插入電腦。使用其GUI,找到並選擇我們的.img文件。對於設備選項,請使用剛插入的SD卡的磁碟機代號。
警告:確保磁碟機代號與您的SD卡相對應,否則您可能會擦除硬碟資料。
然後,按一下“寫入”按鈕並等待其完成。此過程可能需要20到25分鐘,具體取決於SD卡和SD卡讀取器的讀/寫速度。
步驟2:準備和連接硬體
2.1 這次,將新複製的SD卡插入Raspberry Pi。 最好在組裝螢幕之前執行此操作,否則必須再次打開螢幕外殼。 同樣,通過Raspberry Pi相機的相機插槽將Raspberry Pi相機連接到Raspberry,如下所示:
2.2 重新組裝併合上螢幕保護裝置套(有關此部分,您可以參考我們的先前文章),然後將攝像頭放在螢幕保護裝置套的頂部攝像頭支架上。 這非常方便,因此您不必為Raspberry Pi相機單獨購買相機套。
2.3 接下來,按照此圖所示的針腳輸出,將中繼板連接到Raspberry Pi
根據您的繼電器板,VCC、GND和IN應該幾乎相同。 而Raspberry Pi GPIO,如果您已經連接了其他東西並可以在程式碼中進行更改,則始終可以將其切換到GPIO17以外的其他引腳。
步驟3:演示時間
3.1 由於我們跳過了在Raspberry Pi中安裝庫的耗時步驟,因此我們直接測試程式。 打開Raspberry Pi,然後等到桌面出現後,再看到以下內容:
從這裡開始,打開檔案管理員。
3.2 前往/ home / pi / hand_switch /並使用Spyder3或您喜歡的任何其他IDE打開hand_switch_demo.py。
3.3 打開IDE後,請按一下運行->運行
3.4 檢查控制台的輸出,然後嘗試將手放在相機前面。 本演示中使用的當前模型是在白色背景前的手部圖像進行訓練的。 因此,不要期望此模型在其他類型的圖像中非常準確。 本文還提供了一個示例視頻。
步驟4:理論和代碼說明
為了開發這個項目,我們必須準備一個卷積神經網路模型(CNN model)來識別手。 以下是分步驟過程:
1. 使用Raspberry Pi v2相機收集圖像
-我們收集了150張手形圖像和150張其他圖像
2. 使用排序後的圖像訓練了CNN模型
-在Python 3.5中Keras和Tensorflow的支持下,我們使用帶GPU的桌上型電腦對模型進行了訓練
3. 將經過訓練的模型複製到Raspberry Pi
這些步驟非常複雜,可能需要花費一些時間來學習。 在以後的文章中將詳細介紹這些部分。
總結一下,這是我們製作的程式的工作方式:
原始圖像是Raspberry Pi每秒獲得的圖像。 然後將圖像調整大小為128 x 128的圖像,使用CNN模型進行處理及識別圖像是否是手。
以下是代碼以及一些注釋:
# 調用必要的Python庫
import picamera
import time
from time import strftime,localtime
import image_classifiers as IC
import os
from skimage import io
import RPi.GPIO as GPIO
# 載入CNN模型及其標籤.txt檔的功能
def ImportClassifierModel(path_name):
model_path = path_name
print(model_path)
model_dir = os.path.dirname(model_path)
txt_dir = os.listdir(model_dir)
for x in txt_dir:
if ".txt" in x:
txt_fname, extension = os.path.splitext(x)
if txt_fname in model_path:
label_path = model_dir + "/" + txt_fname + ".txt"
print(label_path)
model = ""
try:
model = IC.ImportGraph(model_path)
class_names = IC.load_labels(label_path)
except Exception as e:
print(e)
return model, class_names
# 載入分類器模型和類名稱
PATH_TO_CLASSIFIER = "/home/pi/hand_switch/hand_cnn_22.h5"
target_model, class_names = ImportClassifierModel(PATH_TO_CLASSIFIER)
# 初始化相機
try:
camera.close()
except:
pass
camera = picamera.PiCamera()
camera.resolution = (640, 640)
# 設置gpio
RELAY = 17
GPIO.setmode(GPIO.BCM)
GPIO.setup(RELAY, GPIO.OUT)
# 其他變數
# required_votes是一個變數,您可以設置該變數來設置開關的靈敏度。
# 這意味著在連續3次識別圖像是手之後,開關打開。
# 這樣可以防止因程式反覆打開和關閉而破壞連接的設備。
second_prev = 0
hand_votes = 0
required_votes = 3
while 1:
time_now = strftime("%Y/%m/%d %H:%M:%S", localtime())
img_filename = strftime("%Y_%m_%d %H_%M_%S", localtime())
second_now = strftime("%S", localtime())
# 運行分類(每秒)
if (second_now != second_prev) and (int(second_now) % 1) == 0:
time.sleep(0.01)
FILENAME = "/home/pi/hand_switch/input.jpg"
camera.capture(FILENAME, resize=(640, 640))
input_image = io.imread(FILENAME)
input_image = (input_image[:,:,::-1])
image_tensor = IC.load_classify_image(input_image, 128)
image_class, score = target_model.predict_by_cnn(image_tensor, 0.5, class_names[0:(len(class_names))])
if image_class == "hand":
hand_votes = hand_votes + 1
else:
hand_votes = hand_votes - 1
hand_votes = max(hand_votes, 0)
hand_votes = min(hand_votes, required_votes)
if hand_votes >= required_votes:
GPIO.output(RELAY, 1)
if hand_votes <= 0:
GPIO.output(RELAY, 0)
RELAY_STAT = GPIO.input(RELAY)
print("Result: " + image_class, " Votes: " + str(hand_votes), " Relay: " + str(RELAY_STAT))
second_prev = second_now