Video van Cloud Object Detector op Raspberry Pi

proloog

’n Video doen nou die rondte op die internet wat wys hoe Tesla se autopilot die pad sien.

Ek jeuk al lank om video verryk met 'n detektor uit te saai, en in reële tyd.

Video van Cloud Object Detector op Raspberry Pi

Die probleem is dat ek video van Framboos wil uitsaai, en die werkverrigting van die neurale netwerkverklikker daarop laat veel te wense oor.

Intel neurale rekenaarstok

Ek het verskillende oplossings oorweeg.

В laaste artikel geëksperimenteer met Intel Neural Computer Stick. Die hardeware is kragtig, maar vereis sy eie netwerkformaat.

Alhoewel Intel omsetters vir groot raamwerke verskaf, is daar 'n aantal slaggate.

Byvoorbeeld, die formaat van die vereiste netwerk kan onversoenbaar wees, en as dit versoenbaar is, kan sommige lae dalk nie op die toestel ondersteun word nie, en as dit ondersteun word, kan foute tydens die omskakelingsproses voorkom, as gevolg daarvan ons kry 'n paar vreemde dinge by die uitset.

Oor die algemeen, as jy 'n soort arbitrêre neurale netwerk wil hê, sal dit dalk nie met NCS werk nie. Daarom het ek besluit om die probleem te probeer oplos deur die mees wydverspreide en toeganklike hulpmiddels te gebruik.

wolk

Die voor die hand liggende alternatief vir 'n plaaslike hardeware-oplossing is om na die wolk te gaan.

Klaargemaakte opsies – my oë loop wild.

Alle leiers:

... En dosyne minder bekendes.

Om tussen hierdie verskeidenheid te kies is glad nie maklik nie.

En ek het besluit om nie te kies nie, maar om die goeie ou werkskema op OpenCV in Docker toe te draai en dit in die wolk te laat loop.

Die voordeel van hierdie benadering is buigsaamheid en beheer - jy kan die neurale netwerk, hosting, bediener verander - in die algemeen, enige gril.

Bediener

Kom ons begin met 'n plaaslike prototipe.

Tradisioneel gebruik ek Flask vir REST API, OpenCV en MobileSSD netwerk.

Nadat ek die huidige weergawes op Docker geïnstalleer het, het ek ontdek dat OpenCV 4.1.2 nie met Mobile SSD v1_coco_2018_01_28 werk nie, en ek moes terugrol na die bewese 11/06_2017.

Aan die begin van die diens laai ons die klasname en netwerk:

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

Op 'n plaaslike docker (op 'n nie baie jong skootrekenaar) neem dit 0.3 sekondes, op Raspberry - 3.5.

Kom ons begin die berekening:

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., Framboos - 1.7.

Verander tensor-uitlaat in leesbare 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

verder voer hierdie operasie via Flask uit(invoer is 'n prentjie, uitset is die resultate van die detektor in json).

'n Alternatiewe opsie, waarin meer werk na die bediener verskuif word: dit self sirkel die voorwerpe wat gevind is en gee die voltooide prent terug.

Hierdie opsie is goed waar ons nie opencv na die bediener wil sleep nie.

Docker

Ons versamel die beeld.

Die kode word gefynkam en op geplaas Github, sal docker dit direk van daar af neem.

As 'n platform sal ons dieselfde Debian Stretch neem as op Raspberry - ons sal nie van die bewese tegnologiestapel afwyk nie.

Jy moet fles, protobuf, versoeke, opencv_python installeer, Mobile SSD, bedienerkode van Github aflaai en die bediener begin.

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

eenvoudige detektor kliënt gebaseer op versoeke.

Publiseer na Docker Hub

Docker-registers vermenigvuldig teen 'n spoed wat nie minder is as wolkverklikkers nie.

Om nie te pla nie, sal ons konserwatief deurgaan DockerHub.

  1. Registreer
  2. Teken aan:
    docker-aanmelding
  3. Kom ons kom met 'n betekenisvolle naam:
    docker tag opencv-detect tprlab/opencv-detect-ssd
  4. Laai die prent op na die bediener:
    docker druk tprlab/opencv-detect-ssd

Ons begin in die wolk

Die keuse van waar om die houer te laat loop is ook redelik wyd.

Al die groot spelers (Google, Microsoft, Amazon) bied 'n mikro-instansie gratis in die eerste jaar.
Nadat ek met Microsoft Azure en Google Cloud geëksperimenteer het, het ek op laasgenoemde besluit omdat dit vinniger opgestyg het.

Ek het nie instruksies hier geskryf nie, aangesien hierdie deel baie spesifiek is vir die gekose verskaffer.

Ek het verskillende hardeware-opsies probeer,
Lae vlakke (gedeel en toegewyd) - 0.4 - 0.5 sekondes.
Kragtiger motors - 0.25 - 0.3.
Wel, selfs in die ergste geval is die winste drie keer, jy kan probeer.

video

Ons loods 'n eenvoudige OpenCV-videostreamer op Raspberry, wat deur Google Cloud bespeur.
Vir die eksperiment is 'n videolêer gebruik wat een keer by 'n ewekansige kruising verfilm is.


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

Met die detector kry ons nie meer as drie rame per sekonde nie, alles gaan baie stadig.
As jy 'n kragtige masjien in GCloud neem, kan jy 4-5 rame per sekonde opspoor, maar die verskil is amper onsigbaar vir die oog, dit is steeds stadig.

Video van Cloud Object Detector op Raspberry Pi

Die wolk- en vervoerkoste het niks daarmee te doen nie; die detektor werk op gewone hardeware en werk teen daardie spoed.

Neurale rekenaarstok

Ek kon nie weerstaan ​​nie en het die maatstaf op NKV gehardloop.

Die spoed van die detektor was effens stadiger as 0.1 sekondes, in elk geval 2-3 keer vinniger as die wolk op 'n swak masjien, dit wil sê 8-9 rame per sekonde.

Video van Cloud Object Detector op Raspberry Pi

Die verskil in resultate word verklaar deur die feit dat NCS Mobile SSD weergawe 2018_01_28 gebruik het.

NS Boonop het eksperimente getoon dat 'n redelik kragtige lessenaarmasjien met 'n I7-verwerker effens beter resultate toon en dit blyk moontlik te wees om 10 rame per sekonde daarop te druk.

Cluster

Die eksperiment het verder gegaan en ek het die detektor op vyf nodusse in Google Kubernetes geïnstalleer.
Die peule self was swak en elkeen van hulle kon nie meer as 2 rame per sekonde verwerk nie.
Maar as jy 'n kluster met N nodusse hardloop en rame in N drade ontleed, dan kan jy met 'n voldoende aantal nodusse (5) die verlangde 10 rame per sekonde bereik.

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

Dit is wat daar gebeur het:

Video van Cloud Object Detector op Raspberry Pi

'n Bietjie minder vinnig as met NKV, maar kragtiger as in een stroom.

Die wins is natuurlik nie lineêr nie - daar is oorleggings vir sinchronisasie en diep kopiëring van opencv-beelde.

Gevolgtrekking

In die algemeen stel die eksperiment ons in staat om tot die gevolgtrekking te kom dat as jy probeer, jy met 'n eenvoudige wolk kan wegkom.

Maar 'n kragtige lessenaar of plaaslike hardeware laat jou toe om beter resultate te behaal, en sonder enige truuks.

verwysings

Bron: will.com

Voeg 'n opmerking