ํ๋กค๋ก๊ทธ
Tesla์ ์๋ ์กฐ์ข ์ฅ์น๊ฐ ๋๋ก๋ฅผ ์ด๋ป๊ฒ ๋ณด๋์ง ๋ณด์ฌ์ฃผ๋ ๋น๋์ค๊ฐ ํ์ฌ ์ธํฐ๋ท์ ์ ํฌ๋๊ณ ์์ต๋๋ค.
ํ์ง๊ธฐ๋ก ๊ฐํ๋ ์์์ ์ค์๊ฐ์ผ๋ก ๋ฐฉ์กํ๊ณ ์ถ์ ๋ง์์ด ์ค๋ซ๋์ ๊ฐ์ ํ์ต๋๋ค.
๋ฌธ์ ๋ ๋ผ์ฆ๋ฒ ๋ฆฌ์์ ๋น๋์ค๋ฅผ ๋ฐฉ์กํ๊ณ ์ถ์๋ฐ, ๊ทธ์ ๋ํ ์ ๊ฒฝ๋ง ํ์ง๊ธฐ์ ์ฑ๋ฅ์ด ์์ฌ์ด ์ ์ด ๋ง๋ค๋ ๊ฒ์
๋๋ค.
์ธํ ์ ๊ฒฝ ์ปดํจํฐ ์คํฑ
๋๋ ๋ค๋ฅธ ํด๊ฒฐ์ฑ ์ ๊ณ ๋ คํ์ต๋๋ค.
ะ
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
๋ ๋์๊ฐ์
๋ ๋ง์ ์์ ์ด ์๋ฒ๋ก ์ด๋๋๋ ๋์ฒด ์ต์ ์ ๋๋ค. ์์ฒด์ ์ผ๋ก ๋ฐ๊ฒฌ๋ ๊ฐ์ฒด๋ฅผ ์ํ์ํค๊ณ ์์ฑ๋ ์ด๋ฏธ์ง๋ฅผ ๋ฐํํฉ๋๋ค.
์ด ์ต์ ์ opencv๋ฅผ ์๋ฒ๋ก ๋๋๊ทธํ๊ณ ์ถ์ง ์์ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค.
๋์ปค
์ฐ๋ฆฌ๋ ์ด๋ฏธ์ง๋ฅผ ์์งํฉ๋๋ค.
์ฝ๋๋ ๋น์ง๋์ด ๊ฒ์๋ฉ๋๋ค.
ํ๋ซํผ์ผ๋ก์ ์ฐ๋ฆฌ๋ 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 ๋ ์ง์คํธ๋ฆฌ๋ ํด๋ผ์ฐ๋ ๊ฐ์ง๊ธฐ๋ณด๋ค ๋น ๋ฅธ ์๋๋ก ์ฆ๊ฐํ๊ณ ์์ต๋๋ค.
๋ฐฉํด๊ฐ ๋์ง ์๋๋ก ๋ณด์์ ์ผ๋ก ์งํํ๊ฒ ์ต๋๋ค.
- ๋ฑ๋กํ๋ค
- ๋ก๊ทธ์ธ:
๋์ปค ๋ก๊ทธ์ธ - ์๋ฏธ์๋ ์ด๋ฆ์ ์๊ฐํด ๋ด
์๋ค.
๋์ปค ํ๊ทธ opencv-๊ฒ์ถ tprlab/opencv-๊ฒ์ถ-ssd - ์ด๋ฏธ์ง๋ฅผ ์๋ฒ์ ์
๋ก๋ํฉ๋๋ค.
๋์ปค ํธ์ 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ํ๋ ์์ ๊ฐ์งํ ์ ์์ง๋ง ๊ทธ ์ฐจ์ด๋ ๋์ ๊ฑฐ์ ๋ณด์ด์ง ์๊ณ ์ฌ์ ํ ๋๋ฆฝ๋๋ค.
ํด๋ผ์ฐ๋ ๋ฐ ์ด์ก ๋น์ฉ์ ๊ทธ๊ฒ๊ณผ ์๋ฌด ๊ด๋ จ์ด ์์ต๋๋ค. ๊ฐ์ง๊ธฐ๋ ์ผ๋ฐ ํ๋์จ์ด์์ ์คํ๋๋ฉฐ ์ด๋ฌํ ์๋๋ก ์๋ํฉ๋๋ค.
์ ๊ฒฝ ์ปดํจํฐ ์คํฑ
๋๋ ์ฐธ์ ์ ์์๊ณ NCS์์ ๋ฒค์น๋งํฌ๋ฅผ ์คํํ์ต๋๋ค.
๊ฐ์ง๊ธฐ์ ์๋๋ 0.1์ด๋ณด๋ค ์ฝ๊ฐ ๋๋ ธ์ผ๋ฉฐ, ์ด์จ๋ ์ฝํ ์์คํ ์ ํด๋ผ์ฐ๋๋ณด๋ค 2~3๋ฐฐ ๋น ๋ฆ ๋๋ค. ์ฆ, ์ด๋น 8~9ํ๋ ์์ ๋๋ค.
๊ฒฐ๊ณผ์ ์ฐจ์ด๋ 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
๋ค์์ ์ผ์ด๋ ์ผ์ ๋๋ค.
NCS๋ณด๋ค ์๋๋ ์ฝ๊ฐ ๋๋ฆฌ์ง๋ง ๋จ์ผ ์คํธ๋ฆผ๋ณด๋ค ํ๋ฐํฉ๋๋ค.
๋ฌผ๋ก ์ด๋์ ์ ํ์ ์ด์ง ์์ต๋๋ค. opencv ์ด๋ฏธ์ง์ ๋๊ธฐํ ๋ฐ ์ฌ์ธต ๋ณต์ฌ๋ฅผ ์ํ ์ค๋ฒ๋ ์ด๊ฐ ์์ต๋๋ค.
๊ฒฐ๋ก
์ ๋ฐ์ ์ผ๋ก ์คํ์ ํตํด ์ฐ๋ฆฌ๋ ์๋ํ๋ค๋ฉด ๊ฐ๋จํ ํด๋ผ์ฐ๋๋ง์ผ๋ก๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋ค๋ ๊ฒฐ๋ก ์ ๋ด๋ฆด ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋ ๊ฐ๋ ฅํ ๋ฐ์คํฌํฑ์ด๋ ๋ก์ปฌ ํ๋์จ์ด๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ฌด๋ฐ ํธ๋ฆญ ์์ด๋ ๋ ๋์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ต๋๋ค.
์ฐธ์กฐ
์ถ์ฒ : habr.com