OpenVINO hackathon: rikonoxximent tal-vuċi u l-emozzjonijiet fuq Raspberry Pi

30 Novembru - 1 Diċembru f'Nizhny Novgorod saret Hackathon OpenVINO. Il-parteċipanti ntalbu joħolqu prototip ta' soluzzjoni ta' prodott bl-użu tal-għodda Intel OpenVINO. L-organizzaturi pproponew lista ta’ suġġetti approssimattivi li jistgħu jiġu ggwidati minn meta jintgħażel kompitu, iżda d-deċiżjoni finali baqgħet f’idejn it-timijiet. Barra minn hekk, ġie mħeġġeġ l-użu ta’ mudelli li mhumiex inklużi fil-prodott.

OpenVINO hackathon: rikonoxximent tal-vuċi u l-emozzjonijiet fuq Raspberry Pi

F'dan l-artikolu ser ngħidulek dwar kif ħloqna l-prototip tagħna tal-prodott, li bih eventwalment ħadna l-ewwel post.

Aktar minn 10 timijiet ipparteċipaw fil-hackathon. Huwa sabiħ li xi wħud minnhom ġew minn reġjuni oħra. Il-post għall-hackathon kien il-kumpless "Kremlinsky on Pochain", fejn ritratti antiki ta 'Nizhny Novgorod kienu mdendlin ġewwa, f'madwaru! (Infakkarkom li bħalissa l-uffiċċju ċentrali ta 'Intel jinsab f'Nizhny Novgorod). Il-parteċipanti ngħataw 26 siegħa biex jiktbu l-kodiċi, u fl-aħħar kellhom jippreżentaw is-soluzzjoni tagħhom. Vantaġġ separat kien il-preżenza ta 'sessjoni demo biex jiġi żgurat li dak kollu ppjanat kien attwalment implimentat u ma jibqax ideat fil-preżentazzjoni. Merch, snacks, ikel, kollox kien hemm ukoll!

Barra minn hekk, Intel ipprovda b'mod fakultattiv kameras, Raspberry PI, Neural Compute Stick 2.

Għażla tal-kompitu

Waħda mill-aktar partijiet diffiċli tal-preparazzjoni għal hackathon b'forma ħielsa hija l-għażla ta 'sfida. Immedjatament iddeċidejna li noħorġu b'xi ħaġa li għadha ma kinitx fil-prodott, peress li t-tħabbira qalet li din kienet milqugħa ħafna.

Wara li analizzat mudelli, li huma inklużi fil-prodott fir-rilaxx attwali, naslu għall-konklużjoni li ħafna minnhom isolvu diversi problemi ta 'viżjoni tal-kompjuter. Barra minn hekk, huwa diffiċli ħafna li toħroġ bi problema fil-qasam tal-viżjoni tal-kompjuter li ma tistax tiġi solvuta bl-użu ta 'OpenVINO, u anke jekk wieħed jista' jiġi ivvintat, huwa diffiċli li ssib mudelli mħarrġa minn qabel fid-dominju pubbliku. Aħna niddeċiedu li nħaffru f'direzzjoni oħra - lejn l-ipproċessar tad-diskors u l-analiżi. Ejja nikkunsidraw kompitu interessanti li nirrikonoxxu l-emozzjonijiet mid-diskors. Wieħed irid jgħid li OpenVINO diġà għandu mudell li jiddetermina l-emozzjonijiet ta’ persuna abbażi ta’ wiċċha, iżda:

  • Fit-teorija, huwa possibbli li jinħoloq algoritmu kombinat li jaħdem kemm fuq il-ħoss kif ukoll fuq l-immaġni, li għandu jagħti żieda fl-eżattezza.
  • Il-kameras normalment ikollhom angolu tal-vista dejjaq; aktar minn kamera waħda hija meħtieġa biex tkopri żona kbira; il-ħoss m'għandux tali limitazzjoni.

Ejja niżviluppaw l-idea: ejja nieħdu l-idea għas-segment tal-bejgħ bl-imnut bħala bażi. Tista 'tkejjel is-sodisfazzjon tal-klijent fil-checkouts tal-maħżen. Jekk wieħed mill-klijenti ma jkunx sodisfatt bis-servizz u jibda jgħolli t-ton tagħhom, tista' immedjatament iċempel lill-amministratur għall-għajnuna.
F'dan il-każ, irridu nżidu r-rikonoxximent tal-vuċi umana, dan jippermettilna niddistingwu l-impjegati tal-maħżen mill-klijenti u nipprovdu analitika għal kull individwu. Ukoll, barra minn hekk, se jkun possibbli li tanalizza l-imġieba tal-impjegati tal-maħżen infushom, tevalwa l-atmosfera fit-tim, tinstema tajjeb!

Aħna nifformulaw ir-rekwiżiti għas-soluzzjoni tagħna:

  • Daqs żgħir tal-apparat fil-mira
  • Operazzjoni f'ħin reali
  • Prezz baxx
  • Skalabbiltà faċli

Bħala riżultat, aħna nagħżlu Raspberry Pi 3 c bħala l-apparat fil-mira Intel NCS 2.

Hawnhekk huwa importanti li wieħed jinnota karatteristika waħda importanti ta 'NCS - taħdem l-aħjar ma' arkitetturi CNN standard, imma jekk għandek bżonn tmexxi mudell b'saffi tad-dwana fuqha, imbagħad tistenna ottimizzazzjoni ta 'livell baxx.

Hemm ħaġa żgħira waħda biss x'tagħmel: għandek bżonn tikseb mikrofonu. Mikrofonu USB regolari se jagħmel, iżda mhux se jidher tajjeb flimkien ma 'l-RPI. Imma anke hawn is-soluzzjoni litteralment “tinsab fil-qrib.” Biex nirreġistra l-vuċi, aħna niddeċiedu li nużaw il-bord tal-Voice Bonnet mill-kit Google AIY Voice Kit, li fuqu hemm mikrofonu stereo bil-fili.

Niżżel Raspbian minn Repożitorju tal-proġetti AIY u ittellah fuq flash drive, ittestja li l-mikrofonu jaħdem billi tuża l-kmand li ġej (se jirreġistra l-awdjo tul 5 sekondi u ssejvjah f'fajl):

arecord -d 5 -r 16000 test.wav

Minnufih għandi ninnota li l-mikrofonu huwa sensittiv ħafna u jiġbor tajjeb l-istorbju. Biex tiffissa dan, ejja mur alsamixer, agħżel Qbid apparati u naqqas il-livell tas-sinjal tad-dħul għal 50-60%.

OpenVINO hackathon: rikonoxximent tal-vuċi u l-emozzjonijiet fuq Raspberry Pi
Aħna nimmodifikaw il-ġisem b'fajl u kollox joqgħod, tista 'saħansitra tagħlaqha b'għatu

Żieda ta 'buttuna indikatur

Filwaqt li nieħdu l-AIY Voice Kit barra, niftakru li hemm buttuna RGB, li d-dawl ta 'wara tagħha jista' jiġi kkontrollat ​​minn softwer. Aħna nfittxu "Google AIY Led" u nsibu dokumentazzjoni: https://aiyprojects.readthedocs.io/en/latest/aiy.leds.html
Għaliex ma tużax din il-buttuna biex turi l-emozzjoni rikonoxxuta, għandna biss 7 klassijiet, u l-buttuna għandha 8 kuluri, biżżejjed!

Aħna nqabbdu l-buttuna permezz ta 'GPIO ma' Voice Bonnet, tagħbija l-libreriji meħtieġa (diġà huma installati fil-kit tad-distribuzzjoni minn proġetti AIY)

from aiy.leds import Leds, Color
from aiy.leds import RgbLeds

Ejja noħolqu dict li fih kull emozzjoni jkollha kulur korrispondenti fil-forma ta 'Tuppla RGB u oġġett tal-klassi aiy.leds.Leds, li permezz tiegħu se naġġornaw il-kulur:

led_dict = {'neutral': (255, 255, 255), 'happy': (0, 255, 0), 'sad': (0, 255, 255), 'angry': (255, 0, 0), 'fearful': (0, 0, 0), 'disgusted':  (255, 0, 255), 'surprised':  (255, 255, 0)} 
leds = Leds()

U fl-aħħarnett, wara kull tbassir ġdid ta 'emozzjoni, aħna se taġġorna l-kulur tal-buttuna skond dan (b'ċavetta).

leds.update(Leds.rgb_on(led_dict.get(classes[prediction])))

OpenVINO hackathon: rikonoxximent tal-vuċi u l-emozzjonijiet fuq Raspberry Pi
Buttuna, ħruq!

Ħidma bil-vuċi

Se nużaw pyaudio biex naqbdu n-nixxiegħa mill-mikrofonu u webrtcvad biex niffiltraw l-istorbju u niskopru l-vuċi. Barra minn hekk, se noħolqu kju li miegħu se nżidu u nneħħu siltiet tal-vuċi b'mod mhux sinkroniku.

Peress li webrtcvad għandu limitazzjoni fuq id-daqs tal-framment fornut - għandu jkun ugwali għal 10/20/30ms, u t-taħriġ tal-mudell għar-rikonoxximent tal-emozzjonijiet (kif ser nitgħallmu aktar tard) sar fuq dataset 48kHz, aħna se jaqbad biċċiet ta' daqs 48000×20ms/1000×1(mono)=960 bytes. Webrtcvad se jirritorna Veru/Falz għal kull wieħed minn dawn il-biċċiet, li jikkorrispondi għall-preżenza jew in-nuqqas ta 'vot fil-biċċa.

Ejja nimplimentaw il-loġika li ġejja:

  • Aħna nżidu mal-lista dawk il-biċċiet fejn hemm vot; jekk ma jkunx hemm vot, allura nżidu l-counter tal-biċċiet vojta.
  • Jekk il-counter ta 'biċċiet vojta huwa> = 30 (600 ms), allura nħarsu lejn id-daqs tal-lista ta' biċċiet akkumulati; jekk ikun> 250, allura nżiduh mal-kju; jekk le, nikkunsidraw li t-tul tar-rekord mhuwiex biżżejjed biex jitimgħu lill-mudell biex jidentifika l-kelliem.
  • Jekk il-counter ta 'biċċiet vojta għadu < 30, u d-daqs tal-lista ta' biċċiet akkumulati jaqbeż it-300, allura aħna se nżidu l-framment mal-kju għal tbassir aktar preċiż. (għax l-emozzjonijiet għandhom it-tendenza li jinbidlu maż-żmien)

 def to_queue(frames):
    d = np.frombuffer(b''.join(frames), dtype=np.int16)
    return d

framesQueue = queue.Queue()
def framesThreadBody():
    CHUNK = 960
    FORMAT = pyaudio.paInt16
    CHANNELS = 1
    RATE = 48000

    p = pyaudio.PyAudio()
    vad = webrtcvad.Vad()
    vad.set_mode(2)
    stream = p.open(format=FORMAT,
                channels=CHANNELS,
                rate=RATE,
                input=True,
                frames_per_buffer=CHUNK)
    false_counter = 0
    audio_frame = []
    while process:
        data = stream.read(CHUNK)
        if not vad.is_speech(data, RATE):
            false_counter += 1
            if false_counter >= 30:
                if len(audio_frame) > 250:              
                    framesQueue.put(to_queue(audio_frame,timestamp_start))
                    audio_frame = []
                    false_counter = 0

        if vad.is_speech(data, RATE):
            false_counter = 0
            audio_frame.append(data)
            if len(audio_frame) > 300:                
                    framesQueue.put(to_queue(audio_frame,timestamp_start))
                    audio_frame = []

Wasal iż-żmien li tfittex mudelli mħarrġa minn qabel fid-dominju pubbliku, mur github, Google, imma ftakar li għandna limitazzjoni fuq l-arkitettura użata. Din hija parti pjuttost diffiċli, għax trid tittestja l-mudelli fuq id-dejta tal-input tiegħek, u barra minn hekk, tikkonvertihom għall-format intern ta 'OpenVINO - IR (Rappreżentanza Intermedja). Ippruvajna madwar 5-7 soluzzjonijiet differenti minn github, u jekk il-mudell għar-rikonoxximent tal-emozzjonijiet ħadem immedjatament, allura bir-rikonoxximent tal-vuċi kellna nistennew aktar - huma jużaw arkitetturi aktar kumplessi.

Aħna niffokaw fuq dan li ġej:

Sussegwentement nitkellmu dwar il-konverżjoni tal-mudelli, nibdew bit-teorija. OpenVINO jinkludi diversi moduli:

  • Open Model Zoo, mudelli li minnhom jistgħu jintużaw u inklużi fil-prodott tiegħek
  • Model Optimzer, li bis-saħħa tiegħu tista' tikkonverti mudell minn diversi formati ta' qafas (Tensorflow, ONNX eċċ) fil-format Intermediate Representation, li miegħu se naħdmu aktar
  • Inference Engine jippermettilek li tħaddem mudelli f'format IR fuq proċessuri Intel, ċipep Myriad u aċċeleraturi Neural Compute Stick
  • L-aktar verżjoni effiċjenti ta' OpenCV (bl-appoġġ tal-Inference Engine)
    Kull mudell fil-format IR huwa deskritt minn żewġ fajls: .xml u .bin.
    Il-mudelli huma kkonvertiti f'format IR permezz ta' Model Optimizer kif ġej:

    python /opt/intel/openvino/deployment_tools/model_optimizer/mo_tf.py --input_model speaker.hdf5.pb --data_type=FP16 --input_shape [1,512,1000,1]

    --data_type jippermettilek tagħżel il-format tad-data li bih il-mudell se jaħdem. FP32, FP16, INT8 huma appoġġjati. L-għażla tat-tip ta 'dejta ottimali tista' tagħti spinta tajba lill-prestazzjoni.
    --input_shape jindika d-dimensjoni tad-dejta tal-input. Il-ħila li tinbidel b'mod dinamiku tidher li hija preżenti fis-C++ API, iżda aħna ma ħafferx daqshekk u sempliċement issewwiha għal wieħed mill-mudelli.
    Sussegwentement, ejja nippruvaw tagħbija l-mudell diġà kkonvertit f'format IR permezz tal-modulu DNN f'OpenCV u tibgħatlu.

    import cv2 as cv
    emotionsNet = cv.dnn.readNet('emotions_model.bin',
                              'emotions_model.xml')
    emotionsNet.setPreferableTarget(cv.dnn.DNN_TARGET_MYRIAD)

    L-aħħar linja f'dan il-każ tippermettilek li terġa 'tidderieġi l-kalkoli lejn in-Neurali Compute Stick, il-kalkoli bażiċi jitwettqu fuq il-proċessur, iżda fil-każ tal-Raspberry Pi dan mhux se jaħdem, ser ikollok bżonn stick.

    Sussegwentement, il-loġika hija kif ġej: aħna naqsmu l-awdjo tagħna fi twieqi ta 'ċertu daqs (għalina huwa 0.4 s), aħna nikkonverti kull waħda minn dawn it-twieqi f'MFCC, li mbagħad nimxu lill-grid:

    emotionsNet.setInput(MFCC_from_window)
    result = emotionsNet.forward()

    Sussegwentement, ejja nieħdu l-aktar klassi komuni għat-twieqi kollha. Soluzzjoni sempliċi, iżda għal hackathon m'għandekx bżonn toħroġ b'xi ħaġa wisq abstruse, biss jekk ikollok ħin. Għad fadlilna ħafna xogħol x’nagħmlu, allura ejja nimxu ‘l quddiem – se nittrattaw ir-rikonoxximent tal-vuċi. Huwa meħtieġ li tinħoloq xi tip ta 'database li fiha jkunu maħżuna spettrogrammi ta' vuċijiet irreġistrati minn qabel. Peress li fadal ftit ħin, se nsolvu din il-kwistjoni mill-aħjar li nistgħu.

    Jiġifieri, noħolqu skript għar-reġistrazzjoni ta 'silta tal-vuċi (taħdem bl-istess mod kif deskritt hawn fuq, biss meta jiġi interrott mit-tastiera se jiffranka l-vuċi għal fajl).

    Ejja nipruvaw:

    python3 voice_db/record_voice.py test.wav

    Nirrekordjaw il-vuċijiet ta’ diversi nies (fil-każ tagħna, tliet membri tat-tim)
    Sussegwentement, għal kull vuċi rreġistrata nwettqu trasformazzjoni fourier veloċi, niksbu spettrogramma u nissejvjawha bħala firxa numpy (.npy):

    for file in glob.glob("voice_db/*.wav"):
            spec = get_fft_spectrum(file)
            np.save(file[:-4] + '.npy', spec)

    Aktar dettalji fil-fajl create_base.py
    Bħala riżultat, meta nħaddmu l-iskript prinċipali, se nġibu inkorporazzjonijiet minn dawn l-ispettrogrammi fil-bidu nett:

    for file in glob.glob("voice_db/*.npy"):
        spec = np.load(file)
        spec = spec.astype('float32')
        spec_reshaped = spec.reshape(1, 1, spec.shape[0], spec.shape[1])
        srNet.setInput(spec_reshaped)
        pred = srNet.forward()
        emb = np.squeeze(pred)

    Wara li nirċievu l-inkorporazzjoni mis-segment ħoss, inkunu nistgħu niddeterminaw lil min jappartjeni billi nieħdu d-distanza tal-cosine mill-passaġġ għall-vuċijiet kollha fid-database (iż-żgħar, l-aktar probabbli) - għad-demo nissettjaw il-limitu sa 0.3):

            dist_list = cdist(emb, enroll_embs, metric="cosine")
            distances = pd.DataFrame(dist_list, columns = df.speaker)

    Fl-aħħar, nixtieq ninnota li l-veloċità tal-inferenza kienet mgħaġġla u għamlitha possibbli li jiżdiedu 1-2 mudelli aktar (għal kampjun ta '7 sekondi ħadet 2.5 għall-inferenza). Ma kellniex aktar ħin biex inżidu mudelli ġodda u ffukajna fuq il-kitba ta’ prototip tal-applikazzjoni tal-web.

    Applikazzjoni tal-web

    Punt importanti: nieħdu router magħna mid-dar u nwaqqfu n-netwerk lokali tagħna, jgħin biex jgħaqqad l-apparat u l-laptops fuq in-netwerk.

    Il-backend huwa kanal ta 'messaġġ tarf sa tarf bejn il-faċċata u Raspberry Pi, ibbażat fuq teknoloġija websocket (protokoll http fuq tcp).

    L-ewwel stadju huwa li tirċievi informazzjoni pproċessata minn lampun, jiġifieri, tbassir ppakkjati f'json, li jiġu ffrankati fid-database f'nofs il-vjaġġ tagħhom sabiex tkun tista 'tiġi ġġenerata statistika dwar l-isfond emozzjonali tal-utent għall-perjodu. Dan il-pakkett imbagħad jintbagħat lill-frontend, li juża l-abbonament u jirċievi pakketti mill-endpoint tal-websocket. Il-mekkaniżmu backend kollu huwa mibni fil-lingwa golang; intgħażel għax huwa adattat tajjeb għal kompiti asinkroniċi, li l-goroutines jimmaniġġjaw tajjeb.
    Meta jaċċessa l-endpoint, l-utent jiġi rreġistrat u mdaħħal fl-istruttura, imbagħad il-messaġġ tiegħu jiġi riċevut. Kemm l-utent kif ukoll il-messaġġ jiddaħħlu f'hub komuni, li minnu l-messaġġi diġà jintbagħtu aktar (għall-faċċata sottoskritta), u jekk l-utent jagħlaq il-konnessjoni (lampun jew quddiem), allura l-abbonament tiegħu jiġi kkanċellat u jitneħħa minn il-hub.

    OpenVINO hackathon: rikonoxximent tal-vuċi u l-emozzjonijiet fuq Raspberry Pi
    Qed nistennew konnessjoni minn wara

    Front-end hija applikazzjoni tal-web miktuba f'JavaScript li tuża l-librerija React biex tħaffef u tissimplifika l-proċess ta 'żvilupp. L-għan ta 'din l-applikazzjoni huwa li jivviżwalizza data miksuba bl-użu ta' algoritmi li jaħdmu fuq in-naħa ta 'wara u direttament fuq il-Raspberry Pi. Il-paġna għandha rotta sezzjonali implimentata bl-użu ta 'react-router, iżda l-paġna ewlenija ta' interess hija l-paġna ewlenija, fejn fluss kontinwu ta 'dejta jiġi riċevut f'ħin reali mis-server bl-użu tat-teknoloġija WebSocket. Raspberry Pi jiskopri vuċi, jiddetermina jekk jappartjenix għal persuna speċifika mid-database reġistrata, u jibgħat lista ta 'probabbiltà lill-klijent. Il-klijent juri l-aħħar data rilevanti, juri l-avatar tal-persuna li x'aktarx tkellmet fil-mikrofonu, kif ukoll l-emozzjoni li biha jippronunzja l-kliem.

    OpenVINO hackathon: rikonoxximent tal-vuċi u l-emozzjonijiet fuq Raspberry Pi
    Home page bi tbassir aġġornat

    Konklużjoni

    Ma kienx possibbli li tlesti kollox kif ippjanat, sempliċement ma kellniex ħin, għalhekk it-tama ewlenija kienet fid-demo, li kollox jaħdem. Fil-preżentazzjoni tkellmu dwar kif jaħdem kollox, x’mudelli ħadu, x’problemi ltaqgħu magħhom. Li jmiss kien il-parti demo - esperti mixi madwar il-kamra f'ordni każwali u avviċinat kull tim biex iħarsu lejn il-prototip tax-xogħol. Saqsewna wkoll mistoqsijiet, kulħadd wieġeb il-parti tiegħu, ħallew il-web fuq il-laptop, u kollox ħadem tassew kif mistenni.

    Ħa ninnota li l-ispiża totali tas-soluzzjoni tagħna kienet $150:

    • Raspberry Pi 3 ~ $35
    • Google AIY Voice Bonnet (tista' tieħu ħlas mill-ġdid) ~ 15$
    • Intel NCS 2 ~ 100$

    Kif tittejjeb:

    • Uża r-reġistrazzjoni mill-klijent - staqsi biex taqra t-test li jiġi ġġenerat bl-addoċċ
    • Żid ftit mudelli oħra: tista 'tiddetermina s-sess u l-età bil-vuċi
    • Ilħna separati li jdoqqu fl-istess ħin (dijarizzazzjoni)

    Repożitorju: https://github.com/vladimirwest/OpenEMO

    OpenVINO hackathon: rikonoxximent tal-vuċi u l-emozzjonijiet fuq Raspberry Pi
    Aħna għajjien imma kuntenti

    Bħala konklużjoni, nixtieq ngħid grazzi lill-organizzaturi u lill-parteċipanti. Fost il-proġetti ta’ timijiet oħra, personalment għoġobna s-soluzzjoni għall-monitoraġġ ta’ spazji ta’ parkeġġ b’xejn. Għalina, kienet esperjenza wildly friska ta 'immersjoni fil-prodott u l-iżvilupp. Nittama li jsiru aktar u aktar avvenimenti interessanti fir-reġjuni, inkluż dwar suġġetti tal-IA.

Sors: www.habr.com

Żid kumment