Video detektora objekata u oblaku na Raspberry Pi

Prolog

Internetom sada kruži video koji pokazuje kako Teslin autopilot vidi cestu.

Već dugo me svrbi da emitujem video obogaćen detektorom, i to u realnom vremenu.

Video detektora objekata u oblaku na Raspberry Pi

Problem je što želim da emitujem video sa Raspberryja, a performanse detektora neuronske mreže na njemu ostavljaju mnogo da se požele.

Intel Neural Computer Stick

Razmišljao sam o različitim rješenjima.

В poslednji članak eksperimentisao sa Intel Neural Computer Stick-om. Hardver je moćan, ali zahtijeva vlastiti mrežni format.

Iako Intel nudi konvertore za glavne okvire, postoji niz zamki.

Na primjer, format tražene mreže može biti nekompatibilan, a ako je kompatibilan, neki slojevi možda neće biti podržani na uređaju, a ako su podržani, može doći do grešaka tokom procesa konverzije, zbog čega dobijamo neke čudne stvari na izlazu.

Općenito, ako želite neku vrstu proizvoljne neuronske mreže, onda možda neće raditi s NCS-om. Stoga sam odlučio pokušati riješiti problem koristeći najraširenije i najpristupačnije alate.

Cloud

Očigledna alternativa lokalnom hardverskom rješenju je odlazak u oblak.

Gotove opcije - oči mi divljaju.

Svi lideri:

... I desetine manje poznatih.

Odabir između ove sorte nije nimalo lak.

I odlučio sam da ne biram, već da umotam staru dobru radnu šemu na OpenCV u Docker i pokrenem je u oblaku.

Prednost ovog pristupa je fleksibilnost i kontrola - možete promijeniti neuronsku mrežu, hosting, server - općenito, bilo koji hir.

Server

Počnimo s lokalnim prototipom.

Tradicionalno koristim Flask za REST API, OpenCV i MobileSSD mrežu.

Nakon što sam instalirao trenutne verzije na Docker-u, otkrio sam da OpenCV 4.1.2 ne radi sa mobilnim SSD-om v1_coco_2018_01_28 i morao sam se vratiti na provjereni 11/06_2017.

Na početku usluge učitavamo nazive klasa i mrežu:

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

Na lokalnom dockeru (na ne baš mladom laptopu) potrebno je 0.3 sekunde, na Raspberryju - 3.5.

Počnimo računanje:

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

Pretvaranje tenzorskog ispuha u čitljiv 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

Nadalje izvezite ovu operaciju preko Flask-a(ulaz je slika, izlaz su rezultati detektora u json-u).

Alternativna opcija, u kojoj se više posla prebacuje na server: on sam kruži pronađene objekte i vraća gotovu sliku.

Ova opcija je dobra kada ne želimo da prevučemo opencv na server.

Docker

Sakupljamo sliku.

Šifra je pročešljana i objavljena Github, docker će ga preuzeti direktno odatle.

Kao platformu, uzet ćemo isti Debian Stretch kao i na Raspberryju - nećemo odstupiti od dokazanog tehnološkog steka.

Morate instalirati flask, protobuf, requests, opencv_python, preuzeti Mobile SSD, serverski kod sa Githuba i pokrenuti server.

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

Jednostavno detektorski klijent na osnovu zahtjeva.

Objavljivanje u Docker Hub

Docker registri se množe brzinom ne manjom od detektora oblaka.

Da se ne zamaramo, proći ćemo konzervativno DockerHub.

  1. Registrirajte se
  2. Ulogovati se:
    docker prijava
  3. Hajde da smislimo smisleno ime:
    docker oznaka opencv-detect tprlab/opencv-detect-ssd
  4. Otpremite sliku na server:
    docker push tprlab/opencv-detect-ssd

Pokrećemo u oblaku

Izbor mjesta za pokretanje kontejnera je također prilično širok.

Svi veliki igrači (Google, Microsoft, Amazon) nude mikro-instancu besplatno za prvu godinu.
Nakon eksperimentiranja s Microsoft Azureom i Google Cloudom, odlučio sam se na ovo drugo jer je brže napredovalo.

Ovdje nisam pisao upute, jer je ovaj dio vrlo specifičan za odabranog provajdera.

Probao sam različite hardverske opcije,
Niski nivoi (dijeljeni i namjenski) - 0.4 - 0.5 sekundi.
Snažniji automobili - 0.25 - 0.3.
Pa, čak i u najgorem slučaju, dobici su tri puta, možete pokušati.

Video

Pokrećemo jednostavan OpenCV video streamer na Raspberry-u, koji detektuje putem Google Cloud-a.
Za eksperiment je korištena video datoteka koja je jednom snimljena na slučajnoj raskrsnici.


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

Sa detektorom ne dobijamo više od tri kadra u sekundi, sve ide jako sporo.
Ako uzmete moćnu mašinu u GCloud, možete detektovati 4-5 sličica u sekundi, ali razlika je skoro nevidljiva oku, i dalje je spora.

Video detektora objekata u oblaku na Raspberry Pi

Oblak i troškovi transporta nemaju nikakve veze s tim; detektor radi na običnom hardveru i radi takvom brzinom.

Neural Computer Stick

Nisam mogao odoljeti i pokrenuo sam benchmark na NCS-u.

Brzina detektora bila je nešto manja od 0.1 sekunde, u svakom slučaju 2-3 puta veća od oblaka na slaboj mašini, odnosno 8-9 sličica u sekundi.

Video detektora objekata u oblaku na Raspberry Pi

Razlika u rezultatima se objašnjava činjenicom da je NCS koristio Mobile SSD verziju 2018_01_28.

PS Osim toga, eksperimenti su pokazali da prilično moćna desktop mašina sa I7 procesorom pokazuje nešto bolje rezultate i pokazalo se da je na njoj moguće stisnuti 10 sličica u sekundi.

Klaster

Eksperiment je otišao dalje i instalirao sam detektor na pet čvorova u Google Kubernetesu.
Same mahune su bile slabe i svaka od njih nije mogla obraditi više od 2 kadra u sekundi.
Ali ako pokrenete klaster sa N čvorova i raščlanite okvire u N niti, onda sa dovoljnim brojem čvorova (5) možete postići željenih 10 sličica u sekundi.

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

Evo šta se dogodilo:

Video detektora objekata u oblaku na Raspberry Pi

Malo manje brzo nego kod NCS-a, ali snažnije nego u jednom streamu.

Dobitak, naravno, nije linearan - postoje prekrivači za sinhronizaciju i dubinsko kopiranje opencv slika.

zaključak

Sve u svemu, eksperiment nam omogućava da zaključimo da ako pokušate, možete se izvući jednostavnim oblakom.

Ali moćan desktop ili lokalni hardver vam omogućava da postignete bolje rezultate, i to bez ikakvih trikova.

reference

izvor: www.habr.com

Dodajte komentar