Video pilveobjektide detektorist Raspberry Pi-l

Proloog

Nüüd ringleb Internetis video, mis näitab, kuidas Tesla autopiloot teed näeb.

Olen juba pikka aega soovinud detektoriga rikastatud videot edastada ja seda reaalajas.

Video pilveobjektide detektorist Raspberry Pi-l

Probleem on selles, et ma tahan Raspberryst videot edastada ja sellel oleva närvivõrgu detektori jõudlus jätab soovida.

Intel Neural Computer Stick

Kaalusin erinevaid lahendusi.

В viimane artikkel katsetas Intel Neural Computer Stickiga. Riistvara on võimas, kuid vajab oma võrguvormingut.

Kuigi Intel pakub suuremate raamistike jaoks muundureid, on sellel mitmeid lõkse.

Näiteks võib vajaliku võrgu formaat olla mitteühilduv ja kui see on ühilduv, siis ei pruugi seade mõnda kihti toetada ja kui need on toetatud, siis võib teisendusprotsessi käigus tekkida tõrkeid, mille tulemusena saame väljundis kummalisi asju.

Üldiselt, kui soovite mingit suvalist närvivõrku, siis see ei pruugi NCS-iga töötada. Seetõttu otsustasin proovida probleemi lahendada kõige levinumate ja ligipääsetavamate tööriistade abil.

Pilv

Ilmselge alternatiiv kohalikule riistvaralahendusele on minna pilve.

Valmis variandid – mu silmad jooksevad metsikult.

Kõik juhid:

... Ja kümneid vähemtuntud.

Selle sordi hulgast valimine pole sugugi lihtne.

Ja otsustasin mitte valida, vaid pakkida vana hea OpenCV tööskeemi Dockerisse ja käivitada see pilves.

Selle lähenemise eeliseks on paindlikkus ja juhtimine - saate muuta närvivõrku, hostimist, serverit - üldiselt mis tahes kapriisi.

Server

Alustame kohaliku prototüübiga.

Traditsiooniliselt kasutan Flask REST API, OpenCV ja MobileSSD võrgu jaoks.

Olles installinud Dockerisse praegused versioonid, avastasin, et OpenCV 4.1.2 ei tööta koos Mobile SSD-ga v1_coco_2018_01_28 ja pidin tagasi pöörduma tõestatud versioonile 11/06_2017.

Teenuse käivitamisel laadime klassinimed ja võrgu:

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

Kohalikus dokis (mitte väga noorel sülearvutil) kulub 0.3 sekundit, Raspberryl - 3.5.

Alustame arvutamist:

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 sek, Vaarikas - 1.7.

Tensori väljalaske muutmine loetavaks jsoniks:

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

Edasi eksportige see toiming Flaski kaudu(sisend on pilt, väljund on detektori tulemused json-vormingus).

Alternatiivne variant, mille puhul nihutatakse rohkem tööd serverile: ta teeb ise leitud objektid ringi ja tagastab valmis pildi.

See valik on hea, kui me ei soovi opencv-d serverisse lohistada.

Docker

Kogume pildi.

Kood kammitakse ja postitatakse Github, võtab docker selle sealt otse.

Platvormina kasutame sama Debian Stretchi, mis Raspberry puhul – me ei kaldu kõrvale tõestatud tehnoloogiast.

Peate installima flask, protobuf, taotlused, opencv_python, alla laadima Githubi mobiilse SSD, serveri koodi ja käivitama serveri.

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

Lihtne detektori klient taotluste põhjal.

Docker Hubis avaldamine

Dockeri registrid paljunevad kiirusega, mis pole väiksem kui pilvedetektorid.

Et mitte tülitada, läheme konservatiivselt läbi DockerHub.

  1. Registreeri
  2. Logi sisse:
    dokkeri sisselogimine
  3. Mõtleme välja tähendusrikka nime:
    dokkeri silt opencv-detect tprlab/opencv-detect-ssd
  4. Laadi pilt serverisse üles:
    Docker push tprlab/opencv-detect-ssd

Käivitame pilves

Valik, kuhu konteiner jooksutada, on samuti üsna lai.

Kõik suured tegijad (Google, Microsoft, Amazon) pakuvad esimesel aastal mikroeksemplari tasuta.
Pärast Microsoft Azure'i ja Google Cloudi katsetamist otsustasin viimase kasuks, kuna see läks kiiremini käima.

Ma ei kirjutanud siia juhiseid, kuna see osa on valitud pakkuja jaoks väga spetsiifiline.

Proovisin erinevaid riistvaravalikuid,
Madalad tasemed (jagatud ja pühendatud) - 0.4 - 0.5 sekundit.
Võimsamad autod - 0.25 - 0.3.
Noh, isegi halvimal juhul on võidud kolmekordsed, võite proovida.

video

Käivitame Raspberrys lihtsa OpenCV-videostriimi, mis tuvastab Google Cloudi kaudu.
Katse jaoks kasutati videofaili, mis filmiti kunagi juhuslikul ristmikul.


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

Detektoriga saame mitte rohkem kui kolm kaadrit sekundis, kõik läheb väga aeglaselt.
Kui võtate võimsa masina GCloudi, saate tuvastada 4-5 kaadrit sekundis, kuid erinevus on silmale peaaegu nähtamatu, see on siiski aeglane.

Video pilveobjektide detektorist Raspberry Pi-l

Pilvel ja transpordikuludel pole sellega midagi pistmist, detektor töötab tavalisel riistvaral ja töötab sellise kiirusega.

Neuraalne arvutipulk

Ma ei suutnud vastu panna ja tegin NCS-i võrdlusaluse.

Detektori kiirus oli veidi aeglasem kui 0.1 sekundit, igal juhul 2-3 korda kiirem kui pilv nõrgal masinal ehk 8-9 kaadrit sekundis.

Video pilveobjektide detektorist Raspberry Pi-l

Tulemuste erinevus on seletatav asjaoluga, et NCS kasutas Mobile SSD versiooni 2018_01_28.

PS Lisaks on katsed näidanud, et üsna võimas I7 protsessoriga lauamasin näitab veidi paremaid tulemusi ja osutus võimalikuks pigistada 10 kaadrit sekundis.

Kobar

Katse läks kaugemale ja paigaldasin detektori Google Kubernetes viiele sõlmele.
Kaunad ise olid nõrgad ja igaüks neist ei suutnud töödelda rohkem kui 2 kaadrit sekundis.
Kuid kui käivitate N sõlmega klastri ja sõelute kaadrit N lõimes, siis piisava arvu sõlmedega (5) saate soovitud 10 kaadrit sekundis saavutada.

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

See on juhtunud:

Video pilveobjektide detektorist Raspberry Pi-l

Natuke vähem kiire kui NCS-iga, kuid jõulisem kui ühes voos.

Kasum ei ole muidugi lineaarne – opencv-piltide sünkroonimiseks ja sügavaks kopeerimiseks on olemas ülekatted.

Järeldus

Üldiselt võimaldab katse järeldada, et kui proovite, pääsete lihtsa pilvega.

Kuid võimas töölaud või kohalik riistvara võimaldab teil saavutada paremaid tulemusi ja ilma igasuguste trikkideta.

Viited

Allikas: www.habr.com

Lisa kommentaar