Kiʻiʻoniʻoni o Cloud Object Detector ma Raspberry Pi

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.

Kiʻiʻoniʻoni o Cloud Object Detector ma Raspberry Pi

ʻ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.

В ʻatikala hope loa hoʻokolohua me Intel Neural Computer Stick. He ikaika ka lakohana, akā pono kona ʻano pūnaewele ponoʻī.

ʻ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 e hoʻokuʻu aku i kēia hana ma o Flask(He kiʻi ka hoʻokomo, ʻo ka hopena ka hopena o ka mea ʻike ma json).

Альтернативный вариант, в котором больше работы перекладывается на сервер: он сам обводит найденные объекты и возвращает готовую картинку.

Такой вариант хорош там, где мы не хотим тянуть opencv на сервер.

Docker

ʻOhi mākou i ke kiʻi.

Hoʻopili ʻia ke code a kau ʻia ma luna Github, e lawe pololei ʻo docker mai laila mai.

В качестве платформы возьмем тот же 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ā клиент для детектора ma muli o nā noi.

Публикация на 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 DockerHub.

  1. Kakau inoa
  2. E ʻeʻe:
    komo docker
  3. Придумаем содержательное имя:
    docker tag opencv-detect tprlab/opencv-detect-ssd
  4. 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.

Kiʻiʻoniʻoni o Cloud Object Detector ma Raspberry Pi

ʻ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.

Kiʻiʻoniʻoni o Cloud Object Detector ma Raspberry Pi

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:

Kiʻiʻoniʻoni o Cloud Object Detector ma Raspberry Pi

ʻ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

Pākuʻi i ka manaʻo hoʻopuka