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

пролог

Сега в интернет се разпространява видео, което показва как автопилотът на Tesla вижда пътя.

Отдавна ме сърби да излъчвам обогатено с детектор видео и то в реално време.

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

Проблемът е, че искам да излъчвам видео от Raspberry и работата на детектора на невронната мрежа върху него оставя много да се желае.

Intel Neural Computer Stick

Обмислях различни решения.

В последната статия експериментира с Intel Neural Computer Stick. Хардуерът е мощен, но изисква собствен мрежов формат.

Въпреки че Intel предоставя конвертори за основни рамки, има редица клопки.

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

Като цяло, ако искате някаква произволна невронна мрежа, тогава тя може да не работи с 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()

Docker - 0.2 сек, Raspberry - 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, докер ще го вземе директно от там.

Като платформа ще вземем същия Debian Stretch като Raspberry - няма да се отклоняваме от доказания технологичен стек.

Трябва да инсталирате flask, protobuf, requests, 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

Регистрите на Docker се размножават със скорост не по-малка от детекторите за облак.

За да не се мъчим, ще минем консервативно DockerHub.

  1. Регистрирам
  2. Влизам:
    вход за докер
  3. Нека измислим смислено име:
    докер етикет opencv-detect tprlab/opencv-detect-ssd
  4. Качете изображението на сървъра:
    докер натискане на tprlab/opencv-detect-ssd

Стартираме в облака

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

Всички големи играчи (Google, Microsoft, Amazon) предлагат микроинстанция безплатно за първата година.
След като експериментирах с 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

Разликата в резултатите се обяснява с факта, че Mobile SSD версия 2018_01_28 беше пусната на NCS.

PS В допълнение, експериментите показаха, че доста мощна настолна машина с процесор 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

Добавяне на нов коментар