Prologue
Myndband er nú í dreifingu á netinu sem sýnir hvernig sjálfstýring Tesla sér veginn.
Mig hefur lengi klæjað að senda út myndband auðgað með skynjara, og það í rauntíma.
Vandamálið er að ég vil senda út myndband frá Raspberry og frammistaða tauganetskynjarans á honum skilur eftir sig miklu.
Intel taugatölvustafur
Ég velti fyrir mér mismunandi lausnum.
В
Jafnvel þó að Intel veiti breytum fyrir helstu ramma, þá eru ýmsar gildrur.
Til dæmis gæti snið tilskilins netkerfis verið ósamrýmanlegt og ef það er samhæft, þá gæti verið að sum lög séu ekki studd á tækinu og ef þau eru studd geta villur komið upp í umbreytingarferlinu, sem leiðir af sér við fáum skrítna hluti við úttakið.
Almennt séð, ef þú vilt einhvers konar handahófskennt tauganet, þá gæti það ekki virka með NCS. Þess vegna ákvað ég að reyna að leysa vandamálið með því að nota útbreiddustu og aðgengilegustu tækin.
Ský
Augljósi valkosturinn við staðbundna vélbúnaðarlausn er að fara í skýið.
Tilbúnir valkostir - augu mín hlaupa villt.
Allir leiðtogar:
... Og tugir minna þekktra.
Það er alls ekki auðvelt að velja á milli þessarar fjölbreytni.
Og ég ákvað að velja ekki, heldur að vefja gamla góða vinnukerfið á OpenCV í Docker og keyra það í skýinu.
Kosturinn við þessa nálgun er sveigjanleiki og stjórn - þú getur breytt taugakerfi, hýsingu, netþjóni - almennt, hvaða duttlunga sem er.
Server
Byrjum á staðbundinni frumgerð.
Hefðbundið nota ég Flask fyrir REST API, OpenCV og MobileSSD net.
Eftir að hafa sett upp núverandi útgáfur á Docker, uppgötvaði ég að OpenCV 4.1.2 virkar ekki með Mobile SSD v1_coco_2018_01_28, og ég varð að snúa aftur til sannaðs 11/06_2017.
Við upphaf þjónustunnar hleðum við flokksnöfnum og netkerfi:
def init():
tf_labels.initLabels(dnn_conf.DNN_LABELS_PATH)
return cv.dnn.readNetFromTensorflow(dnn_conf.DNN_PATH, dnn_conf.DNN_TXT_PATH)
Á staðbundnum tengikví (á ekki mjög ungri fartölvu) tekur það 0.3 sekúndur, á Raspberry - 3.5.
Byrjum á útreikningnum:
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, hindber - 1.7.
Breytir tensor útblástur í læsilegt 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
Nánari
Annar valkostur, þar sem meiri vinna er færð yfir á netþjóninn: hann sjálft hringir um fundna hluti og skilar fulluninni mynd.
Þessi valkostur er góður þar sem við viljum ekki draga opencv á netþjóninn.
Hafnarmaður
Við söfnum myndinni.
Kóðinn er greiddur og settur á
Sem vettvangur tökum við sömu Debian Stretch og á Raspberry - við munum ekki víkja frá hinum sannaða tæknistafla.
Þú þarft að setja upp flösku, protobuf, beiðnir, opencv_python, hlaða niður Mobile SSD, miðlarakóða frá Github og ræsa netþjóninn.
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"]
Einfalt
Birtir á Docker Hub
Docker skrár eru að fjölga sér á ekki minni hraða en skýskynjarar.
Til þess að trufla okkur ekki munum við fara íhaldssamt í gegn
- Skráðu þig
- Skrá inn:
docker innskráningu - Við skulum finna merkingarbært nafn:
docker tag opencv-detect tprlab/opencv-detect-ssd - Hladdu upp myndinni á netþjóninn:
docker ýta á tprlab/opencv-detect-ssd
Við ræsum í skýinu
Valið um hvar á að keyra gáminn er líka nokkuð breitt.
Allir stóru leikmennirnir (Google, Microsoft, Amazon) bjóða upp á örtilvik ókeypis fyrsta árið.
Eftir tilraunir með Microsoft Azure og Google Cloud, settist ég á hið síðarnefnda vegna þess að það tók hraðar á loft.
Ég skrifaði ekki leiðbeiningar hér, þar sem þessi hluti er mjög sérstakur fyrir valinn þjónustuaðila.
Ég prófaði mismunandi vélbúnaðarvalkosti,
Lág gildi (samnýtt og hollt) - 0.4 - 0.5 sekúndur.
Öflugri bílar - 0.25 - 0.3.
Jæja, jafnvel í versta falli, eru vinningarnir þrisvar sinnum, þú getur reynt.
video
Við kynnum einfaldan OpenCV vídeóstraumspilara á Raspberry, uppgötvum í gegnum Google Cloud.
Fyrir tilraunina var notuð myndbandsskrá sem var einu sinni tekin upp á handahófskenndum gatnamótum.
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ð skynjaranum fáum við ekki meira en þrjá ramma á sekúndu, allt gengur mjög hægt.
Ef þú tekur öfluga vél inn í GCloud geturðu greint 4-5 ramma á sekúndu, en munurinn er næstum ósýnilegur fyrir augað, hann er samt hægur.
Skýið og flutningskostnaður hefur ekkert með það að gera; skynjarinn keyrir á venjulegum vélbúnaði og vinnur á þeim hraða.
Tauga tölvustafur
Ég gat ekki staðist og rak viðmiðið á NCS.
Hraði skynjarans var aðeins hægari en 0.1 sekúnda, alla vega 2-3 sinnum meiri en skýið á veikri vél, þ.e.a.s. 8-9 rammar á sekúndu.
Munurinn á niðurstöðum skýrist af því að NCS var að keyra Mobile SSD útgáfu 2018_01_28.
PS Auk þess hafa tilraunir sýnt að nokkuð öflug borðvél með I7 örgjörva sýnir aðeins betri árangur og það reyndist hægt að kreista 10 ramma á sekúndu á hana.
Klasa
Tilraunin gekk lengra og ég setti skynjarann á fimm hnúta í Google Kubernetes.
Belgirnir sjálfir voru veikir og hver þeirra gat ekki unnið meira en 2 ramma á sekúndu.
En ef þú keyrir þyrping með N hnútum og greinir ramma í N þræði, þá geturðu náð 5 römmum á sekúndu með nægilegum fjölda hnúta (10).
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
Hér er það sem gerðist:
Örlítið hraðari en með NCS, en öflugri en í einum straumi.
Hagnaðurinn er auðvitað ekki línulegur - það eru yfirlög fyrir samstillingu og djúpa afritun á opencv myndum.
Ályktun
Á heildina litið gerir tilraunin okkur kleift að álykta að ef þú reynir geturðu komist upp með einfalt ský.
En öflugur skjáborðs- eða staðbundinn vélbúnaður gerir þér kleift að ná betri árangri og án allra brellna.
tilvísanir
Heimild: www.habr.com