Raspberry Pi์˜ Cloud Object Detector ๋™์˜์ƒ

ํ”„๋กค๋กœ๊ทธ

Tesla์˜ ์ž๋™ ์กฐ์ข… ์žฅ์น˜๊ฐ€ ๋„๋กœ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ณด๋Š”์ง€ ๋ณด์—ฌ์ฃผ๋Š” ๋น„๋””์˜ค๊ฐ€ ํ˜„์žฌ ์ธํ„ฐ๋„ท์— ์œ ํฌ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํƒ์ง€๊ธฐ๋กœ ๊ฐ•ํ™”๋œ ์˜์ƒ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐฉ์†กํ•˜๊ณ  ์‹ถ์€ ๋งˆ์Œ์ด ์˜ค๋žซ๋™์•ˆ ๊ฐ„์ ˆํ–ˆ์Šต๋‹ˆ๋‹ค.

Raspberry Pi์˜ Cloud Object Detector ๋™์˜์ƒ

๋ฌธ์ œ๋Š” ๋ผ์ฆˆ๋ฒ ๋ฆฌ์—์„œ ๋น„๋””์˜ค๋ฅผ ๋ฐฉ์†กํ•˜๊ณ  ์‹ถ์€๋ฐ, ๊ทธ์— ๋Œ€ํ•œ ์‹ ๊ฒฝ๋ง ํƒ์ง€๊ธฐ์˜ ์„ฑ๋Šฅ์ด ์•„์‰ฌ์šด ์ ์ด ๋งŽ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ธํ…” ์‹ ๊ฒฝ ์ปดํ“จํ„ฐ ์Šคํ‹ฑ

๋‚˜๋Š” ๋‹ค๋ฅธ ํ•ด๊ฒฐ์ฑ…์„ ๊ณ ๋ คํ–ˆ์Šต๋‹ˆ๋‹ค.

ะ’ ๋งˆ์ง€๋ง‰ ๊ธฐ์‚ฌ Intel Neural Computer Stick์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ—˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋“œ์›จ์–ด๋Š” ๊ฐ•๋ ฅํ•˜์ง€๋งŒ ์ž์ฒด ๋„คํŠธ์›Œํฌ ํ˜•์‹์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Intel์ด ์ฃผ์š” ํ”„๋ ˆ์ž„์›Œํฌ์šฉ ๋ณ€ํ™˜๊ธฐ๋ฅผ ์ œ๊ณตํ•˜๋”๋ผ๋„ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํ•จ์ •์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ํ•„์š”ํ•œ ๋„คํŠธ์›Œํฌ์˜ ํ˜•์‹์ด ํ˜ธํ™˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ˜ธํ™˜๋˜๋Š” ๊ฒฝ์šฐ ์ผ๋ถ€ ๋ ˆ์ด์–ด๊ฐ€ ์žฅ์น˜์—์„œ ์ง€์›๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ง€์›๋˜๋Š” ๊ฒฝ์šฐ ๋ณ€ํ™˜ ํ”„๋กœ์„ธ์Šค ์ค‘์— ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ทธ ๊ฒฐ๊ณผ ์ถœ๋ ฅ์—์„œ ์ด์ƒํ•œ ์ผ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์ž„์˜์˜ ์‹ ๊ฒฝ๋ง์„ ์›ํ•˜๋Š” ๊ฒฝ์šฐ NCS์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ €๋Š” ๊ฐ€์žฅ ๊ด‘๋ฒ”์œ„ํ•˜๊ณ  ์ ‘๊ทผํ•˜๊ธฐ ์‰ฌ์šด ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌ๋ฆ„

๋กœ์ปฌ ํ•˜๋“œ์›จ์–ด ์†”๋ฃจ์…˜์— ๋Œ€ํ•œ ํ™•์‹คํ•œ ๋Œ€์•ˆ์€ ํด๋ผ์šฐ๋“œ๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ธฐ์„ฑํ’ˆ ์˜ต์…˜ - ๋‚ด ๋ˆˆ์ด ๊ฑฐ์น ๊ฒŒ ์›€์ง์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  ์ง€๋„์ž:

... ๊ทธ๋ฆฌ๊ณ  ๋œ ์•Œ๋ ค์ง„ ๊ฒƒ๋“ค๋„ ์ˆ˜์‹ญ ๊ฐœ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋‹ค์–‘์„ฑ ์ค‘์—์„œ ์„ ํƒํ•˜๋Š” ๊ฒƒ์€ ๊ฒฐ์ฝ” ์‰ฌ์šด ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ €๋Š” ์„ ํƒํ•˜์ง€ ์•Š๊ณ  OpenCV์˜ ๊ธฐ์กด ์ž‘์—… ๋ฐฉ์‹์„ Docker๋กœ ๋ž˜ํ•‘ํ•˜์—ฌ ํด๋ผ์šฐ๋“œ์—์„œ ์‹คํ–‰ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์žฅ์ ์€ ์œ ์—ฐ์„ฑ๊ณผ ์ œ์–ด์ž…๋‹ˆ๋‹ค. ์‹ ๊ฒฝ๋ง, ํ˜ธ์ŠคํŒ…, ์„œ๋ฒ„ ๋“ฑ ์ผ๋ฐ˜์ ์œผ๋กœ ์›ํ•˜๋Š” ๋Œ€๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„œ๋ฒ„

๋กœ์ปฌ ํ”„๋กœํ† ํƒ€์ž…๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ „ํ†ต์ ์œผ๋กœ ์ €๋Š” REST API, OpenCV ๋ฐ MobileSSD ๋„คํŠธ์›Œํฌ์— Flask๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Docker์— ์ตœ์‹  ๋ฒ„์ „์„ ์„ค์น˜ํ•œ ํ›„ OpenCV 4.1.2๊ฐ€ ๋ชจ๋ฐ”์ผ 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์ดˆ, ๋ผ์ฆˆ๋ฒ ๋ฆฌ์—์„œ๋Š” 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๊ฐ€ ๊ฑฐ๊ธฐ์—์„œ ์ง์ ‘ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

ํ”Œ๋žซํผ์œผ๋กœ์„œ ์šฐ๋ฆฌ๋Š” Raspberry์—์„œ์™€ ๋™์ผํ•œ Debian Stretch๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ž…์ฆ๋œ ๊ธฐ์ˆ  ์Šคํƒ์—์„œ ๋ฒ—์–ด๋‚˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ”Œ๋ผ์Šคํฌ, protobuf, ์š”์ฒญ, opencv_python์„ ์„ค์น˜ํ•˜๊ณ  Github์—์„œ ๋ชจ๋ฐ”์ผ SSD, ์„œ๋ฒ„ ์ฝ”๋“œ๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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 ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋Š” ํด๋ผ์šฐ๋“œ ๊ฐ์ง€๊ธฐ๋ณด๋‹ค ๋น ๋ฅธ ์†๋„๋กœ ์ฆ๊ฐ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐฉํ•ด๊ฐ€ ๋˜์ง€ ์•Š๋„๋ก ๋ณด์ˆ˜์ ์œผ๋กœ ์ง„ํ–‰ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋„์ปคํ—ˆ๋ธŒ.

  1. ๋“ฑ๋กํ•˜๋‹ค
  2. ๋กœ๊ทธ์ธ:
    ๋„์ปค ๋กœ๊ทธ์ธ
  3. ์˜๋ฏธ์žˆ๋Š” ์ด๋ฆ„์„ ์ƒ๊ฐํ•ด ๋ด…์‹œ๋‹ค.
    ๋„์ปค ํƒœ๊ทธ opencv-๊ฒ€์ถœ tprlab/opencv-๊ฒ€์ถœ-ssd
  4. ์ด๋ฏธ์ง€๋ฅผ ์„œ๋ฒ„์— ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
    ๋„์ปค ํ‘ธ์‹œ tprlab/opencv-Detect-ssd

์šฐ๋ฆฌ๋Š” ํด๋ผ์šฐ๋“œ์—์„œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค

์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•  ์œ„์น˜์˜ ์„ ํƒ๋„ ์ƒ๋‹นํžˆ ๋„“์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ๋Œ€ํ˜• ํ”Œ๋ ˆ์ด์–ด(Google, Microsoft, Amazon)๋Š” ์ฒซํ•ด์— ๋งˆ์ดํฌ๋กœ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฌด๋ฃŒ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
Microsoft Azure์™€ Google Cloud๋ฅผ ์‹คํ—˜ํ•œ ํ›„ ๋” ๋นจ๋ฆฌ ์„ฑ๊ณตํ•˜๋Š” ํ›„์ž๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ถ€๋ถ„์€ ์„ ํƒํ•œ ๊ณต๊ธ‰์ž์— ๋”ฐ๋ผ ๋งค์šฐ ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๊ธฐ์— ์ง€์นจ์„ ์ž‘์„ฑํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋‹ค์–‘ํ•œ ํ•˜๋“œ์›จ์–ด ์˜ต์…˜์„ ์‹œ๋„ํ–ˆ์ง€๋งŒ,
๋‚ฎ์€ ์ˆ˜์ค€(๊ณต์œ  ๋ฐ ์ „์šฉ) - 0.4 - 0.5์ดˆ.
๋” ๊ฐ•๋ ฅํ•œ ์ž๋™์ฐจ - 0.25 - 0.3.
๊ธ€์Ž„์š”, ์ตœ์•…์˜ ๊ฒฝ์šฐ์—๋„ ์Šน๋ฆฌ๋Š” ์„ธ ๋ฐฐ์ž…๋‹ˆ๋‹ค. ์‹œ๋„ํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋น„๋””์˜ค

Google Cloud๋ฅผ ํ†ตํ•ด ๊ฐ์ง€ํ•˜์—ฌ Raspberry์—์„œ ๊ฐ„๋‹จํ•œ OpenCV ๋น„๋””์˜ค ์ŠคํŠธ๋ฆฌ๋จธ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
์‹คํ—˜์—๋Š” ์ž„์˜์˜ ๊ต์ฐจ๋กœ์—์„œ XNUMXํšŒ ์ดฌ์˜๋œ ๋™์˜์ƒ ํŒŒ์ผ์ด ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


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

ํƒ์ง€๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ดˆ๋‹น XNUMX๊ฐœ ์ด์ƒ์˜ ํ”„๋ ˆ์ž„์„ ์–ป์„ ์ˆ˜ ์—†์œผ๋ฉฐ ๋ชจ๋“  ๊ฒƒ์ด ๋งค์šฐ ๋Š๋ฆฌ๊ฒŒ ์ง„ํ–‰๋ฉ๋‹ˆ๋‹ค.
๊ฐ•๋ ฅํ•œ ๋จธ์‹ ์„ GCloud๋กœ ๊ฐ€์ ธ์˜ค๋ฉด ์ดˆ๋‹น 4~5ํ”„๋ ˆ์ž„์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ ์ฐจ์ด๋Š” ๋ˆˆ์— ๊ฑฐ์˜ ๋ณด์ด์ง€ ์•Š๊ณ  ์—ฌ์ „ํžˆ ๋Š๋ฆฝ๋‹ˆ๋‹ค.

Raspberry Pi์˜ Cloud Object Detector ๋™์˜์ƒ

ํด๋ผ์šฐ๋“œ ๋ฐ ์šด์†ก ๋น„์šฉ์€ ๊ทธ๊ฒƒ๊ณผ ์•„๋ฌด ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ฐ์ง€๊ธฐ๋Š” ์ผ๋ฐ˜ ํ•˜๋“œ์›จ์–ด์—์„œ ์‹คํ–‰๋˜๋ฉฐ ์ด๋Ÿฌํ•œ ์†๋„๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์‹ ๊ฒฝ ์ปดํ“จํ„ฐ ์Šคํ‹ฑ

๋‚˜๋Š” ์ฐธ์„ ์ˆ˜ ์—†์—ˆ๊ณ  NCS์—์„œ ๋ฒค์น˜๋งˆํฌ๋ฅผ ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ์ง€๊ธฐ์˜ ์†๋„๋Š” 0.1์ดˆ๋ณด๋‹ค ์•ฝ๊ฐ„ ๋Š๋ ธ์œผ๋ฉฐ, ์–ด์จŒ๋“  ์•ฝํ•œ ์‹œ์Šคํ…œ์˜ ํด๋ผ์šฐ๋“œ๋ณด๋‹ค 2~3๋ฐฐ ๋น ๋ฆ…๋‹ˆ๋‹ค. ์ฆ‰, ์ดˆ๋‹น 8~9ํ”„๋ ˆ์ž„์ž…๋‹ˆ๋‹ค.

Raspberry Pi์˜ Cloud Object Detector ๋™์˜์ƒ

๊ฒฐ๊ณผ์˜ ์ฐจ์ด๋Š” NCS๊ฐ€ ๋ชจ๋ฐ”์ผ SSD ๋ฒ„์ „ 2018_01_28์„ ์‹คํ–‰ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค๋กœ ์„ค๋ช…๋ฉ๋‹ˆ๋‹ค.

์ถ”์‹ : ๋˜ํ•œ ์‹คํ—˜์— ๋”ฐ๋ฅด๋ฉด I7 ํ”„๋กœ์„ธ์„œ๋ฅผ ํƒ‘์žฌํ•œ ์ƒ๋‹นํžˆ ๊ฐ•๋ ฅํ•œ ๋ฐ์Šคํฌํ†ฑ ์ปดํ“จํ„ฐ๋Š” ์•ฝ๊ฐ„ ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์—ฌ์ฃผ๋ฉฐ ์ดˆ๋‹น 10ํ”„๋ ˆ์ž„์„ ์งœ๋‚ผ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.

ํด๋Ÿฌ์Šคํ„ฐ

์‹คํ—˜์€ ๋” ์ง„ํ–‰๋˜์–ด Google Kubernetes์˜ XNUMX๊ฐœ ๋…ธ๋“œ์— ๊ฐ์ง€๊ธฐ๋ฅผ ์„ค์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค.
ํฌ๋“œ ์ž์ฒด๋Š” ์•ฝํ–ˆ๊ณ  ๊ฐ๊ฐ ์ดˆ๋‹น 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์˜ Cloud Object Detector ๋™์˜์ƒ

NCS๋ณด๋‹ค ์†๋„๋Š” ์•ฝ๊ฐ„ ๋Š๋ฆฌ์ง€๋งŒ ๋‹จ์ผ ์ŠคํŠธ๋ฆผ๋ณด๋‹ค ํ™œ๋ฐœํ•ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ด๋“์€ ์„ ํ˜•์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. opencv ์ด๋ฏธ์ง€์˜ ๋™๊ธฐํ™” ๋ฐ ์‹ฌ์ธต ๋ณต์‚ฌ๋ฅผ ์œ„ํ•œ ์˜ค๋ฒ„๋ ˆ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

์ „๋ฐ˜์ ์œผ๋กœ ์‹คํ—˜์„ ํ†ตํ•ด ์šฐ๋ฆฌ๋Š” ์‹œ๋„ํ•œ๋‹ค๋ฉด ๊ฐ„๋‹จํ•œ ํด๋ผ์šฐ๋“œ๋งŒ์œผ๋กœ๋„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒฐ๋ก ์„ ๋‚ด๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๊ฐ•๋ ฅํ•œ ๋ฐ์Šคํฌํ†ฑ์ด๋‚˜ ๋กœ์ปฌ ํ•˜๋“œ์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ฌด๋Ÿฐ ํŠธ๋ฆญ ์—†์ด๋„ ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ์กฐ

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€