Նախաբան
Այժմ համացանցում շրջանառվում է մի տեսանյութ, որը ցույց է տալիս, թե ինչպես է Tesla-ի ավտոպիլոտը տեսնում ճանապարհը:
Ես երկար ժամանակ քոր էի զգում դետեկտորով հարստացված տեսանյութ հեռարձակելու համար և իրական ժամանակում։

Խնդիրն այն է, որ ես ուզում եմ հեռարձակել տեսանյութ Raspberry-ից, և դրա վրա նեյրոնային ցանցի դետեկտորի աշխատանքը շատ ցանկալի է թողնում:
Intel Neural Computer Stick
Տարբեր լուծումներ եմ դիտարկել։
В փորձարկել է Intel Neural Computer Stick-ը: Սարքավորումը հզոր է, բայց պահանջում է իր ցանցային ձևաչափը:
Չնայած Intel-ը փոխակերպիչներ է տրամադրում հիմնական շրջանակների համար, կան մի շարք որոգայթներ:
Օրինակ, պահանջվող ցանցի ձևաչափը կարող է անհամատեղելի լինել, իսկ եթե այն համատեղելի է, ապա որոշ շերտեր կարող են չաջակցվել սարքի վրա, իսկ եթե դրանք աջակցվում են, ապա փոխարկման գործընթացում կարող են առաջանալ սխալներ, ինչի արդյունքում մենք ելքում ինչ-որ տարօրինակ բաներ ենք ստանում:
Ընդհանրապես, եթե ցանկանում եք ինչ-որ կամայական նեյրոնային ցանց, ապա այն կարող է չաշխատել NCS-ի հետ: Ուստի որոշեցի փորձել լուծել խնդիրը՝ օգտագործելով ամենատարածված և հասանելի գործիքները։
Cloud
Տեղական ապարատային լուծման ակնհայտ այլընտրանքը ամպին գնալն է:
Պատրաստի տարբերակներ - աչքերս վազում են:
Բոլոր առաջնորդները.
... Եվ տասնյակ քիչ հայտնիներ:
Այս բազմազանության մեջ ընտրելն ամենևին էլ հեշտ չէ։
Եվ ես որոշեցի չընտրել, այլ փաթաթել 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()
Docker - 0.2 վրկ, Raspberry - 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
Հետագա (մուտքագրումը նկար է, ելքը դետեկտորի արդյունքներն են json-ում):
Այլընտրանքային տարբերակ, որտեղ ավելի շատ աշխատանք տեղափոխվում է սերվեր. նա ինքն է պտտվում հայտնաբերված օբյեկտների վրա և վերադարձնում պատրաստի պատկերը:
Այս տարբերակը լավ է այնտեղ, որտեղ մենք չենք ցանկանում opencv-ին քաշել սերվեր:
Դոկեր
Մենք հավաքում ենք պատկերը:
Կոդը սանրված և փակցված է , docker-ը այն անմիջապես այնտեղից կվերցնի:
В качестве платформы возьмем тот же Debian Stretch, что и на Raspberry — не будем уходить от проверенного техстека.
Դուք պետք է տեղադրեք flask, protobuf, հարցումներ, 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 ռեգիստրները բազմապատկվում են ոչ պակաս արագությամբ, քան ամպային դետեկտորները:
Որպեսզի չանհանգստանանք, պահպանողական կերպով կանցնենք .
- Գրանցվել
- Մուտք գործեք՝
docker մուտք - Եկեք մի իմաստալից անուն գտնենք.
docker պիտակ opencv-detect tprlab/opencv-detect-ssd - Վերբեռնեք պատկերը սերվեր.
docker push tprlab/opencv-detect-ssd
Մենք գործարկում ենք ամպի մեջ
Բավական լայն է նաև կոնտեյների տեղադրման վայրի ընտրությունը:
Բոլոր խոշոր խաղացողները (Google, Microsoft, Amazon) առաջին տարում առաջարկում են միկրո ատյան անվճար:
Microsoft Azure-ի և Google Cloud-ի հետ փորձարկումներից հետո ես որոշեցի վերջինիս վրա, քանի որ այն ավելի արագ հեռացավ:
Ես այստեղ հրահանգներ չեմ գրել, քանի որ այս մասը շատ հատուկ է ընտրված մատակարարին:
Ես փորձեցի տարբեր ապարատային տարբերակներ,
Ցածր մակարդակներ (համօգտագործվող և նվիրված) - 0.4 - 0.5 վայրկյան:
Ավելի հզոր մեքենաներ՝ 0.25 - 0.3:
Դե, նույնիսկ ամենավատ սցենարի դեպքում, շահումները երեք անգամ են, կարող եք փորձել:
Video
Մենք գործարկում ենք մի պարզ 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 կադր, բայց տարբերությունը գրեթե անտեսանելի է աչքի համար, այն դեռ դանդաղ է:

Ամպը և տրանսպորտի ծախսերը դրա հետ կապ չունեն. դետեկտորն աշխատում է սովորական սարքաշարի վրա և աշխատում է այդ արագությամբ։
Neural Computer Stick
Ես չկարողացա դիմադրել և գործարկեցի NCS-ի չափանիշը:
Դետեկտորի արագությունը մի փոքր ավելի դանդաղ էր, քան 0.1 վայրկյան, ամեն դեպքում 2-3 անգամ ավելի արագ, քան թույլ մեքենայի ամպը, այսինքն՝ 8-9 կադր վայրկյանում:

Արդյունքների տարբերությունը բացատրվում է նրանով, որ 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
Ահա թե ինչ է տեղի ունեցել.

Մի փոքր ավելի քիչ արագ, քան NCS-ով, բայց ավելի եռանդուն, քան մեկ հոսքում:
Շահույթը, իհարկե, գծային չէ. կան ծածկույթներ opencv պատկերների համաժամացման և խորը պատճենման համար:
Ամփոփում
Ընդհանուր առմամբ, փորձը թույլ է տալիս եզրակացնել, որ եթե փորձեք, կարող եք ազատվել պարզ ամպից:
Բայց հզոր աշխատասեղան կամ տեղական սարքավորումը թույլ է տալիս ավելի լավ արդյունքների հասնել և առանց որևէ հնարքների:
Սայլակ
Source: www.habr.com
