Hackathon OpenVINO: adnabod llais ac emosiynau ar Raspberry Pi

Tachwedd 30 - Rhagfyr 1 yn Nizhny Novgorod ei gynnal hacathon OpenVINO. Gofynnwyd i gyfranogwyr greu prototeip o ddatrysiad cynnyrch gan ddefnyddio pecyn cymorth Intel OpenVINO. Cynigiodd y trefnwyr restr o bynciau bras y gellid eu harwain wrth ddewis tasg, ond y timau oedd yn gyfrifol am y penderfyniad terfynol. Yn ogystal, anogwyd y defnydd o fodelau nad ydynt wedi'u cynnwys yn y cynnyrch.

Hackathon OpenVINO: adnabod llais ac emosiynau ar Raspberry Pi

Yn yr erthygl hon byddwn yn dweud wrthych sut y gwnaethom greu ein prototeip o'r cynnyrch, y daethom i'r brig yn y pen draw.

Cymerodd mwy na 10 tîm ran yn yr hacathon. Mae'n braf bod rhai ohonyn nhw'n dod o ranbarthau eraill. Lleoliad yr hacathon oedd y cyfadeilad “Kremlinsky on Pochain”, lle cafodd ffotograffau hynafol o Nizhny Novgorod eu hongian y tu mewn, mewn entourage! (Rwy'n eich atgoffa bod swyddfa ganolog Intel wedi'i lleoli yn Nizhny Novgorod ar hyn o bryd). Rhoddwyd 26 awr i gyfranogwyr ysgrifennu cod, ac ar y diwedd roedd yn rhaid iddynt gyflwyno eu datrysiad. Mantais ar wahân oedd presenoldeb sesiwn demo i wneud yn siŵr bod popeth a gynlluniwyd yn cael ei weithredu mewn gwirionedd ac nad oedd yn aros yn syniadau yn y cyflwyniad. Merch, byrbrydau, bwyd, roedd popeth yno hefyd!

Yn ogystal, darparodd Intel gamerâu yn ddewisol, Raspberry PI, Neural Compute Stick 2.

Dewis tasg

Un o'r rhannau anoddaf o baratoi ar gyfer hacathon ffurf rydd yw dewis her. Fe wnaethom benderfynu ar unwaith feddwl am rywbeth nad oedd yn y cynnyrch eto, gan fod y cyhoeddiad yn dweud bod croeso mawr i hyn.

Wedi dadansoddi modelau, sydd wedi'u cynnwys yn y cynnyrch yn y datganiad presennol, rydym yn dod i'r casgliad bod y rhan fwyaf ohonynt yn datrys problemau gweledigaeth cyfrifiadurol amrywiol. Ar ben hynny, mae'n anodd iawn dod o hyd i broblem ym maes gweledigaeth gyfrifiadurol na ellir ei datrys gan ddefnyddio OpenVINO, a hyd yn oed os gellir dyfeisio un, mae'n anodd dod o hyd i fodelau sydd wedi'u hyfforddi ymlaen llaw yn y parth cyhoeddus. Rydym yn penderfynu cloddio i gyfeiriad arall - tuag at brosesu lleferydd a dadansoddeg. Gadewch i ni ystyried tasg ddiddorol o adnabod emosiynau o lleferydd. Rhaid dweud bod gan OpenVINO fodel eisoes sy'n pennu emosiynau person yn seiliedig ar ei wyneb, ond:

  • Mewn theori, mae'n bosibl creu algorithm cyfun a fydd yn gweithio ar sain a delwedd, a ddylai roi cynnydd mewn cywirdeb.
  • Fel arfer mae gan gamerâu ongl wylio gul; mae angen mwy nag un camera i orchuddio ardal fawr; nid oes gan sain gyfyngiad o'r fath.

Gadewch i ni ddatblygu'r syniad: gadewch i ni gymryd y syniad ar gyfer y segment manwerthu fel sail. Gallwch fesur boddhad cwsmeriaid wrth ddesg dalu siopau. Os yw un o'r cwsmeriaid yn anfodlon â'r gwasanaeth ac yn dechrau codi ei naws, gallwch ffonio'r gweinyddwr ar unwaith am gymorth.
Yn yr achos hwn, mae angen i ni ychwanegu cydnabyddiaeth llais dynol, bydd hyn yn ein galluogi i wahaniaethu rhwng gweithwyr y siop a chwsmeriaid a darparu dadansoddeg ar gyfer pob unigolyn. Wel, yn ogystal, bydd yn bosibl dadansoddi ymddygiad gweithwyr y siop eu hunain, gwerthuso'r awyrgylch yn y tîm, swnio'n dda!

Rydym yn llunio'r gofynion ar gyfer ein datrysiad:

  • Maint bach y ddyfais targed
  • Gweithrediad amser real
  • Pris isel
  • Scalability hawdd

O ganlyniad, rydym yn dewis Raspberry Pi 3 c fel y ddyfais targed Intel NCS 2.

Yma mae'n bwysig nodi un nodwedd bwysig o NCS - mae'n gweithio orau gyda phensaernïaeth safonol CNN, ond os oes angen i chi redeg model gyda haenau arfer arno, yna disgwyliwch optimeiddio lefel isel.

Dim ond un peth bach sydd i'w wneud: mae angen i chi gael meicroffon. Bydd meicroffon USB rheolaidd yn gwneud, ond ni fydd yn edrych yn dda ynghyd â'r RPI. Ond hyd yn oed yma mae'r ateb yn llythrennol “gerllaw.” I recordio llais, rydyn ni'n penderfynu defnyddio bwrdd Voice Bonnet o'r cit Pecyn Llais Google AIY, y mae meicroffon stereo â gwifrau arno.

Lawrlwythwch Raspbian o Ystorfa prosiectau AIY a'i uwchlwytho i yriant fflach, profwch fod y meicroffon yn gweithio gan ddefnyddio'r gorchymyn canlynol (bydd yn recordio sain 5 eiliad o hyd a'i gadw mewn ffeil):

arecord -d 5 -r 16000 test.wav

Dylwn nodi ar unwaith bod y meicroffon yn sensitif iawn ac yn codi sŵn yn dda. I drwsio hyn, gadewch i ni fynd i alsamixer, dewiswch Dal dyfeisiau a lleihau lefel y signal mewnbwn i 50-60%.

Hackathon OpenVINO: adnabod llais ac emosiynau ar Raspberry Pi
Rydyn ni'n addasu'r corff gyda ffeil ac mae popeth yn ffitio, gallwch chi hyd yn oed ei gau gyda chaead

Ychwanegu botwm dangosydd

Wrth dynnu'r Pecyn Llais AIY ar wahân, cofiwn fod botwm RGB, y gellir rheoli ei ôl-olau gan feddalwedd. Rydym yn chwilio am “Google AIY Led” ac yn dod o hyd i ddogfennaeth: https://aiyprojects.readthedocs.io/en/latest/aiy.leds.html
Beth am ddefnyddio'r botwm yma i arddangos yr emosiwn cydnabyddedig, dim ond 7 dosbarth sydd gyda ni, ac mae gan y botwm 8 lliw, dim ond digon!

Rydym yn cysylltu'r botwm trwy GPIO i Voice Bonnet, yn llwytho'r llyfrgelloedd angenrheidiol (maen nhw eisoes wedi'u gosod yn y pecyn dosbarthu o brosiectau AIY)

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

Gadewch i ni greu dict lle bydd gan bob emosiwn liw cyfatebol ar ffurf Tuple RGB a gwrthrych o'r dosbarth aiy.leds.Leds, a thrwy hynny byddwn yn diweddaru'r lliw:

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

Ac yn olaf, ar ôl pob rhagfynegiad newydd o emosiwn, byddwn yn diweddaru lliw y botwm yn unol ag ef (yn ôl allwedd).

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

Hackathon OpenVINO: adnabod llais ac emosiynau ar Raspberry Pi
Botwm, llosgi!

Gweithio gyda llais

Byddwn yn defnyddio pyaudio i ddal y nant o'r meicroffon a webrtcvad i hidlo sŵn a chanfod llais. Yn ogystal, byddwn yn creu ciw y byddwn yn ychwanegu a thynnu dyfyniadau llais ato yn anghydamserol.

Gan fod gan webrtcvad gyfyngiad ar faint y darn a gyflenwir - rhaid iddo fod yn hafal i 10/20/30ms, a chynhaliwyd hyfforddiant y model ar gyfer adnabod emosiynau (fel y byddwn yn dysgu yn nes ymlaen) ar set ddata 48kHz, byddwn yn dal darnau o faint 48000 × 20ms / 1000 × 1 ( mono) = 960 beit. Bydd Webrtcvad yn dychwelyd Gwir/Gau ar gyfer pob un o'r talpiau hyn, sy'n cyfateb i bresenoldeb neu absenoldeb pleidlais yn y talp.

Gadewch i ni weithredu'r rhesymeg ganlynol:

  • Byddwn yn ychwanegu at y rhestr y talpiau hynny lle mae pleidlais; os nad oes pleidlais, yna byddwn yn cynyddu'r cownter o dalpiau gwag.
  • Os mai rhifydd y talpiau gwag yw >=30 (600 ms), yna edrychwn ar faint y rhestr o dalpiau cronedig; os yw'n >250, yna rydym yn ei ychwanegu at y ciw; os na, rydym yn ystyried bod yr hyd o'r cofnod ddim yn ddigon i'w fwydo i'r model i adnabod y siaradwr.
  • Os yw rhifydd y talpiau gwag yn dal i fod < 30, a maint y rhestr o dalpiau cronedig yn fwy na 300, yna byddwn yn ychwanegu'r darn i'r ciw i gael rhagfynegiad mwy cywir. (gan fod emosiynau'n tueddu i newid dros amser)

 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 = []

Mae'n bryd chwilio am fodelau sydd wedi'u hyfforddi ymlaen llaw yn y parth cyhoeddus, ewch i github, Google, ond cofiwch fod gennym gyfyngiad ar y bensaernïaeth a ddefnyddir. Mae hon yn rhan eithaf anodd, oherwydd mae'n rhaid i chi brofi'r modelau ar eich data mewnbwn, ac yn ogystal, eu trosi i fformat mewnol OpenVINO - IR (Cynrychiolaeth Ganolradd). Fe wnaethon ni roi cynnig ar 5-7 o atebion gwahanol o github, ac os oedd y model ar gyfer adnabod emosiynau yn gweithio ar unwaith, yna gyda chydnabyddiaeth llais roedd yn rhaid i ni aros yn hirach - maen nhw'n defnyddio pensaernïaeth fwy cymhleth.

Rydym yn canolbwyntio ar y canlynol:

Nesaf byddwn yn siarad am drosi modelau, gan ddechrau gyda theori. Mae OpenVINO yn cynnwys sawl modiwl:

  • Sw Model Agored, modelau y gellid eu defnyddio a'u cynnwys yn eich cynnyrch
  • Model Optimzer, diolch y gallwch chi drosi model o wahanol fformatau fframwaith (Tensorflow, ONNX ac ati) i fformat Cynrychiolaeth Ganolradd, y byddwn yn gweithio ymhellach ag ef
  • Mae Inference Engine yn caniatáu ichi redeg modelau mewn fformat IR ar broseswyr Intel, sglodion Myriad a chyflymwyr Neural Compute Stick
  • Y fersiwn fwyaf effeithlon o OpenCV (gyda chefnogaeth Inference Engine)
    Disgrifir pob model mewn fformat IR gan ddwy ffeil: .xml a .bin.
    Trosir modelau i fformat IR trwy Model Optimizer fel a ganlyn:

    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 yn eich galluogi i ddewis y fformat data y bydd y model yn gweithio ag ef. Cefnogir FP32, FP16, INT8. Gall dewis y math data gorau posibl roi hwb perfformiad da.
    --input_shape yn dynodi dimensiwn y data mewnbwn. Mae'n ymddangos bod y gallu i'w newid yn ddeinamig yn bresennol yn yr API C ++, ond ni wnaethom gloddio mor bell â hynny a'i osod yn syml ar gyfer un o'r modelau.
    Nesaf, gadewch i ni geisio llwytho'r model sydd eisoes wedi'i drawsnewid mewn fformat IR trwy'r modiwl DNN i OpenCV a'i anfon ymlaen ato.

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

    Mae'r llinell olaf yn yr achos hwn yn caniatáu ichi ailgyfeirio cyfrifiadau i'r Neural Compute Stick, gwneir cyfrifiadau sylfaenol ar y prosesydd, ond yn achos y Raspberry Pi ni fydd hyn yn gweithio, bydd angen ffon arnoch.

    Nesaf, mae'r rhesymeg fel a ganlyn: rydyn ni'n rhannu ein sain yn ffenestri o faint penodol (0.4 s yw hi i ni), rydyn ni'n trosi pob un o'r ffenestri hyn yn MFCC, rydyn ni wedyn yn ei fwydo i'r grid:

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

    Nesaf, gadewch i ni gymryd y dosbarth mwyaf cyffredin ar gyfer pob ffenestr. Datrysiad syml, ond ar gyfer hacathon nid oes angen i chi feddwl am rywbeth rhy astrus, dim ond os oes gennych amser. Mae gennym lawer o waith i'w wneud o hyd, felly gadewch i ni symud ymlaen - byddwn yn delio ag adnabod llais. Mae angen creu rhyw fath o gronfa ddata lle byddai sbectrogramau o leisiau wedi'u recordio ymlaen llaw yn cael eu storio. Gan nad oes llawer o amser ar ôl, byddwn yn datrys y mater hwn orau y gallwn.

    Sef, rydym yn creu sgript ar gyfer recordio dyfyniad llais (mae'n gweithio yn yr un modd ag y disgrifir uchod, dim ond pan fydd y bysellfwrdd yn torri ar ei draws y bydd yn arbed y llais i ffeil).

    Gadewch i ni geisio:

    python3 voice_db/record_voice.py test.wav

    Rydyn ni'n recordio lleisiau sawl person (tri aelod o'r tîm yn ein hachos ni)
    Nesaf, ar gyfer pob llais a recordiwyd rydym yn perfformio trawsffurfiad pedwariad cyflym, yn cael sbectrogram a'i gadw fel arae numpy (.npy):

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

    Mwy o fanylion yn y ffeil create_base.py
    O ganlyniad, pan fyddwn yn rhedeg y brif sgript, byddwn yn cael mewnosodiadau o'r sbectrogramau hyn ar y cychwyn cyntaf:

    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)

    Ar ôl derbyn yr ymgorfforiad o'r segment sain, byddwn yn gallu penderfynu i bwy y mae'n perthyn trwy gymryd y pellter cosin o'r darn i'r holl leisiau yn y gronfa ddata (y lleiaf, y mwyaf tebygol) - ar gyfer y demo rydym yn gosod y trothwy i 0.3):

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

    Yn y diwedd, hoffwn nodi bod y cyflymder casglu yn gyflym ac yn ei gwneud hi'n bosibl ychwanegu 1-2 yn fwy o fodelau (am sampl 7 eiliad o hyd cymerodd 2.5 ar gyfer casgliad). Nid oedd gennym amser bellach i ychwanegu modelau newydd a chanolbwyntiwyd ar ysgrifennu prototeip o'r rhaglen we.

    Cymhwysiad gwe

    Pwynt pwysig: rydyn ni'n mynd â llwybrydd gyda ni gartref ac yn sefydlu ein rhwydwaith lleol, mae'n helpu i gysylltu'r ddyfais a'r gliniaduron dros y rhwydwaith.

    Mae'r backend yn sianel neges diwedd-i-ddiwedd rhwng y blaen a Raspberry Pi, yn seiliedig ar dechnoleg websocket (http over tcp protocol).

    Y cam cyntaf yw derbyn gwybodaeth wedi'i phrosesu gan mafon, hynny yw, rhagfynegwyr wedi'u pacio mewn json, sy'n cael eu cadw yn y gronfa ddata hanner ffordd trwy eu taith fel y gellir cynhyrchu ystadegau am gefndir emosiynol y defnyddiwr ar gyfer y cyfnod. Yna mae'r pecyn hwn yn cael ei anfon i'r frontend, sy'n defnyddio tanysgrifiad ac yn derbyn pecynnau o bwynt terfyn y soced gwe. Mae'r mecanwaith backend cyfan wedi'i adeiladu yn yr iaith golang; fe'i dewiswyd oherwydd ei fod yn addas iawn ar gyfer tasgau asyncronaidd, y mae goroutines yn eu trin yn dda.
    Wrth gyrchu'r pwynt terfyn, mae'r defnyddiwr wedi'i gofrestru a'i gofnodi yn y strwythur, yna derbynnir ei neges. Mae'r defnyddiwr a'r neges yn cael eu rhoi mewn canolbwynt cyffredin, lle mae negeseuon eisoes yn cael eu hanfon ymhellach (i'r blaen tanysgrifiedig), ac os yw'r defnyddiwr yn cau'r cysylltiad (mafon neu flaen), yna mae ei danysgrifiad yn cael ei ganslo a chaiff ei dynnu o y canolbwynt.

    Hackathon OpenVINO: adnabod llais ac emosiynau ar Raspberry Pi
    Rydym yn aros am gysylltiad o'r cefn

    Mae Front-end yn gymhwysiad gwe wedi'i ysgrifennu yn JavaScript gan ddefnyddio'r llyfrgell React i gyflymu a symleiddio'r broses ddatblygu. Pwrpas y cymhwysiad hwn yw delweddu data a gafwyd gan ddefnyddio algorithmau sy'n rhedeg ar yr ochr gefn ac yn uniongyrchol ar y Raspberry Pi. Mae llwybriad adrannol ar waith ar y dudalen gan ddefnyddio llwybrydd adweithio, ond y brif dudalen o ddiddordeb yw'r brif dudalen, lle mae llif parhaus o ddata yn cael ei dderbyn mewn amser real gan y gweinydd gan ddefnyddio technoleg WebSocket. Mae Raspberry Pi yn canfod llais, yn penderfynu a yw'n perthyn i berson penodol o'r gronfa ddata gofrestredig, ac yn anfon rhestr tebygolrwydd at y cleient. Mae'r cleient yn arddangos y data perthnasol diweddaraf, yn arddangos avatar y person sydd fwyaf tebygol o siarad yn y meicroffon, yn ogystal â'r emosiwn y mae'n ynganu'r geiriau ag ef.

    Hackathon OpenVINO: adnabod llais ac emosiynau ar Raspberry Pi
    Tudalen gartref gyda rhagfynegiadau wedi'u diweddaru

    Casgliad

    Nid oedd yn bosibl cwblhau popeth fel y cynlluniwyd, yn syml, nid oedd gennym amser, felly roedd y prif obaith yn y demo, y byddai popeth yn gweithio. Yn y cyflwyniad buont yn siarad am sut mae popeth yn gweithio, pa fodelau a gymerwyd ganddynt, pa broblemau y daethant ar eu traws. Nesaf oedd y rhan demo - cerddodd arbenigwyr o amgylch yr ystafell mewn trefn ar hap a mynd at bob tîm i edrych ar y prototeip oedd yn gweithio. Fe wnaethon nhw ofyn cwestiynau i ni hefyd, atebodd pawb eu rhan, gadawsant y we ar y gliniadur, a gweithiodd popeth yn wir yn ôl y disgwyl.

    Gadewch imi nodi mai cyfanswm cost ein datrysiad oedd $150:

    • Raspberry Pi 3 ~ $35
    • Bonnet Llais Google AIY (gallwch gymryd ffi ailseinydd) ~ 15$
    • Intel NCS 2 ~ 100$

    Sut i wella:

    • Defnyddiwch gofrestriad gan y cleient - gofynnwch am gael darllen y testun a gynhyrchir ar hap
    • Ychwanegwch ychydig mwy o fodelau: gallwch chi bennu rhyw ac oedran yn ôl llais
    • Gwahanu lleisiau sy'n swnio ar yr un pryd (dyddiadur)

    Ystorfa: https://github.com/vladimirwest/OpenEMO

    Hackathon OpenVINO: adnabod llais ac emosiynau ar Raspberry Pi
    Rydyn ni wedi blino ond yn hapus

    I gloi, hoffwn ddiolch i’r trefnwyr a’r cyfranogwyr. Ymhlith prosiectau timau eraill, rydym yn bersonol yn hoffi'r ateb ar gyfer monitro mannau parcio am ddim. I ni, roedd yn brofiad hynod o cŵl o drochi yn y cynnyrch a datblygiad. Rwy'n gobeithio y bydd mwy a mwy o ddigwyddiadau diddorol yn cael eu cynnal yn y rhanbarthau, gan gynnwys ar bynciau AI.

Ffynhonnell: hab.com

Ychwanegu sylw