Video e detektorit të objekteve në renë në Raspberry Pi

prolog

Një video po qarkullon tani në internet që tregon se si autopiloti i Teslës e sheh rrugën.

Prej kohësh më kruhet për të transmetuar video të pasuruar me detektor dhe në kohë reale.

Video e detektorit të objekteve në renë në Raspberry Pi

Problemi është se unë dua të transmetoj video nga Raspberry, dhe performanca e detektorit të rrjetit nervor në të lë shumë për të dëshiruar.

Intel Neural Computer Stick

Kam konsideruar zgjidhje të ndryshme.

В artikulli i fundit eksperimentuar me Intel Neural Computer Stick. Pajisja është e fuqishme, por kërkon formatin e vet të rrjetit.

Edhe pse Intel ofron konvertues për kornizat kryesore, ka një numër grackash.

Për shembull, formati i rrjetit të kërkuar mund të jetë i papajtueshëm, dhe nëse është i pajtueshëm, atëherë disa shtresa mund të mos mbështeten në pajisje, dhe nëse ato mbështeten, atëherë mund të ndodhin gabime gjatë procesit të konvertimit, si rezultat i të cilave ne marrim disa gjëra të çuditshme në dalje.

Në përgjithësi, nëse doni një lloj rrjeti nervor arbitrar, atëherë mund të mos funksionojë me NCS. Prandaj, vendosa të përpiqem ta zgjidh problemin duke përdorur mjetet më të përhapura dhe të arritshme.

re

Alternativa e qartë për një zgjidhje harduerike lokale është të shkoni në cloud.

Opsione të gatshme - sytë i kam të egra.

Të gjithë drejtuesit:

... Dhe dhjetëra më pak të njohur.

Zgjedhja midis kësaj shumëllojshmërie nuk është aspak e lehtë.

Dhe vendosa të mos zgjedh, por të mbështjell skemën e mirë të vjetër të punës në OpenCV në Docker dhe ta ekzekutoj në re.

Avantazhi i kësaj qasjeje është fleksibiliteti dhe kontrolli - ju mund të ndryshoni rrjetin nervor, hostin, serverin - në përgjithësi, çdo tekë.

Serveri

Le të fillojmë me një prototip lokal.

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

Pasi instalova versionet aktuale në Docker, zbulova se OpenCV 4.1.2 nuk funksionon me Mobile SSD v1_coco_2018_01_28, dhe më duhej të kthehesha në 11/06_2017 të provuar.

Në fillim të shërbimit, ne 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ë një doker lokal (në një laptop jo shumë të ri) duhen 0.3 sekonda, në Raspberry - 3.5.

Le të fillojmë 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 sek, Raspberry - 1.7.

Shndërrimi i shkarkimit të tensorit 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ë tej eksportoni këtë operacion nëpërmjet Flask(hyrja është një foto, dalja janë rezultatet e detektorit në json).

Një opsion alternativ, në të cilin më shumë punë zhvendoset te serveri: ai vetë rrethon objektet e gjetura dhe kthen imazhin e përfunduar.

Ky opsion është i mirë kur nuk duam të tërhiqim opencv në server.

Doker

Ne mbledhim imazhin.

Kodi është krehur dhe postuar në Github, docker do ta marrë atë direkt nga atje.

Si platformë, ne do të marrim të njëjtin Debian Stretch si në Raspberry - nuk do të devijojmë nga grupi i provuar i teknologjisë.

Duhet të instaloni flask, protobuf, kërkesa, opencv_python, të shkarkoni SSD Mobile, kodin e serverit nga Github dhe të nisni 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"]

I thjeshtë klient detektor në bazë të kërkesave.

Publikimi në Docker Hub

Regjistrat e dokerit po shumohen me një shpejtësi jo më të vogël se detektorët e reve.

Për të mos u shqetësuar, ne do të kalojmë në mënyrë konservative DockerHub.

  1. Regjistrohu
  2. Identifikohu:
    hyrje në doker
  3. Le të gjejmë një emër kuptimplotë:
    etiketa docker opencv-detect tprlab/opencv-detect-ssd
  4. Ngarkoni imazhin në server:
    docker shtytje tprlab/opencv-detect-ssd

Ne nisim në re

Zgjedhja se ku do të vendoset kontejneri është gjithashtu mjaft e gjerë.

Të gjithë lojtarët e mëdhenj (Google, Microsoft, Amazon) ofrojnë një mikro-instancë falas për vitin e parë.
Pasi eksperimentova me Microsoft Azure dhe Google Cloud, u vendosa në këtë të fundit sepse u ngrit më shpejt.

Unë nuk kam shkruar udhëzime këtu, pasi kjo pjesë është shumë specifike për ofruesin e zgjedhur.

Provova opsione të ndryshme harduerike,
Nivele të ulëta (të përbashkëta dhe të dedikuara) - 0.4 - 0.5 sekonda.
Makina më të fuqishme - 0.25 - 0.3.
Epo, edhe në skenarin më të keq, fitimet janë trefish, mund të provoni.

Video

Ne lëshojmë një transmetues të thjeshtë video OpenCV në Raspberry, i cili zbulohet përmes Google Cloud.
Për eksperimentin, u përdor një skedar video që dikur ishte filmuar në një kryqëzim 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/jpegrnrn' + bytearray(outFrame) + b'rn')

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

Me detektorin marrim jo më shumë se tre korniza në sekondë, gjithçka shkon shumë ngadalë.
Nëse futni një makinë të fuqishme në GCloud, mund të zbuloni 4-5 korniza në sekondë, por ndryshimi është pothuajse i padukshëm për syrin, është ende i ngadaltë.

Video e detektorit të objekteve në renë në Raspberry Pi

Reja dhe kostot e transportit nuk kanë të bëjnë me të; detektor funksionon me pajisje të zakonshme dhe punon me një shpejtësi të tillë.

Neural Computer Stick

Unë nuk mund të rezistoja dhe zbatova standardin në NCS.

Shpejtësia e detektorit ishte pak më e ngadaltë se 0.1 sekonda, në çdo rast 2-3 herë më e shpejtë se reja në një makinë të dobët, pra 8-9 korniza në sekondë.

Video e detektorit të objekteve në renë në Raspberry Pi

Dallimi në rezultate shpjegohet me faktin se NCS po ekzekutonte versionin SSD Mobile 2018_01_28.

PS Për më tepër, eksperimentet kanë treguar se një makinë mjaft e fuqishme desktop me një procesor I7 tregon rezultate pak më të mira dhe doli të jetë e mundur të shtrydhni 10 korniza për sekondë mbi të.

Grumbull

Eksperimenti shkoi më tej dhe unë instalova detektorin në pesë nyje në Google Kubernetes.
Vetë podet ishin të dobëta dhe secila prej tyre nuk mund të përpunonte më shumë se 2 korniza në sekondë.
Por nëse drejtoni një grup me N nyje dhe analizoni kornizat në N fije, atëherë me një numër të mjaftueshëm nyjesh (5) mund të arrini 10 kornizat e dëshiruara 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

Ja çfarë ndodhi:

Video e detektorit të objekteve në renë në Raspberry Pi

Pak më pak i shpejtë sesa me NCS, por më i fuqishëm se në një rrjedhë.

Fitimi, natyrisht, nuk është linear - ka mbivendosje për sinkronizimin dhe kopjimin e thellë të imazheve opencv.

Përfundim

Në përgjithësi, eksperimenti na lejon të konkludojmë se nëse provoni, mund të shpëtoni me një re të thjeshtë.

Por një desktop i fuqishëm ose harduer lokal ju lejon të arrini rezultate më të mira dhe pa asnjë mashtrim.

Referencat

Burimi: www.habr.com

Shto një koment