Hackathon OpenVINO: ngakuan sora sareng émosi dina Raspberry Pi

30 Nopémber - 1 Désémber di Nizhny Novgorod dilaksanakeun OpenVINO hackathon. Pamilon dipenta pikeun nyieun prototipe solusi produk ngagunakeun toolkit Intel OpenVINO. Panitia ngusulkeun daptar perkiraan topik anu tiasa dipandu nalika milih tugas, tapi kaputusan ahir tetep aya dina tim. Salaku tambahan, panggunaan modél anu henteu kalebet dina produk didorong.

Hackathon OpenVINO: ngakuan sora sareng émosi dina Raspberry Pi

Dina tulisan ieu kami bakal nyarioskeun ka anjeun ngeunaan kumaha urang nyiptakeun prototipe produk, anu antukna urang nyandak tempat munggaran.

Langkung ti 10 tim milu dina hackathon. Alusna mah sawaréh ti wewengkon séjén. Tempat pikeun hackathon nyaéta kompleks "Kremlinsky on Pochain", dimana poto-poto kuno Nizhny Novgorod digantung di jero, dina rombongan! (Kuring ngingetan yén dina momen kantor sentral Intel aya di Nizhny Novgorod). Pamilon dibéré 26 jam pikeun nulis kode, sarta dina tungtungna maranéhna kudu nampilkeun solusi maranéhanana. Kauntungannana anu misah nyaéta ayana sési demo pikeun mastikeun yén sadayana anu direncanakeun leres-leres dilaksanakeun sareng henteu tetep ideu dina presentasi. Merch, snacks, kadaharan, sagalana aya ogé!

Salaku tambahan, Intel sacara opsional nyayogikeun kaméra, Raspberry PI, Neural Compute Stick 2.

Pamilihan tugas

Salah sahiji bagian anu paling hese pikeun nyiapkeun hackathon gratis nyaéta milih tantangan. Urang langsung mutuskeun pikeun datang nepi ka hiji hal anu teu acan aya dina produk, saprak pengumuman ngomong yén ieu kacida wilujeng sumping.

Sanggeus dianalisis model, Nu kaasup dina produk dina release ayeuna, urang datang ka kacindekan yen kalobaannana ngajawab rupa masalah visi komputer. Leuwih ti éta, hésé pisan datang nepi ka masalah dina widang visi komputer nu teu bisa direngsekeun maké OpenVINO, komo lamun hiji bisa nimukeun, hese neangan model pre-dilatih dina domain publik. Urang mutuskeun pikeun ngagali arah anu sanés - nuju ngolah pidato sareng analitik. Hayu urang nganggap hiji tugas metot recognizing emosi tina ucapan. Ieu kudu ngomong yén OpenVINO geus boga model nu nangtukeun émosi hiji jalma dumasar kana beungeut maranéhanana, tapi:

  • Dina tiori, kasebut nyaéta dimungkinkeun pikeun nyieun hiji algoritma digabungkeun anu bakal dianggo dina duanana sora jeung gambar, nu kedah masihan kanaékan akurasi.
  • Kaméra biasana gaduh sudut pandang anu sempit; langkung ti hiji kaméra diperyogikeun pikeun nutupan daérah anu lega; sora henteu gaduh watesan sapertos kitu.

Hayu urang ngamekarkeun ide: hayu urang nyandak ide pikeun bagean ritel salaku dasar. Anjeun tiasa ngukur kapuasan customer di toko checkouts. Lamun salah sahiji konsumén sugema kalayan layanan sarta mimiti ngangkat nada maranéhanana, anjeun bisa langsung nelepon administrator pikeun pitulung.
Dina hal ieu, urang kudu nambahan pangakuan sora manusa, ieu bakal ngidinan urang ngabedakeun karyawan toko ti konsumén jeung nyadiakeun analytics pikeun tiap individu. Nya, salian ti éta, anjeun tiasa nganalisa paripolah para karyawan toko sorangan, ngira-ngira atmosfir di tim, disada saé!

Kami ngarumuskeun syarat pikeun solusi kami:

  • Ukuran leutik alat target
  • Operasi waktos nyata
  • Harga rendah
  • Skalabilitas gampang

Hasilna, urang milih buah prambus Pi 3 c salaku alat target Intel NCS 2.

Di dieu hal anu penting pikeun dicatet hiji fitur penting NCS - gawéna pangalusna kalawan arsitéktur CNN baku, tapi lamun kudu ngajalankeun modél kalawan lapisan custom di dinya, lajeng nyangka optimasi-tingkat low.

Aya ngan hiji hal leutik pikeun ngalakukeun: Anjeun kudu meunang mikropon. A mikropon USB biasa bakal ngalakukeun, tapi moal kasampak alus bareng jeung RPI. Tapi bahkan di dieu solusina sacara harfiah "bohong caket dieu." Pikeun ngarekam sora, urang mutuskeun pikeun ngagunakeun dewan Bonnet Sora ti kit Kit Sora Google AIY, nu aya mikropon stereo kabel.

Unduh Raspbian ti Repositori proyék AIY sareng unggah kana flash drive, uji yén mikropon tiasa dianggo nganggo paréntah di handap ieu (bakal ngarékam audio salami 5 detik sareng simpen kana file):

arecord -d 5 -r 16000 test.wav

Kuring kudu geuwat dicatet yén mikropon sensitip pisan jeung nyokot noise ogé. Pikeun ngalereskeun ieu, hayu urang angkat ka alsamixer, pilih Capture devices sareng ngirangan tingkat sinyal input ka 50-60%.

Hackathon OpenVINO: ngakuan sora sareng émosi dina Raspberry Pi
Kami ngarobih awak kalayan file sareng sadayana pas, anjeun bahkan tiasa nutup ku tutup

Nambahkeun tombol indikator

Nalika misahkeun Kit Sora AIY, urang émut yén aya tombol RGB, lampu tukangna tiasa dikontrol ku parangkat lunak. Kami milarian "Google AIY Led" sareng mendakan dokuméntasi: https://aiyprojects.readthedocs.io/en/latest/aiy.leds.html
Naha henteu nganggo tombol ieu pikeun nembongkeun émosi dipikawanoh, urang ngan 7 kelas, sarta tombol boga 8 kelir, ngan cukup!

Kami nyambungkeun tombol via GPIO ka Voice Bonnet, muatkeun perpustakaan anu diperyogikeun (aranjeunna parantos dipasang dina kit distribusi tina proyék AIY)

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

Hayu urang ngadamel dict dimana unggal émosi bakal gaduh warna anu cocog dina bentuk RGB Tuple sareng obyék kelas aiy.leds.Leds, dimana urang bakal ngamutahirkeun warna:

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

Sarta pamustunganana, sanggeus unggal prediksi anyar tina hiji emosi, urang bakal ngamutahirkeun warna tombol luyu jeung eta (ku konci).

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

Hackathon OpenVINO: ngakuan sora sareng émosi dina Raspberry Pi
Kancing, duruk!

Gawe sareng sora

Urang bakal make pyaudio pikeun newak stream ti mikropon jeung webrtcvad pikeun nyaring noise jeung ngadeteksi sora. Sajaba ti éta, urang bakal nyieun antrian nu urang asynchronously nambahkeun jeung cabut excerpts sora.

Kusabab webrtcvad gaduh watesan dina ukuran fragmen anu disayogikeun - éta kedah sami sareng 10/20/30ms, sareng palatihan modél pikeun ngenal émosi (sakumaha urang bakal diajar engké) dilaksanakeun dina set data 48kHz, urang bakal newak sakumpulan ukuran 48000 × 20ms / 1000 × 1 (mono) = 960 bait. Webrtcvad bakal balik Leres / Palsu pikeun tiap sakumpulan ieu, nu pakait jeung ayana atawa henteuna hiji sora dina chunk nu.

Hayu urang nerapkeun logika handap:

  • Kami bakal nambihan kana daptar potongan-potongan dimana aya sora; upami teu aya sora, maka kami bakal naékkeun jumlah potongan kosong.
  • Lamun counter sakumpulan kosong nyaeta > = 30 (600 mdet), lajeng urang tingali dina ukuran daptar sakumpulan akumulasi; lamun éta> 250, teras urang tambahkeun ka antrian; lamun henteu, urang tempo yén panjangna. tina catetan teu cukup pikeun eupan ka model pikeun ngaidentipikasi speaker.
  • Lamun counter sakumpulan kosong masih <30, sarta ukuran daptar sakumpulan akumulasi ngaleuwihan 300, lajeng urang bakal nambahan sempalan kana antrian pikeun prediksi leuwih akurat. (sabab émosi condong ngarobah kana waktu)

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

Waktosna milarian modél anu tos dilatih dina domain umum, angkat ka github, Google, tapi émut yén urang gaduh watesan dina arsitéktur anu dianggo. Ieu mangrupikeun bagian anu rada hese, sabab anjeun kedah nguji modél dina data input anjeun, sareng salian ti éta, ngarobih kana format internal OpenVINO - IR (Representasi Perantara). Kami nyobian ngeunaan 5-7 solusi anu béda ti github, sareng upami modél pikeun ngenalkeun émosi langsung dianggo, maka kalayan pangakuan sora urang kedah ngantosan langkung lami - aranjeunna nganggo arsitéktur anu langkung rumit.

Urang difokuskeun di handap:

Salajengna urang bakal ngobrol ngeunaan ngarobah model, dimimitian ku téori. OpenVINO ngawengku sababaraha modul:

  • Buka Model Zoo, modél anu tiasa dianggo sareng kalebet dina produk anjeun
  • Modél Optimzer, hatur nuhun pikeun anjeun tiasa ngarobih modél tina sababaraha format kerangka (Tensorflow, ONNX jsb) kana format Perwakilan Perantara, anu kami bakal damel salajengna.
  • Inferensi Engine ngamungkinkeun anjeun ngajalankeun modél dina format IR dina prosesor Intel, Myriad chip sareng akselerator Neural Compute Stick.
  • Versi OpenCV anu paling éfisién (kalayan dukungan Inferensi Engine)
    Unggal model dina format IR digambarkeun ku dua file: .xml na .bin.
    Model dirobih kana format IR via Modél Optimizer sapertos kieu:

    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 ngidinan Anjeun pikeun milih format data nu model bakal dianggo. FP32, FP16, INT8 dirojong. Milih tipe data optimal bisa méré dorongan kinerja alus.
    --input_shape nunjukkeun diménsi data input. Kamampuhan pikeun ngarobah dinamis sigana hadir dina C ++ API, tapi urang teu ngagali jauh jeung saukur ngalereskeun eta pikeun salah sahiji model.
    Salajengna, hayu urang cobian ngamuat modél anu parantos dirobih dina format IR ngalangkungan modul DNN kana OpenCV teras teraskeun ka dinya.

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

    Baris panungtungan dina hal ieu ngidinan Anjeun pikeun alihan itungan ka neural Compute Stick, itungan dasar dipigawé dina processor, tapi dina kasus Raspberry Pi ieu moal jalan, anjeun bakal kudu iteuk.

    Salajengna, logika nyaéta kieu: urang ngabagi audio kana jandéla ukuran nu tangtu (pikeun urang éta 0.4 s), urang ngarobah unggal jandela ieu kana MFCC, nu lajeng urang eupan kana grid nu.

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

    Salajengna, hayu urang nyandak kelas paling umum pikeun sakabéh jandéla. Hiji leyuran basajan, tapi pikeun hackathon anjeun teu perlu datang nepi ka hal teuing abstruse, ngan lamun boga waktu. Urang masih gaduh seueur padamelan, janten hayu urang teraskeun - urang bakal ngurus pangakuan sora. Perlu nyieun sababaraha jinis database dimana spéktrogram sora anu tos dirékam bakal disimpen. Kusabab aya sakedik waktos, kami bakal ngabéréskeun masalah ieu sabisa-bisa.

    Nyaéta, urang nyiptakeun skrip pikeun ngarékam kutipan sora (jantenna sami sareng anu dijelaskeun di luhur, ngan nalika diganggu tina keyboard éta bakal ngahémat sora kana file).

    Hayu urang coba:

    python3 voice_db/record_voice.py test.wav

    Kami ngarékam sora sababaraha jalma (dina kasus urang, tilu anggota tim)
    Salajengna, pikeun unggal sora anu dirékam, urang ngalakukeun transformasi fourier gancang, kéngingkeun spéktrogram sareng simpen salaku array numpy (.npy):

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

    Langkung rinci dina file create_base.py
    Hasilna, nalika urang ngajalankeun skrip utama, urang bakal nampi émbeddings tina spéktrogram ieu di awal:

    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)

    Saatos nampi embedding tina ruas anu disada, urang bakal tiasa nangtoskeun saha éta milik ku cara nyandak jarak kosinus tina petikan ka sadaya sora dina pangkalan data (leutik, langkung dipikaresep) - pikeun demo kami nyetél bangbarung. nepi ka 0.3):

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

    Tungtungna, abdi hoyong dicatet yén speed inferensi éta gancang sarta ngamungkinkeun pikeun nambahkeun 1-2 model langkung (pikeun sampel 7 detik lila nyandak 2.5 pikeun inferensi). Kami henteu deui ngagaduhan waktos pikeun nambihan modél énggal sareng museurkeun kana nyerat prototipe aplikasi wéb.

    Aplikasi wéb

    Titik penting: urang nyandak router sareng urang ti bumi sareng nyetél jaringan lokal urang, éta ngabantosan nyambungkeun alat sareng laptop dina jaringan.

    Backend mangrupa saluran pesen tungtung-to-tungtung antara hareup jeung Raspberry Pi, dumasar kana téhnologi websocket (http leuwih protokol tcp).

    Tahap kahiji nyaéta pikeun nampa informasi olahan tina buah prambus, nyaeta, predictors dipak dina json, nu disimpen dina database satengahna ngaliwatan lalampahan maranéhanana ku kituna statistik bisa dihasilkeun ngeunaan kasang tukang emosi pamaké pikeun periode. pakét ieu lajeng dikirim ka frontend, nu ngagunakeun langganan sarta narima pakét ti tungtung websocket. Sakabéh mékanisme backend diwangun dina basa golang; ieu dipilih sabab éta ogé cocog pikeun tugas asynchronous, nu goroutines nanganan ogé.
    Nalika ngaksés titik tungtung, pangguna kadaptar sareng diasupkeun kana struktur, teras pesenna ditampi. Duanana pamaké sarta pesen diasupkeun kana hub umum, ti mana pesen geus dikirim salajengna (ka hareup ngalanggan), sarta lamun pamaké nutup sambungan (raspberry atawa hareup), langganan na dibolaykeun sarta anjeunna dikaluarkeun tina. hub teh.

    Hackathon OpenVINO: ngakuan sora sareng émosi dina Raspberry Pi
    Kami ngantosan sambungan ti tukang

    Front-end nyaéta aplikasi wéb anu ditulis dina JavaScript nganggo perpustakaan React pikeun nyepetkeun sareng nyederhanakeun prosés pangwangunan. Tujuan tina aplikasi ieu nyaéta pikeun ngabayangkeun data anu dicandak nganggo algoritma anu dijalankeun di sisi tukang sareng langsung dina Raspberry Pi. Kaca geus sectional routing dilaksanakeun maké meta-router, tapi kaca utama dipikaresep téh kaca utama, dimana aliran kontinyu data ditampi sacara real waktu ti server ngagunakeun téhnologi WebSocket. Buah prambus Pi ngadeteksi sora, nangtukeun naha éta milik hiji jalma husus tina database didaptarkeun, sarta ngirimkeun daptar probabiliti ka klien nu. Klién nampilkeun data anu relevan panganyarna, nunjukkeun avatar jalma anu paling dipikaresep nyarios kana mikropon, ogé émosi anu anjeunna ngucapkeun kecap.

    Hackathon OpenVINO: ngakuan sora sareng émosi dina Raspberry Pi
    Kaca imah kalawan prediksi diropéa

    kacindekan

    Teu mungkin pikeun ngarengsekeun sagalana sakumaha rencanana, urang ngan teu boga waktu, jadi harepan utama dina demo, yén sagalana bakal jalan. Dina presentasi aranjeunna ngobrol ngeunaan kumaha sagalana jalan, model naon maranéhna nyokot, naon masalah aranjeunna encountered. Salajengna éta bagian demo - ahli walked sabudeureun kamar dina urutan acak sarta ditilik unggal tim pikeun nempo prototipe digawé. Aranjeunna naroskeun ka kami ogé, sadayana ngajawab bagianna, aranjeunna ngantunkeun wéb dina laptop, sareng sadayana leres-leres damel sapertos anu diharapkeun.

    Hayu atuh dicatet yén total biaya solusi urang éta $150:

    • Raspberry Pi 3 ~ $35
    • Google AIY Voice Bonnet (anjeun tiasa nyandak biaya spiker) ~ 15$
    • Intel NCS 2 ~ 100$

    Kumaha ningkatkeun:

    • Paké pendaptaran ti klien nu - ménta maca téks nu dihasilkeun acak
    • Tambahkeun sababaraha model deui: Anjeun bisa nangtukeun gender jeung umur ku sora
    • Pisahkeun sakaligus sora sora (diarisasi)

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

    Hackathon OpenVINO: ngakuan sora sareng émosi dina Raspberry Pi
    Capé tapi bagja we

    Kasimpulanana, sim kuring ngahaturkeun nuhun ka panitia sareng pamilon. Diantara proyék tim anu sanés, kami pribadi resep solusi pikeun ngawaskeun tempat parkir gratis. Pikeun kami, éta mangrupikeun pangalaman anu luar biasa tina immersion dina produk sareng pamekaran. Kuring miharep yén acara beuki loba metot bakal dilaksanakeun di wewengkon, kaasup dina jejer AI.

sumber: www.habr.com

Tambahkeun komentar