DesignSpark Electrical Logolinkedin
菜单 搜寻
提问问题

Raspberry Pi人手檢測開關(繁體)

作者 Dan 羅傑瑞
難度 中等
所需時間 1.5小時

 

最近幾年以來,Raspberry Pi迅速發展不同應用。 現在人們開始研究更成熟的主題,例如將Raspberry Pi用於深度學習應用程式。 在本文中,我們想知道如何將Raspberry Pi用於基本的深度學習應用程式,例如圖像分類。本文提供 一個非常簡單的示例,我們使用卷積神經網路(CNN)預訓練了一個簡單的手部識別模型。 以下是樣本訓練圖像:

其他

 

本文的目的是演示使用Raspberry Pi處理圖像的示例深度學習應用程式。 我們想要識別Raspberry Pi相機看到的圖像,並將其分類為手或其他。 在這種情況下,其他物件是位於白色背景前面的任何其他物件。 一旦檢測到手,就可以打開/關閉繼電器以打開/關閉電氣設備。

以下是我們將用於此專案的組件:

材料和組件

  1. Raspberry Pi 3B +
  2. Raspberry Pi相機v2
  3. 16GB(或32GB)空白SD卡
  4. USB電源
  5. 7英寸Raspberry Pi顯示幕
  6. 5V繼電器板

自選:

  1. 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

CAVEDU Education is devoted into robotics education and maker movement since 2008, and is intensively active in teaching fundamental knowledge and skills. We had published many books for readers in all ages, topics including App Inventor, Lego robot and IoT (Arduino / Raspberry Pi). Please check CAVEDU's website for more information: http://www.cavedu.com, http://www.appinventor.tw

2 Dec 2019, 6:43