Видео од Cloud Object Detector на Raspberry Pi

Пролог

На интернет сега кружи видео кое покажува како автопилотот на Тесла го гледа патот.

Долго време ме чеша за да емитувам видео збогатено со детектор и тоа во реално време.

Видео од Cloud Object Detector на Raspberry Pi

Проблемот е што сакам да емитувам видео од Raspberry, а перформансите на детекторот за невронска мрежа на него оставаат многу да се посакуваат.

Интел невронски компјутерски стик

Размислував за различни решенија.

В последна статија експериментирал со Intel Neural Computer Stick. Хардверот е моќен, но бара сопствен мрежен формат.

И покрај тоа што Интел обезбедува конвертори за главните рамки, има голем број стапици.

На пример, форматот на потребната мрежа може да биде некомпатибилен, а ако е компатибилен, тогаш некои слоеви може да не се поддржани на уредот, а ако се поддржани, тогаш може да се појават грешки при процесот на конверзија, како резултат на што добиваме некои чудни работи на излезот.

Во принцип, ако сакате некаква произволна невронска мрежа, тогаш таа може да не работи со NCS. Затоа, решив да се обидам да го решам проблемот користејќи ги најраспространетите и достапни алатки.

Облак

Очигледната алтернатива на локалното хардверско решение е да се оди на облакот.

Готови опции - моите очи дивеат.

Сите лидери:

... И десетици помалку познати.

Изборот меѓу оваа сорта не е воопшто лесен.

И решив да не изберам, туку да ја завиткам старата добра работна шема на OpenCV во Docker и да ја стартувам во облакот.

Предноста на овој пристап е флексибилност и контрола - можете да ја промените невронската мрежа, хостинг, серверот - воопшто, секој каприц.

Сервер

Да почнеме со локален прототип.

Традиционално користам Flask за REST API, OpenCV и MobileSSD мрежа.

Откако ги инсталирав тековните верзии на Docker, открив дека OpenCV 4.1.2 не работи со Mobile SSD v1_coco_2018_01_28 и морав да се вратам на докажаниот 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)

На локален докер (на не многу млад лаптоп) потребни се 0.3 секунди, на Raspberry - 3.5.

Да ја започнеме пресметката:

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

Докер - 0.2 сек., Малина - 1.7.

Претворање на издувните гасови на тензорот во читлив 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

Понатаму извезете ја оваа операција преку Flask(влезот е слика, излезот се резултатите од детекторот во json).

Алтернативна опција, во која повеќе работа се префрла на серверот: тој самиот ги заокружува пронајдените предмети и ја враќа завршената слика.

Оваа опција е добра каде што не сакаме да го влечеме opencv на серверот.

Докер

Ја собираме сликата.

Кодот е исчешлан и објавен на Github, Docker ќе го земе директно од таму.

Како платформа, ќе го земеме истиот Debian Stretch како кај Raspberry - нема да отстапиме од докажаниот технолошки оџак.

Треба да инсталирате flask, protobuf, барања, opencv_python, да преземете Mobile SSD, код на серверот од Github и да го стартувате серверот.

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

Едноставно детектор клиент врз основа на барања.

Објавување на Docker Hub

Докерските регистри се множат со брзина не помала од детекторите на облак.

За да не се замараме, конзервативно ќе поминеме DockerHub.

  1. Регистрирајте се
  2. Логирај Се:
    најава за докер
  3. Ајде да смислиме значајно име:
    докер ознака opencv-detect tprlab/opencv-detect-ssd
  4. Поставете ја сликата на серверот:
    docker push tprlab/opencv-detect-ssd

Лансираме во облакот

Изборот каде да се пушти контејнерот е исто така доста широк.

Сите големи играчи (Гугл, Мајкрософт, Амазон) нудат микро-инстанца бесплатно првата година.
Откако експериментирав со Microsoft Azure и Google Cloud, се решив на второто затоа што полета побрзо.

Не напишав упатства овде, бидејќи овој дел е многу специфичен за избраниот провајдер.

Пробав различни хардверски опции,
Ниски нивоа (споделени и посветени) - 0.4 - 0.5 секунди.
Помоќни автомобили - 0.25 - 0.3.
Па, дури и во најлошото сценарио, добивките се трикратни, можете да се обидете.

Видео

Лансираме едноставен 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")

Со детекторот добиваме не повеќе од три фрејмови во секунда, сè оди многу бавно.
Ако земете моќна машина во GCloud, можете да откриете 4-5 фрејмови во секунда, но разликата е речиси невидлива за окото, сепак е бавна.

Видео од Cloud Object Detector на Raspberry Pi

Облакот и транспортните трошоци немаат никаква врска со тоа, детекторот работи на обичен хардвер и работи со таква брзина.

Неврален компјутерски стик

Не можев да одолеам и го извршив реперот на NCS.

Брзината на детекторот беше малку помала од 0.1 секунда, во секој случај 2-3 пати поголема од облакот на слаба машина, односно 8-9 фрејмови во секунда.

Видео од Cloud Object Detector на Raspberry Pi

Разликата во резултатите се објаснува со фактот дека NCS ја користел верзијата за мобилен SSD 2018_01_28.

П.С. Покрај тоа, експериментите покажаа дека прилично моќна десктоп машина со I7 процесор покажува малку подобри резултати и се покажа дека е можно да се притисне 10 фрејмови во секунда на неа.

Грозд

Експериментот отиде понатаму и го инсталирав детекторот на пет јазли во Google Kubernetes.
Самите мешунки беа слаби и секој од нив не можеше да обработи повеќе од 2 фрејма во секунда.
Но, ако извршите кластер со N јазли и анализирате рамки во N нишки, тогаш со доволен број јазли (5) можете да ги постигнете саканите 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

Еве што се случи:

Видео од Cloud Object Detector на Raspberry Pi

Малку помалку брзо отколку со NCS, но поенергично отколку во еден тек.

Добивката, се разбира, не е линеарна - има преклопувања за синхронизација и длабоко копирање на слики од opencv.

Заклучок

Генерално, експериментот ни овозможува да заклучиме дека ако се обидете, можете да се извлечете со едноставен облак.

Но, моќниот десктоп или локален хардвер ви овозможува да постигнете подобри резултати и без никакви трикови.

референци

Извор: www.habr.com

Додадете коментар