Video detektoru cloudových objektů na Raspberry Pi

Prolog

Na internetu nyní koluje video, které ukazuje, jak autopilot Tesly vidí silnici.

Už dlouho mě toužilo vysílat video obohacené o detektor a v reálném čase.

Video detektoru cloudových objektů na Raspberry Pi

Problém je v tom, že chci vysílat video z Raspberry a výkon detektoru neuronové sítě na něm ponechává mnoho přání.

Intel Neural Computer Stick

Zvažoval jsem různá řešení.

В poslední článek experimentoval s Intel Neural Computer Stick. Hardware je výkonný, ale vyžaduje vlastní síťový formát.

I když Intel poskytuje konvertory pro hlavní frameworky, existuje řada úskalí.

Například formát požadované sítě může být nekompatibilní, a pokud je kompatibilní, pak některé vrstvy nemusí být na zařízení podporovány, a pokud jsou podporovány, může dojít k chybám během procesu převodu, v důsledku čehož na výstupu dostáváme nějaké divné věci.

Obecně, pokud chcete nějakou libovolnou neuronovou síť, pak to nemusí fungovat s NCS. Proto jsem se rozhodl pokusit se problém vyřešit pomocí nejrozšířenějších a nejdostupnějších nástrojů.

Cloud

Zjevnou alternativou k místnímu hardwarovému řešení je přejít do cloudu.

Hotové možnosti - oči mi tečou.

Všichni vedoucí:

... A desítky méně známých.

Vybrat si mezi touto odrůdou není vůbec jednoduché.

A rozhodl jsem se nevybrat, ale zabalit staré dobré fungující schéma na OpenCV v Dockeru a spustit ho v cloudu.

Výhodou tohoto přístupu je flexibilita a ovládání - můžete změnit neuronovou síť, hosting, server - obecně jakýkoli rozmar.

Server

Začněme s lokálním prototypem.

Tradičně používám Flask pro REST API, OpenCV a MobileSSD síť.

Po instalaci aktuálních verzí na Docker jsem zjistil, že OpenCV 4.1.2 nefunguje s Mobile SSD v1_coco_2018_01_28 a musel jsem se vrátit zpět k osvědčenému 11.

Na začátku služby načteme názvy tříd a síť:

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

Na místním dockeru (na nepříliš mladém notebooku) to trvá 0.3 sekundy, na Raspberry - 3.5.

Začněme výpočet:

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 s, Raspberry - 1.7.

Přeměna výfuku tensoru na čitelný 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

Dále exportovat tuto operaci přes Flask(vstupem je obrázek, výstupem jsou výsledky detektoru v json).

Alternativní možnost, ve které je více práce přesunuto na server: sám zakroužkuje nalezené objekty a vrátí hotový obrázek.

Tato volba je dobrá tam, kde nechceme přetahovat opencv na server.

Přístavní dělník

Sbíráme obraz.

Kód je vyčesán a vyvěšen Github, docker to vezme přímo odtud.

Jako platformu použijeme stejný Debian Stretch jako na Raspberry – nebudeme se odchylovat od osvědčeného technologického zásobníku.

Musíte nainstalovat flask, protobuf, requests, opencv_python, stáhnout Mobile SSD, kód serveru z Github a spustit server.

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

Jednoduché klient detektoru na základě žádostí.

Publikování na Docker Hub

Registry Docker se množí rychlostí ne menší než cloudové detektory.

Abychom se neobtěžovali, konzervativně projdeme DockerHub.

  1. Registrovat
  2. Přihlásit se:
    přihlášení do doku
  3. Pojďme vymyslet smysluplný název:
    docker tag opencv-detect tprlab/opencv-detect-ssd
  4. Nahrajte obrázek na server:
    docker push tprlab/opencv-detect-ssd

Spouštíme v cloudu

Poměrně široký je i výběr, kam kontejner spustit.

Všichni velcí hráči (Google, Microsoft, Amazon) nabízejí v prvním roce mikroinstanci zdarma.
Po experimentování s Microsoft Azure a Google Cloud jsem se rozhodl pro to druhé, protože se to rozjelo rychleji.

Návod jsem zde nepsal, protože tato část je velmi specifická pro vybraného poskytovatele.

Zkoušel jsem různé možnosti hardwaru,
Nízké úrovně (sdílené a vyhrazené) - 0.4 - 0.5 sekundy.
Silnější auta - 0.25 - 0.3.
No, i v nejhorším případě jsou výhry trojnásobné, můžete to zkusit.

Video

Spouštíme jednoduchý OpenCV video streamer na Raspberry, který detekuje prostřednictvím Google Cloud.
Pro experiment byl použit video soubor, který byl kdysi natočen na náhodném průsečíku.


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

S detektorem dostáváme maximálně tři snímky za sekundu, vše jde velmi pomalu.
Pokud do GCloudu vezmete výkonný stroj, můžete detekovat 4-5 snímků za sekundu, ale rozdíl je pro oko téměř neviditelný, je to stále pomalé.

Video detektoru cloudových objektů na Raspberry Pi

Cloud a náklady na dopravu s tím nemají nic společného, ​​detektor běží na běžném hardwaru a pracuje takovou rychlostí.

Neural Computer Stick

Neodolal jsem a spustil benchmark na NCS.

Rychlost detektoru byla o něco nižší než 0.1 sekundy, každopádně 2-3krát rychlejší než cloud na slabém stroji, tedy 8-9 snímků za sekundu.

Video detektoru cloudových objektů na Raspberry Pi

Rozdíl ve výsledcích je vysvětlen skutečností, že NCS používalo Mobile SSD verze 2018_01_28.

PS Navíc experimenty ukázaly, že docela výkonný stolní stroj s procesorem I7 vykazuje o něco lepší výsledky a ukázalo se, že na něm lze vymáčknout 10 snímků za sekundu.

Cluster

Experiment šel dále a detektor jsem nainstaloval na pět uzlů v Google Kubernetes.
Samotné moduly byly slabé a každý z nich nedokázal zpracovat více než 2 snímky za sekundu.
Pokud ale provozujete cluster s N uzly a analyzujete snímky v N vláknech, pak s dostatečným počtem uzlů (5) můžete dosáhnout požadovaných 10 snímků za sekundu.

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

Zde je to, co se stalo:

Video detektoru cloudových objektů na Raspberry Pi

Trochu méně rychlé než s NCS, ale energičtější než v jednom proudu.

Zisk samozřejmě není lineární – existují překryvy pro synchronizaci a hluboké kopírování opencv obrázků.

Závěr

Celkově nám experiment umožňuje dojít k závěru, že pokud se o to pokusíte, můžete se dostat pryč s jednoduchým cloudem.

Ale výkonný desktop nebo lokální hardware vám umožní dosáhnout lepších výsledků, a to bez jakýchkoli triků.

reference

Zdroj: www.habr.com

Přidat komentář