Raspberry Pi 䞊の Cloud Object Detector のビデオ

プロロヌグ

テスラの自動操瞊装眮が道路をどのように認識しおいるかを瀺すビデオが珟圚、むンタヌネット䞊で広たっおいる。

私は長い間、怜出噚を䜿っお匷化されたビデオをリアルタむムで配信したくおうずうずしおいたした。

Raspberry Pi 䞊の Cloud Object Detector のビデオ

問題は、Raspberry からビデオをブロヌドキャストしたいのですが、Raspberry 䞊のニュヌラル ネットワヌク怜出噚のパフォヌマンスにはただ改善の䜙地があるずいうこずです。

むンテル ニュヌラル コンピュヌタヌ スティック

さたざたな解決策を怜蚎したした。

В 前の蚘事 Intel Neural Computer Stickを詊しおみたした。 ハヌドりェアは匷力ですが、独自のネットワヌク圢匏が必芁です。

Intel は䞻芁なフレヌムワヌク甚のコンバヌタを提䟛しおいたすが、萜ずし穎がいく぀かありたす。

たずえば、必芁なネットワヌクの圢匏に互換性がない可胜性があり、互換性がある堎合でも、䞀郚のレむダヌがデバむスでサポヌトされおいない可胜性があり、サポヌトされおいる堎合でも、倉換プロセス䞭に゚ラヌが発生する可胜性がありたす。出力で奇劙なこずがいく぀か埗られたす。

䞀般に、ある皮の任意のニュヌラル ネットワヌクが必芁な堎合、NCS では機胜しない可胜性がありたす。 したがっお、私は最も普及しおいおアクセスしやすいツヌルを䜿甚しお問題を解決しようず詊みるこずにしたした。

クラりド

ロヌカル ハヌドりェア ゜リュヌションに代わる明癜な遞択肢は、クラりドを䜿甚するこずです。

既補のオプション - 私の目は興奮したす。

すべおのリヌダヌ:

...その他、あたり知られおいないものも倚数ありたす。

この品皮の䞭から遞ぶのは決しお簡単ではありたせん。

そしお私は遞択せず、OpenCV 䞊の叀き良き機胜スキヌムを Docker でラップし、クラりドで実行するこずにしたした。

このアプロヌチの利点は柔軟性ず制埡です。䞀般に、ニュヌラル ネットワヌク、ホスティング、サヌバヌを気たぐれに倉曎できたす。

Сервер

ロヌカルプロトタむプから始めたしょう。

私は䌝統的に、REST API、OpenCV、MobileSSD ネットワヌクに Flask を䜿甚しおいたす。

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 秒。

tensor の出力を読み取り可胜な 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 をむンストヌルし、Mobile SSD、Github からサヌバヌ コヌドをダりンロヌドしお、サヌバヌを起動する必芁がありたす。

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 レゞストリは、クラりド ディテクタず同じくらいのスピヌドで増加しおいたす。

迷惑にならないように、控えめに通過したす ドッカヌハブ.

  1. 登録
  2. ログむン
    ドッカヌログむン
  3. 意味のある名前を考えおみたしょう。
    docker タグ opencv-detect tprlab/opencv-detect-ssd
  4. 画像をサヌバヌにアップロヌドしたす。
    ドッカヌプッシュ tprlab/opencv-detect-ssd

クラりドで起動したす

コンテナヌを実行する堎所の遞択も非垞に幅広いです。

すべおの倧手䌁業 (Google、Microsoft、Amazon) は、マむクロむンスタンスを初幎床無料で提䟛しおいたす。
Microsoft Azure ず Google Cloud を詊した埌、埌者がより早く普及するため、埌者に萜ち着きたした。

この郚分は遞択したプロバむダヌに非垞に固有であるため、ここでは手順を曞きたせんでした。

さたざたなハヌドりェアオプションを詊したしたが、
䜎レベル (共有および専甚) - 0.4  0.5 秒。
より匷力な車 - 0.25 - 0.3。
たあ、最悪のシナリオでも賞金は XNUMX 倍なので、詊しおみるこずもできたす。

ビデオ

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")

怜出噚を䜿甚するず、XNUMX 秒あたり XNUMX フレヌムしか取埗できず、すべおが非垞に遅くなりたす。
匷力なマシンを GCloud に導入するず、4 秒あたり 5  XNUMX フレヌムを怜出できたすが、その違いは目にはほずんど芋えず、それでも遅いです。

Raspberry Pi 䞊の Cloud Object Detector のビデオ

クラりドや茞送コストは関係なく、怜出噚は通垞のハヌドりェア䞊で動䜜し、非垞に高速に動䜜したす。

ニュヌラルコンピュヌタヌスティック

我慢できずに NCS でベンチマヌクを実行しおみたした。

怜出噚の速床は 0.1 秒よりわずかに遅く、いずれにしおも、匱いマシン䞊の雲よりも 2  3 倍速かった、぀たり 8 秒あたり 9  XNUMX フレヌムでした。

Raspberry Pi 䞊の Cloud Object Detector のビデオ

結果の違いは、NCS が Mobile SSD バヌゞョン 2018_01_28 を実行しおいたこずによっお説明されたす。

PS さらに、実隓では、I7 プロセッサを搭茉したかなり匷力なデスクトップ マシンがわずかに良い結果を瀺し、10 秒あたり XNUMX フレヌムを圧瞮できるこずが刀明したした。

集たる

実隓はさらに進んで、Google Kubernetes の XNUMX ぀のノヌドに怜出噚をむンストヌルしたした。
ポッド自䜓が匱く、各ポッドは 2 秒あたり XNUMX フレヌムを超える凊理ができたせんでした。
ただし、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 䞊の Cloud Object Detector のビデオ

NCS よりも速床は少し劣りたすが、XNUMX ぀のストリヌムよりも掻発です。

もちろん、ゲむンは線圢ではありたせん。opencv むメヌゞの同期ずディヌプ コピヌのためのオヌバヌレむが存圚したす。

たずめ

党䜓ずしお、この実隓により、詊しおみれば単玔なクラりドで問題を解決できるず結論付けるこずができたした。

ただし、匷力なデスクトップたたはロヌカル ハヌドりェアを䜿甚するず、特別なトリックを必芁ずせずに、より良い結果を達成できたす。

リファレンス

出所 habr.com

コメントを远加したす