Video Detektor Objek Cloud di Raspberry Pi

Prolog

Sebuah video kini beredar di Internet yang menunjukkan bagaimana autopilot Tesla melihat jalan.

Saya sudah lama ingin menyiarkan video yang diperkaya dengan detektor, dan secara real time.

Video Detektor Objek Cloud di Raspberry Pi

Masalahnya adalah saya ingin menyiarkan video dari Raspberry, dan kinerja detektor jaringan saraf di dalamnya masih jauh dari yang diinginkan.

Tongkat Komputer Neural Intel

Saya mempertimbangkan solusi yang berbeda.

Π’ artikel terakhir bereksperimen dengan Intel Neural Computer Stick. Perangkat kerasnya kuat, tetapi memerlukan format jaringannya sendiri.

Meskipun Intel menyediakan konverter untuk kerangka kerja utama, ada sejumlah kendala.

Misalnya, format jaringan yang diperlukan mungkin tidak kompatibel, dan jika kompatibel, beberapa lapisan mungkin tidak didukung pada perangkat, dan jika didukung, kesalahan mungkin terjadi selama proses konversi, akibatnya kami mendapatkan beberapa hal aneh pada output.

Secara umum, jika Anda menginginkan semacam jaringan saraf arbitrer, jaringan tersebut mungkin tidak berfungsi dengan NCS. Oleh karena itu, saya memutuskan untuk mencoba menyelesaikan masalah ini dengan menggunakan alat yang paling luas dan mudah diakses.

Cloud

Alternatif yang jelas untuk solusi perangkat keras lokal adalah beralih ke cloud.

Opsi yang sudah jadi - mata saya menjadi liar.

Semua pemimpin:

... Dan lusinan yang kurang dikenal.

Memilih di antara varietas ini tidaklah mudah.

Dan saya memutuskan untuk tidak memilih, tetapi untuk menggabungkan skema kerja lama yang bagus di OpenCV di Docker dan menjalankannya di cloud.

Keuntungan dari pendekatan ini adalah fleksibilitas dan kontrol - Anda dapat mengubah jaringan saraf, hosting, server - secara umum, apa pun keinginannya.

Server

Mari kita mulai dengan prototipe lokal.

Secara tradisional saya menggunakan Flask untuk REST API, OpenCV dan jaringan MobileSSD.

Setelah menginstal versi saat ini di Docker, saya menemukan bahwa OpenCV 4.1.2 tidak berfungsi dengan Mobile SSD v1_coco_2018_01_28, dan saya harus memutar kembali ke 11/06_2017 yang telah terbukti.

Di awal layanan, kami memuat nama kelas dan jaringan:

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

Pada buruh pelabuhan lokal (pada laptop yang tidak terlalu muda) dibutuhkan 0.3 detik, pada Raspberry - 3.5.

Mari kita mulai perhitungannya:

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

Mengubah knalpot tensor menjadi json yang dapat dibaca:

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

Selanjutnya ekspor operasi ini melalui Flask(inputnya berupa gambar, outputnya adalah hasil detektor di json).

Opsi alternatif, di mana lebih banyak pekerjaan dialihkan ke server: server itu sendiri mengelilingi objek yang ditemukan dan mengembalikan gambar yang sudah jadi.

Opsi ini bagus jika kita tidak ingin menyeret opencv ke server.

Buruh pelabuhan

Kami mengumpulkan gambarnya.

Kode disisir dan dipasang Github, buruh pelabuhan akan mengambilnya langsung dari sana.

Sebagai sebuah platform, kami akan menggunakan Debian Stretch yang sama seperti pada Raspberry - kami tidak akan menyimpang dari tumpukan teknologi yang telah terbukti.

Anda perlu menginstal flask, protobuf, request, opencv_python, mengunduh Mobile SSD, kode server dari Github dan memulai 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"]

Sederhana klien detektor berdasarkan permintaan.

Menerbitkan ke Docker Hub

Registri Docker berkembang biak dengan kecepatan yang tidak kalah dengan detektor cloud.

Agar tidak repot, kita akan melaluinya secara konservatif DockerHub.

  1. Daftar
  2. Gabung:
    login buruh pelabuhan
  3. Mari kita temukan nama yang bermakna:
    tag buruh pelabuhan opencv-deteksi tprlab/opencv-deteksi-ssd
  4. Unggah gambar ke server:
    buruh pelabuhan mendorong tprlab/opencv-detect-ssd

Kami meluncurkannya di cloud

Pilihan tempat menjalankan container juga cukup luas.

Semua pemain besar (Google, Microsoft, Amazon) menawarkan contoh mikro gratis untuk tahun pertama.
Setelah bereksperimen dengan Microsoft Azure dan Google Cloud, saya memilih yang terakhir karena lebih cepat.

Saya tidak menulis instruksi di sini, karena bagian ini sangat spesifik untuk penyedia yang dipilih.

Saya mencoba opsi perangkat keras yang berbeda,
Level rendah (bersama dan khusus) - 0.4 - 0.5 detik.
Mobil yang lebih bertenaga - 0.25 - 0.3.
Nah, dalam skenario terburuk sekalipun, kemenangannya tiga kali lipat, Anda bisa mencobanya.

Video

Kami meluncurkan streamer video OpenCV sederhana di Raspberry, mendeteksi melalui Google Cloud.
Untuk percobaan, file video digunakan yang pernah difilmkan di persimpangan acak.


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

Dengan detektor kami mendapatkan tidak lebih dari tiga frame per detik, semuanya berjalan sangat lambat.
Jika Anda menggunakan mesin yang kuat ke GCloud, Anda dapat mendeteksi 4-5 frame per detik, namun perbedaannya hampir tidak terlihat oleh mata, masih lambat.

Video Detektor Objek Cloud di Raspberry Pi

Cloud dan biaya transportasi tidak ada hubungannya dengan hal ini; detektor berjalan pada perangkat keras biasa dan bekerja dengan kecepatan seperti itu.

Tongkat Komputer Neural

Saya tidak bisa menolak dan menjalankan benchmark di NCS.

Kecepatan detektor sedikit lebih lambat dari 0.1 detik, setidaknya 2-3 kali lebih cepat dari cloud pada mesin yang lemah, yaitu 8-9 frame per detik.

Video Detektor Objek Cloud di Raspberry Pi

Perbedaan hasil ini dijelaskan oleh fakta bahwa NCS menjalankan Mobile SSD versi 2018_01_28.

PS Selain itu, percobaan telah menunjukkan bahwa mesin desktop yang cukup kuat dengan prosesor i7 menunjukkan hasil yang sedikit lebih baik dan ternyata dapat menghasilkan 10 frame per detik di dalamnya.

Gugus

Eksperimen berjalan lebih jauh dan saya memasang detektor pada lima node di Google Kubernetes.
Podnya sendiri lemah dan masing-masing pod tidak dapat memproses lebih dari 2 frame per detik.
Tetapi jika Anda menjalankan cluster dengan N node dan mengurai frame dalam N thread, maka dengan jumlah node yang cukup (5) Anda dapat mencapai 10 frame per detik yang diinginkan.

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

Inilah yang terjadi:

Video Detektor Objek Cloud di Raspberry Pi

Sedikit kurang cepat dibandingkan dengan NCS, tetapi lebih bertenaga dibandingkan dalam satu aliran.

Keuntungannya, tentu saja, tidak linier - ada overlay untuk sinkronisasi dan penyalinan gambar opencv secara mendalam.

Kesimpulan

Secara keseluruhan, eksperimen ini memungkinkan kami menyimpulkan bahwa jika Anda mencobanya, Anda dapat lolos dengan cloud sederhana.

Namun desktop atau perangkat keras lokal yang kuat memungkinkan Anda mencapai hasil yang lebih baik, dan tanpa trik apa pun.

referensi

Sumber: www.habr.com

Tambah komentar