Video Cloud Object Detector trên Raspberry Pi

Mở đầu

Một đoạn video hiện đang lan truyền trên Internet cho thấy hệ thống lái tự động của Tesla nhìn thấy đường như thế nào.

Tôi đã mong muốn phát sóng video được làm giàu bằng máy dò trong thời gian thực trong một thời gian dài.

Video Cloud Object Detector trên Raspberry Pi

Vấn đề là tôi muốn phát video từ Raspberry và hiệu suất của bộ dò mạng thần kinh trên đó còn nhiều điều chưa được mong đợi.

Thanh máy tính thần kinh Intel

Tôi đã xem xét các giải pháp khác nhau.

В bài viết cuối cùng đã thử nghiệm với Intel Neural Computer Stick. Phần cứng mạnh mẽ nhưng yêu cầu định dạng mạng riêng.

Mặc dù Intel cung cấp bộ chuyển đổi cho các khung chính nhưng vẫn có một số cạm bẫy.

Ví dụ: định dạng của mạng được yêu cầu có thể không tương thích và nếu nó tương thích thì một số lớp có thể không được hỗ trợ trên thiết bị và nếu chúng được hỗ trợ thì có thể xảy ra lỗi trong quá trình chuyển đổi, do đó chúng tôi nhận được một số điều kỳ lạ ở đầu ra.

Nói chung, nếu bạn muốn một loại mạng thần kinh tùy ý nào đó thì nó có thể không hoạt động với NCS. Vì vậy, tôi quyết định cố gắng giải quyết vấn đề bằng các công cụ phổ biến và dễ tiếp cận nhất.

Đám mây

Giải pháp thay thế rõ ràng cho giải pháp phần cứng cục bộ là truy cập vào đám mây.

Các lựa chọn làm sẵn - mắt tôi hoang mang.

Tất cả các nhà lãnh đạo:

... Và hàng chục cái ít được biết đến hơn.

Việc lựa chọn giữa sự đa dạng này không hề dễ dàng chút nào.

Và tôi quyết định không chọn mà kết hợp sơ đồ hoạt động cũ tốt trên OpenCV trong Docker và chạy nó trên đám mây.

Ưu điểm của phương pháp này là tính linh hoạt và khả năng kiểm soát - bạn có thể thay đổi mạng lưới thần kinh, dịch vụ lưu trữ, máy chủ - nói chung là bất kỳ ý tưởng nào.

Máy chủ

Hãy bắt đầu với một nguyên mẫu địa phương.

Theo truyền thống, tôi sử dụng Flask cho mạng REST API, OpenCV và MobileSSD.

Sau khi cài đặt các phiên bản hiện tại trên Docker, tôi phát hiện ra rằng OpenCV 4.1.2 không hoạt động với Mobile SSD v1_coco_2018_01_28 và tôi phải quay lại phiên bản 11/06/2017 đã được chứng minh.

Khi bắt đầu dịch vụ, chúng tôi tải tên lớp và mạng:

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

Trên một docker cục bộ (trên một máy tính xách tay không quá trẻ), phải mất 0.3 giây, trên Raspberry - 3.5.

Hãy bắt đầu tính toán:

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 giây, Raspberry - 1.7.

Biến ống xả tensor thành json có thể đọc được:

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

Hơn nữa xuất hoạt động này qua Flask(đầu vào là hình ảnh, đầu ra là kết quả của máy dò trong json).

Một tùy chọn thay thế, trong đó nhiều công việc hơn được chuyển đến máy chủ: nó tự khoanh tròn các đối tượng tìm thấy và trả về hình ảnh hoàn thiện.

Tùy chọn này phù hợp khi chúng tôi không muốn kéo opencv vào máy chủ.

docker

Chúng tôi thu thập hình ảnh.

Mã được chải kỹ và đăng trên Github, docker sẽ lấy nó trực tiếp từ đó.

Với tư cách là một nền tảng, chúng tôi sẽ sử dụng Debian Stretch giống như trên Raspberry - chúng tôi sẽ không đi chệch khỏi nền tảng công nghệ đã được chứng minh.

Bạn cần cài đặt jar, protobuf, request, opencv_python, tải xuống SSD di động, mã máy chủ từ Github và khởi động máy chủ.

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

Đơn giản máy dò khách hàng dựa trên yêu cầu.

Xuất bản lên Docker Hub

Các đăng ký Docker đang nhân lên với tốc độ không kém gì các máy dò đám mây.

Để không bận tâm, chúng tôi sẽ thực hiện một cách thận trọng DockerHub.

  1. Đăng ký
  2. Đăng nhập:
    đăng nhập docker
  3. Hãy nghĩ ra một cái tên có ý nghĩa:
    thẻ docker opencv-phát hiện tprlab/opencv-Detect-ssd
  4. Tải hình ảnh lên máy chủ:
    docker đẩy tprlab/opencv-phát hiện-ssd

Chúng tôi khởi chạy trên đám mây

Sự lựa chọn nơi chạy container cũng khá rộng.

Tất cả những ông lớn (Google, Microsoft, Amazon) đều cung cấp phiên bản vi mô miễn phí trong năm đầu tiên.
Sau khi thử nghiệm với Microsoft Azure và Google Cloud, tôi quyết định chọn cái thứ hai vì nó phát triển nhanh hơn.

Tôi không viết hướng dẫn ở đây vì phần này rất cụ thể đối với nhà cung cấp đã chọn.

Tôi đã thử các tùy chọn phần cứng khác nhau,
Mức độ thấp (chia sẻ và dành riêng) - 0.4 - 0.5 giây.
Xe mạnh hơn - 0.25 - 0.3.
Chà, ngay cả trong trường hợp xấu nhất, số tiền thắng sẽ gấp ba lần, bạn có thể thử.

Video

Chúng tôi khởi chạy trình phát video OpenCV đơn giản trên Raspberry, phát hiện thông qua Google Cloud.
Đối với thử nghiệm, một tệp video đã được sử dụng đã từng được quay tại một giao lộ ngẫu nhiên.


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

Với máy dò, chúng tôi nhận được không quá ba khung hình mỗi giây, mọi thứ diễn ra rất chậm.
Nếu đưa máy mạnh vào GCloud thì có thể dò được 4-5 khung hình/giây, nhưng mắt thường gần như không nhìn thấy được sự khác biệt, vẫn còn chậm.

Video Cloud Object Detector trên Raspberry Pi

Đám mây và chi phí vận chuyển không liên quan gì đến nó; máy dò chạy trên phần cứng thông thường và hoạt động ở tốc độ như vậy.

Gậy máy tính thần kinh

Tôi không thể cưỡng lại và chạy benchmark trên NCS.

Tốc độ của máy dò hơi chậm hơn 0.1 giây, trong mọi trường hợp nhanh hơn 2-3 lần so với đám mây trên máy yếu, tức là 8-9 khung hình mỗi giây.

Video Cloud Object Detector trên Raspberry Pi

Sự khác biệt về kết quả được giải thích là do NCS đang chạy Mobile SSD phiên bản 2018_01_28.

PS Ngoài ra, các thử nghiệm đã chỉ ra rằng một máy tính để bàn khá mạnh với bộ xử lý I7 cho kết quả tốt hơn một chút và hóa ra có thể ép 10 khung hình mỗi giây trên đó.

Cluster

Thử nghiệm đã tiến xa hơn và tôi đã cài đặt trình phát hiện trên năm nút trong Google Kubernetes.
Bản thân các nhóm này rất yếu và mỗi nhóm không thể xử lý nhiều hơn 2 khung hình mỗi giây.
Nhưng nếu bạn chạy một cụm có N nút và phân tích các khung trong N luồng, thì với số lượng nút đủ (5), bạn có thể đạt được 10 khung hình mỗi giây như mong muốn.

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

Đây là những gì đã xảy ra:

Video Cloud Object Detector trên Raspberry Pi

Nhanh hơn một chút so với NCS, nhưng mạnh mẽ hơn so với trong một luồng.

Tất nhiên, mức tăng không phải là tuyến tính - có các lớp phủ để đồng bộ hóa và sao chép sâu các hình ảnh opencv.

Kết luận

Nhìn chung, thử nghiệm cho phép chúng tôi kết luận rằng nếu cố gắng, bạn có thể thoát khỏi một đám mây đơn giản.

Nhưng một máy tính để bàn hoặc phần cứng cục bộ mạnh mẽ cho phép bạn đạt được kết quả tốt hơn mà không cần bất kỳ thủ thuật nào.

tài liệu tham khảo

Nguồn: www.habr.com

Thêm một lời nhận xét