ืกืจื˜ื•ืŸ ืฉืœ ื’ืœืื™ ืื•ื‘ื™ื™ืงื˜ื™ื ื‘ืขื ืŸ ื‘-Raspberry Pi

ืคืจื•ืœื•ื’

ืกืจื˜ื•ืŸ ืžืกืชื•ื‘ื‘ ื›ืขืช ื‘ืื™ื ื˜ืจื ื˜ ื”ืžืจืื” ื›ื™ืฆื“ ื”ื˜ื™ื™ืก ื”ืื•ื˜ื•ืžื˜ื™ ืฉืœ ื˜ืกืœื” ืจื•ืื” ืืช ื”ื›ื‘ื™ืฉ.

ื›ื‘ืจ ื”ืจื‘ื” ื–ืžืŸ ืฉืื ื™ ืžื’ืจื“ ืœืฉื“ืจ ื•ื™ื“ืื• ืžื•ืขืฉืจ ื‘ื’ืœืื™, ื•ื‘ื–ืžืŸ ืืžืช.

ืกืจื˜ื•ืŸ ืฉืœ ื’ืœืื™ ืื•ื‘ื™ื™ืงื˜ื™ื ื‘ืขื ืŸ ื‘-Raspberry Pi

ื”ื‘ืขื™ื” ื”ื™ื ืฉืื ื™ ืจื•ืฆื” ืœืฉื“ืจ ื•ื™ื“ืื• ืž-Raspberry, ื•ื”ื‘ื™ืฆื•ืขื™ื ืฉืœ ื’ืœืื™ ื”ืจืฉืช ื”ืขืฆื‘ื™ืช ืขืœื™ื• ืžืฉืื™ืจื™ื ื”ืจื‘ื” ืžื” ืœืจืฆื•ืช.

Intel Neural Computer Stick

ืฉืงืœืชื™ ืคืชืจื•ื ื•ืช ืฉื•ื ื™ื.

ะ’ ื”ืžืืžืจ ื”ืื—ืจื•ืŸ ื”ืชื ืกื” ืขื Intel Neural Computer Stick. ื”ื—ื•ืžืจื” ื—ื–ืงื”, ืืš ื“ื•ืจืฉืช ืคื•ืจืžื˜ ืจืฉืช ืžืฉืœื”.

ืœืžืจื•ืช ืฉืื™ื ื˜ืœ ืžืกืคืงืช ืžืžื™ืจื™ื ืœืžืกื’ืจื•ืช ืขื™ืงืจื™ื•ืช, ื™ืฉื ืŸ ืžืกืคืจ ืžืœื›ื•ื“ื•ืช.

ืœื“ื•ื’ืžื”, ื”ืคื•ืจืžื˜ ืฉืœ ื”ืจืฉืช ื”ื ื“ืจืฉืช ืขืฉื•ื™ ืœื”ื™ื•ืช ืœื ืชื•ืื, ื•ืื ื”ื•ื ืชื•ืื, ื™ื™ืชื›ืŸ ืฉื—ืœืง ืžื”ืฉื›ื‘ื•ืช ืœื ื™ื”ื™ื• ื ืชืžื›ื•ืช ื‘ืžื›ืฉื™ืจ, ื•ืื ื”ืŸ ื ืชืžื›ื•ืช, ืขืœื•ืœื•ืช ืœื”ืชืจื—ืฉ ืฉื’ื™ืื•ืช ื‘ืžื”ืœืš ืชื”ืœื™ืš ื”ื”ืžืจื”, ื•ื›ืชื•ืฆืื” ืžื›ืš ืื ื—ื ื• ืžืงื‘ืœื™ื ื›ืžื” ื“ื‘ืจื™ื ืžื•ื–ืจื™ื ื‘ืคืœื˜.

ื‘ืื•ืคืŸ ื›ืœืœื™, ืื ืืชื” ืจื•ืฆื” ืื™ื–ื•ืฉื”ื™ ืจืฉืช ืขืฆื‘ื™ืช ืฉืจื™ืจื•ืชื™ืช, ื™ื™ืชื›ืŸ ืฉื”ื™ื ืœื ืชืขื‘ื•ื“ ืขื 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()

ื“ื•ืงืจ - 0.2 ืฉื ื™ื•ืช, ืคื˜ืœ - 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, docker ื™ื™ืงื— ืื•ืชื• ื™ืฉื™ืจื•ืช ืžืฉื.

ื›ืคืœื˜ืคื•ืจืžื”, ื ื™ืงื— ืืช ืื•ืชื” 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. ื‘ื•ืื• ื ืžืฆื™ื ืฉื ื‘ืขืœ ืžืฉืžืขื•ืช:
    docker tag opencv-detect tprlab/opencv-detect-ssd
  4. ื”ืขืœื” ืืช ื”ืชืžื•ื ื” ืœืฉืจืช:
    docker push tprlab/opencv-detect-ssd

ืื ื—ื ื• ืžืฉื™ืงื™ื ื‘ืขื ืŸ

ื’ื ื”ื‘ื—ื™ืจื” ื”ื™ื›ืŸ ืœื”ืคืขื™ืœ ืืช ื”ืžื›ื•ืœื” ื”ื™ื ืจื—ื‘ื” ืœืžื“ื™.

ื›ืœ ื”ืฉื—ืงื ื™ื ื”ื’ื“ื•ืœื™ื (ื’ื•ื’ืœ, ืžื™ืงืจื•ืกื•ืคื˜, ืืžื–ื•ืŸ) ืžืฆื™ืขื™ื ืžื™ืงืจื•-ืžื•ืคืข ื‘ื—ื™ื ื ื‘ืฉื ื” ื”ืจืืฉื•ื ื”.
ืœืื—ืจ ื”ืชื ืกื•ืช ืขื 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 ืคืจื™ื™ืžื™ื ื‘ืฉื ื™ื™ื”, ืื‘ืœ ื”ื”ื‘ื“ืœ ื›ืžืขื˜ ื‘ืœืชื™ ื ืจืื” ืœืขื™ืŸ, ื”ื•ื ืขื“ื™ื™ืŸ ืื™ื˜ื™.

ืกืจื˜ื•ืŸ ืฉืœ ื’ืœืื™ ืื•ื‘ื™ื™ืงื˜ื™ื ื‘ืขื ืŸ ื‘-Raspberry Pi

ืื™ืŸ ืฉื•ื ืงืฉืจ ืœืขื ืŸ ื•ืœืขืœื•ื™ื•ืช ื”ืชื—ื‘ื•ืจื”; ื”ื’ืœืื™ ืคื•ืขืœ ืขืœ ื—ื•ืžืจื” ืจื’ื™ืœื” ื•ืขื•ื‘ื“ ื‘ืžื”ื™ืจื•ืช ื›ื–ื•.

ืžืงืœ ืžื—ืฉื‘ ืขืฆื‘ื™

ืœื ื™ื›ื•ืœืชื™ ืœื”ืชืืคืง ื•ื”ืจืฆืชื™ ืืช ื”ืžื“ื“ ื‘-NCS.

ืžื”ื™ืจื•ืช ื”ื’ืœืื™ ื”ื™ื™ืชื” ืžืขื˜ ื™ื•ืชืจ ืื™ื˜ื™ืช ืž-0.1 ืฉื ื™ื•ืช, ื‘ื›ืœ ืžืงืจื” ืžื”ื™ืจื” ืคื™ 2-3 ืžื”ืขื ืŸ ื‘ืžื›ื•ื ื” ื—ืœืฉื”, ื›ืœื•ืžืจ 8-9 ืคืจื™ื™ืžื™ื ืœืฉื ื™ื™ื”.

ืกืจื˜ื•ืŸ ืฉืœ ื’ืœืื™ ืื•ื‘ื™ื™ืงื˜ื™ื ื‘ืขื ืŸ ื‘-Raspberry Pi

ื”ื”ื‘ื“ืœ ื‘ืชื•ืฆืื•ืช ืžื•ืกื‘ืจ ืขืœ ื™ื“ื™ ื”ืขื•ื‘ื“ื” ืฉ-NCS ื”ืจื™ืฆื” Mobile SSD ื’ืจืกืช 2018_01_28.

ื .ื‘ ื‘ื ื•ืกืฃ, ื ื™ืกื•ื™ื™ื ื”ืจืื• ืฉืžื›ื•ื ื” ืฉื•ืœื—ื ื™ืช ื—ื–ืงื” ืœืžื“ื™ ืขื ืžืขื‘ื“ 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

ื”ื ื” ืžื” ืฉืงืจื”:

ืกืจื˜ื•ืŸ ืฉืœ ื’ืœืื™ ืื•ื‘ื™ื™ืงื˜ื™ื ื‘ืขื ืŸ ื‘-Raspberry Pi

ืงืฆืช ืคื—ื•ืช ืžื”ื™ืจ ืžืืฉืจ ืขื NCS, ืื‘ืœ ื ืžืจืฅ ื™ื•ืชืจ ืžืืฉืจ ื‘ื–ืจื ืื—ื“.

ื”ืจื•ื•ื—, ื›ืžื•ื‘ืŸ, ืื™ื ื• ืœื™ื ื™ืืจื™ - ื™ืฉ ืฉื›ื‘ื•ืช ืœืกื ื›ืจื•ืŸ ื•ื”ืขืชืงื” ืขืžื•ืงื” ืฉืœ ืชืžื•ื ื•ืช opencv.

ืžืกืงื ื”

ื‘ืกืš ื”ื›ืœ, ื”ื ื™ืกื•ื™ ืžืืคืฉืจ ืœื ื• ืœื”ืกื™ืง ืฉืื ืชื ืกื”, ืชื•ื›ืœ ืœื‘ืจื•ื— ืขื ืขื ืŸ ืคืฉื•ื˜.

ืื‘ืœ ืฉื•ืœื—ืŸ ืขื‘ื•ื“ื” ื—ื–ืง ืื• ื—ื•ืžืจื” ืžืงื•ืžื™ืช ืžืืคืฉืจ ืœืš ืœื”ืฉื™ื’ ืชื•ืฆืื•ืช ื˜ื•ื‘ื•ืช ื™ื•ืชืจ, ื•ืœืœื ื›ืœ ื˜ืจื™ืงื™ื.

ืชื–ื›ื•ืจ

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”