Videoposnetek detektorja objektov v oblaku na Raspberry Pi

Prolog

Po spletu zdaj kroži posnetek, ki prikazuje, kako Teslin avtopilot vidi cesto.

Že dolgo sem hrepenel po predvajanju videa obogatenega z detektorjem in to v realnem času.

Videoposnetek detektorja objektov v oblaku na Raspberry Pi

Težava je v tem, da želim oddajati video iz Raspberryja in zmogljivost detektorja nevronske mreže na njem pušča veliko želenega.

Intel Neural Computer Stick

Razmišljal sem o različnih rešitvah.

В zadnji članek eksperimentiral z Intel Neural Computer Stick. Strojna oprema je zmogljiva, vendar zahteva svoj omrežni format.

Čeprav Intel ponuja pretvornike za glavna ogrodja, obstajajo številne pasti.

Na primer, format zahtevanega omrežja je lahko nezdružljiv, in če je združljiv, potem nekateri sloji morda niso podprti v napravi, in če so podprti, lahko pride do napak med postopkom pretvorbe, zaradi česar na izhodu dobimo nekaj čudnih stvari.

Na splošno, če želite nekakšno poljubno nevronsko mrežo, morda ne bo delovala z NCS. Zato sem se odločil, da poskusim težavo rešiti z uporabo najbolj razširjenih in dostopnih orodij.

Oblak

Očitna alternativa lokalni rešitvi strojne opreme je prehod v oblak.

Pripravljene možnosti - oči divjajo.

Vsi voditelji:

... In na desetine manj znanih.

Izbira med to sorto ni lahka.

In odločil sem se, da ne bom izbral, ampak staro dobro delovno shemo na OpenCV zapakiram v Docker in jo zaženem v oblaku.

Prednost tega pristopa je prilagodljivost in nadzor - lahko spremenite nevronsko mrežo, gostovanje, strežnik - na splošno vsako muho.

Strežnik

Začnimo z lokalnim prototipom.

Tradicionalno uporabljam Flask za REST API, OpenCV in MobileSSD omrežje.

Po namestitvi trenutnih različic na Docker sem ugotovil, da OpenCV 4.1.2 ne deluje z Mobile SSD v1_coco_2018_01_28, zato sem se moral vrniti na preverjeno 11/06_2017.

Na začetku storitve naložimo imena razredov in omrežje:

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

Na lokalnem dockerju (na ne zelo mladem prenosniku) traja 0.3 sekunde, na Raspberryju - 3.5.

Začnimo z izračunom:

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

Pretvarjanje tenzorskega izpuha v berljiv 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

Nadalje izvozite to operacijo prek Flaska(vhod je slika, izhod rezultati detektorja v json).

Alternativna možnost, pri kateri se več dela prenese na strežnik: sam obkroži najdene predmete in vrne končano sliko.

Ta možnost je dobra, če ne želimo povleči opencv na strežnik.

Docker

Zbiramo sliko.

Koda je prečesana in objavljena Github, ga bo docker prevzel neposredno od tam.

Kot platformo bomo vzeli isti Debian Stretch kot na Raspberryju - ne bomo odstopali od preizkušenega tehnološkega sklopa.

Namestiti morate flask, protobuf, requests, opencv_python, prenesti Mobile SSD, kodo strežnika iz Githuba in zagnati strežnik.

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

Enostavno odjemalec detektorja na podlagi prošenj.

Objavljanje v Docker Hub

Registri Docker se množijo s hitrostjo, ki ni manjša od hitrosti detektorjev oblakov.

Da ne bi motili, bomo šli skozi konzervativno DockerHub.

  1. Registrirajte se
  2. Vpiši se:
    docker prijava
  3. Izmislimo si pomenljivo ime:
    docker oznaka opencv-detect tprlab/opencv-detect-ssd
  4. Naložite sliko na strežnik:
    docker push tprlab/opencv-detect-ssd

Zaženemo v oblaku

Tudi izbira, kam zapeljati kontejner, je precej široka.

Vsi veliki igralci (Google, Microsoft, Amazon) nudijo mikroinstanco brezplačno prvo leto.
Po eksperimentiranju z Microsoft Azure in Google Cloud sem se odločil za slednjega, ker se je hitreje razvijal.

Tukaj nisem pisal navodil, saj je ta del zelo specifičen za izbranega ponudnika.

Preizkusil sem različne možnosti strojne opreme,
Nizke ravni (deljene in namenske) - 0.4 - 0.5 sekunde.
Močnejši avtomobili - 0.25 - 0.3.
No, tudi v najslabšem primeru je dobitek trikratnik, lahko poskusite.

video

Zaženemo preprost OpenCV video streamer na Raspberry, ki zazna prek Google Cloud.
Za poskus je bila uporabljena video datoteka, ki je bila nekoč posneta na naključnem križišču.


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

Z detektorjem ne dobimo več kot tri slike na sekundo, vse poteka zelo počasi.
Če vzamete zmogljiv stroj v GCloud, lahko zaznate 4-5 sličic na sekundo, vendar je razlika očem skoraj nevidna, še vedno je počasen.

Videoposnetek detektorja objektov v oblaku na Raspberry Pi

Oblak in stroški transporta nimajo nobene zveze, detektor deluje na navadni strojni opremi in deluje s tako hitrostjo.

Nevronska računalniška palica

Nisem se mogel upreti in opravil merilo uspešnosti na NCS.

Hitrost detektorja je bila nekoliko nižja od 0.1 sekunde, v vsakem primeru 2-3 krat večja od oblaka na šibkem stroju, to je 8-9 sličic na sekundo.

Videoposnetek detektorja objektov v oblaku na Raspberry Pi

Razlika v rezultatih je razložena z dejstvom, da je NCS uporabljal mobilni SSD različice 2018_01_28.

PS Poleg tega so poskusi pokazali, da precej zmogljiv namizni stroj s procesorjem I7 kaže nekoliko boljše rezultate in izkazalo se je, da je na njem mogoče stisniti 10 sličic na sekundo.

Grozd

Eksperiment je šel dlje in detektor sem namestil na pet vozlišč v Google Kubernetes.
Stroki sami so bili šibki in vsak od njih ni mogel obdelati več kot 2 sličici na sekundo.
Če pa zaženete gručo z N vozlišči in razčlenite okvirje v N nitih, potem lahko z zadostnim številom vozlišč (5) dosežete želenih 10 sličic na sekundo.

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

Evo, kaj se je zgodilo:

Videoposnetek detektorja objektov v oblaku na Raspberry Pi

Malo manj hitro kot pri NCS, vendar bolj živahno kot v enem toku.

Dobiček seveda ni linearen - obstajajo prekrivanja za sinhronizacijo in globoko kopiranje slik opencv.

Zaključek

Na splošno nam eksperiment omogoča sklep, da lahko, če poskusite, pobegnete s preprostim oblakom.

Toda zmogljiva namizna ali lokalna strojna oprema vam omogoča doseganje boljših rezultatov brez kakršnih koli trikov.

reference

Vir: www.habr.com

Dodaj komentar