Vídeo de Cloud Object Detector en Raspberry Pi

Prólogo

Agora circula por Internet un vídeo que mostra como o piloto automático de Tesla ve a estrada.

Levo moito tempo ansioso por emitir vídeo enriquecido cun detector, e en tempo real.

Vídeo de Cloud Object Detector en Raspberry Pi

O problema é que quero transmitir vídeo desde Raspberry, e o rendemento do detector de rede neuronal nel deixa moito que desexar.

Intel Neural Computer Stick

Considerei diferentes solucións.

В último artigo experimentou con Intel Neural Computer Stick. O hardware é potente, pero require o seu propio formato de rede.

Aínda que Intel ofrece conversores para marcos principais, hai unha serie de trampas.

Por exemplo, o formato da rede requirida pode ser incompatible e, se é compatible, é posible que algunhas capas non sexan compatibles no dispositivo e, se son compatibles, poden producirse erros durante o proceso de conversión, como resultado do cal obtemos cousas estrañas na saída.

En xeral, se queres algún tipo de rede neuronal arbitraria, é posible que non funcione con NCS. Por iso, decidín intentar resolver o problema utilizando as ferramentas máis estendidas e accesibles.

Nube

A alternativa obvia a unha solución de hardware local é ir á nube.

Opcións preparadas: os meus ollos están locos.

Todos os líderes:

... E ducias de menos coñecidos.

Elixir entre esta variedade non é nada sinxelo.

E decidín non escoller, senón envolver o bo vello esquema de traballo en OpenCV en Docker e executalo na nube.

A vantaxe deste enfoque é a flexibilidade e o control - pode cambiar a rede neuronal, aloxamento, servidor - en xeral, calquera capricho.

Servidor

Comecemos cun prototipo local.

Tradicionalmente uso Flask para REST API, OpenCV e rede MobileSSD.

Despois de instalar as versións actuais en Docker, descubrín que OpenCV 4.1.2 non funciona con Mobile SSD v1_coco_2018_01_28 e tiven que volver ao probado 11/06_2017.

Ao inicio do servizo, cargamos os nomes das clases e a rede:

def init():
    tf_labels.initLabels(dnn_conf.DNN_LABELS_PATH)
    return cv.dnn.readNetFromTensorflow(dnn_conf.DNN_PATH, dnn_conf.DNN_TXT_PATH)

Nun docker local (nun portátil non moi novo) leva 0.3 segundos, en Raspberry - 3.5.

Imos comezar o cálculo:

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 segundos, Raspberry - 1.7.

Convertendo o escape tensor en json lexible:

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

Ademais exportar esta operación a través de Flask(a entrada é unha imaxe, a saída son os resultados do detector en json).

Unha opción alternativa, na que se traslada máis traballo ao servidor: el mesmo rodea os obxectos atopados e devolve a imaxe rematada.

Esta opción é boa onde non queremos arrastrar opencv ao servidor.

Docker

Recollemos a imaxe.

O código está peiteado e publicado Github, Docker levarao directamente desde alí.

Como plataforma, adoptaremos o mesmo Debian Stretch que en Raspberry; non nos desviaremos da probada pila tecnolóxica.

Debe instalar flask, protobuf, requests, opencv_python, descargar Mobile SSD, código do servidor de Github e iniciar o servidor.

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

Simple cliente detector en base a solicitudes.

Publicación en Docker Hub

Os rexistros Docker multiplícanse a unha velocidade non inferior á dos detectores de nubes.

Para non molestar, imos pasar de forma conservadora DockerHub.

  1. Rexístrate
  2. Acceder:
    inicio de sesión docker
  3. Imos buscar un nome significativo:
    etiqueta docker opencv-detect tprlab/opencv-detect-ssd
  4. Cargue a imaxe ao servidor:
    docker push tprlab/opencv-detect-ssd

Lanzamos na nube

A elección de onde executar o recipiente tamén é bastante ampla.

Todos os grandes xogadores (Google, Microsoft, Amazon) ofrecen unha microinstancia de balde durante o primeiro ano.
Despois de experimentar con Microsoft Azure e Google Cloud, decidín este último porque despegou máis rápido.

Non escribín instrucións aquí, xa que esta parte é moi específica para o provedor seleccionado.

Probei diferentes opcións de hardware,
Niveis baixos (compartidos e dedicados) - 0.4 - 0.5 segundos.
Coches máis potentes - 0.25 - 0.3.
Ben, mesmo no peor dos casos, as ganancias son tres veces, podes probar.

Vídeo

Lanzamos un sinxelo emisión de vídeo OpenCV en Raspberry, que se detecta a través de Google Cloud.
Para o experimento, utilizouse un ficheiro de vídeo que unha vez foi filmado nunha intersección aleatoria.


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

Co detector non chegamos máis de tres fotogramas por segundo, todo vai moi lentamente.
Se levas unha máquina potente a GCloud, podes detectar 4-5 fotogramas por segundo, pero a diferenza é case invisible para o ollo, aínda é lenta.

Vídeo de Cloud Object Detector en Raspberry Pi

A nube e os custos de transporte non teñen nada que ver con iso; o detector funciona con hardware común e funciona a tal velocidade.

Stick de ordenador neural

Non puiden resistirme e executei a referencia en NCS.

A velocidade do detector foi lixeiramente máis lenta que 0.1 segundos, en calquera caso 2-3 veces máis rápida que a nube nunha máquina débil, é dicir, 8-9 cadros por segundo.

Vídeo de Cloud Object Detector en Raspberry Pi

A diferenza de resultados explícase polo feito de que NCS estaba a executar Mobile SSD versión 2018_01_28.

PD Ademais, os experimentos demostraron que unha máquina de escritorio bastante potente cun procesador I7 mostra resultados lixeiramente mellores e resultou posible espremer 10 cadros por segundo nela.

Clúster

O experimento foi máis alá e instalei o detector en cinco nodos de Google Kubernetes.
As vainas eran débiles e cada unha delas non podía procesar máis de 2 fotogramas por segundo.
Pero se executas un clúster con N nós e analizas cadros en N fíos, entón cun número suficiente de nós (5) podes acadar os 10 fotogramas por segundo desexados.

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

Aquí tes o que pasou:

Vídeo de Cloud Object Detector en Raspberry Pi

Un pouco menos rápido que con NCS, pero máis vigoroso que nun fluxo.

A ganancia, por suposto, non é lineal: hai superposicións para a sincronización e a copia profunda de imaxes opencv.

Conclusión

En xeral, o experimento permítenos concluír que se o intentas, podes saír cunha simple nube.

Pero un potente escritorio ou hardware local permítelle conseguir mellores resultados, e sen ningún truco.

referencias

Fonte: www.habr.com

Engadir un comentario