Raspberry Pi 上的雲物件偵測器視頻

序幕

現在網路上流傳著一段視頻,展示了特斯拉的自動駕駛儀如何看待道路。

很長一段時間以來,我一直渴望即時播放用探測器豐富的影片。

Raspberry Pi 上的雲物件偵測器視頻

問題是我想從 Raspberry 播放視頻,而其上的神經網絡檢測器的性能還有很多不足之處。

英特爾神經電腦棒

我考慮了不同的解決方案。

В 上一篇文章 嘗試了英特爾神經計算機棒。 硬體功能強大,但需要自己的網路格式。

儘管英特爾為主要框架提供了轉換器,但仍存在許多缺陷。

例如,所需網路的格式可能不相容,如果相容,則裝置上可能不支援某些層,如果支持,則在轉換過程中可能會出現錯誤,從而導致我們在輸出中得到一些奇怪的東西。

一般來說,如果你想要某種任意的神經網絡,那麼它可能不適用於 NCS。 因此,我決定嘗試使用最廣泛且易於使用的工具來解決該問題。

本地硬體解決方案的明顯替代方案是遷移到雲端。

現成的選擇-我的眼睛變得瘋狂。

各位領導:

……還有幾十個鮮為人知的。

在這個品種中進行選擇並不容易。

我決定不選擇,而是將 OpenCV 上良好的舊工作方案包裝在 Docker 中並在雲端中運行。

這種方法的優點是靈活性和控制性——你可以改變神經網路、託管、伺服器——一般來說,任何突發奇想。

服務器

讓我們從本地原型開始。

傳統上我使用 Flask 來實作 REST API、OpenCV 和 MobileSSD 網路。

在 Docker 上安裝了當前版本後,我發現 OpenCV 4.1.2 不適用於 Mobile SSD v1_coco_2018_01_28,我必須回滾到經過驗證的 11/06_2017。

在服務啟動時,我們載入類別名稱和網路:

def init():
    tf_labels.initLabels(dnn_conf.DNN_LABELS_PATH)
    return cv.dnn.readNetFromTensorflow(dnn_conf.DNN_PATH, dnn_conf.DNN_TXT_PATH)

在本機 docker 上(在一台不太年輕的筆記型電腦上)需要 0.3 秒,在 Raspberry 上需要 3.5 秒。

我們開始計算:

def inference(img):
    net.setInput(cv.dnn.blobFromImage(img, 1.0/127.5, (300, 300), (127.5, 127.5, 127.5), swapRB=True, crop=False))
    return net.forward()

Docker - 0.2 秒,Raspberry - 1.7。

將張量排氣轉換為可讀的 json:

def build_detection(data, thr, rows, cols):
    ret = []
    for detection in data[0,0,:,:]:
        score = float(detection[2])
        if score > thr:
            cls = int(detection[1])
            a = {"class" : cls, "name" : tf_labels.getLabel(cls),  "score" : score}
            a["x"] = int(detection[3] * cols)
            a["y"] = int(detection[4] * rows)
            a["w"] = int(detection[5] * cols ) - a["x"]
            a["h"] = int(detection[6] * rows) - a["y"]
            ret.append(a)
    return ret

更遠 透過 Flask 導出此操作(輸入是圖片,輸出是json格式的偵測器結果)。

另一個選擇是將更多工作轉移到伺服器:它本身會圈出找到的物件並傳回完成的映像。

當我們不想將 opencv 拖曳到伺服器時,此選項非常有用。

碼頭工人

我們收集圖像。

程式碼梳理了一下,貼在 吉圖布,docker會直接從那裡獲取它。

作為一個平台,我們將採用與 Raspberry 相同的 Debian Stretch - 我們不會偏離經過驗證的技術堆疊。

您需要安裝flask、protobuf、requests、opencv_python、從Github下載Mobile SSD、伺服器程式碼並啟動伺服器。

FROM python:3.7-stretch

RUN pip3 install flask
RUN pip3 install protobuf
RUN pip3 install requests
RUN pip3 install opencv_python

ADD http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_11_06_2017.tar.gz /
RUN tar -xvf /ssd_mobilenet_v1_coco_11_06_2017.tar.gz

ADD https://github.com/tprlab/docker-detect/archive/master.zip /
RUN unzip /master.zip

EXPOSE 80

CMD ["python3", "/docker-detect-master/detect-app/app.py"]

簡單 探測器客戶端 根據要求。

發佈到 Docker Hub

Docker 註冊表的倍增速度不亞於雲端偵測器。

為了不打擾,我們會保守地經歷 DockerHub.

  1. 登記
  2. 登入:
    碼頭登入
  3. 讓我們取一個有意義的名字:
    docker 標籤 opencv-偵測 tprlab/opencv-偵測-ssd
  4. 將圖片上傳到伺服器:
    docker Push tprlab/opencv-檢測-ssd

我們在雲端啟動

在哪裡運行容器的選擇也相當廣泛。

所有大型企業(Google、微軟、亞馬遜)第一年都免費提供微型實例。
在嘗試了 Microsoft Azure 和 Google Cloud 後,我選擇了後者,因為它發展得更快。

我沒有在這裡寫說明,因為這部分是針對所選提供者的。

我嘗試了不同的硬體選項,
低等級(共享和專用)- 0.4 - 0.5 秒。
更強大的汽車 - 0.25 - 0.3。
好吧,即使在最壞的情況下,獎金也是三倍,你可以嘗試。

視頻

我們在 Raspberry 上啟動了一個簡單的 OpenCV 視訊串流傳輸器,透過 Google Cloud 進行偵測。
在實驗中,使用了曾經在隨機十字路口拍攝的影片檔。


def handle_frame(frame):
    return detect.detect_draw_img(frame)
       
def generate():
    while True:
        rc, frame = vs.read()
        outFrame = handle_frame(frame)
        if outFrame is None:
            (rc, outFrame) = cv.imencode(".jpg", frame)
        yield(b'--framern' b'Content-Type: image/jpegrnrn' + bytearray(outFrame) + b'rn')

@app.route("/stream")
def video_feed():
    return Response(generate(), mimetype = "multipart/x-mixed-replace; boundary=frame")

使用探測器,我們每秒獲得的幀數不超過三幀,一切都進行得很慢。
如果你把一台功能強大的機器放入GCloud,你可以每秒偵測到4-5幀,但肉眼幾乎看不到差別,它仍然很慢。

Raspberry Pi 上的雲物件偵測器視頻

雲端和運輸成本與此無關;探測器在普通硬體上運行並以這樣的速度工作。

神經電腦棒

我無法抗拒並在 NCS 上運行了基準測試。

偵測器的速度略慢於 0.1 秒,無論如何都比在弱機器上的雲快 2-3 倍,即每秒 8-9 幀。

Raspberry Pi 上的雲物件偵測器視頻

結果差異的原因是行動 SSD 版本 2018_01_28 是在 NCS 上推出的。

PS 另外,實驗表明,配備 I7 處理器的功能相當強大的桌上型電腦顯示出稍微好一些的結果,並且事實證明可以在其上壓縮每秒 10 幀的速度。

實驗更進一步,我在 Google Kubernetes 的五個節點上安裝了偵測器。
Pod 本身很弱,每個 Pod 每秒處理的幀數不能超過 2 幀。
但是,如果您運行具有 N 個節點的叢集並在 N 個執行緒中解析幀,那麼透過足夠數量的節點 (5),您可以實現所需的每秒 10 幀。

def generate():
    while True:
        rc, frame = vs.read()
        if frame is not None:
            future = executor.submit(handle_frame, (frame.copy()))
            Q.append(future)

        keep_polling = len(Q) > 0
        while(keep_polling):            
            top = Q[0]
            if top.done():
                outFrame = top.result()
                Q.popleft()
                if outFrame:
                    yield(b'--framern' b'Content-Type: image/jpegrnrn' + bytearray(outFrame) + b'rn')
                keep_polling = len(Q) > 0
            else:
                keep_polling = len(Q) >= M

以下是發生的事情:

Raspberry Pi 上的雲物件偵測器視頻

比 NCS 速度稍慢,但比單流更有活力。

當然,增益不是線性的——有用於同步和深度複製 opencv 影像的覆蓋範圍。

結論

總的來說,這個實驗讓我們得出這樣的結論:如果你嘗試,你就可以使用簡單的雲。

但是強大的桌面或本機硬體可以讓您獲得更好的結果,並且無需任何技巧。

引用

來源: www.habr.com

添加評論