Prologue
Ke holo nei kahi wikiō ma ka Pūnaewele e hōʻike ana i ka ʻike ʻana o ka autopilot Tesla i ke ala.
Ua lōʻihi wau e hoʻolaha i ka wikiō i hoʻonui ʻia me kahi mea ʻike, a i ka manawa maoli.
ʻO ka pilikia, makemake wau e hoʻolaha wikiō mai Raspberry, a ʻo ka hana ʻana o ka neural network detector ma luna ona e waiho nui i ka makemake.
ʻO Intel Neural Computer Stick
Ua noʻonoʻo au i nā hoʻonā ʻokoʻa.
В
ʻOiai hāʻawi ʻo Intel i nā mea hoʻololi no nā frameworks nui, aia kekahi mau pitfalls.
Например, формат нужной сети может быть несовместим, а если совместим, то какие-то слои могут не поддерживаться на девайсе, а если поддерживаются, то в процессе конвертации могут происходить ошибки, в результате которых на выходе получаем какие-то странные вещи.
Ma keʻano laulā, inā makemake ʻoe i kahi ʻano neural network arbitrary, a laila ʻaʻole ia e hana me NCS. No laila, ua hoʻoholo wau e hoʻāʻo e hoʻoponopono i ka pilikia me ka hoʻohana ʻana i nā mea hana ākea a hiki ke loaʻa.
Aia
ʻO ka ʻokoʻa ʻē aʻe i kahi hoʻonā ʻenehana kūloko e hele i ke ao.
Nā koho i hoʻomākaukau ʻia - holo kaʻu mau maka.
Nā alakaʻi a pau:
... A he mau kakini o nā mea ʻike ʻole ʻia.
ʻAʻole maʻalahi ke koho i waena o kēia ʻano.
A ua hoʻoholo wau ʻaʻole e koho, akā e hoʻopili i ka hoʻolālā hana kahiko maikaʻi ma OpenCV ma Docker a holo i ke ao.
Преимущество такого подхода в гибкости и контроле — можно поменять нейросеть, хостинг, сервер — в общем, любой каприз.
Server
Начнем с локального прототипа.
Hoʻohana au i ka Flask no REST API, OpenCV a me MobileSSD pūnaewele.
Ma hope o ka hoʻokomo ʻana i nā mana o kēia manawa ma Docker, ʻike wau ʻaʻole hana ʻo OpenCV 4.1.2 me Mobile SSD v1_coco_2018_01_28, a pono wau e ʻōwili i hope i ka 11/06_2017.
На старте сервиса загружаем имена классов и сеть:
def init():
tf_labels.initLabels(dnn_conf.DNN_LABELS_PATH)
return cv.dnn.readNetFromTensorflow(dnn_conf.DNN_PATH, dnn_conf.DNN_TXT_PATH)
Ma kahi docker kūloko (ma kahi pona ʻōpio ʻaʻole ʻōpio) e lawe ia i 0.3 kekona, ma Raspberry - 3.5.
E hoʻomaka kākou i ka helu ʻana:
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 kekona, Raspberry - 1.7.
Ke hoʻololi nei i ka pauku tensor i json hiki ke heluhelu ʻia:
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
ʻOi aku
Альтернативный вариант, в котором больше работы перекладывается на сервер: он сам обводит найденные объекты и возвращает готовую картинку.
Такой вариант хорош там, где мы не хотим тянуть opencv на сервер.
Docker
ʻOhi mākou i ke kiʻi.
Hoʻopili ʻia ke code a kau ʻia ma luna
В качестве платформы возьмем тот же Debian Stretch, что и на Raspberry — не будем уходить от проверенного техстека.
Надо поставить flask, protobuf, requests, opencv_python, скачать Mobile SSD, код сервера с Гитхаба и запустить сервер.
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"]
Māmā
Публикация на Docker Hub
Ke hoʻonui nei nā papa inoa Docker i ka wikiwiki ma mua o nā mea ʻike kapua.
I ʻole e pilikia, e hele mākou me ka conservatively
- Kakau inoa
- E ʻeʻe:
komo docker - Придумаем содержательное имя:
docker tag opencv-detect tprlab/opencv-detect-ssd - Hoʻouka i ke kiʻi i ke kikowaena:
docker push tprlab/opencv-detect-ssd
Запускаем в облаке
ʻO ke koho o kahi e holo ai ka pahu he ākea loa.
Все большие игроки (Гугл, Микрософт, Амазон) предлагают микроинстанс бесплатно в первый год.
Ma hope o ka hoʻāʻo ʻana me Microsoft Azure a me Google Cloud, ua hoʻoholo wau i ka hope no ka mea ʻoi aku ka wikiwiki.
ʻAʻole wau i kākau i nā ʻōlelo aʻo ma aneʻi, no ka mea, kikoʻī loa kēia ʻāpana i ka mea hāʻawi i koho ʻia.
Ua hoʻāʻo au i nā koho lako lako like ʻole,
Низкие уровни (shared и выделенные) — 0.4 — 0.5 секунды.
Машины помощнее — 0.25 — 0.3.
ʻAe, ʻoiai i loko o ke kūlana ʻino loa, ʻekolu mau manawa lanakila, hiki iā ʻoe ke hoʻāʻo.
wikiō
Запускаем простой OpenCV видеостример на Raspberry, детектируя через Google Cloud.
Для эксперимента был использован видеофайл, когда-то снятый на случайном перекрестке.
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")
С детектором получается не более трех кадров в секунду, все идет очень медленно.
Inā lawe ʻoe i kahi mīkini ikaika i loko o GCloud, hiki iā ʻoe ke ʻike i nā kiʻi 4-5 i kēlā me kēia kekona, akā ʻaʻole ʻike ʻia ka ʻokoʻa i ka maka, lohi mau.
ʻAʻohe pili o ke ao a me nā kumukūʻai; holo ka mea ʻike ma luna o nā lako hana maʻamau a hana i kēlā wikiwiki.
Neural Computer Stick
ʻAʻole hiki iaʻu ke kūʻē a holo i ka benchmark ma NCS.
ʻOi aku ka lohi o ka mea ʻike ma mua o 0.1 kekona, i kēlā me kēia hihia 2-3 mau manawa ʻoi aku ka wikiwiki ma mua o ke ao ma kahi mīkini nāwaliwali, ʻo ia hoʻi 8-9 mau papa i kekona.
Ua wehewehe ʻia ka ʻokoʻa o nā hopena e ka holo ʻana o NCS Mobile SSD version 2018_01_28.
PS Eia kekahi, ua hōʻike ʻia nā hoʻokolohua e hōʻike ana kahi mīkini papapihi ikaika loa me kahi kaʻina I7 i nā hopena maikaʻi aʻe a ua hiki ke hoʻopaʻa i nā kiʻi 10 i kēlā me kēia kekona.
Kāpena
Эксперимент пошел дальше и я поставил детектор на пяти узлах в Google Kubernetes.
Сами по себе поды были слабые и каждый из них не мог обработать больше 2х кадров в секунду.
Akā inā e holo ʻoe i kahi pūʻulu me nā nodes N a e hoʻokaʻawale i nā kiʻi i nā kaula N, a laila me ka nui o nā nodes (5) hiki iā ʻoe ke hoʻokō i nā kiʻi 10 i makemake ʻia i kēlā me kēia kekona.
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
Eia ka mea i hanaia:
ʻOi aku ka wikiwiki ma mua o ka NCS, akā ʻoi aku ka ikaika ma mua o hoʻokahi kahawai.
Выигрыш, конечно, не линеен — выстреливают накладки на синхронизацию и глубокое копирование картинок opencv.
hopena
В целом, эксперимент позволяет сделать вывод, что, если постараться, можно выкрутиться с простым облаком.
Akā ʻo ka pākaukau ikaika a i ʻole nā mea hana kūloko e hiki ai iā ʻoe ke hoʻokō i nā hopena maikaʻi aʻe, me ka ʻole o nā hoʻopunipuni.
kūmole
Source: www.habr.com