Video ar mākoņa objektu detektoru uz Raspberry Pi

Prologs

Tagad internetā cirkulē video, kurā redzams, kā Teslas autopilots redz ceļu.

Man jau ilgu laiku ir gribējies pārraidīt video, kas bagātināts ar detektoru, turklāt reāllaikā.

Video ar mākoņa objektu detektoru uz Raspberry Pi

Problēma ir tāda, ka es vēlos pārraidīt video no Raspberry, un neironu tīkla detektora veiktspēja tajā atstāj daudz vēlamo.

Intel Neural Computer Stick

Es apsvēru dažādus risinājumus.

Š’ pēdējais raksts eksperimentēja ar Intel Neural Computer Stick. AparatÅ«ra ir jaudÄ«ga, taču tai ir nepiecieÅ”ams savs tÄ«kla formāts.

Lai gan Intel nodroÅ”ina pārveidotājus galvenajām sistēmām, pastāv vairākas nepilnÄ«bas.

Piemēram, vajadzÄ«gā tÄ«kla formāts var bÅ«t nesaderÄ«gs, un, ja tas ir saderÄ«gs, tad daži slāņi var netikt atbalstÄ«ti ierÄ«cē, un, ja tie tiek atbalstÄ«ti, tad konvertÄ“Å”anas procesā var rasties kļūdas, kuru rezultātā izejā saņemam dÄ«vainas lietas.

Kopumā, ja vēlaties kaut kādu patvaļīgu neironu tīklu, tas var nedarboties ar NCS. Tāpēc es nolēmu mēģināt atrisināt problēmu, izmantojot visizplatītākos un pieejamākos rīkus.

Mākonis

Acīmredzama alternatīva vietējam aparatūras risinājumam ir pāriet uz mākoni.

Gatavi varianti - manas acis skrien mežonīgas.

Visi vadītāji:

... Un desmitiem mazāk zināmu.

Izvēle starp Å”o Ŕķirni nepavisam nav vienkārÅ”a.

Un es nolēmu neizvēlēties, bet ietīt veco labo darba shēmu uz OpenCV programmā Docker un palaist to mākonī.

Šīs pieejas priekŔrocība ir elastība un kontrole - jūs varat mainīt neironu tīklu, hostingu, serveri - kopumā jebkura kaprīze.

Serveris

Sāksim ar vietējo prototipu.

Tradicionāli es izmantoju Flask REST API, OpenCV un MobileSSD tīklam.

Instalējot paÅ”reizējās versijas Docker, es atklāju, ka OpenCV 4.1.2 nedarbojas ar mobilo SSD v1_coco_2018_01_28, un man bija jāatgriežas uz pārbaudÄ«to versiju 11/06_2017.

Pakalpojuma sākumā mēs ielādējam klaÅ”u nosaukumus un tÄ«klu:

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

Vietējā dokā (ne pārāk jaunā klēpjdatorā) tas aizņem 0.3 sekundes, Raspberry - 3.5.

Sāksim aprēķinu:

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.

Tensora izplÅ«des pārvērÅ”ana par lasāmu 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

Tālāk eksportēt Å”o darbÄ«bu, izmantojot Kolbu(ievade ir attēls, izvade ir detektora rezultāti JSON).

Alternatīva iespēja, kurā vairāk darba tiek pārcelts uz serveri: tas pats riņķo atrastos objektus un atgriež gatavo attēlu.

Šī opcija ir laba, ja mēs nevēlamies vilkt opencv uz serveri.

Docker

Mēs savācam attēlu.

Kods ir izÄ·emmēts un ievietots Github, dokeris to paņems tieÅ”i no turienes.

Kā platforma mēs izmantosim to paÅ”u Debian Stretch kā Raspberry ā€” mēs neatkāpsimies no pārbaudÄ«tās tehnoloÄ£iju kopas.

Jums jāinstalē flask, protobuf, requests, opencv_python, jālejupielādē Mobile SSD, servera kods no Github un jāstartē serveris.

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

VienkārŔs detektora klients pamatojoties uz pieprasījumiem.

PublicēŔana Docker Hub

Docker reģistri vairojas ar ātrumu, kas nav mazāks par mākoņu detektoru ātrumu.

Lai neapgrūtinātu, iesim konservatīvi cauri DockerHub.

  1. Reģistrēties
  2. Pieslēgties:
    docker pieteikŔanās
  3. Izdomāsim jēgpilnu nosaukumu:
    docker tag opencv-detect tprlab/opencv-detect-ssd
  4. AugÅ”upielādējiet attēlu serverÄ«:
    docker push tprlab/opencv-detect-ssd

Mēs startējam mākonī

ArÄ« izvēle, kur palaist konteineru, ir diezgan plaÅ”a.

Visi lielie spēlētāji (Google, Microsoft, Amazon) pirmo gadu piedāvā mikroinstanci bez maksas.
Pēc eksperimentÄ“Å”anas ar Microsoft Azure un Google Cloud es izvēlējos pēdējo, jo tas sāka darboties ātrāk.

Es Å”eit nerakstÄ«ju instrukcijas, jo Ŕī daļa ir ļoti specifiska atlasÄ«tajam pakalpojumu sniedzējam.

Es izmēģināju dažādas aparatūras iespējas,
Zemi līmeņi (koplietoti un paredzēti) - 0.4 - 0.5 sekundes.
Jaudīgākas automaŔīnas - 0.25 - 0.3.
Nu, pat sliktākajā gadÄ«jumā laimests ir trÄ«skārÅ”s, varat mēģināt.

Video

Mēs palaižam vienkārÅ”u OpenCV video straumētāju vietnē Raspberry, kas tiek atklāts, izmantojot Google Cloud.
Eksperimentam tika izmantots video fails, kas savulaik tika filmēts nejauŔā krustojumā.


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

Ar detektoru mēs iegūstam ne vairāk kā trīs kadrus sekundē, viss notiek ļoti lēni.
Ja izmantojat jaudÄ«gu iekārtu GCloud, varat noteikt 4-5 kadrus sekundē, taču atŔķirÄ«ba ir gandrÄ«z neredzama acÄ«m, tā joprojām ir lēna.

Video ar mākoņa objektu detektoru uz Raspberry Pi

Mākonim un transporta izmaksām ar to nav nekāda sakara; detektors darbojas ar parastu aparatūru un darbojas tādā ātrumā.

Neironu datora stick

Es nevarēju pretoties un izpildīju NCS etalonu.

Detektora ātrums bija nedaudz mazāks par 0.1 sekundi, katrā ziņā 2-3 reizes lielāks nekā mākonis uz vājas maŔīnas, t.i., 8-9 kadri sekundē.

Video ar mākoņa objektu detektoru uz Raspberry Pi

Rezultātu atŔķirība ir izskaidrojama ar to, ka NCS darbojās Mobile SSD versija 2018_01_28.

PS Turklāt eksperimenti ir parādÄ«juÅ”i, ka diezgan jaudÄ«ga galda maŔīna ar I7 procesoru uzrāda nedaudz labākus rezultātus un izrādÄ«jās, ka uz tās ir iespējams izspiest 10 kadrus sekundē.

Kopa

Eksperiments gāja tālāk, un es instalēju detektoru piecos Google Kubernetes mezglos.
PaÅ”i podi bija vāji, un katrs no tiem nevarēja apstrādāt vairāk par 2 kadriem sekundē.
Bet, ja palaižat klasteru ar N mezgliem un parsējat kadrus N pavedienos, tad ar pietiekamu skaitu mezglu (5) varat sasniegt vēlamos 10 kadrus sekundē.

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

LÅ«k, kas notika:

Video ar mākoņa objektu detektoru uz Raspberry Pi

Nedaudz mazāk ātri nekā ar NCS, bet enerģiskāk nekā vienā straumē.

Ieguvums, protams, nav lineārs - ir pārklājumi opencv attēlu sinhronizācijai un dziļai kopÄ“Å”anai.

Secinājums

Kopumā eksperiments ļauj secināt, ka, ja jÅ«s mēģināt, jÅ«s varat tikt galā ar vienkārÅ”u mākoni.

Taču jaudīga darbvirsma vai vietējā aparatūra ļauj sasniegt labākus rezultātus un bez jebkādiem trikiem.

atsauces

Avots: www.habr.com

Pievieno komentāru