Video me detektor objektesh në re të funksionuar në Raspberry Pi

Prologu

Një video po qarkullon në internet - si e sheh autopiloti i Teslës rrugën.

Ka kohë që kam pasur dëshirë të transmetoj një video të pasuruar me detektor, madje në kohë reale.

Video me detektor objektesh në re të funksionuar në Raspberry Pi

Problemi është se dëshiroj të transmetoj video me Raspberry, dhe performanca e detektorit të rrjetit nervor atje lë shumë për të dëshiruar.

Intel Neural Computer Stick

Kam shqyrtuar opsione të ndryshme për zgjidhje.

Në artikullin e kaluar. kam eksperimentuar me Intel Neural Computer Stick. Pajisja është e fuqishme, por kërkon formatin e saj të rrjetit.

Megjithëse Intel ofron konvertorë për kornizat kryesore, këtu ka disa kërcime.

Për shembull, formati i nevojshëm i rrjetit mund të jetë i papërshtatshëm, dhe nëse është i përshtatshëm, disa ndarje mund të mos përkrahen në pajisje, madje nëse përkrahen, gjatë procesit të konvertimit mund të ndodhin gabime, duke rezultuar në daljen e disa gjërave të çuditshme.

Në përgjithësi, nëse dëshiron ndonjë rrjet nervor të rastësishëm, me NCS mund të mos e arrish. Prandaj, vendosa të provoj të zgjidh problemin përmes mjeteve më masive dhe të accessibles.

Rehati

Një alternativë e dukshme për një zgjidhje lokale-harduer është të kalosh në cloud.

Opsionet e gatshme - të gjitha janë në dispozicion.

Të gjitha liderët:


 dhe dhjetëra të tjerë të panjohur.

Të zgjedhësh ndërmjet kësaj shumëllojshmërie nuk është aspak e lehtë.

Dhe vendosa të mos zgjedh, por të bllokoj një skemë të vjetër të njohur të punës në OpenCV dhe ta nisin atë në cloud.

Përparësia e këtij qasje është fleksibiliteti dhe kontrolli - mund të ndërosh rrjetin nervor, hosting, server - në përgjithësi, çdo kapriç.

Serveri

Le të fillojmë me një prototip lokal.

Tradicionalisht, unë përdor Flask për REST API, OpenCV dhe rrjetin MobileSSD.

Pas instalimit të versioneve aktuale në docker, zbulova se OpenCV 4.1.2 nuk funksionon me Mobile SSD v1_coco_2018_01_28, dhe duhej të kthehem në versionin e provuar 11_06_2017.

Në fillimin e shërbimit ngarkojmë emrat e klasave dhe rrjetin:

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

Në dockerin lokal (në një laptop jo shumë të ri) kjo merr 0.3 sekonda, në Raspberry - 3.5.

Nisim llogaritjen:

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

Kthejmë daljen tensor në json të lexueshëm:

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

Më pas eksportojmë këtë operacion përmes Flask(në hyrje një imazh, në dalje - rezultatet e detektorit në json).

Një variant alternativ, në të cilin më shumë punë transfertë në server: ai vetë rrethon objektet e gjetura dhe kthen një imazh të gatshëm.

Ky ky është një opsion i mirë atje ku nuk duam të tërheqim opencv në server.

Docker

Po mbledhim imazhin.

Kodi është rregulluar dhe është vendosur në GitHub, docker do ta marrë drejtpërdrejt nga aty.

Si platformĂ« do tĂ« pĂ«rdorim po atĂ« Debian Stretch qĂ« e kemi nĂ« Raspberry — nuk do tĂ« largohemi nga stoku i provuar teknik.

Duhet të instalojmë flask, protobuf, requests, opencv_python, të shkarkojmë Mobile SSD, kodin e serverit nga GitHub dhe të nisim serverin.

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

E thjeshtë klienti për detektor në bazë të requests.

Publikimi në Docker Hub

Regjistrat e docker-it shpejtohen me një ritëm të ngjashëm me atë të detektorëve në cloud.

Për të mos u ndërlikuar, ne do të shkojmë konservatorisht përmes DockerHub.

  1. Regjistrohuni
  2. Autorizohemi:
    docker login
  3. Do të mendojmë një emër domethënës:
    docker tag opencv-detect tprlab/opencv-detect-ssd
  4. Ngarko imazhin në server:
    docker push tprlab/opencv-detect-ssd

Nisim në cloud

Zgjedhja e vendit ku të nisni kontejnerin është gjithashtu shumë e gjerë.

Të gjithë lojtarët e mëdhenj (Google, Microsoft, Amazon) ofrojnë mikroinstancë falas për vitin e parë.
Pas eksperimentimit me Microsoft Azure dhe Google Cloud, kam ndaluar tek e fundit — sepse u ngjit mĂ« shpejt.

Nuk shkrova këtu një udhëzim, sepse kjo pjesë është shumë e specifiq për ofruesin e zgjedhur.

Provova variante të ndryshme të harduerit,
Niveli i ulĂ«t (shared dhe dedikuar) — 0.4 — 0.5 sekonda.
Makinat mĂ« tĂ« fuqishme — 0.25 — 0.3.
ÇfarĂ«, madje edhe nĂ« rastin mĂ« tĂ« keq fitimi Ă«shtĂ« tri herĂ« mĂ« i lartĂ«, mund ta provojmĂ«.

Video

Nisim një transmetues video të thjeshtë OpenCV në Raspberry, duke detektuar përmes Google Cloud.
Për eksperimentin u përdor një skedar video, njëherë i regjistruar në një kruzhd të rastësishëm.


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/jpeg

' + bytearray(outFrame) + b'
')

@app.route("/stream")
def video_feed():
    return Response(generate(), mimetype = "multipart/x-mixed-replace; boundary=frame")

Me detektorin arrihet jo më shumë se tre kadra në sekondë, gjithçka shkon shumë ngadalë.
Nëse marrim një makinë të fuqishme në GCloud, mund të detektojmë 4-5 kadra në sekondë, por ndryshimi është pothuajse i padukshëm me syrin, gjithsesi është ngadalë.

Video me detektor objektesh në re të funksionuar në Raspberry Pi

Cloud dhe kostot e transportit nuk kanë të bëjnë me këtë, detektori punon me një shpejtësi të tillë edhe në harduer të zakonshëm.

Neural Computer Stick

Nuk e mbajta veten dhe e provoj një benchmark në NCS.

Shpejtësia e detektorit ishte pak më e vogël se 0.1 sekonda, në çdo rast 2-3 herë më e shpejtë se cloud në një makinë të përçarë, pra 8-9 kadra në sekondë.

Video me detektor objektesh në re të funksionuar në Raspberry Pi

Ndryshimi në rezultatet shpjegohet me faktin se në NCS u ekzekutua Mobile SSD versioni 2018_01_28.

P.S. Për më tepër, eksperimentet treguan se një makinë desktop mjaft e fuqishme me procesorin I7 tregon rezultate pak më të mira dhe ndodhi që të mund të nxirrej 10 kadra në sekondë.

Klastri

Eksperimenti shkoi më tej dhe vendosa një detektor në pesë nyje në Google Kubernetes.
Për shkak të vetë, gjinjtë ishin të dobët dhe secili prej tyre nuk mund të përpunonte më shumë se 2 korniza në sekondë.
Por nëse nisim një klaster me N nyje dhe analizojmë kornizat në N procese - atëherë me një numër të mjaftueshëm nyjesh (5) mund të arrijmë 10 korniza në sekondë.

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

Këtu është rezultati:

Video me detektor objektesh në re të funksionuar në Raspberry Pi

Më pak shpejt sesa me NCS, por më aktiv se në një proces.

Fitimi, sigurisht, nuk është linear - ngarkesat e sinkronizimit dhe kopjimi i thellë i imazheve opencv janë të pranishme.

Përfundimi

Në përgjithësi, eksperimenti tregon se, nëse përpiqesh, mund të menaxhosh me një cloud të thjeshtë.

Por një desktop i fuqishëm ose një makinë lokale ofrojnë rezultate më të mira, pa asnjë shtrirje.

Linke

Burimi: habr.com

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster